Skip to content

Conversation

@llvmbot
Copy link
Member

@llvmbot llvmbot commented Dec 5, 2025

Backport 370db9c ed07b30

(the fix and a follow up fix for the test case)

Requested by: @DavidSpickett

clayborg and others added 2 commits December 5, 2025 13:55
GCC doesn't add DW_AT_data_member_location attributes to the
DW_TAG_member children of DW_TAG_union_type types. An error was being
emitted incorrectly for these cases fr om the DWARFASTParserClang. This
fixes that issue and adds a test.

(cherry picked from commit 370db9c)
Fixes llvm#159401

On Windows there is no hex prefix, I suspect because somewhere we
print a pointer. I'd prefer to fix that itself but can't get to
a Windows machine at the moment. It's not important to the purpose
of the test anyway.

(cherry picked from commit ed07b30)
@llvmbot
Copy link
Member Author

llvmbot commented Dec 5, 2025

@Michael137 What do you think about merging this PR to the release branch?

@llvmbot
Copy link
Member Author

llvmbot commented Dec 5, 2025

@llvm/pr-subscribers-lldb

Author: None (llvmbot)

Changes

Backport 370db9c ed07b30

Requested by: @DavidSpickett


Full diff: https://github.com/llvm/llvm-project/pull/170854.diff

2 Files Affected:

  • (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp (+5-1)
  • (added) lldb/test/Shell/SymbolFile/DWARF/union-types-no-member-location.yaml (+182)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 8916c58beec0f..90431fd388674 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -3109,7 +3109,11 @@ void DWARFASTParserClang::ParseSingleMember(
       uint64_t parent_byte_size =
           parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX);
 
-      if (attrs.member_byte_offset >= parent_byte_size) {
+      // If the attrs.member_byte_offset is still set to UINT32_MAX this means
+      // that the DW_TAG_member didn't have a DW_AT_data_member_location, so
+      // don't emit an error if this is the case.
+      if (attrs.member_byte_offset != UINT32_MAX &&
+          attrs.member_byte_offset >= parent_byte_size) {
         if (member_array_size != 1 &&
             (member_array_size != 0 ||
              attrs.member_byte_offset > parent_byte_size)) {
diff --git a/lldb/test/Shell/SymbolFile/DWARF/union-types-no-member-location.yaml b/lldb/test/Shell/SymbolFile/DWARF/union-types-no-member-location.yaml
new file mode 100644
index 0000000000000..fbdc626ed113f
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/union-types-no-member-location.yaml
@@ -0,0 +1,182 @@
+# This test produces DWARF that contains a union type whose DW_TAG_member does
+# not have a DW_AT_data_member_location set to zero. This is how GCC emits
+# debug information for unions. There was code in the DWARFASTParserClang that
+# was emitting an invalid error in this case. This test verifies that this
+# error does not get emitted.
+#
+# 0x0000000b: DW_TAG_compile_unit
+#               DW_AT_name        ("main.cpp")
+#               DW_AT_language    (DW_LANG_C)
+#
+# 0x00000011:   DW_TAG_base_type
+#                 DW_AT_name      ("int")
+#                 DW_AT_encoding  (DW_ATE_signed_char)
+#                 DW_AT_byte_size (0x04)
+#
+# 0x00000018:   DW_TAG_base_type
+#                 DW_AT_name      ("__ARRAY_SIZE_TYPE__")
+#                 DW_AT_encoding  (DW_ATE_unsigned)
+#                 DW_AT_byte_size (0x08)
+#
+# 0x0000001f:   DW_TAG_array_type
+#                 DW_AT_type      (0x00000011 "int")
+#
+# 0x00000024:     DW_TAG_subrange_type
+#                   DW_AT_type    (0x00000018 "__ARRAY_SIZE_TYPE__")
+#                   DW_AT_count   (0x20)
+#
+# 0x0000002a:     NULL
+#
+# 0x0000002b:   DW_TAG_union_type
+#                 DW_AT_name      ("UnionType")
+#                 DW_AT_byte_size (0x20)
+#
+# 0x00000031:     DW_TAG_member
+#                   DW_AT_name    ("array")
+#                   DW_AT_type    (0x0000001f "int[32]")
+#
+# 0x0000003a:     NULL
+#
+# 0x0000003b:   DW_TAG_subprogram
+#                 DW_AT_low_pc    (0x0000000000001000)
+#                 DW_AT_high_pc   (0x0000000000001050)
+#                 DW_AT_name      ("foo")
+#                 DW_AT_type      (0x00000031 "array")
+#
+# 0x00000054:   NULL
+
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test symbols --name=UnionType --find=type %t > %t.stdout
+# RUN: cat %t.stdout | FileCheck --check-prefix=STDOUT %s
+# RUN: lldb-test symbols --name=UnionType --find=type %t 2> %t.stderr
+# RUN: cat %t.stderr | FileCheck --allow-empty --check-prefix=STDERR %s
+
+# STDOUT: Found 1 types:
+# STDOUT: {{(0x)?[0-9a-fA-F]+}}: Type{0x0000002b} , name = "UnionType", size = 32, compiler_type = 0x{{[0-9a-fA-F]+}} union UnionType {
+
+# STDERR-NOT: error: union-types-no-member-location.yaml.tmp 0x00000031: DW_TAG_member 'array' refers to type 0x000000000000001f which extends beyond the bounds of 0x0000002b
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+DWARF:
+  debug_str:
+    - ''
+    - main.cpp
+    - int
+    - __ARRAY_SIZE_TYPE__
+    - UnionType
+    - array
+  debug_abbrev:
+    - ID:              0
+      Table:
+        - Code:            0x1
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_language
+              Form:            DW_FORM_udata
+        - Code:            0x2
+          Tag:             DW_TAG_base_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_encoding
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_byte_size
+              Form:            DW_FORM_data1
+        - Code:            0x3
+          Tag:             DW_TAG_array_type
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref4
+        - Code:            0x4
+          Tag:             DW_TAG_subrange_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref4
+            - Attribute:       DW_AT_count
+              Form:            DW_FORM_data1
+        - Code:            0x5
+          Tag:             DW_TAG_union_type
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_byte_size
+              Form:            DW_FORM_data1
+        - Code:            0x6
+          Tag:             DW_TAG_member
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref4
+        - Code:            0x7
+          Tag:             DW_TAG_subprogram
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_low_pc
+              Form:            DW_FORM_addr
+            - Attribute:       DW_AT_high_pc
+              Form:            DW_FORM_addr
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_string
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref4
+  debug_info:
+    - Length:          0x51
+      Version:         4
+      AbbrevTableID:   0
+      AbbrOffset:      0x0
+      AddrSize:        8
+      Entries:
+        - AbbrCode:        0x1
+          Values:
+            - Value:           0x1
+            - Value:           0x2
+        - AbbrCode:        0x2
+          Values:
+            - Value:           0xA
+            - Value:           0x6
+            - Value:           0x4
+        - AbbrCode:        0x2
+          Values:
+            - Value:           0xE
+            - Value:           0x7
+            - Value:           0x8
+        - AbbrCode:        0x3
+          Values:
+            - Value:           0x11
+        - AbbrCode:        0x4
+          Values:
+            - Value:           0x18
+            - Value:           0x20
+        - AbbrCode:        0x0
+        - AbbrCode:        0x5
+          Values:
+            - Value:           0x22
+            - Value:           0x20
+        - AbbrCode:        0x6
+          Values:
+            - Value:           0x2C
+            - Value:           0x1F
+        - AbbrCode:        0x0
+        - AbbrCode:        0x7
+          Values:
+            - Value:           0x1000
+            - Value:           0x1050
+            - Value:           0xDEADBEEFDEADBEEF
+              CStr:            foo
+            - Value:           0x31
+        - AbbrCode:        0x0
+...

@DavidSpickett
Copy link
Collaborator

Some supporting information: Fixed some months ago but reported by a user of 21.1.6 yesterday - #170685.

This has been a problem since at least lldb 20, I expect it's always been a problem. The fix looks quite narrow to me but I leave it up to the experts to judge.

If 21.1.8 is not accepting fixes for pre-existing issues like this, I understand rejecting this request.

@DavidSpickett DavidSpickett changed the title release/21.x: [lldb][test] Make hex prefix optional in DWARF union types test release/21.x: [lldb] Fix a bug where an error was emitted for GCC union types. Dec 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Needs Triage

Development

Successfully merging this pull request may close these issues.

3 participants