aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Labath <pavel@labath.sk>2024-05-21 12:45:59 +0200
committerGitHub <noreply@github.com>2024-05-21 12:45:59 +0200
commit9677e8171c19f1a15c0234724f083bc9473c545a (patch)
tree46fb3eb40d39b66838a46d58ff0d8eeb23530ca6
parentbb3d261f55e72e313fd8ddfefac3b47cfca2f656 (diff)
downloadllvm-9677e8171c19f1a15c0234724f083bc9473c545a.zip
llvm-9677e8171c19f1a15c0234724f083bc9473c545a.tar.gz
llvm-9677e8171c19f1a15c0234724f083bc9473c545a.tar.bz2
[lldb/dwarf] Fix DW_IDX_parent processing for split dwarf (#92745)
DWARFDebugInfo only knows how to resolve references in its own file, but in split dwarf, the index entries will refer to DIEs in the separate (DWO) file. To resolve the DIERef correctly we'd either need to go through the SymbolFileDWARF to get the full logic for resolving a DIERef, or use the fact that ToDIERef already looks up the correct unit while computing its result. This patch does the latter. This bug manifested itself in not being able to find type definitions for types in namespaces, so I've modified one of our type resolving test cases to run with debug_names, and added a namespaced class into it (it originally contained only a top-level class).
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp6
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h5
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp26
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h1
-rw-r--r--lldb/test/API/lang/cpp/limit-debug-info/Makefile2
-rw-r--r--lldb/test/API/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py40
-rw-r--r--lldb/test/API/lang/cpp/limit-debug-info/base.cpp9
-rw-r--r--lldb/test/API/lang/cpp/limit-debug-info/base.h22
-rw-r--r--lldb/test/API/lang/cpp/limit-debug-info/derived.cpp11
-rw-r--r--lldb/test/API/lang/cpp/limit-debug-info/derived.h37
-rw-r--r--lldb/test/API/lang/cpp/limit-debug-info/main.cpp6
-rw-r--r--lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp24
12 files changed, 105 insertions, 84 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 44febcf..d28da72 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -259,9 +259,3 @@ 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 c1f0cb0..456ebd9 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -44,11 +44,6 @@ public:
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/DebugNamesDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
index 4da0d56..fcf2947 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
@@ -48,26 +48,30 @@ DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) {
return result;
}
-std::optional<DIERef>
-DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) const {
+DWARFUnit *
+DebugNamesDWARFIndex::GetNonSkeletonUnit(const DebugNames::Entry &entry) const {
// Look for a DWARF unit offset (CU offset or local TU offset) as they are
// both offsets into the .debug_info section.
std::optional<uint64_t> unit_offset = entry.getCUOffset();
if (!unit_offset) {
unit_offset = entry.getLocalTUOffset();
if (!unit_offset)
- return std::nullopt;
+ return nullptr;
}
DWARFUnit *cu =
m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *unit_offset);
- if (!cu)
- return std::nullopt;
+ return cu ? &cu->GetNonSkeletonUnit() : nullptr;
+}
- cu = &cu->GetNonSkeletonUnit();
+std::optional<DIERef>
+DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) const {
+ DWARFUnit *unit = GetNonSkeletonUnit(entry);
+ if (!unit)
+ return std::nullopt;
if (std::optional<uint64_t> die_offset = entry.getDIEUnitOffset())
- return DIERef(cu->GetSymbolFileDWARF().GetFileIndex(),
- DIERef::Section::DebugInfo, cu->GetOffset() + *die_offset);
+ return DIERef(unit->GetSymbolFileDWARF().GetFileIndex(),
+ DIERef::Section::DebugInfo, unit->GetOffset() + *die_offset);
return std::nullopt;
}
@@ -306,10 +310,10 @@ bool DebugNamesDWARFIndex::SameParentChain(
auto maybe_dieoffset = entry.getDIEUnitOffset();
if (!maybe_dieoffset)
return false;
- auto die_ref = ToDIERef(entry);
- if (!die_ref)
+ DWARFUnit *unit = GetNonSkeletonUnit(entry);
+ if (!unit)
return false;
- return name == m_debug_info.PeekDIEName(*die_ref);
+ return name == unit->PeekDIEName(unit->GetOffset() + *maybe_dieoffset);
};
// If the AT_name of any parent fails to match the expected name, we don't
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
index b54dd11..392ec55 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
@@ -84,6 +84,7 @@ private:
std::unique_ptr<DebugNames> m_debug_names_up;
ManualDWARFIndex m_fallback;
+ DWARFUnit *GetNonSkeletonUnit(const DebugNames::Entry &entry) const;
std::optional<DIERef> ToDIERef(const DebugNames::Entry &entry) const;
bool ProcessEntry(const DebugNames::Entry &entry,
llvm::function_ref<bool(DWARFDIE die)> callback);
diff --git a/lldb/test/API/lang/cpp/limit-debug-info/Makefile b/lldb/test/API/lang/cpp/limit-debug-info/Makefile
index 30230b3..cbb9690 100644
--- a/lldb/test/API/lang/cpp/limit-debug-info/Makefile
+++ b/lldb/test/API/lang/cpp/limit-debug-info/Makefile
@@ -1,5 +1,3 @@
CXX_SOURCES = main.cpp derived.cpp base.cpp
-CFLAGS_EXTRAS = $(LIMIT_DEBUG_INFO_FLAGS)
-
include Makefile.rules
diff --git a/lldb/test/API/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py b/lldb/test/API/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py
index a4422ce..ebd9e66 100644
--- a/lldb/test/API/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py
+++ b/lldb/test/API/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py
@@ -5,13 +5,8 @@ from lldbsuite.test import lldbutil
class TestWithLimitDebugInfo(TestBase):
- @add_test_categories(["dwarf", "dwo"])
- def test_limit_debug_info(self):
- self.build()
-
- src_file = os.path.join(self.getSourceDir(), "main.cpp")
- src_file_spec = lldb.SBFileSpec(src_file)
- self.assertTrue(src_file_spec.IsValid(), "breakpoint file")
+ def _run_test(self, build_dict):
+ self.build(dictionary=build_dict)
# Get the path of the executable
exe_path = self.getBuildArtifact("a.out")
@@ -21,9 +16,11 @@ class TestWithLimitDebugInfo(TestBase):
self.assertTrue(target.IsValid(), VALID_TARGET)
# Break on main function
- breakpoint = target.BreakpointCreateBySourceRegex("break here", src_file_spec)
- self.assertTrue(
- breakpoint.IsValid() and breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT
+ lldbutil.run_break_set_by_file_and_line(
+ self, "derived.h", line_number("derived.h", "// break1")
+ )
+ lldbutil.run_break_set_by_file_and_line(
+ self, "derived.h", line_number("derived.h", "// break2")
)
# Launch the process
@@ -32,14 +29,23 @@ class TestWithLimitDebugInfo(TestBase):
# Get the thread of the process
self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
- thread.StepInto()
- # Get frame for current thread
- frame = thread.GetSelectedFrame()
+ self.expect_expr("1", result_type="int", result_value="1")
+ self.expect_expr("this", result_type="Foo *")
+ self.expect_expr("this->x", result_type="int", result_value="12345")
+
+ self.runCmd("continue")
self.expect_expr("1", result_type="int", result_value="1")
+ self.expect_expr("this", result_type="ns::Foo2 *")
+ self.expect_expr("this->x", result_type="int", result_value="23456")
- v2 = frame.EvaluateExpression("this")
- self.assertTrue(v2.IsValid(), "'expr this' results in a valid SBValue object")
- self.assertSuccess(v2.GetError(), "'expr this' succeeds without an error.")
+ @add_test_categories(["dwarf", "dwo"])
+ def test_default(self):
+ self._run_test(dict(CFLAGS_EXTRAS="$(LIMIT_DEBUG_INFO_FLAGS)"))
+
+ @add_test_categories(["dwarf", "dwo"])
+ def test_debug_names(self):
+ self._run_test(
+ dict(CFLAGS_EXTRAS="$(LIMIT_DEBUG_INFO_FLAGS) -gdwarf-5 -gpubnames")
+ )
diff --git a/lldb/test/API/lang/cpp/limit-debug-info/base.cpp b/lldb/test/API/lang/cpp/limit-debug-info/base.cpp
index 2968644..062eaa3 100644
--- a/lldb/test/API/lang/cpp/limit-debug-info/base.cpp
+++ b/lldb/test/API/lang/cpp/limit-debug-info/base.cpp
@@ -1,8 +1,7 @@
#include "base.h"
-FooNS::FooNS() : x(12345) {}
-
-void FooNS::bar() {
- x = 54321;
-}
+FooBase::FooBase() : x(12345) {}
+ns::Foo2Base::Foo2Base() : x(23456) {}
+void FooBase::bar() {}
+void ns::Foo2Base::bar() {}
diff --git a/lldb/test/API/lang/cpp/limit-debug-info/base.h b/lldb/test/API/lang/cpp/limit-debug-info/base.h
index f4da767..8e4dd17 100644
--- a/lldb/test/API/lang/cpp/limit-debug-info/base.h
+++ b/lldb/test/API/lang/cpp/limit-debug-info/base.h
@@ -1,12 +1,22 @@
-class FooNS
-{
+class FooBase {
public:
- virtual void bar();
- virtual char baz() = 0;
+ virtual void bar();
protected:
- FooNS();
+ FooBase();
- int x;
+ int x;
};
+namespace ns {
+class Foo2Base {
+public:
+ virtual void bar();
+
+protected:
+ Foo2Base();
+
+ int x;
+};
+
+} // namespace ns
diff --git a/lldb/test/API/lang/cpp/limit-debug-info/derived.cpp b/lldb/test/API/lang/cpp/limit-debug-info/derived.cpp
index 911fe3d..cbda8e7 100644
--- a/lldb/test/API/lang/cpp/limit-debug-info/derived.cpp
+++ b/lldb/test/API/lang/cpp/limit-debug-info/derived.cpp
@@ -1,11 +1,10 @@
#include "derived.h"
-Foo foo1;
-Foo foo2;
-
Foo::Foo() { a = 12345; }
+ns::Foo2::Foo2() { a = 23456; }
-char Foo::baz() {
- return (char)(x&0xff);
-}
+Foo foo1;
+Foo foo2;
+ns::Foo2 foo2_1;
+ns::Foo2 foo2_2;
diff --git a/lldb/test/API/lang/cpp/limit-debug-info/derived.h b/lldb/test/API/lang/cpp/limit-debug-info/derived.h
index 8f95c52..a4aab37 100644
--- a/lldb/test/API/lang/cpp/limit-debug-info/derived.h
+++ b/lldb/test/API/lang/cpp/limit-debug-info/derived.h
@@ -1,19 +1,36 @@
#include "base.h"
-class Foo : public FooNS
-{
+class Foo : public FooBase {
public:
- Foo();
+ Foo();
- // Deliberately defined by hand.
- Foo &operator=(const Foo &rhs) {
- a = rhs.a;
- return *this;
- }
+ // Deliberately defined by hand.
+ Foo &operator=(const Foo &rhs) {
+ x = rhs.x; // break1
+ a = rhs.a;
+ return *this;
+ }
+ int a;
+};
+
+namespace ns {
+class Foo2 : public Foo2Base {
+public:
+ Foo2();
- char baz() override;
- int a;
+ // Deliberately defined by hand.
+ Foo2 &operator=(const Foo2 &rhs) {
+ x = rhs.x; // break2
+ a = rhs.a;
+ return *this;
+ }
+
+ int a;
};
+} // namespace ns
extern Foo foo1;
extern Foo foo2;
+
+extern ns::Foo2 foo2_1;
+extern ns::Foo2 foo2_2;
diff --git a/lldb/test/API/lang/cpp/limit-debug-info/main.cpp b/lldb/test/API/lang/cpp/limit-debug-info/main.cpp
index 35cb037..405fc2c 100644
--- a/lldb/test/API/lang/cpp/limit-debug-info/main.cpp
+++ b/lldb/test/API/lang/cpp/limit-debug-info/main.cpp
@@ -1,8 +1,6 @@
#include "derived.h"
int main() {
- foo1 = foo2; // break here
-
- foo1.bar();
- return foo1.baz();
+ foo1 = foo2;
+ foo2_1 = foo2_2;
}
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
index bcb2118..20742ea 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
@@ -9,6 +9,7 @@
#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
#include "TestingSupport/Symbol/YAMLModuleTester.h"
+#include "lldb/Core/dwarf.h"
#include "llvm/ADT/STLExtras.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -169,21 +170,20 @@ DWARF:
YAMLModuleTester t(yamldata);
auto *symbol_file =
llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile());
- auto &debug_info = symbol_file->DebugInfo();
+ DWARFUnit *unit = symbol_file->DebugInfo().GetUnitAtIndex(0);
- DIERef first_die(std::nullopt, DIERef::Section::DebugInfo,
- 11 /*FirstDIEOffset*/);
- EXPECT_EQ(debug_info.PeekDIEName(first_die), "");
+ dw_offset_t first_die_offset = 11;
+ EXPECT_EQ(unit->PeekDIEName(first_die_offset), "");
- DIERef second_die(std::nullopt, DIERef::Section::DebugInfo, 14);
- EXPECT_EQ(debug_info.PeekDIEName(second_die), "NameType1");
+ dw_offset_t second_die_offset = 14;
+ EXPECT_EQ(unit->PeekDIEName(second_die_offset), "NameType1");
- DIERef third_die(std::nullopt, DIERef::Section::DebugInfo, 19);
- EXPECT_EQ(debug_info.PeekDIEName(third_die), "NameType2");
+ dw_offset_t third_die_offset = 19;
+ EXPECT_EQ(unit->PeekDIEName(third_die_offset), "NameType2");
- DIERef fourth_die(std::nullopt, DIERef::Section::DebugInfo, 24);
- EXPECT_EQ(debug_info.PeekDIEName(fourth_die), "NameType1");
+ dw_offset_t fourth_die_offset = 24;
+ EXPECT_EQ(unit->PeekDIEName(fourth_die_offset), "NameType1");
- DIERef fifth_die(std::nullopt, DIERef::Section::DebugInfo, 26);
- EXPECT_EQ(debug_info.PeekDIEName(fifth_die), "NameType2");
+ dw_offset_t fifth_die_offset = 26;
+ EXPECT_EQ(unit->PeekDIEName(fifth_die_offset), "NameType2");
}