Skip to content

[lldb/dwarf] Fix DW_IDX_parent processing for split dwarf #92745

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
5 changes: 0 additions & 5 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@ 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
Expand Down
26 changes: 15 additions & 11 deletions lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class DebugNamesDWARFIndex : public DWARFIndex {
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);
Expand Down
2 changes: 0 additions & 2 deletions lldb/test/API/lang/cpp/limit-debug-info/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
CXX_SOURCES = main.cpp derived.cpp base.cpp

CFLAGS_EXTRAS = $(LIMIT_DEBUG_INFO_FLAGS)

include Makefile.rules
40 changes: 23 additions & 17 deletions lldb/test/API/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,8 @@


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")
Expand All @@ -21,9 +16,11 @@ def test_limit_debug_info(self):
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
Expand All @@ -32,14 +29,23 @@ def test_limit_debug_info(self):

# 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")
)
9 changes: 4 additions & 5 deletions lldb/test/API/lang/cpp/limit-debug-info/base.cpp
Original file line number Diff line number Diff line change
@@ -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() {}
22 changes: 16 additions & 6 deletions lldb/test/API/lang/cpp/limit-debug-info/base.h
Original file line number Diff line number Diff line change
@@ -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
11 changes: 5 additions & 6 deletions lldb/test/API/lang/cpp/limit-debug-info/derived.cpp
Original file line number Diff line number Diff line change
@@ -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;
37 changes: 27 additions & 10 deletions lldb/test/API/lang/cpp/limit-debug-info/derived.h
Original file line number Diff line number Diff line change
@@ -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;
6 changes: 2 additions & 4 deletions lldb/test/API/lang/cpp/limit-debug-info/main.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#include "derived.h"

int main() {
foo1 = foo2; // break here

foo1.bar();
return foo1.baz();
foo1 = foo2;
foo2_1 = foo2_2;
}
24 changes: 12 additions & 12 deletions lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -169,21 +170,20 @@ TEST(DWARFDIETest, PeekName) {
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");
}
Loading