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 @@ -494,6 +494,11 @@ const lldb_private::FileSpecList &GetTypeUnitSupportFiles(DWARFTypeUnit &tu); + void InitializeFirstCodeAddressRecursive( + const lldb_private::SectionList §ion_list); + + void InitializeFirstCodeAddress(); + lldb::ModuleWP m_debug_map_module_wp; SymbolFileDWARFDebugMap *m_debug_map_symfile; @@ -529,6 +534,13 @@ llvm::DenseMap m_type_unit_support_files; std::vector m_lldb_cu_to_dwarf_unit; + /// DWARF does not provide a good way for traditional (concatenating) linkers + /// to invalidate debug info describing dead-stripped code. These linkers will + /// keep the debug info but resolve any addresses referring to such code as + /// zero (BFD) or a small positive integer (zero + relocation addend -- GOLD). + /// Try to filter out this debug info by comparing it to the lowest code + /// address in the module. + lldb::addr_t m_first_code_address = LLDB_INVALID_ADDRESS; }; #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_SYMBOLFILEDWARF_H 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 @@ -468,6 +468,8 @@ void SymbolFileDWARF::InitializeObject() { Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + InitializeFirstCodeAddress(); + if (!GetGlobalPluginProperties().IgnoreFileIndexes()) { StreamString module_desc; GetObjectFile()->GetModule()->GetDescription(module_desc.AsRawOstream(), @@ -512,6 +514,25 @@ std::make_unique(*GetObjectFile()->GetModule(), *this); } +void SymbolFileDWARF::InitializeFirstCodeAddress() { + InitializeFirstCodeAddressRecursive( + *m_objfile_sp->GetModule()->GetSectionList()); + if (m_first_code_address == LLDB_INVALID_ADDRESS) + m_first_code_address = 0; +} + +void SymbolFileDWARF::InitializeFirstCodeAddressRecursive( + const lldb_private::SectionList §ion_list) { + for (SectionSP section_sp : section_list) { + if (section_sp->GetChildren().GetSize() > 0) { + InitializeFirstCodeAddressRecursive(section_sp->GetChildren()); + } else if (section_sp->GetType() == eSectionTypeCode) { + m_first_code_address = + std::min(m_first_code_address, section_sp->GetFileAddress()); + } + } +} + bool SymbolFileDWARF::SupportedVersion(uint16_t version) { return version >= 2 && version <= 5; } @@ -1111,6 +1132,12 @@ // The Sequences view contains only valid line sequences. Don't iterate over // the Rows directly. for (const llvm::DWARFDebugLine::Sequence &seq : line_table->Sequences) { + // Ignore line sequences that do not start after the first code address. + // All addresses generated in a sequence are incremental so we only need + // to check the first one of the sequence. Check the comment at the + // m_first_code_address declaration for more details on this. + if (seq.LowPC < m_first_code_address) + continue; std::unique_ptr sequence = LineTable::CreateLineSequenceContainer(); for (unsigned idx = seq.FirstRowIndex; idx < seq.LastRowIndex; ++idx) { @@ -2236,12 +2263,9 @@ addr = sc.function->GetAddressRange().GetBaseAddress(); } - - if (auto section_sp = addr.GetSection()) { - if (section_sp->GetPermissions() & ePermissionsExecutable) { - sc_list.Append(sc); - return true; - } + if (addr.IsValid() && addr.GetFileAddress() >= m_first_code_address) { + sc_list.Append(sc); + return true; } } diff --git a/lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg b/lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg --- a/lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg +++ b/lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg @@ -1 +1 @@ -config.suffixes = ['.cpp', '.m', '.mm', '.s', '.test', '.ll', '.c'] +config.suffixes = ['.cpp', '.m', '.mm', '.s', '.test', '.ll', '.c', '.yaml'] diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/dead-code-filtering.yaml b/lldb/test/Shell/SymbolFile/DWARF/x86/dead-code-filtering.yaml new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/dead-code-filtering.yaml @@ -0,0 +1,152 @@ +# RUN: yaml2obj %s > %t +# RUN: %lldb %t -o "image dump line-table a.c" -o "image lookup -n _start" -o "image lookup -n f" -o exit | FileCheck %s + +# CHECK-LABEL: image dump line-table a.c +# CHECK-NEXT: Line table for a.c +# CHECK-NEXT: 0x0000000000000080: a.c:1 +# CHECK-NEXT: 0x0000000000000084: a.c:1 +# CHECK-NEXT: 0x0000000000000086: a.c:1 +# CHECK-EMPTY: +# CHECK-NEXT: image lookup -n _start +# CHECK-NEXT: 1 match found +# CHECK-LABEL: image lookup -n f +# CHECK-EMPTY: + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +ProgramHeaders: + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + Offset: 0x0000 + FirstSec: .text + LastSec: .text + Align: 0x1000 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x80 + AddressAlign: 0x10 + Content: 554889E55DC3 + - Name: .debug_abbrev + Type: SHT_PROGBITS + AddressAlign: 0x1 + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x1 + - Name: .debug_line + Type: SHT_PROGBITS + AddressAlign: 0x1 +DWARF: + debug_ranges: + - Offset: 0x0 + AddrSize: 0x8 + Entries: + - LowOffset: 0x0 + HighOffset: 0x6 + - LowOffset: 0x80 + HighOffset: 0x86 + debug_abbrev: + - ID: 0 + Table: + - Code: 0x0000000000000001 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_producer + Form: DW_FORM_string + - Attribute: DW_AT_name + Form: DW_FORM_string + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_ranges + Form: DW_FORM_sec_offset + - Code: 0x0000000000000002 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Attribute: DW_AT_name + Form: DW_FORM_string + debug_info: + - Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0000000000000000 + AddrSize: 8 + Entries: + - AbbrCode: 0x00000001 + Values: + - CStr: Hand-written DWARF + - CStr: a.c + - Value: 0x0000000000000000 + - Value: 0x0000000000000000 + - Value: 0x0000000000000000 + - AbbrCode: 0x00000002 + Values: + - Value: 0x0000000000000000 + - Value: 0x0000000000000006 + - CStr: f + - AbbrCode: 0x00000002 + Values: + - Value: 0x0000000000000080 + - Value: 0x0000000000000006 + - CStr: _start + - AbbrCode: 0x00000000 + debug_line: + - Version: 4 + MinInstLength: 1 + MaxOpsPerInst: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: [] + Files: + - Name: a.c + DirIdx: 0 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_set_prologue_end + Data: 0 + - Opcode: 0x4a + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 2 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 0x000080 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_set_prologue_end + Data: 0 + - Opcode: 0x4a + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 2 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 +...