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 <michaelbuc...@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 <michaelbuc...@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 <michaelbuc...@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 <michaelbuc...@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 <michaelbuc...@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 <michaelbuc...@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 <michaelbuc...@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; } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits