[Lldb-commits] [lldb] [lldb][DWARFASTParserClang] Support constant index encoding of DW_AT_object_pointer (PR #144998)
Michael Buch via lldb-commits
lldb-commits at lists.llvm.org
Mon Jun 23 09:31:50 PDT 2025
https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/144998
>From 90cbdaf1bc0151cb57465b0741b2cf1560edce62 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Wed, 29 Jan 2025 12:15:35 +0000
Subject: [PATCH 1/7] [lldb][DWARFASTParserClang] Support constant index
encoding of DW_AT_object_pointer
Starting with https://github.com/llvm/llvm-project/pull/124790, Clang
emits `DW_AT_object_pointer` encoded as integer constants rather than
DIE references. This patch accounts for this.
---
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 49 +++--
.../x86/explicit-member-function-quals.cpp | 21 +-
.../DWARF/DWARFASTParserClangTests.cpp | 196 ++++++++++++++++++
3 files changed, 245 insertions(+), 21 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index d3912ad55a235..df92cd6477022 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -167,9 +167,42 @@ DWARFASTParserClang::GetObjectParameter(const DWARFDIE &subprogram,
subprogram.Tag() == DW_TAG_inlined_subroutine ||
subprogram.Tag() == DW_TAG_subroutine_type);
- if (DWARFDIE object_parameter =
- subprogram.GetAttributeValueAsReferenceDIE(DW_AT_object_pointer))
- return object_parameter;
+ // The DW_AT_object_pointer may be either encoded as a reference to a DIE,
+ // in which case that's the object parameter we want. Or it can be a constant
+ // index of the parameter.
+ std::optional<size_t> object_pointer_index;
+ DWARFFormValue form_value;
+ if (subprogram.GetDIE()->GetAttributeValue(
+ subprogram.GetCU(), DW_AT_object_pointer, form_value,
+ /*end_attr_offset_ptr=*/nullptr, /*check_elaborating_dies=*/true)) {
+ if (auto ref = form_value.Reference())
+ return ref;
+
+ object_pointer_index = form_value.Unsigned();
+ }
+
+ // Try to find the DW_TAG_formal_parameter via object_pointer_index.
+ DWARFDIE object_pointer;
+ size_t param_index = 0;
+ for (const auto &child : subprogram.children()) {
+ if (child.Tag() != DW_TAG_formal_parameter)
+ continue;
+
+ if (param_index == object_pointer_index.value_or(0))
+ object_pointer = child;
+
+ ++param_index;
+ }
+
+ // No formal parameter found for object pointer index.
+ // Nothing to be done.
+ if (!object_pointer)
+ return {};
+
+ // We found the object pointer encoded via DW_AT_object_pointer.
+ // No need for the remaining heuristics.
+ if (object_pointer_index)
+ return object_pointer;
// If no DW_AT_object_pointer was specified, assume the implicit object
// parameter is the first parameter to the function, is called "this" and is
@@ -178,16 +211,6 @@ DWARFASTParserClang::GetObjectParameter(const DWARFDIE &subprogram,
if (!decl_ctx_die.IsStructUnionOrClass())
return {};
- auto children = subprogram.children();
- auto it = llvm::find_if(children, [](const DWARFDIE &child) {
- return child.Tag() == DW_TAG_formal_parameter;
- });
-
- if (it == children.end())
- return {};
-
- DWARFDIE object_pointer = *it;
-
if (!object_pointer.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
return {};
diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp b/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp
index 33001db69f83e..f89f0f4a4f0bf 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp
@@ -1,4 +1,9 @@
// XFAIL: *
+//
+// FIXME: Explicit object parameter is not shown in
+// type lookup output. This is because we don't attach
+// valid source locations to decls in the DWARF AST,
+// so the ParmVarDecl::isExplicitObjectParameter fails.
// Tests that we correctly deduce the CV-quals and storage
// class of explicit object member functions.
@@ -8,15 +13,15 @@
//
// CHECK: (lldb) type lookup Foo
// CHECK-NEXT: struct Foo {
-// CHECK-NEXT: void Method(Foo);
-// CHECK-NEXT: void cMethod(const Foo &) const;
-// CHECK-NEXT: void vMethod(volatile Foo &) volatile;
-// CHECK-NEXT: void cvMethod(const volatile Foo &) const volatile;
+// CHECK-NEXT: void Method(this Foo);
+// CHECK-NEXT: void cMethod(this const Foo &) const;
+// CHECK-NEXT: void vMethod(this volatile Foo &) volatile;
+// CHECK-NEXT: void cvMethod(this const volatile Foo &) const volatile;
// CHECK-NEXT: }
struct Foo {
- void Method(this Foo) {}
- void cMethod(this Foo const &) {}
- void vMethod(this Foo volatile &) {}
- void cvMethod(this Foo const volatile &) {}
+ [[gnu::always_inline]] void Method(this Foo) {}
+ [[gnu::always_inline]] void cMethod(this Foo const &) {}
+ [[gnu::always_inline]] void vMethod(this Foo volatile &) {}
+ [[gnu::always_inline]] void cvMethod(this Foo const volatile &) {}
} f;
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index fa05cd174fc7b..73b52d821e5ea 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -1423,3 +1423,199 @@ TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ParameterCreation) {
EXPECT_EQ(func->getParamDecl(1)->getDeclContext(), func);
EXPECT_EQ(func->getParamDecl(1)->getName(), "namedParam");
}
+
+TEST_F(DWARFASTParserClangTests, TestParseDWARFAttributes_ObjectPointerIndex) {
+ // This tests the behaviour of ParsedDWARFTypeAttributes
+ // for DW_TAG_subprogram definitions which have a DW_AT_object_pointer
+ // that encodes a constant index (instead of a DIE reference).
+
+ const char *yamldata = R"(
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_AARCH64
+DWARF:
+ debug_str:
+ - Context
+ - func
+ - this
+ - self
+ - arg
+ debug_abbrev:
+ - ID: 0
+ Table:
+ - Code: 0x1
+ Tag: DW_TAG_compile_unit
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_language
+ Form: DW_FORM_data2
+ - Code: 0x2
+ Tag: DW_TAG_structure_type
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_strp
+ - Code: 0x3
+ Tag: DW_TAG_subprogram
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_strp
+ - Attribute: DW_AT_declaration
+ Form: DW_FORM_flag_present
+ - Attribute: DW_AT_object_pointer
+ Form: DW_FORM_implicit_const
+ Value: 1
+ - Attribute: DW_AT_external
+ Form: DW_FORM_flag_present
+ - Code: 0x4
+ Tag: DW_TAG_subprogram
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_strp
+ - Attribute: DW_AT_declaration
+ Form: DW_FORM_flag_present
+ - Attribute: DW_AT_object_pointer
+ Form: DW_FORM_implicit_const
+ Value: 0
+ - Attribute: DW_AT_external
+ Form: DW_FORM_flag_present
+
+ - Code: 0x5
+ Tag: DW_TAG_formal_parameter
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_strp
+
+ - Code: 0x6
+ Tag: DW_TAG_formal_parameter
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_strp
+ - Attribute: DW_AT_artificial
+ Form: DW_FORM_flag_present
+
+ debug_info:
+ - Version: 5
+ UnitType: DW_UT_compile
+ AddrSize: 8
+ Entries:
+
+# DW_TAG_compile_unit
+# DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus)
+
+ - AbbrCode: 0x1
+ Values:
+ - Value: 0x04
+
+# DW_TAG_structure_type
+# DW_AT_name [DW_FORM_strp] ("Context")
+
+ - AbbrCode: 0x2
+ Values:
+ - Value: 0x0
+
+# DW_TAG_subprogram
+# DW_AT_name [DW_FORM_strp] ("func")
+# DW_AT_object_pointer [DW_FORM_implicit_const] (1)
+ - AbbrCode: 0x3
+ Values:
+ - Value: 0x8
+ - Value: 0x1
+ - Value: 0x1
+ - Value: 0x1
+
+# DW_TAG_formal_parameter
+# DW_AT_name [DW_FORM_strp] ("arg")
+ - AbbrCode: 0x5
+ Values:
+ - Value: 0x17
+
+# DW_TAG_formal_parameter
+# DW_AT_name [DW_FORM_strp] ("self")
+# DW_AT_artificial
+ - AbbrCode: 0x6
+ Values:
+ - Value: 0x12
+ - Value: 0x1
+
+ - AbbrCode: 0x0
+ - AbbrCode: 0x0
+
+# DW_TAG_subprogram
+# DW_AT_object_pointer [DW_FORM_implicit_const] (0)
+# DW_AT_name [DW_FORM_strp] ("func")
+ - AbbrCode: 0x4
+ Values:
+ - Value: 0x8
+ - Value: 0x1
+ - Value: 0x1
+ - Value: 0x1
+
+# DW_TAG_formal_parameter
+# DW_AT_name [DW_FORM_strp] ("this")
+# DW_AT_artificial
+ - AbbrCode: 0x6
+ Values:
+ - Value: 0xd
+ - Value: 0x1
+
+# DW_TAG_formal_parameter
+# DW_AT_name [DW_FORM_strp] ("arg")
+ - AbbrCode: 0x5
+ Values:
+ - Value: 0x17
+
+ - AbbrCode: 0x0
+ - AbbrCode: 0x0
+...
+)";
+
+ YAMLModuleTester t(yamldata);
+
+ DWARFUnit *unit = t.GetDwarfUnit();
+ ASSERT_NE(unit, nullptr);
+ const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
+ ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
+ ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
+ DWARFDIE cu_die(unit, cu_entry);
+
+ auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
+ auto &ast_ctx = *holder->GetAST();
+ DWARFASTParserClangStub ast_parser(ast_ctx);
+
+ auto context_die = cu_die.GetFirstChild();
+ ASSERT_TRUE(context_die.IsValid());
+ ASSERT_EQ(context_die.Tag(), DW_TAG_structure_type);
+
+ auto sub1 = context_die.GetFirstChild();
+ ASSERT_TRUE(sub1.IsValid());
+ ASSERT_EQ(sub1.Tag(), DW_TAG_subprogram);
+
+ auto sub2 = sub1.GetSibling();
+ ASSERT_TRUE(sub2.IsValid());
+ ASSERT_EQ(sub2.Tag(), DW_TAG_subprogram);
+
+ // Object parameter is at constant index 1
+ {
+ auto param_die = sub1.GetFirstChild().GetSibling();
+ ASSERT_TRUE(param_die.IsValid());
+
+ EXPECT_EQ(param_die, ast_parser.GetCXXObjectParameter(sub1, context_die));
+ }
+
+ // Object parameter is at constant index 0
+ {
+ auto param_die = sub2.GetFirstChild();
+ ASSERT_TRUE(param_die.IsValid());
+
+ EXPECT_EQ(param_die,
+ ast_parser.GetCXXObjectParameter(param_die, context_die));
+ }
+}
>From bcab05d6e63d564845b578f7cff5fbda8f47ccc8 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 20 Jun 2025 10:00:00 +0100
Subject: [PATCH 2/7] fixup! revert redundant test changes
---
.../DWARF/x86/explicit-member-function-quals.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp b/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp
index f89f0f4a4f0bf..c592122e7a973 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp
@@ -20,8 +20,8 @@
// CHECK-NEXT: }
struct Foo {
- [[gnu::always_inline]] void Method(this Foo) {}
- [[gnu::always_inline]] void cMethod(this Foo const &) {}
- [[gnu::always_inline]] void vMethod(this Foo volatile &) {}
- [[gnu::always_inline]] void cvMethod(this Foo const volatile &) {}
+ void Method(this Foo) {}
+ void cMethod(this Foo const &) {}
+ void vMethod(this Foo volatile &) {}
+ void cvMethod(this Foo const volatile &) {}
} f;
>From ed52a3580e5d3a244acda1f3a3a683e953830a5a Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Sun, 22 Jun 2025 12:00:23 +0100
Subject: [PATCH 3/7] fixup! rename GetCXXObjectParameter in test
---
lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index 73b52d821e5ea..8f2dd2ff7d930 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -1607,7 +1607,7 @@ TEST_F(DWARFASTParserClangTests, TestParseDWARFAttributes_ObjectPointerIndex) {
auto param_die = sub1.GetFirstChild().GetSibling();
ASSERT_TRUE(param_die.IsValid());
- EXPECT_EQ(param_die, ast_parser.GetCXXObjectParameter(sub1, context_die));
+ EXPECT_EQ(param_die, ast_parser.GetObjectParameter(sub1, context_die));
}
// Object parameter is at constant index 0
@@ -1615,7 +1615,6 @@ TEST_F(DWARFASTParserClangTests, TestParseDWARFAttributes_ObjectPointerIndex) {
auto param_die = sub2.GetFirstChild();
ASSERT_TRUE(param_die.IsValid());
- EXPECT_EQ(param_die,
- ast_parser.GetCXXObjectParameter(param_die, context_die));
+ EXPECT_EQ(param_die, ast_parser.GetObjectParameter(param_die, context_die));
}
}
>From 200df32caf11c4446e3d1aadc95259a119d77a32 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Sun, 22 Jun 2025 12:02:18 +0100
Subject: [PATCH 4/7] fixup! rename test
---
lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index 8f2dd2ff7d930..d9acf1ced47c2 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -1424,8 +1424,8 @@ TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ParameterCreation) {
EXPECT_EQ(func->getParamDecl(1)->getName(), "namedParam");
}
-TEST_F(DWARFASTParserClangTests, TestParseDWARFAttributes_ObjectPointerIndex) {
- // This tests the behaviour of ParsedDWARFTypeAttributes
+TEST_F(DWARFASTParserClangTests, TestObjectPointer_IndexEncoding) {
+ // This tests the behaviour of DWARFASTParserClang
// for DW_TAG_subprogram definitions which have a DW_AT_object_pointer
// that encodes a constant index (instead of a DIE reference).
>From e2c2dabbb6d8e153a66d097396dd69cfee148aff Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Sun, 22 Jun 2025 23:32:53 +0100
Subject: [PATCH 5/7] fixup! fix yaml
---
lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index d9acf1ced47c2..10141b13bb799 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -1546,7 +1546,6 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer_IndexEncoding) {
- Value: 0x1
- AbbrCode: 0x0
- - AbbrCode: 0x0
# DW_TAG_subprogram
# DW_AT_object_pointer [DW_FORM_implicit_const] (0)
>From 84d75a73e30c327313a87d3427138f68fdf3d174 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 23 Jun 2025 10:00:41 +0100
Subject: [PATCH 6/7] fixup! fix test assertion
---
lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index 10141b13bb799..d608a57382096 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -1614,6 +1614,6 @@ TEST_F(DWARFASTParserClangTests, TestObjectPointer_IndexEncoding) {
auto param_die = sub2.GetFirstChild();
ASSERT_TRUE(param_die.IsValid());
- EXPECT_EQ(param_die, ast_parser.GetObjectParameter(param_die, context_die));
+ EXPECT_EQ(param_die, ast_parser.GetObjectParameter(sub2, context_die));
}
}
>From 3df8d0a877503451a63697e775b8a342569716d4 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 23 Jun 2025 10:39:31 +0100
Subject: [PATCH 7/7] fixup! early exit from paramater loop
---
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index df92cd6477022..c76d67b47b336 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -188,8 +188,10 @@ DWARFASTParserClang::GetObjectParameter(const DWARFDIE &subprogram,
if (child.Tag() != DW_TAG_formal_parameter)
continue;
- if (param_index == object_pointer_index.value_or(0))
+ if (param_index == object_pointer_index.value_or(0)) {
object_pointer = child;
+ break;
+ }
++param_index;
}
More information about the lldb-commits
mailing list