From 265a38fbc547adc0e2b71a98dac4d0a60b0dd63c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Afonso?= Date: Sun, 18 Oct 2020 10:33:25 -0700 Subject: [PATCH] Check if debug line sequences are starting after the first code segment I found a few cases where entries in the debug_line for a specific line of code have invalid entries (the address is outside of a code section or no section at all) and also valid entries. When this happens lldb might not set the breakpoint because the first line entry it will find in the line table might be the invalid one and since it's range is "invalid" no location is resolved. To get around this I changed the way we parse the line sequences to ignore those starting at an address under the first code segment. Greg suggested to implement it this way so we don't need to check all sections for every line sequence. Reviewed By: clayborg Differential Revision: https://reviews.llvm.org/D87172 --- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 25 ++ .../SymbolFile/DWARF/SymbolFileDWARF.h | 10 + .../DWARF/line-entries-invalid-addresses.yaml | 421 ++++++++++++++++++ 3 files changed, 456 insertions(+) create mode 100644 lldb/test/Shell/SymbolFile/DWARF/line-entries-invalid-addresses.yaml diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index b19881ff929f..43aa8bca23f8 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -497,6 +497,25 @@ void SymbolFileDWARF::InitializeObject() { m_index = std::make_unique(*GetObjectFile()->GetModule(), *this); + + const SectionList *section_list = m_objfile_sp->GetModule()->GetSectionList(); + if (section_list) + InitializeFirstCodeAddress(*section_list); +} + +void SymbolFileDWARF::InitializeFirstCodeAddress( + const lldb_private::SectionList §ion_list) { + const uint32_t num_sections = section_list.GetSize(); + for (uint32_t i = 0; i < num_sections; ++i) { + SectionSP section_sp(section_list.GetSectionAtIndex(i)); + if (section_sp->GetChildren().GetSize() > 0) { + InitializeFirstCodeAddress(section_sp->GetChildren()); + } else if (section_sp->GetType() == eSectionTypeCode) { + const addr_t section_file_address = section_sp->GetFileAddress(); + if (m_first_code_address > section_file_address) + m_first_code_address = section_file_address; + } + } } bool SymbolFileDWARF::SupportedVersion(uint16_t version) { @@ -1040,6 +1059,12 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { // 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) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 019f76c67c63..56c803eda33e 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -482,6 +482,9 @@ protected: const lldb_private::FileSpecList &GetTypeUnitSupportFiles(DWARFTypeUnit &tu); + void + InitializeFirstCodeAddress(const lldb_private::SectionList §ion_list); + lldb::ModuleWP m_debug_map_module_wp; SymbolFileDWARFDebugMap *m_debug_map_symfile; @@ -517,6 +520,13 @@ protected: 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), a small positive integer (zero + relocation addend -- GOLD), + /// or -1/-2 (LLD). 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/test/Shell/SymbolFile/DWARF/line-entries-invalid-addresses.yaml b/lldb/test/Shell/SymbolFile/DWARF/line-entries-invalid-addresses.yaml new file mode 100644 index 000000000000..0714302dc61b --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/line-entries-invalid-addresses.yaml @@ -0,0 +1,421 @@ +# RUN: yaml2obj %s > %t +# RUN: %lldb %t -b -o "image lookup -f main.cpp -l 2 -v" | FileCheck %s +# CHECK: 1 match found in main.cpp:2 {{.*}} +# CHECK: LineEntry: {{.*}}main.cpp:2:{{.*}} + +# int foo() { +# return 42; +# } +# +# int main() { +# int x = foo(); +# return x; +# } +# dwarfdump -debug-line: +# Address Line Column File ISA Discriminator Flags +# ------------------ ------ ------ ------ --- ------------- ------------- +# 0x0000000100000f80 1 0 1 0 0 is_stmt +# 0x0000000100000f84 2 5 1 0 0 is_stmt prologue_end +# 0x0000000100000f8b 2 5 1 0 0 is_stmt end_sequence +# 0x0000000100000f90 5 0 1 0 0 is_stmt +# 0x0000000100000f90 5 0 1 0 0 is_stmt end_sequence +# 0x000000000000000f 2 13 1 0 0 is_stmt prologue_end +# 0x0000000000000014 2 9 1 0 0 +# 0x0000000000000017 3 12 1 0 0 is_stmt +# 0x000000000000001d 3 12 1 0 0 end_sequence +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x0000000A + ncmds: 7 + sizeofcmds: 1400 + flags: 0x00000000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_UUID + cmdsize: 24 + uuid: 605D6BBF-4DB2-39F7-8068-F9BB3896DF0C + - cmd: LC_BUILD_VERSION + cmdsize: 24 + platform: 1 + minos: 659200 + sdk: 659206 + ntools: 0 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 4096 + nsyms: 3 + stroff: 4144 + strsize: 37 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __PAGEZERO + vmaddr: 0 + vmsize: 1 + fileoff: 0 + filesize: 0 + maxprot: 0 + initprot: 0 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __TEXT + vmaddr: 4294967296 + vmsize: 4096 + fileoff: 0 + filesize: 0 + maxprot: 5 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0000000100000F80 + size: 48 + offset: 0x00000000 + align: 4 + reloff: 0x00000000 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: CFFAEDFE07000001030000000A000000070000007805000000000000000000001B00000018000000605D6BBF4DB239F7 + - sectname: __unwind_info + segname: __TEXT + addr: 0x0000000100000FB0 + size: 72 + offset: 0x00000000 + align: 2 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: CFFAEDFE07000001030000000A000000070000007805000000000000000000001B00000018000000605D6BBF4DB239F78068F9BB3896DF0C320000001800000001000000000F0A00 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 4294971392 + vmsize: 4096 + fileoff: 4096 + filesize: 85 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 952 + segname: __DWARF + vmaddr: 4294975488 + vmsize: 4096 + fileoff: 8192 + filesize: 839 + maxprot: 7 + initprot: 3 + nsects: 4 + flags: 0 + Sections: + - sectname: __debug_line + segname: __DWARF + addr: 0x0000000100002000 + size: 96 + offset: 0x00002000 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_info + segname: __DWARF + addr: 0x00000001000020E9 + size: 119 + offset: 0x000020E9 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_abbrev + segname: __DWARF + addr: 0x0000000100002160 + size: 90 + offset: 0x00002160 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_str + segname: __DWARF + addr: 0x00000001000021BA + size: 130 + offset: 0x000021BA + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 +LinkEditData: + NameList: + - n_strx: 2 + n_type: 0x0F + n_sect: 1 + n_desc: 0 + n_value: 4294971264 + - n_strx: 11 + n_type: 0x0F + n_sect: 1 + n_desc: 16 + n_value: 4294967296 + - n_strx: 31 + n_type: 0x0F + n_sect: 1 + n_desc: 0 + n_value: 4294971280 + StringTable: + - '' + - '' + - __Z3foov + - __mh_execute_header + - _main +DWARF: + debug_str: + - '' + - 'Apple clang version 11.0.3 (clang-1103.0.32.62)' + - main.cpp + - '/Users/aadsm/toolchain_dev/external/llvm-project' + - _Z3foov + - foo + - main + - x + - int + debug_abbrev: + - ID: 0 + Table: + - Code: 0x0000000000000001 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_producer + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_data2 + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Attribute: DW_AT_comp_dir + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - 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_frame_base + Form: DW_FORM_exprloc + - Attribute: DW_AT_linkage_name + Form: DW_FORM_strp + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + - Attribute: DW_AT_external + Form: DW_FORM_flag_present + - Code: 0x0000000000000003 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Attribute: DW_AT_frame_base + Form: DW_FORM_exprloc + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + - Attribute: DW_AT_external + Form: DW_FORM_flag_present + - Code: 0x0000000000000004 + Tag: DW_TAG_variable + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_location + Form: DW_FORM_exprloc + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_type + Form: DW_FORM_ref_addr + - Code: 0x0000000000000005 + Tag: DW_TAG_base_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_encoding + Form: DW_FORM_data1 + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 + debug_info: + - Length: 0x0000000000000073 + Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0000000000000000 + AddrSize: 8 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 0x0000000000000001 + - Value: 0x0000000000000004 + - Value: 0x0000000000000031 + - Value: 0x0000000000000000 + - Value: 0x000000000000003A + - Value: 0x0000000100000F80 + - Value: 0x0000000000000030 + - AbbrCode: 0x00000002 + Values: + - Value: 0x0000000100000F80 + - Value: 0x000000000000000B + - Value: 0x0000000000000001 + BlockData: [ 0x56 ] + - Value: 0x000000000000006B + - Value: 0x0000000000000073 + - Value: 0x0000000000000001 + - Value: 0x0000000000000001 + - Value: 0x000000000000006F + - Value: 0x0000000000000001 + - AbbrCode: 0x00000003 + Values: + - Value: 0x0000000100000F90 + - Value: 0x0000000000000020 + - Value: 0x0000000000000001 + BlockData: [ 0x56 ] + - Value: 0x0000000000000077 + - Value: 0x0000000000000001 + - Value: 0x0000000000000005 + - Value: 0x000000000000006F + - Value: 0x0000000000000001 + - AbbrCode: 0x00000004 + Values: + - Value: 0x0000000000000002 + BlockData: [ 0x91, 0x78 ] + - Value: 0x000000000000007C + - Value: 0x0000000000000001 + - Value: 0x0000000000000006 + - Value: 0x000000000000006F + - AbbrCode: 0x00000000 + - AbbrCode: 0x00000005 + Values: + - Value: 0x000000000000007E + - Value: 0x0000000000000005 + - Value: 0x0000000000000004 + - AbbrCode: 0x00000000 + debug_line: + - Length: 92 + Version: 4 + PrologueLength: 32 + 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: main.cpp + DirIdx: 0 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 4294971264 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_set_column + Data: 5 + - Opcode: DW_LNS_set_prologue_end + Data: 0 + - Opcode: 0x4B + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 7 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 + # Sequence manually added (not produced by the source code) + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 4294971280 + - Opcode: 0x16 + Data: 0 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 + # Sequence manually added (not produced by the source code) + - Opcode: DW_LNS_set_column + Data: 13 + - Opcode: DW_LNS_set_prologue_end + Data: 0 + - Opcode: 0xE5 + Data: 0 + - Opcode: DW_LNS_set_column + Data: 9 + - Opcode: DW_LNS_negate_stmt + Data: 0 + - Opcode: 0x58 + Data: 0 + - Opcode: DW_LNS_set_column + Data: 12 + - Opcode: DW_LNS_negate_stmt + Data: 0 + - Opcode: 0x3D + Data: 0 + - Opcode: DW_LNS_negate_stmt + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 6 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 +...