Skip to content

Commit 4530047

Browse files
authored
[lldb] Add the ability to load DWARF64 .debug_str_offsets tables for DWARF32 DWARF units in .dwp files in LLDB. (#167997)
This patch is updating the reading capabilities of the LLDB DWARF parser for a llvm-dwp patch llvm/llvm-project#167457 that will emit .dwp files where the compile units are DWARF32 and the .debug_str_offsets tables will be emitted as DWARF64 to allow .debug_str sections that exceed 4GB in size.
1 parent 4eea157 commit 4530047

File tree

5 files changed

+195
-10
lines changed

5 files changed

+195
-10
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,10 @@ void DWARFUnit::ExtractDIEsRWLocked() {
348348
void DWARFUnit::SetDwoStrOffsetsBase() {
349349
lldb::offset_t baseOffset = 0;
350350

351+
// Size of offset for .debug_str_offsets is same as DWARF offset byte size
352+
// of the DWARFUnit as a default. We might override this if below if needed.
353+
m_str_offset_size = m_header.getDwarfOffsetByteSize();
354+
351355
if (const llvm::DWARFUnitIndex::Entry *entry = m_header.getIndexEntry()) {
352356
if (const auto *contribution =
353357
entry->getContribution(llvm::DW_SECT_STR_OFFSETS))
@@ -357,14 +361,17 @@ void DWARFUnit::SetDwoStrOffsetsBase() {
357361
}
358362

359363
if (GetVersion() >= 5) {
360-
const DWARFDataExtractor &strOffsets =
361-
GetSymbolFileDWARF().GetDWARFContext().getOrLoadStrOffsetsData();
362-
uint64_t length = strOffsets.GetU32(&baseOffset);
363-
if (length == 0xffffffff)
364-
length = strOffsets.GetU64(&baseOffset);
365-
364+
const llvm::DWARFDataExtractor &strOffsets = GetSymbolFileDWARF()
365+
.GetDWARFContext()
366+
.getOrLoadStrOffsetsData()
367+
.GetAsLLVMDWARF();
368+
369+
uint64_t length;
370+
llvm::dwarf::DwarfFormat format;
371+
std::tie(length, format) = strOffsets.getInitialLength(&baseOffset);
372+
m_str_offset_size = format == llvm::dwarf::DwarfFormat::DWARF64 ? 8 : 4;
366373
// Check version.
367-
if (strOffsets.GetU16(&baseOffset) < 5)
374+
if (strOffsets.getU16(&baseOffset) < 5)
368375
return;
369376

370377
// Skip padding.
@@ -409,7 +416,16 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
409416
SetRangesBase(form_value.Unsigned());
410417
break;
411418
case DW_AT_str_offsets_base:
419+
// When we have a DW_AT_str_offsets_base attribute, it points us to the
420+
// first string offset for this DWARFUnit which is after the string
421+
// offsets table header. In this case we use the DWARF32/DWARF64 of the
422+
// DWARFUnit to determine the string offset byte size. DWO files do not
423+
// use this attribute and they point to the start of the string offsets
424+
// table header which can be used to determine the DWARF32/DWARF64 status
425+
// of the string table. See SetDwoStrOffsetsBase() for now it figures out
426+
// the m_str_offset_size value that should be used.
412427
SetStrOffsetsBase(form_value.Unsigned());
428+
m_str_offset_size = m_header.getDwarfOffsetByteSize();
413429
break;
414430
case DW_AT_low_pc:
415431
SetBaseAddress(form_value.Address());
@@ -1079,10 +1095,9 @@ uint32_t DWARFUnit::GetHeaderByteSize() const { return m_header.getSize(); }
10791095

10801096
std::optional<uint64_t>
10811097
DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const {
1082-
lldb::offset_t offset =
1083-
GetStrOffsetsBase() + index * m_header.getDwarfOffsetByteSize();
1098+
lldb::offset_t offset = GetStrOffsetsBase() + index * m_str_offset_size;
10841099
return m_dwarf.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64(
1085-
&offset, m_header.getDwarfOffsetByteSize());
1100+
&offset, m_str_offset_size);
10861101
}
10871102

10881103
llvm::Expected<llvm::DWARFAddressRangesVector>

lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ class DWARFUnit : public DWARFExpression::Delegate, public UserID {
364364
dw_offset_t m_line_table_offset = DW_INVALID_OFFSET;
365365

366366
dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base.
367+
dw_offset_t m_str_offset_size = 4; // Size in bytes of a string offset.
367368

368369
std::optional<llvm::DWARFDebugRnglistTable> m_rnglist_table;
369370
bool m_rnglist_table_done = false;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
--- !ELF
2+
FileHeader:
3+
Class: ELFCLASS64
4+
Data: ELFDATA2LSB
5+
Type: ET_REL
6+
Machine: EM_X86_64
7+
SectionHeaderStringTable: .strtab
8+
Sections:
9+
- Name: .debug_abbrev.dwo
10+
Type: SHT_PROGBITS
11+
Flags: [ SHF_EXCLUDE ]
12+
AddressAlign: 0x1
13+
Content: 01110125251305032576250000022E01111B1206401803253A0B3B0B49133F190000030500021803253A0B3B0B4913000004240003253E0B0B0B0000050F00491300000626004913000000
14+
- Name: .debug_str.dwo
15+
Type: SHT_PROGBITS
16+
Flags: [ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ]
17+
AddressAlign: 0x1
18+
EntSize: 0x1
19+
Content: 6D61696E00696E74006172676300617267760063686172004170706C6520636C616E672076657273696F6E2031372E302E302028636C616E672D313730302E342E342E3129006D61696E2E6D696E696D616C2E637070006D61696E2E6D696E696D616C2E64776F00
20+
- Name: .debug_str_offsets.dwo
21+
Type: SHT_PROGBITS
22+
Flags: [ SHF_EXCLUDE ]
23+
AddressAlign: 0x1
24+
Content: 'FFFFFFFF4400000000000000050000000000000000000000050000000000000009000000000000000E000000000000001300000000000000180000000000000046000000000000005700000000000000'
25+
- Name: .debug_info.dwo
26+
Type: SHT_PROGBITS
27+
Flags: [ SHF_EXCLUDE ]
28+
AddressAlign: 0x1
29+
Content: 54000000050005080000000099E97383BBC6980B0105210006070200160000000156000001400000000302917802000140000000030291700300014400000000040105040549000000054E00000006530000000404060100
30+
- Name: .debug_cu_index
31+
Type: SHT_PROGBITS
32+
AddressAlign: 0x1
33+
Content: 05000000030000000100000002000000000000000000000099E97383BBC6980B0000000001000000010000000300000006000000000000000000000000000000580000004B00000028000000
34+
- Type: SectionHeaderTable
35+
Sections:
36+
- Name: .strtab
37+
- Name: .debug_abbrev.dwo
38+
- Name: .debug_str.dwo
39+
- Name: .debug_str_offsets.dwo
40+
- Name: .debug_info.dwo
41+
- Name: .debug_cu_index
42+
- Name: .symtab
43+
Symbols: []
44+
...
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
--- !ELF
2+
FileHeader:
3+
Class: ELFCLASS64
4+
Data: ELFDATA2LSB
5+
Type: ET_EXEC
6+
Machine: EM_X86_64
7+
ProgramHeaders:
8+
- Type: PT_PHDR
9+
Flags: [ PF_R ]
10+
VAddr: 0x200040
11+
Align: 0x8
12+
Offset: 0x40
13+
- Type: PT_LOAD
14+
Flags: [ PF_R ]
15+
FirstSec: .eh_frame
16+
LastSec: .eh_frame
17+
VAddr: 0x200000
18+
Align: 0x1000
19+
Offset: 0x0
20+
- Type: PT_LOAD
21+
Flags: [ PF_X, PF_R ]
22+
FirstSec: .text
23+
LastSec: .text
24+
VAddr: 0x201160
25+
Align: 0x1000
26+
Offset: 0x160
27+
- Type: PT_GNU_STACK
28+
Flags: [ PF_W, PF_R ]
29+
Align: 0x0
30+
Offset: 0x0
31+
Sections:
32+
- Name: .eh_frame
33+
Type: SHT_PROGBITS
34+
Flags: [ SHF_ALLOC ]
35+
Address: 0x200120
36+
AddressAlign: 0x8
37+
Content: 1400000000000000017A5200017810011B0C0708900100001C0000001C000000201000001600000000410E108602430D06510C070800000000000000
38+
- Name: .text
39+
Type: SHT_PROGBITS
40+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
41+
Address: 0x201160
42+
AddressAlign: 0x10
43+
Content: 554889E5C745FC00000000897DF8488975F031C05DC3
44+
- Name: .debug_abbrev
45+
Type: SHT_PROGBITS
46+
AddressAlign: 0x1
47+
Content: 014A00101772171B25B442197625111B12067317000000
48+
- Name: .debug_info
49+
Type: SHT_PROGBITS
50+
AddressAlign: 0x1
51+
Content: 24000000050004080000000099E97383BBC6980B0100000000080000000001001600000008000000
52+
- Name: .debug_str_offsets
53+
Type: SHT_PROGBITS
54+
AddressAlign: 0x1
55+
Content: 0C000000050000000000000002000000
56+
- Name: .debug_gnu_pubnames
57+
Type: SHT_PROGBITS
58+
AddressAlign: 0x1
59+
Content: 18000000020000000000280000001A000000306D61696E0000000000
60+
- Name: .debug_gnu_pubtypes
61+
Type: SHT_PROGBITS
62+
AddressAlign: 0x1
63+
Content: '21000000020000000000280000004000000090696E74005300000090636861720000000000'
64+
- Name: .comment
65+
Type: SHT_PROGBITS
66+
Flags: [ SHF_MERGE, SHF_STRINGS ]
67+
AddressAlign: 0x1
68+
EntSize: 0x1
69+
Content: 004170706C6520636C616E672076657273696F6E2031372E302E302028636C616E672D313730302E342E342E3129004C696E6B65723A204C4C442032322E302E30202868747470733A2F2F6769746875622E636F6D2F636C6179626F72672F6C6C766D2D70726F6A6563742E67697420613234333130363863303837656463303938393330303934343864343162356138336361303363392900
70+
- Name: .debug_line
71+
Type: SHT_PROGBITS
72+
AddressAlign: 0x1
73+
Content: 5A0000000500080037000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E0102000000004E0649A10A56ED4D381C49A3DB4F6825040000090260112000000000000105030A0821060B2E0202000101
74+
- Name: .debug_line_str
75+
Type: SHT_PROGBITS
76+
Flags: [ SHF_MERGE, SHF_STRINGS ]
77+
AddressAlign: 0x1
78+
EntSize: 0x1
79+
Content: 2E006D61696E2E6D696E696D616C2E63707000
80+
Symbols:
81+
- Name: main.minimal.cpp
82+
Type: STT_FILE
83+
Index: SHN_ABS
84+
- Name: main
85+
Type: STT_FUNC
86+
Section: .text
87+
Binding: STB_GLOBAL
88+
Value: 0x201160
89+
Size: 0x16
90+
DWARF:
91+
debug_str:
92+
- .
93+
- main.minimal.dwo
94+
debug_addr:
95+
- Length: 0xC
96+
Version: 0x5
97+
AddressSize: 0x8
98+
Entries:
99+
- Address: 0x201160
100+
...
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# This test verifies that LLDB can read a .dwp file that has a DWARF32 compile
2+
# unit that has a DWARF64 .debug_str_offsets table. This will be needed for
3+
# llvm-dwp changes that will start emitting 64 bit line tables for compile units
4+
# that have strings in the .debug_str section whose string offsets exceed 4GB.
5+
# By having a 64 bit .debug_str_offsets table, we can emit .debug_str sections
6+
# with no size limits.
7+
8+
# RUN: yaml2obj %S/Inputs/dwp-str-offsets-dwarf64-exe.yaml > %t
9+
# RUN: yaml2obj %S/Inputs/dwp-str-offsets-dwarf64-dwp.yaml > %t.dwp
10+
# RUN: %lldb %t -b \
11+
# RUN: -o 'image lookup --verbose --address 0x0000000000201172' | \
12+
# RUN: FileCheck %s
13+
14+
# CHECK: (lldb) image lookup --verbose --address 0x0000000000201172
15+
# CHECK-NEXT: Address: dwp-str-offsets-dwarf64.test.tmp[0x0000000000201172] (dwp-str-offsets-dwarf64.test.tmp.PT_LOAD[1]..text + 18)
16+
# CHECK-NEXT: Summary: dwp-str-offsets-dwarf64.test.tmp`main + 18 at main.minimal.cpp:2:3
17+
# CHECK-NEXT: Module: file = "{{.*}}/dwp-str-offsets-dwarf64.test.tmp", arch = "x86_64"
18+
# CHECK-NEXT: CompileUnit: id = {0x00000000}, file = "main.minimal.cpp", language = "<not loaded>"
19+
# CHECK-NEXT: Function: id = {0x7fffff000000001a}, name = "main", range = [0x0000000000201160-0x0000000000201176)
20+
# CHECK-NEXT: FuncType: id = {0x7fffff000000001a}, byte-size = 0, decl = main.minimal.cpp:1, compiler_type = "int (int, const char **)"
21+
# CHECK-NEXT: Blocks: id = {0x7fffff000000001a}, range = [0x00201160-0x00201176)
22+
# CHECK-NEXT: LineEntry: [0x0000000000201172-0x0000000000201174): main.minimal.cpp:2:3
23+
# CHECK-NEXT: Symbol: id = {0x00000002}, range = [0x0000000000201160-0x0000000000201176), name="main"
24+
# CHECK-NEXT: Variable: id = {0x7fffff0000000029}, name = "argc", type = "int", valid ranges = <block>, location = DW_OP_fbreg -8, decl = main.minimal.cpp:1
25+
# CHECK-NEXT: Variable: id = {0x7fffff0000000034}, name = "argv", type = "const char **", valid ranges = <block>, location = DW_OP_fbreg -16, decl = main.minimal.cpp:1

0 commit comments

Comments
 (0)