[Lldb-commits] [lldb] 6f2423c - [lldb] Allow SymbolFileDWARFDebugMap to register multiple compile units
Augusto Noronha via lldb-commits
lldb-commits at lists.llvm.org
Wed Oct 19 13:50:05 PDT 2022
Author: Augusto Noronha
Date: 2022-10-19T13:49:40-07:00
New Revision: 6f2423c6fe97bec77da66d87a7a997917f6b489e
URL: https://github.com/llvm/llvm-project/commit/6f2423c6fe97bec77da66d87a7a997917f6b489e
DIFF: https://github.com/llvm/llvm-project/commit/6f2423c6fe97bec77da66d87a7a997917f6b489e.diff
LOG: [lldb] Allow SymbolFileDWARFDebugMap to register multiple compile units
Currently, SymbolFileDWARFDebugMap works on the assumption that there is
only one compile unit per object file. This patch documents this
limitation (when using the general SymbolFile API), and allows users of
the concrete SymbolFileDWARFDebugMap class to find out about these extra
compile units.
Differential Revision: https://reviews.llvm.org/D136114
Added:
lldb/test/API/lang/c/full_lto_stepping/Makefile
lldb/test/API/lang/c/full_lto_stepping/TestFullLtoStepping.py
lldb/test/API/lang/c/full_lto_stepping/foo.c
lldb/test/API/lang/c/full_lto_stepping/foo.h
lldb/test/API/lang/c/full_lto_stepping/main.c
Modified:
lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
Removed:
################################################################################
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
index 9ca160b474fc9..ced03752aadc2 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -53,28 +53,21 @@ void DWARFCompileUnit::BuildAddressRangeTable(
}
if (debug_aranges->GetNumRanges() == num_debug_aranges) {
- // We got nothing from the debug info, maybe we have a line tables only
- // situation. Check the line tables and build the arange table from this.
+ // We got nothing from the debug info, try to build the arange table from
+ // the debug map OSO aranges.
SymbolContext sc;
sc.comp_unit = m_dwarf.GetCompUnitForDWARFCompUnit(*this);
if (sc.comp_unit) {
SymbolFileDWARFDebugMap *debug_map_sym_file =
m_dwarf.GetDebugMapSymfile();
- if (debug_map_sym_file == nullptr) {
- if (LineTable *line_table = sc.comp_unit->GetLineTable()) {
- LineTable::FileAddressRanges file_ranges;
- const bool append = true;
- const size_t num_ranges =
- line_table->GetContiguousFileAddressRanges(file_ranges, append);
- for (uint32_t idx = 0; idx < num_ranges; ++idx) {
- const LineTable::FileAddressRanges::Entry &range =
- file_ranges.GetEntryRef(idx);
- debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
- range.GetRangeEnd());
- }
- }
- } else
- debug_map_sym_file->AddOSOARanges(&m_dwarf, debug_aranges);
+ if (debug_map_sym_file) {
+ auto *cu_info =
+ debug_map_sym_file->GetCompileUnitInfo(&GetSymbolFileDWARF());
+ // If there are extra compile units the OSO entries aren't a reliable
+ // source of information.
+ if (cu_info->compile_units_sps.empty())
+ debug_map_sym_file->AddOSOARanges(&m_dwarf, debug_aranges);
+ }
}
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index d029e4da86175..42a0302351dd6 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -702,9 +702,9 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
// We already parsed this compile unit, had out a shared pointer to it
cu_sp = comp_unit->shared_from_this();
} else {
- if (dwarf_cu.GetOffset() == 0 && GetDebugMapSymfile()) {
+ if (GetDebugMapSymfile()) {
// Let the debug map create the compile unit
- cu_sp = m_debug_map_symfile->GetCompileUnit(this);
+ cu_sp = m_debug_map_symfile->GetCompileUnit(this, dwarf_cu);
dwarf_cu.SetUserData(cu_sp.get());
} else {
ModuleSP module_sp(m_objfile_sp->GetModule());
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index 97140704ad33e..015633727f18d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -7,7 +7,9 @@
//===----------------------------------------------------------------------===//
#include "SymbolFileDWARFDebugMap.h"
+#include "DWARFCompileUnit.h"
#include "DWARFDebugAranges.h"
+#include "DWARFDebugInfo.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
@@ -17,6 +19,7 @@
#include "lldb/Utility/RangeMap.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Timer.h"
+#include "lldb/Utility/StreamString.h"
//#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT
#if defined(DEBUG_OSO_DMAP)
@@ -586,25 +589,42 @@ CompUnitSP SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) {
const uint32_t cu_count = GetNumCompileUnits();
if (cu_idx < cu_count) {
- Module *oso_module = GetModuleByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
+ auto &cu_info = m_compile_unit_infos[cu_idx];
+ Module *oso_module = GetModuleByCompUnitInfo(&cu_info);
if (oso_module) {
FileSpec so_file_spec;
if (GetFileSpecForSO(cu_idx, so_file_spec)) {
// User zero as the ID to match the compile unit at offset zero in each
- // .o file since each .o file can only have one compile unit for now.
+ // .o file.
lldb::user_id_t cu_id = 0;
- m_compile_unit_infos[cu_idx].compile_unit_sp =
+ cu_info.compile_units_sps.push_back(
std::make_shared<CompileUnit>(
m_objfile_sp->GetModule(), nullptr, so_file_spec, cu_id,
- eLanguageTypeUnknown, eLazyBoolCalculate);
-
- if (m_compile_unit_infos[cu_idx].compile_unit_sp) {
- SetCompileUnitAtIndex(cu_idx,
- m_compile_unit_infos[cu_idx].compile_unit_sp);
+ eLanguageTypeUnknown, eLazyBoolCalculate));
+ cu_info.id_to_index_map.insert({0, 0});
+ SetCompileUnitAtIndex(cu_idx, cu_info.compile_units_sps[0]);
+ // If there's a symbol file also register all the extra compile units.
+ if (SymbolFileDWARF *oso_symfile =
+ GetSymbolFileByCompUnitInfo(&cu_info)) {
+ auto num_dwarf_units = oso_symfile->DebugInfo().GetNumUnits();
+ for (size_t i = 0; i < num_dwarf_units; ++i) {
+ auto *dwarf_unit = oso_symfile->DebugInfo().GetUnitAtIndex(i);
+ if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(dwarf_unit)) {
+ // The "main" one was already registered.
+ if (dwarf_cu->GetID() == 0)
+ continue;
+ cu_info.compile_units_sps.push_back(std::make_shared<CompileUnit>(
+ m_objfile_sp->GetModule(), nullptr, so_file_spec,
+ dwarf_cu->GetID(), eLanguageTypeUnknown, eLazyBoolCalculate));
+ cu_info.id_to_index_map.insert(
+ {dwarf_cu->GetID(), cu_info.compile_units_sps.size() - 1});
+ }
+ }
}
}
}
- comp_unit_sp = m_compile_unit_infos[cu_idx].compile_unit_sp;
+ if (!cu_info.compile_units_sps.empty())
+ comp_unit_sp = cu_info.compile_units_sps[0];
}
return comp_unit_sp;
@@ -619,7 +639,12 @@ SymbolFileDWARFDebugMap::CompileUnitInfo *
SymbolFileDWARFDebugMap::GetCompUnitInfo(const CompileUnit &comp_unit) {
const uint32_t cu_count = GetNumCompileUnits();
for (uint32_t i = 0; i < cu_count; ++i) {
- if (&comp_unit == m_compile_unit_infos[i].compile_unit_sp.get())
+ auto &id_to_index_map = m_compile_unit_infos[i].id_to_index_map;
+
+ auto it = id_to_index_map.find(comp_unit.GetID());
+ if (it != id_to_index_map.end() &&
+ &comp_unit ==
+ m_compile_unit_infos[i].compile_units_sps[it->getSecond()].get())
return &m_compile_unit_infos[i];
}
return nullptr;
@@ -1239,18 +1264,21 @@ void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s) {
}
lldb::CompUnitSP
-SymbolFileDWARFDebugMap::GetCompileUnit(SymbolFileDWARF *oso_dwarf) {
+SymbolFileDWARFDebugMap::GetCompileUnit(SymbolFileDWARF *oso_dwarf, DWARFCompileUnit &dwarf_cu) {
if (oso_dwarf) {
const uint32_t cu_count = GetNumCompileUnits();
for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
SymbolFileDWARF *oso_symfile =
GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
if (oso_symfile == oso_dwarf) {
- if (!m_compile_unit_infos[cu_idx].compile_unit_sp)
- m_compile_unit_infos[cu_idx].compile_unit_sp =
- ParseCompileUnitAtIndex(cu_idx);
-
- return m_compile_unit_infos[cu_idx].compile_unit_sp;
+ if (m_compile_unit_infos[cu_idx].compile_units_sps.empty())
+ ParseCompileUnitAtIndex(cu_idx);
+
+ auto &id_to_index_map = m_compile_unit_infos[cu_idx].id_to_index_map;
+ auto it = id_to_index_map.find(dwarf_cu.GetID());
+ if (it != id_to_index_map.end())
+ return m_compile_unit_infos[cu_idx]
+ .compile_units_sps[it->getSecond()];
}
}
}
@@ -1280,11 +1308,17 @@ void SymbolFileDWARFDebugMap::SetCompileUnit(SymbolFileDWARF *oso_dwarf,
SymbolFileDWARF *oso_symfile =
GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
if (oso_symfile == oso_dwarf) {
- if (m_compile_unit_infos[cu_idx].compile_unit_sp) {
- assert(m_compile_unit_infos[cu_idx].compile_unit_sp.get() ==
+ if (!m_compile_unit_infos[cu_idx].compile_units_sps.empty()) {
+ assert(m_compile_unit_infos[cu_idx].compile_units_sps[0].get() ==
cu_sp.get());
} else {
- m_compile_unit_infos[cu_idx].compile_unit_sp = cu_sp;
+ assert(cu_sp->GetID() == 0 &&
+ "Setting first compile unit but with id
diff erent than 0!");
+ auto &compile_units_sps = m_compile_unit_infos[cu_idx].compile_units_sps;
+ compile_units_sps.push_back(cu_sp);
+ m_compile_unit_infos[cu_idx].id_to_index_map.insert(
+ {cu_sp->GetID(), compile_units_sps.size() - 1});
+
SetCompileUnitAtIndex(cu_idx, cu_sp);
}
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index d743954a9bafb..dcc1a74033270 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -19,6 +19,7 @@
#include "UniqueDWARFASTType.h"
class SymbolFileDWARF;
+class DWARFCompileUnit;
class DWARFDebugAranges;
class DWARFDeclContext;
@@ -174,7 +175,10 @@ class SymbolFileDWARFDebugMap : public lldb_private::SymbolFileCommon {
llvm::sys::TimePoint<> oso_mod_time;
lldb_private::Status oso_load_error;
OSOInfoSP oso_sp;
- lldb::CompUnitSP compile_unit_sp;
+ /// The compile units that an object file contains.
+ llvm::SmallVector<lldb::CompUnitSP, 2> compile_units_sps;
+ /// A map from the compile unit ID to its index in the vector.
+ llvm::SmallDenseMap<uint64_t, uint64_t, 2> id_to_index_map;
uint32_t first_symbol_index = UINT32_MAX;
uint32_t last_symbol_index = UINT32_MAX;
uint32_t first_symbol_id = UINT32_MAX;
@@ -182,10 +186,7 @@ class SymbolFileDWARFDebugMap : public lldb_private::SymbolFileCommon {
FileRangeMap file_range_map;
bool file_range_map_valid = false;
- CompileUnitInfo()
- : so_file(), oso_path(), oso_mod_time(), oso_sp(), compile_unit_sp(),
-
- file_range_map() {}
+ CompileUnitInfo() = default;
const FileRangeMap &GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile);
};
@@ -193,7 +194,17 @@ class SymbolFileDWARFDebugMap : public lldb_private::SymbolFileCommon {
// Protected Member Functions
void InitOSO();
+ /// This function actually returns the number of object files, which may be
+ /// less than the actual number of compile units, since an object file may
+ /// contain more than one compile unit. SymbolFileDWARFDebugMap looks up the
+ /// number of compile units by reading the nlist symbol table, which
+ /// currently, on macOS, only reports one compile unit per object file, and
+ /// there's no efficient way to calculate the actual number of compile units
+ /// upfront.
uint32_t CalculateNumCompileUnits() override;
+
+ /// This function actually returns the first compile unit the object file at
+ /// the given index contains.
lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
static uint32_t GetOSOIndexFromUserID(lldb::user_id_t uid) {
@@ -263,7 +274,11 @@ class SymbolFileDWARFDebugMap : public lldb_private::SymbolFileCommon {
void SetCompileUnit(SymbolFileDWARF *oso_dwarf,
const lldb::CompUnitSP &cu_sp);
- lldb::CompUnitSP GetCompileUnit(SymbolFileDWARF *oso_dwarf);
+ /// Returns the compile unit associated with the dwarf compile unit. This may
+ /// be one of the extra compile units an object file contains which isn't
+ /// reachable by ParseCompileUnitAtIndex(uint32_t).
+ lldb::CompUnitSP GetCompileUnit(SymbolFileDWARF *oso_dwarf,
+ DWARFCompileUnit &dwarf_cu);
CompileUnitInfo *GetCompileUnitInfo(SymbolFileDWARF *oso_dwarf);
diff --git a/lldb/test/API/lang/c/full_lto_stepping/Makefile b/lldb/test/API/lang/c/full_lto_stepping/Makefile
new file mode 100644
index 0000000000000..395410b18f93d
--- /dev/null
+++ b/lldb/test/API/lang/c/full_lto_stepping/Makefile
@@ -0,0 +1,4 @@
+C_SOURCES := main.c foo.c
+CFLAGS_EXTRAS = -flto=full -Wl,-object_path_lto -Wl,$(BUILDDIR)/lto.o
+
+include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lang/c/full_lto_stepping/TestFullLtoStepping.py b/lldb/test/API/lang/c/full_lto_stepping/TestFullLtoStepping.py
new file mode 100644
index 0000000000000..e697a53103b31
--- /dev/null
+++ b/lldb/test/API/lang/c/full_lto_stepping/TestFullLtoStepping.py
@@ -0,0 +1,29 @@
+"""Test that stepping in object files with multiple compile units works."""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+import lldbsuite.test.lldbutil as lldbutil
+
+
+class TestFullLtoStepping(TestBase):
+
+ @skipIf(compiler=no_match("clang"))
+ @skipUnlessDarwin
+ def test(self):
+ self.build()
+ target = self.createTestTarget()
+
+ breakpoint = target.BreakpointCreateByName("main")
+ self.assertTrue(
+ breakpoint and breakpoint.IsValid(),
+ "Breakpoint is valid")
+
+ _, _, thread, _ = lldbutil.run_to_breakpoint_do_run(self, target, breakpoint)
+ name = thread.frames[0].GetFunctionName()
+ # Check that we start out in main.
+ self.assertEqual(name, 'main')
+ thread.StepInto()
+ name = thread.frames[0].GetFunctionName()
+ # Check that we stepped into f.
+ self.assertEqual(name, 'f')
diff --git a/lldb/test/API/lang/c/full_lto_stepping/foo.c b/lldb/test/API/lang/c/full_lto_stepping/foo.c
new file mode 100644
index 0000000000000..f84c1e9ac8ac5
--- /dev/null
+++ b/lldb/test/API/lang/c/full_lto_stepping/foo.c
@@ -0,0 +1,3 @@
+int f() {
+ return 42;
+}
diff --git a/lldb/test/API/lang/c/full_lto_stepping/foo.h b/lldb/test/API/lang/c/full_lto_stepping/foo.h
new file mode 100644
index 0000000000000..e12f6446729d6
--- /dev/null
+++ b/lldb/test/API/lang/c/full_lto_stepping/foo.h
@@ -0,0 +1 @@
+int f(void);
diff --git a/lldb/test/API/lang/c/full_lto_stepping/main.c b/lldb/test/API/lang/c/full_lto_stepping/main.c
new file mode 100644
index 0000000000000..70002dacd4b03
--- /dev/null
+++ b/lldb/test/API/lang/c/full_lto_stepping/main.c
@@ -0,0 +1,6 @@
+#include "foo.h"
+
+int main(void) {
+ int i = f();
+ return 0;
+}
More information about the lldb-commits
mailing list