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 @@ -517,6 +517,17 @@ llvm::DenseMap m_type_unit_support_files; std::vector m_lldb_cu_to_dwarf_unit; + /// Many linkers will concatenate all available DWARF, even if parts of that DWARF + /// should have been dead stripped. Some linkers will place tombstone values in for + /// addresses that should have been dead stripped, with a value like -1 or -2. But many + /// linkers will apply a relocation and attempt to set the value to zero. This is problematic + /// in that we can end up with many addresses that are zero or close to zero due to there + /// being an addend on the relocation whose base is at zero. Here we attempt to avoid + /// addresses that are zero or close to zero by finding the first valid code address by looking + /// at the sections and finding the first one that has read + execute permissions. This allows + /// us to do a quick and cheap comparison against this address when parsing line tables and + /// parsing functions where the DWARF should have been dead stripped. + 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 @@ -433,7 +433,13 @@ m_debug_map_module_wp(), m_debug_map_symfile(nullptr), m_context(m_objfile_sp->GetModule()->GetSectionList(), dwo_section_list), m_fetched_external_modules(false), - m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {} + m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) { + auto first_code_section_sp = + m_objfile_sp->GetModule()->GetSectionList()->FindSectionByType( + eSectionTypeCode, true, 0); + if (first_code_section_sp) + m_first_code_address = first_code_section_sp->GetFileAddress(); +} SymbolFileDWARF::~SymbolFileDWARF() {} @@ -1040,6 +1046,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) { diff --git a/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt b/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt --- a/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt +++ b/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt @@ -8,17 +8,20 @@ lldbHost lldbSymbol lldbPluginObjectFilePECOFF + lldbPluginObjectFileMachO lldbPluginSymbolFileDWARF lldbPluginSymbolFilePDB lldbPluginTypeSystemClang lldbUtilityHelpers lldbPluginPlatformMacOSX + LLVMTestingSupport LINK_COMPONENTS Support DebugInfoPDB ) set(test_inputs - test-dwarf.exe) + test-dwarf.exe + test-invalid-addresses.yaml) add_unittest_inputs(SymbolFileDWARFTests "${test_inputs}") diff --git a/lldb/unittests/SymbolFile/DWARF/Inputs/test-invalid-addresses.yaml b/lldb/unittests/SymbolFile/DWARF/Inputs/test-invalid-addresses.yaml new file mode 100644 --- /dev/null +++ b/lldb/unittests/SymbolFile/DWARF/Inputs/test-invalid-addresses.yaml @@ -0,0 +1,532 @@ +# 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: 4294967296 + 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: 11 + 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_pubnames + segname: __DWARF + addr: 0x0000000100002060 + size: 47 + offset: 0x00002060 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_pubtypes + segname: __DWARF + addr: 0x000000010000208F + size: 26 + offset: 0x0000208F + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_aranges + segname: __DWARF + addr: 0x00000001000020A9 + size: 64 + offset: 0x000020A9 + 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 + - sectname: __apple_names + segname: __DWARF + addr: 0x000000010000223C + size: 116 + offset: 0x0000223C + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 485341480100000003000000030000000C0000000000000001000000010006000000000001000000FFFFFFFF8973880BEB28616A6A7F9A7C44000000540000006400000073000000010000002A000000000000006B000000010000002A0000000000000077000000010000004700000000000000 + - sectname: __apple_namespac + segname: __DWARF + addr: 0x00000001000022B0 + size: 36 + offset: 0x000022B0 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF + - sectname: __apple_types + segname: __DWARF + addr: 0x00000001000022D4 + size: 79 + offset: 0x000022D4 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 48534148010000000100000001000000180000000000000004000000010006000300050005000B0006000600000000003080880B380000007E000000010000006F000000240000A4283A0C00000000 + - sectname: __apple_objc + segname: __DWARF + addr: 0x0000000100002323 + size: 36 + offset: 0x00002323 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF +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_aranges: + - Length: 0x000000000000003C + Version: 2 + CuOffset: 0x0000000000000000 + AddressSize: 0x08 + Descriptors: + - Address: 0x0000000100000F80 + Length: 0x000000000000000B + - Address: 0x0000000100000F90 + Length: 0x0000000000000020 + debug_pubnames: + Length: 0x000000000000002B + Version: 2 + UnitOffset: 0 + UnitSize: 119 + Entries: + - DieOffset: 0x0000002A + Name: _Z3foov + - DieOffset: 0x0000002A + Name: foo + - DieOffset: 0x00000047 + Name: main + debug_pubtypes: + Length: 0x0000000000000016 + Version: 2 + UnitOffset: 0 + UnitSize: 119 + Entries: + - DieOffset: 0x0000006F + Name: int + 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 + - 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 + - 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 +... diff --git a/lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp b/lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp --- a/lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp +++ b/lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp @@ -14,6 +14,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h" #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h" #include "Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h" #include "Plugins/SymbolFile/DWARF/DWARFDataExtractor.h" @@ -40,8 +41,8 @@ using namespace lldb_private; class SymbolFileDWARFTests : public testing::Test { - SubsystemRAII + SubsystemRAII subsystems; public: @@ -70,7 +71,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start1) { // Test that if we have a .debug_abbrev that contains ordered abbreviation // codes that start at 1, that we get O(1) access. - + const auto byte_order = eByteOrderLittle; const uint8_t addr_size = 4; StreamString encoder(Stream::eBinary, addr_size, byte_order); @@ -81,7 +82,7 @@ encoder.PutULEB128(DW_FORM_strp); encoder.PutULEB128(0); encoder.PutULEB128(0); - + encoder.PutULEB128(2); // Abbrev code 2 encoder.PutULEB128(DW_TAG_subprogram); encoder.PutHex8(DW_CHILDREN_no); @@ -89,9 +90,9 @@ encoder.PutULEB128(DW_FORM_strp); encoder.PutULEB128(0); encoder.PutULEB128(0); - + encoder.PutULEB128(0); // Abbrev code 0 (termination) - + DWARFDataExtractor data; data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); DWARFAbbreviationDeclarationSet abbrev_set; @@ -101,7 +102,7 @@ // Make sure we have O(1) access to each abbreviation by making sure the // index offset is 1 and not UINT32_MAX EXPECT_EQ(abbrev_set.GetIndexOffset(), 1u); - + auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(1); EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit); EXPECT_TRUE(abbrev1->HasChildren()); @@ -115,7 +116,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start5) { // Test that if we have a .debug_abbrev that contains ordered abbreviation // codes that start at 5, that we get O(1) access. - + const auto byte_order = eByteOrderLittle; const uint8_t addr_size = 4; StreamString encoder(Stream::eBinary, addr_size, byte_order); @@ -126,7 +127,7 @@ encoder.PutULEB128(DW_FORM_strp); encoder.PutULEB128(0); encoder.PutULEB128(0); - + encoder.PutULEB128(6); // Abbrev code 6 encoder.PutULEB128(DW_TAG_subprogram); encoder.PutHex8(DW_CHILDREN_no); @@ -134,9 +135,9 @@ encoder.PutULEB128(DW_FORM_strp); encoder.PutULEB128(0); encoder.PutULEB128(0); - + encoder.PutULEB128(0); // Abbrev code 0 (termination) - + DWARFDataExtractor data; data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); DWARFAbbreviationDeclarationSet abbrev_set; @@ -146,7 +147,7 @@ // Make sure we have O(1) access to each abbreviation by making sure the // index offset is 5 and not UINT32_MAX EXPECT_EQ(abbrev_set.GetIndexOffset(), 5u); - + auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(5); EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit); EXPECT_TRUE(abbrev1->HasChildren()); @@ -160,7 +161,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevOutOfOrder) { // Test that if we have a .debug_abbrev that contains unordered abbreviation // codes, that we can access the information correctly. - + const auto byte_order = eByteOrderLittle; const uint8_t addr_size = 4; StreamString encoder(Stream::eBinary, addr_size, byte_order); @@ -171,7 +172,7 @@ encoder.PutULEB128(DW_FORM_strp); encoder.PutULEB128(0); encoder.PutULEB128(0); - + encoder.PutULEB128(1); // Abbrev code 1 encoder.PutULEB128(DW_TAG_subprogram); encoder.PutHex8(DW_CHILDREN_no); @@ -179,9 +180,9 @@ encoder.PutULEB128(DW_FORM_strp); encoder.PutULEB128(0); encoder.PutULEB128(0); - + encoder.PutULEB128(0); // Abbrev code 0 (termination) - + DWARFDataExtractor data; data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); DWARFAbbreviationDeclarationSet abbrev_set; @@ -191,7 +192,7 @@ // Make sure we don't have O(1) access to each abbreviation by making sure // the index offset is UINT32_MAX EXPECT_EQ(abbrev_set.GetIndexOffset(), UINT32_MAX); - + auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(2); EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit); EXPECT_TRUE(abbrev1->HasChildren()); @@ -205,7 +206,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevInvalidNULLTag) { // Test that we detect when an abbreviation has a NULL tag and that we get // an error when decoding. - + const auto byte_order = eByteOrderLittle; const uint8_t addr_size = 4; StreamString encoder(Stream::eBinary, addr_size, byte_order); @@ -214,9 +215,9 @@ encoder.PutHex8(DW_CHILDREN_no); encoder.PutULEB128(0); encoder.PutULEB128(0); - + encoder.PutULEB128(0); // Abbrev code 0 (termination) - + DWARFDataExtractor data; data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); DWARFAbbreviationDeclarationSet abbrev_set; @@ -232,7 +233,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevNullAttrValidForm) { // Test that we detect when an abbreviation has a NULL attribute and a non // NULL form and that we get an error when decoding. - + const auto byte_order = eByteOrderLittle; const uint8_t addr_size = 4; StreamString encoder(Stream::eBinary, addr_size, byte_order); @@ -245,7 +246,7 @@ encoder.PutULEB128(0); encoder.PutULEB128(0); // Abbrev code 0 (termination) - + DWARFDataExtractor data; data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); DWARFAbbreviationDeclarationSet abbrev_set; @@ -255,13 +256,12 @@ EXPECT_TRUE(bool(error)); EXPECT_EQ("malformed abbreviation declaration attribute", llvm::toString(std::move(error))); - } TEST_F(SymbolFileDWARFTests, TestAbbrevValidAttrNullForm) { // Test that we detect when an abbreviation has a valid attribute and a // NULL form and that we get an error when decoding. - + const auto byte_order = eByteOrderLittle; const uint8_t addr_size = 4; StreamString encoder(Stream::eBinary, addr_size, byte_order); @@ -272,9 +272,9 @@ encoder.PutULEB128(0); // NULL form encoder.PutULEB128(0); encoder.PutULEB128(0); - + encoder.PutULEB128(0); // Abbrev code 0 (termination) - + DWARFDataExtractor data; data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); DWARFAbbreviationDeclarationSet abbrev_set; @@ -290,7 +290,7 @@ // Test that we detect when an abbreviation has a valid attribute and a // form, but is missing the NULL attribute and form that terminates an // abbreviation - + const auto byte_order = eByteOrderLittle; const uint8_t addr_size = 4; StreamString encoder(Stream::eBinary, addr_size, byte_order); @@ -300,7 +300,7 @@ encoder.PutULEB128(DW_AT_name); encoder.PutULEB128(DW_FORM_strp); // Don't add the NULL DW_AT and NULL DW_FORM terminator - + DWARFDataExtractor data; data.SetData(encoder.GetData(), encoder.GetSize(), byte_order); DWARFAbbreviationDeclarationSet abbrev_set; @@ -346,3 +346,24 @@ llvm::toString(std::move(error))); EXPECT_EQ(off, 12U); // Parser should read no further than the segment size } + +TEST_F(SymbolFileDWARFTests, EnsureLineEntriesExistInAfterFirstCodeSection) { + auto ExpectedFile = TestFile::fromYamlFile("test-invalid-addresses.yaml"); + ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded()); + + lldb::ModuleSP module_sp = + std::make_shared(ExpectedFile->moduleSpec()); + SymbolFile *symfile = module_sp->GetSymbolFile(); + ASSERT_NE(symfile, nullptr); + + FileSpec file_spec("main.cpp"); + SymbolContextList sc_list; + EXPECT_NE(symfile->ResolveSymbolContext(file_spec, 2, false, + eSymbolContextCompUnit, sc_list), + 0U); + SymbolContext sc; + sc_list.GetContextAtIndex(0, sc); + auto section_sp = sc.line_entry.range.GetBaseAddress().GetSection(); + ASSERT_NE(section_sp.get(), nullptr); + EXPECT_EQ(section_sp->GetType(), eSectionTypeCode); +}