diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp @@ -92,8 +92,8 @@ } const DWARFDataExtractor &DWARFContext::getOrLoadMacroData() { - return LoadOrGetSection(eSectionTypeDWARFDebugMacro, llvm::None, - m_data_debug_macro); + return LoadOrGetSection(eSectionTypeDWARFDebugMacro, + eSectionTypeDWARFDebugMacro, m_data_debug_macro); } const DWARFDataExtractor &DWARFContext::getOrLoadRangesData() { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h @@ -24,6 +24,17 @@ class SymbolFileDWARF; +class DWARFStrOffsetsInfo { + lldb::offset_t cu_str_offset; + const lldb_private::DWARFDataExtractor &data; + +public: + DWARFStrOffsetsInfo(lldb::offset_t cu_str_offset, + const lldb_private::DWARFDataExtractor &data) + : cu_str_offset(cu_str_offset), data(data) {} + uint64_t GetOffset(uint64_t index) const; +}; + class DWARFDebugMacroHeader { public: enum HeaderFlagMask { @@ -53,6 +64,7 @@ static void ReadMacroEntries(const lldb_private::DWARFDataExtractor &debug_macro_data, const lldb_private::DWARFDataExtractor &debug_str_data, + const DWARFStrOffsetsInfo *str_offsets_info, const bool offset_is_64_bit, lldb::offset_t *sect_offset, SymbolFileDWARF *sym_file_dwarf, lldb_private::DebugMacrosSP &debug_macros_sp); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp @@ -16,6 +16,11 @@ using namespace lldb_private; using namespace lldb_private::dwarf; +uint64_t DWARFStrOffsetsInfo::GetOffset(uint64_t index) const { + uint64_t offset = cu_str_offset + data.GetDWARFSizeOfOffset() * index; + return data.GetU32(&offset); +} + DWARFDebugMacroHeader DWARFDebugMacroHeader::ParseHeader(const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset) { @@ -59,7 +64,8 @@ void DWARFDebugMacroEntry::ReadMacroEntries( const DWARFDataExtractor &debug_macro_data, - const DWARFDataExtractor &debug_str_data, const bool offset_is_64_bit, + const DWARFDataExtractor &debug_str_data, + const DWARFStrOffsetsInfo *str_offsets_info, const bool offset_is_64_bit, lldb::offset_t *offset, SymbolFileDWARF *sym_file_dwarf, DebugMacrosSP &debug_macros_sp) { llvm::dwarf::MacroEntryType type = @@ -97,6 +103,22 @@ debug_macros_sp->AddMacroEntry( DebugMacroEntry::CreateUndefEntry(line, macro_str)); break; + case DW_MACRO_define_strx: + case DW_MACRO_undef_strx: + line = debug_macro_data.GetULEB128(offset); + str_offset = debug_macro_data.GetULEB128(offset); + if (!str_offsets_info) + // Can't do much in this case, skip all such entries + continue; + str_offset = str_offsets_info->GetOffset(str_offset); + macro_str = debug_str_data.GetCStr(&str_offset); + if (type == DW_MACRO_define_strx) + debug_macros_sp->AddMacroEntry( + DebugMacroEntry::CreateDefineEntry(line, macro_str)); + else + debug_macros_sp->AddMacroEntry( + DebugMacroEntry::CreateUndefEntry(line, macro_str)); + break; case DW_MACRO_start_file: line = debug_macro_data.GetULEB128(offset); debug_line_file_idx = debug_macro_data.GetULEB128(offset); @@ -113,7 +135,7 @@ else new_offset = debug_macro_data.GetU32(offset); debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateIndirectEntry( - sym_file_dwarf->ParseDebugMacros(&new_offset))); + sym_file_dwarf->ParseDebugMacros(&new_offset, str_offsets_info))); break; default: // TODO: Add support for other standard operations. diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -55,6 +55,8 @@ class SymbolFileDWARFDwo; class SymbolFileDWARFDwp; +class DWARFStrOffsetsInfo; + #define DIE_IS_BEING_PARSED ((lldb_private::Type *)1) class SymbolFileDWARF : public lldb_private::SymbolFileCommon, @@ -246,7 +248,9 @@ bool Supports_DW_AT_APPLE_objc_complete_type(DWARFUnit *cu); - lldb_private::DebugMacrosSP ParseDebugMacros(lldb::offset_t *offset); + lldb_private::DebugMacrosSP + ParseDebugMacros(lldb::offset_t *offset, + const DWARFStrOffsetsInfo *str_offsets_info); static DWARFDIE GetParentSymbolContextDIE(const DWARFDIE &die); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1194,7 +1194,8 @@ } lldb_private::DebugMacrosSP -SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) { +SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset, + const DWARFStrOffsetsInfo *str_offsets_info) { auto iter = m_debug_macros_map.find(*offset); if (iter != m_debug_macros_map.end()) return iter->second; @@ -1210,8 +1211,8 @@ const DWARFDebugMacroHeader &header = DWARFDebugMacroHeader::ParseHeader(debug_macro_data, offset); DWARFDebugMacroEntry::ReadMacroEntries( - debug_macro_data, m_context.getOrLoadStrData(), header.OffsetIs64Bit(), - offset, this, debug_macros_sp); + debug_macro_data, m_context.getOrLoadStrData(), str_offsets_info, + header.OffsetIs64Bit(), offset, this, debug_macros_sp); return debug_macros_sp; } @@ -1219,7 +1220,7 @@ bool SymbolFileDWARF::ParseDebugMacros(CompileUnit &comp_unit) { std::lock_guard guard(GetModuleMutex()); - DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); + DWARFUnit *dwarf_cu = &GetDWARFCompileUnit(&comp_unit)->GetNonSkeletonUnit(); if (dwarf_cu == nullptr) return false; @@ -1235,8 +1236,15 @@ if (sect_offset == DW_INVALID_OFFSET) return false; - comp_unit.SetDebugMacros(ParseDebugMacros(§_offset)); + std::unique_ptr str_offsets_info; + lldb::offset_t cu_str_offset = dwarf_cu->GetStrOffsetsBase(); + SymbolFileDWARF &symfile = dwarf_cu->GetSymbolFileDWARF(); + if (cu_str_offset && cu_str_offset != DW_INVALID_OFFSET) + str_offsets_info = std::make_unique( + cu_str_offset, symfile.GetDWARFContext().getOrLoadStrOffsetsData()); + comp_unit.SetDebugMacros( + symfile.ParseDebugMacros(§_offset, str_offsets_info.get())); return true; } diff --git a/lldb/test/API/commands/expression/macros/Makefile b/lldb/test/API/commands/expression/macros/Makefile --- a/lldb/test/API/commands/expression/macros/Makefile +++ b/lldb/test/API/commands/expression/macros/Makefile @@ -5,5 +5,6 @@ # GCC produces incorrect .debug_macro section when "-include" option is used: # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93075. NO_TEST_COMMON_H := 1 +CFLAGS_EXTRAS := -fdebug-macro include Makefile.rules diff --git a/lldb/test/API/commands/expression/macros/TestMacros.py b/lldb/test/API/commands/expression/macros/TestMacros.py --- a/lldb/test/API/commands/expression/macros/TestMacros.py +++ b/lldb/test/API/commands/expression/macros/TestMacros.py @@ -8,12 +8,6 @@ class TestMacros(TestBase): - @expectedFailureAll( - compiler="clang", - bugnumber="clang does not emit .debug_macro[.dwo] sections.") - @expectedFailureAll( - debug_info="dwo", - bugnumber="GCC produces multiple .debug_macro.dwo sections and the spec is unclear as to what it means") @expectedFailureAll( hostoslist=["windows"], compiler="gcc", diff --git a/lldb/test/API/lang/c/macro/Makefile b/lldb/test/API/lang/c/macro/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/c/macro/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -fdebug-macro + +include Makefile.rules diff --git a/lldb/test/API/lang/c/macro/TestMacro.py b/lldb/test/API/lang/c/macro/TestMacro.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/c/macro/TestMacro.py @@ -0,0 +1,31 @@ +"""Tests lldb macro evaluation.""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class MacroTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.c', '// Set break point at this line.') + + def test(self): + self.build() + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break inside the main. + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + self.expect("expr DM + DF(10)", VARIABLES_DISPLAYED_CORRECTLY, + substrs=['int', '62']) + diff --git a/lldb/test/API/lang/c/macro/main.c b/lldb/test/API/lang/c/macro/main.c new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/c/macro/main.c @@ -0,0 +1,7 @@ +#define DM 10 +#define DF(x) (42 + (x)) + +int main (int argc, char const *argv[]) +{ + return 0; //// Set break point at this line. +}