[Lldb-commits] [lldb] [lldb][DWARFUnit] Implement PeekDIEName query (PR #78486)
Felipe de Azevedo Piovezan via lldb-commits
lldb-commits at lists.llvm.org
Thu Jan 18 15:23:34 PST 2024
https://github.com/felipepiovezan updated https://github.com/llvm/llvm-project/pull/78486
>From b0a33481162e24a7106cbd554b33ddb098df7612 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 7 Dec 2023 11:26:52 -0800
Subject: [PATCH 1/4] [lldb][DWARFUnit] Implement PeekDIEName query
This allows us to query the AT_Name of a DIE without parsing the entire CU.
Part of the ongoing effort to support IDX_Parent in accelerator tables [1].
[1]: https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/44
---
.../SymbolFile/DWARF/DWARFDebugInfo.cpp | 7 +++
.../Plugins/SymbolFile/DWARF/DWARFDebugInfo.h | 5 ++
.../Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 8 +++
.../Plugins/SymbolFile/DWARF/DWARFUnit.h | 5 ++
.../SymbolFile/DWARF/DWARFDIETest.cpp | 59 +++++++++++++++++++
5 files changed, 84 insertions(+)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 553b6a4c551d205..775b7a2e73f512f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -191,3 +191,10 @@ DWARFDebugInfo::GetDIE(const DIERef &die_ref) {
return cu->GetNonSkeletonUnit().GetDIE(die_ref.die_offset());
return DWARFDIE(); // Not found
}
+
+llvm::StringRef
+DWARFDebugInfo::PeekDIEName(const DIERef &die_ref) {
+ if(DWARFUnit *cu = GetUnit(die_ref))
+ return cu->GetNonSkeletonUnit().PeekDIEName(die_ref.die_offset());
+ return llvm::StringRef();
+}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
index d5e48f312ea0e98..a8b5abc3beed2d0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -43,6 +43,11 @@ class DWARFDebugInfo {
bool ContainsTypeUnits();
DWARFDIE GetDIE(const DIERef &die_ref);
+ /// Returns the AT_Name of this DIE, if it exists, without parsing the entire
+ /// compile unit. An empty is string is returned upon error or if the
+ /// attribute is not present.
+ llvm::StringRef PeekDIEName(const DIERef &die_ref);
+
enum {
eDumpFlag_Verbose = (1 << 0), // Verbose dumping
eDumpFlag_ShowForm = (1 << 1), // Show the DW_form type
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 0e2f4d45543bb53..7db279ed37d04aa 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -663,6 +663,14 @@ DWARFUnit::GetDIE(dw_offset_t die_offset) {
return DWARFDIE(); // Not found
}
+llvm::StringRef DWARFUnit::PeekDIEName(dw_offset_t die_offset) {
+ const DWARFDataExtractor &data = GetData();
+ DWARFDebugInfoEntry die;
+ if (!die.Extract(data, this, &die_offset))
+ return llvm::StringRef();
+ return die.GetName(this);
+}
+
DWARFUnit &DWARFUnit::GetNonSkeletonUnit() {
ExtractUnitDIEIfNeeded();
if (m_dwo)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index 3f528e913d8cfab..bc225a52e1d0309 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -187,6 +187,11 @@ class DWARFUnit : public UserID {
DWARFDIE GetDIE(dw_offset_t die_offset);
+ /// Returns the AT_Name of the DIE at `die_offset`, if it exists, without
+ /// parsing the entire compile unit. An empty is string is returned upon
+ /// error or if the attribute is not present.
+ llvm::StringRef PeekDIEName(dw_offset_t die_offset);
+
DWARFUnit &GetNonSkeletonUnit();
static uint8_t GetAddressByteSize(const DWARFUnit *cu);
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
index 8497855b2f3db59..ff433c7a14ef7be 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
#include "TestingSupport/Symbol/YAMLModuleTester.h"
#include "llvm/ADT/STLExtras.h"
#include "gmock/gmock.h"
@@ -104,3 +105,61 @@ TEST(DWARFDIETest, ChildIteration) {
DWARFDIE no_children_die(unit, die_child0);
EXPECT_TRUE(no_children_die.children().empty());
}
+
+TEST(DWARFDIETest, PeekName) {
+ const char *yamldata = R"(
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_386
+DWARF:
+ debug_str:
+ - 'NameType1'
+ - 'NameType2'
+ debug_abbrev:
+ - Table:
+ - Code: 0x00000001
+ Tag: DW_TAG_compile_unit
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_language
+ Form: DW_FORM_data2
+ - Code: 0x00000002
+ Tag: DW_TAG_base_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_strp
+ debug_info:
+ - Version: 4
+ AddrSize: 8
+ Entries:
+ - AbbrCode: 0x00000001
+ Values:
+ - Value: 0x000000000000000C
+ - AbbrCode: 0x00000002
+ Values:
+ - Value: 0x0000000000000000 # Name = NameType1
+ - AbbrCode: 0x00000002
+ Values:
+ - Value: 0x000000000000000a # Name = NameType2
+ - AbbrCode: 0x00000000
+)";
+
+ YAMLModuleTester t(yamldata);
+ auto *symbol_file =
+ llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile());
+ auto &debug_info = symbol_file->DebugInfo();
+
+ DIERef first_die(std::nullopt, DIERef::Section::DebugInfo,
+ 11 /*FirstDIEOffset*/);
+ EXPECT_EQ(debug_info.PeekDIEName(first_die), "");
+
+ DIERef second_die(std::nullopt, DIERef::Section::DebugInfo, 14);
+ EXPECT_EQ(debug_info.PeekDIEName(second_die), "NameType1");
+
+ DIERef third_die(std::nullopt, DIERef::Section::DebugInfo, 19);
+ EXPECT_EQ(debug_info.PeekDIEName(third_die), "NameType2");
+}
>From 7a76ff2affd9d3c5df783aa07f50816d981baf7e Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Wed, 17 Jan 2024 13:00:33 -0800
Subject: [PATCH 2/4] fixup! Add tests with AT_specification and
AT_abstract_origin
---
.../SymbolFile/DWARF/DWARFDIETest.cpp | 24 +++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
index ff433c7a14ef7be..bcb211815f9f351 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
@@ -132,6 +132,18 @@ TEST(DWARFDIETest, PeekName) {
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_strp
+ - Code: 0x00000003
+ Tag: DW_TAG_base_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_abstract_origin
+ Form: DW_FORM_ref1
+ - Code: 0x00000004
+ Tag: DW_TAG_base_type
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_specification
+ Form: DW_FORM_ref1
debug_info:
- Version: 4
AddrSize: 8
@@ -145,6 +157,12 @@ TEST(DWARFDIETest, PeekName) {
- AbbrCode: 0x00000002
Values:
- Value: 0x000000000000000a # Name = NameType2
+ - AbbrCode: 0x00000003
+ Values:
+ - Value: 0x000000000000000e # Ref abstract origin to NameType1 DIE.
+ - AbbrCode: 0x00000004
+ Values:
+ - Value: 0x0000000000000013 # Ref specification to NameType2 DIE.
- AbbrCode: 0x00000000
)";
@@ -162,4 +180,10 @@ TEST(DWARFDIETest, PeekName) {
DIERef third_die(std::nullopt, DIERef::Section::DebugInfo, 19);
EXPECT_EQ(debug_info.PeekDIEName(third_die), "NameType2");
+
+ DIERef fourth_die(std::nullopt, DIERef::Section::DebugInfo, 24);
+ EXPECT_EQ(debug_info.PeekDIEName(fourth_die), "NameType1");
+
+ DIERef fifth_die(std::nullopt, DIERef::Section::DebugInfo, 26);
+ EXPECT_EQ(debug_info.PeekDIEName(fifth_die), "NameType2");
}
>From a11a77beba2bdbb688eed1b4b2ce97a689766038 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Wed, 17 Jan 2024 13:05:55 -0800
Subject: [PATCH 3/4] fixup! clang-format
---
lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 775b7a2e73f512f..340b9acf80d023b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -192,9 +192,8 @@ DWARFDebugInfo::GetDIE(const DIERef &die_ref) {
return DWARFDIE(); // Not found
}
-llvm::StringRef
-DWARFDebugInfo::PeekDIEName(const DIERef &die_ref) {
- if(DWARFUnit *cu = GetUnit(die_ref))
+llvm::StringRef DWARFDebugInfo::PeekDIEName(const DIERef &die_ref) {
+ if (DWARFUnit *cu = GetUnit(die_ref))
return cu->GetNonSkeletonUnit().PeekDIEName(die_ref.die_offset());
return llvm::StringRef();
}
>From 6e38496571407582c652d23260c2bbc94c5548a7 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 18 Jan 2024 15:23:10 -0800
Subject: [PATCH 4/4] fixup! Dont parse DIEs when following
AT_specification/abstract_origin
---
.../SymbolFile/DWARF/DWARFFormValue.cpp | 24 +++++++++++--------
.../Plugins/SymbolFile/DWARF/DWARFFormValue.h | 6 +++++
.../Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 22 ++++++++++++++---
3 files changed, 39 insertions(+), 13 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index 0a7029a55c047bb..e1f73f1997e3692 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -18,8 +18,6 @@
#include "DWARFFormValue.h"
#include "DWARFUnit.h"
-class DWARFUnit;
-
using namespace lldb_private;
using namespace lldb_private::dwarf;
using namespace lldb_private::plugin::dwarf;
@@ -502,7 +500,8 @@ dw_addr_t DWARFFormValue::Address() const {
&offset, index_size);
}
-DWARFDIE DWARFFormValue::Reference() const {
+std::pair<DWARFUnit *, uint64_t>
+DWARFFormValue::ReferencedUnitAndOffset() const {
uint64_t value = m_value.value.uval;
switch (m_form) {
case DW_FORM_ref1:
@@ -516,9 +515,9 @@ DWARFDIE DWARFFormValue::Reference() const {
if (!m_unit->ContainsDIEOffset(value)) {
m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
"DW_FORM_ref* DIE reference {0:x16} is outside of its CU", value);
- return {};
+ return {nullptr, 0};
}
- return const_cast<DWARFUnit *>(m_unit)->GetDIE(value);
+ return {const_cast<DWARFUnit *>(m_unit), value};
case DW_FORM_ref_addr: {
DWARFUnit *ref_cu =
@@ -527,24 +526,29 @@ DWARFDIE DWARFFormValue::Reference() const {
if (!ref_cu) {
m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
"DW_FORM_ref_addr DIE reference {0:x16} has no matching CU", value);
- return {};
+ return {nullptr, 0};
}
- return ref_cu->GetDIE(value);
+ return {ref_cu, value};
}
case DW_FORM_ref_sig8: {
DWARFTypeUnit *tu =
m_unit->GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(value);
if (!tu)
- return {};
- return tu->GetDIE(tu->GetTypeOffset());
+ return {nullptr, 0};
+ return {tu, tu->GetTypeOffset()};
}
default:
- return {};
+ return {nullptr, 0};
}
}
+DWARFDIE DWARFFormValue::Reference() const {
+ auto [unit, offset] = ReferencedUnitAndOffset();
+ return unit ? unit->GetDIE(offset) : DWARFDIE();
+}
+
uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {
uint64_t value = m_value.value.uval;
switch (m_form) {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index 445749a6aac3ac7..fdd5b3c278a4e80 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -60,6 +60,12 @@ class DWARFFormValue {
const DWARFUnit *u);
std::optional<uint8_t> GetFixedSize() const;
DWARFDIE Reference() const;
+
+ /// If this is a reference to another DIE, return the corresponding DWARFUnit
+ /// and DIE offset such that Unit->GetDIE(offset) produces the desired DIE.
+ /// Otherwise, a nullptr and unspecified offset are returned.
+ std::pair<DWARFUnit *, uint64_t> ReferencedUnitAndOffset() const;
+
uint64_t Reference(dw_offset_t offset) const;
bool Boolean() const { return m_value.value.uval != 0; }
uint64_t Unsigned() const { return m_value.value.uval; }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 7db279ed37d04aa..c07309547fbe09b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -664,11 +664,27 @@ DWARFUnit::GetDIE(dw_offset_t die_offset) {
}
llvm::StringRef DWARFUnit::PeekDIEName(dw_offset_t die_offset) {
- const DWARFDataExtractor &data = GetData();
DWARFDebugInfoEntry die;
- if (!die.Extract(data, this, &die_offset))
+ if (!die.Extract(GetData(), this, &die_offset))
return llvm::StringRef();
- return die.GetName(this);
+
+ // Does die contain an AT_Name?
+ if (const char *name =
+ die.GetAttributeValueAsString(this, DW_AT_name, nullptr))
+ return name;
+
+ // Does its specification or abstract_origin contain an AT_Name?
+ for (auto attr : {DW_AT_specification, DW_AT_abstract_origin}) {
+ DWARFFormValue form_value;
+ if (!die.GetAttributeValue(this, attr, form_value))
+ continue;
+ auto [unit, offset] = form_value.ReferencedUnitAndOffset();
+ if (unit)
+ if (auto name = unit->PeekDIEName(offset); !name.empty())
+ return name;
+ }
+
+ return llvm::StringRef();
}
DWARFUnit &DWARFUnit::GetNonSkeletonUnit() {
More information about the lldb-commits
mailing list