diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 94fc2e83e899d..b78e6ce807bca 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -348,6 +348,10 @@ void DWARFUnit::ExtractDIEsRWLocked() { void DWARFUnit::SetDwoStrOffsetsBase() { lldb::offset_t baseOffset = 0; + // Size of offset for .debug_str_offsets is same as DWARF offset byte size + // of the DWARFUnit as a default. We might override this if below if needed. + m_str_offset_size = m_header.getDwarfOffsetByteSize(); + if (const llvm::DWARFUnitIndex::Entry *entry = m_header.getIndexEntry()) { if (const auto *contribution = entry->getContribution(llvm::DW_SECT_STR_OFFSETS)) @@ -357,14 +361,17 @@ void DWARFUnit::SetDwoStrOffsetsBase() { } if (GetVersion() >= 5) { - const DWARFDataExtractor &strOffsets = - GetSymbolFileDWARF().GetDWARFContext().getOrLoadStrOffsetsData(); - uint64_t length = strOffsets.GetU32(&baseOffset); - if (length == 0xffffffff) - length = strOffsets.GetU64(&baseOffset); - + const llvm::DWARFDataExtractor &strOffsets = GetSymbolFileDWARF() + .GetDWARFContext() + .getOrLoadStrOffsetsData() + .GetAsLLVMDWARF(); + + uint64_t length; + llvm::dwarf::DwarfFormat format; + std::tie(length, format) = strOffsets.getInitialLength(&baseOffset); + m_str_offset_size = format == llvm::dwarf::DwarfFormat::DWARF64 ? 8 : 4; // Check version. - if (strOffsets.GetU16(&baseOffset) < 5) + if (strOffsets.getU16(&baseOffset) < 5) return; // Skip padding. @@ -409,7 +416,16 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { SetRangesBase(form_value.Unsigned()); break; case DW_AT_str_offsets_base: + // When we have a DW_AT_str_offsets_base attribute, it points us to the + // first string offset for this DWARFUnit which is after the string + // offsets table header. In this case we use the DWARF32/DWARF64 of the + // DWARFUnit to determine the string offset byte size. DWO files do not + // use this attribute and they point to the start of the string offsets + // table header which can be used to determine the DWARF32/DWARF64 status + // of the string table. See SetDwoStrOffsetsBase() for now it figures out + // the m_str_offset_size value that should be used. SetStrOffsetsBase(form_value.Unsigned()); + m_str_offset_size = m_header.getDwarfOffsetByteSize(); break; case DW_AT_low_pc: SetBaseAddress(form_value.Address()); @@ -1079,10 +1095,9 @@ uint32_t DWARFUnit::GetHeaderByteSize() const { return m_header.getSize(); } std::optional DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const { - lldb::offset_t offset = - GetStrOffsetsBase() + index * m_header.getDwarfOffsetByteSize(); + lldb::offset_t offset = GetStrOffsetsBase() + index * m_str_offset_size; return m_dwarf.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64( - &offset, m_header.getDwarfOffsetByteSize()); + &offset, m_str_offset_size); } llvm::Expected diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 91a693860c55a..b5199a891e3bd 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -364,6 +364,7 @@ class DWARFUnit : public DWARFExpression::Delegate, public UserID { dw_offset_t m_line_table_offset = DW_INVALID_OFFSET; dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base. + dw_offset_t m_str_offset_size = 4; // Size in bytes of a string offset. std::optional m_rnglist_table; bool m_rnglist_table_done = false; diff --git a/lldb/test/Shell/SymbolFile/DWARF/Inputs/dwp-str-offsets-dwarf64-dwp.yaml b/lldb/test/Shell/SymbolFile/DWARF/Inputs/dwp-str-offsets-dwarf64-dwp.yaml new file mode 100644 index 0000000000000..d4e2ceea9c4f6 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/Inputs/dwp-str-offsets-dwarf64-dwp.yaml @@ -0,0 +1,44 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 + SectionHeaderStringTable: .strtab +Sections: + - Name: .debug_abbrev.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE ] + AddressAlign: 0x1 + Content: 01110125251305032576250000022E01111B1206401803253A0B3B0B49133F190000030500021803253A0B3B0B4913000004240003253E0B0B0B0000050F00491300000626004913000000 + - Name: .debug_str.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 6D61696E00696E74006172676300617267760063686172004170706C6520636C616E672076657273696F6E2031372E302E302028636C616E672D313730302E342E342E3129006D61696E2E6D696E696D616C2E637070006D61696E2E6D696E696D616C2E64776F00 + - Name: .debug_str_offsets.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE ] + AddressAlign: 0x1 + Content: 'FFFFFFFF4400000000000000050000000000000000000000050000000000000009000000000000000E000000000000001300000000000000180000000000000046000000000000005700000000000000' + - Name: .debug_info.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE ] + AddressAlign: 0x1 + Content: 54000000050005080000000099E97383BBC6980B0105210006070200160000000156000001400000000302917802000140000000030291700300014400000000040105040549000000054E00000006530000000404060100 + - Name: .debug_cu_index + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 05000000030000000100000002000000000000000000000099E97383BBC6980B0000000001000000010000000300000006000000000000000000000000000000580000004B00000028000000 + - Type: SectionHeaderTable + Sections: + - Name: .strtab + - Name: .debug_abbrev.dwo + - Name: .debug_str.dwo + - Name: .debug_str_offsets.dwo + - Name: .debug_info.dwo + - Name: .debug_cu_index + - Name: .symtab +Symbols: [] +... diff --git a/lldb/test/Shell/SymbolFile/DWARF/Inputs/dwp-str-offsets-dwarf64-exe.yaml b/lldb/test/Shell/SymbolFile/DWARF/Inputs/dwp-str-offsets-dwarf64-exe.yaml new file mode 100644 index 0000000000000..3785bbe6ecbe0 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/Inputs/dwp-str-offsets-dwarf64-exe.yaml @@ -0,0 +1,100 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +ProgramHeaders: + - Type: PT_PHDR + Flags: [ PF_R ] + VAddr: 0x200040 + Align: 0x8 + Offset: 0x40 + - Type: PT_LOAD + Flags: [ PF_R ] + FirstSec: .eh_frame + LastSec: .eh_frame + VAddr: 0x200000 + Align: 0x1000 + Offset: 0x0 + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + FirstSec: .text + LastSec: .text + VAddr: 0x201160 + Align: 0x1000 + Offset: 0x160 + - Type: PT_GNU_STACK + Flags: [ PF_W, PF_R ] + Align: 0x0 + Offset: 0x0 +Sections: + - Name: .eh_frame + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x200120 + AddressAlign: 0x8 + Content: 1400000000000000017A5200017810011B0C0708900100001C0000001C000000201000001600000000410E108602430D06510C070800000000000000 + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x201160 + AddressAlign: 0x10 + Content: 554889E5C745FC00000000897DF8488975F031C05DC3 + - Name: .debug_abbrev + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 014A00101772171B25B442197625111B12067317000000 + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 24000000050004080000000099E97383BBC6980B0100000000080000000001001600000008000000 + - Name: .debug_str_offsets + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 0C000000050000000000000002000000 + - Name: .debug_gnu_pubnames + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 18000000020000000000280000001A000000306D61696E0000000000 + - Name: .debug_gnu_pubtypes + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: '21000000020000000000280000004000000090696E74005300000090636861720000000000' + - Name: .comment + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 004170706C6520636C616E672076657273696F6E2031372E302E302028636C616E672D313730302E342E342E3129004C696E6B65723A204C4C442032322E302E30202868747470733A2F2F6769746875622E636F6D2F636C6179626F72672F6C6C766D2D70726F6A6563742E67697420613234333130363863303837656463303938393330303934343864343162356138336361303363392900 + - Name: .debug_line + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 5A0000000500080037000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E0102000000004E0649A10A56ED4D381C49A3DB4F6825040000090260112000000000000105030A0821060B2E0202000101 + - Name: .debug_line_str + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 2E006D61696E2E6D696E696D616C2E63707000 +Symbols: + - Name: main.minimal.cpp + Type: STT_FILE + Index: SHN_ABS + - Name: main + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x201160 + Size: 0x16 +DWARF: + debug_str: + - . + - main.minimal.dwo + debug_addr: + - Length: 0xC + Version: 0x5 + AddressSize: 0x8 + Entries: + - Address: 0x201160 +... diff --git a/lldb/test/Shell/SymbolFile/DWARF/dwp-str-offsets-dwarf64.test b/lldb/test/Shell/SymbolFile/DWARF/dwp-str-offsets-dwarf64.test new file mode 100644 index 0000000000000..b010aa0995971 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/dwp-str-offsets-dwarf64.test @@ -0,0 +1,25 @@ +# This test verifies that LLDB can read a .dwp file that has a DWARF32 compile +# unit that has a DWARF64 .debug_str_offsets table. This will be needed for +# llvm-dwp changes that will start emitting 64 bit line tables for compile units +# that have strings in the .debug_str section whose string offsets exceed 4GB. +# By having a 64 bit .debug_str_offsets table, we can emit .debug_str sections +# with no size limits. + +# RUN: yaml2obj %S/Inputs/dwp-str-offsets-dwarf64-exe.yaml > %t +# RUN: yaml2obj %S/Inputs/dwp-str-offsets-dwarf64-dwp.yaml > %t.dwp +# RUN: %lldb %t -b \ +# RUN: -o 'image lookup --verbose --address 0x0000000000201172' | \ +# RUN: FileCheck %s + +# CHECK: (lldb) image lookup --verbose --address 0x0000000000201172 +# CHECK-NEXT: Address: dwp-str-offsets-dwarf64.test.tmp[0x0000000000201172] (dwp-str-offsets-dwarf64.test.tmp.PT_LOAD[1]..text + 18) +# CHECK-NEXT: Summary: dwp-str-offsets-dwarf64.test.tmp`main + 18 at main.minimal.cpp:2:3 +# CHECK-NEXT: Module: file = "{{.*}}/dwp-str-offsets-dwarf64.test.tmp", arch = "x86_64" +# CHECK-NEXT: CompileUnit: id = {0x00000000}, file = "main.minimal.cpp", language = "" +# CHECK-NEXT: Function: id = {0x7fffff000000001a}, name = "main", range = [0x0000000000201160-0x0000000000201176) +# CHECK-NEXT: FuncType: id = {0x7fffff000000001a}, byte-size = 0, decl = main.minimal.cpp:1, compiler_type = "int (int, const char **)" +# CHECK-NEXT: Blocks: id = {0x7fffff000000001a}, range = [0x00201160-0x00201176) +# CHECK-NEXT: LineEntry: [0x0000000000201172-0x0000000000201174): main.minimal.cpp:2:3 +# CHECK-NEXT: Symbol: id = {0x00000002}, range = [0x0000000000201160-0x0000000000201176), name="main" +# CHECK-NEXT: Variable: id = {0x7fffff0000000029}, name = "argc", type = "int", valid ranges = , location = DW_OP_fbreg -8, decl = main.minimal.cpp:1 +# CHECK-NEXT: Variable: id = {0x7fffff0000000034}, name = "argv", type = "const char **", valid ranges = , location = DW_OP_fbreg -16, decl = main.minimal.cpp:1