Skip to content

Commit da0828b

Browse files
[lldb] Enable support for DWARF64 format handling (#145645)
This PR introduces support for the DWARF64 format, enabling handling of 64-bit DWARF sections as defined by the DWARF specification. The update includes adjustments to header parsing and modification of form values to accommodate 64-bit offsets and values. Also Added the testcase to verify the DWARF64 format.
1 parent 857815f commit da0828b

File tree

6 files changed

+103
-28
lines changed

6 files changed

+103
-28
lines changed

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

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
7777
case DW_FORM_strp:
7878
case DW_FORM_line_strp:
7979
case DW_FORM_sec_offset:
80-
m_value.uval = data.GetMaxU64(offset_ptr, 4);
80+
assert(m_unit);
81+
ref_addr_size = m_unit->GetFormParams().getDwarfOffsetByteSize();
82+
m_value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);
8183
break;
8284
case DW_FORM_addrx1:
8385
case DW_FORM_strx1:
@@ -119,10 +121,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
119121
break;
120122
case DW_FORM_ref_addr:
121123
assert(m_unit);
122-
if (m_unit->GetVersion() <= 2)
123-
ref_addr_size = m_unit->GetAddressByteSize();
124-
else
125-
ref_addr_size = 4;
124+
ref_addr_size = m_unit->GetFormParams().getRefAddrByteSize();
126125
m_value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);
127126
break;
128127
case DW_FORM_indirect:
@@ -165,7 +164,7 @@ static FormSize g_form_sizes[] = {
165164
{1, 1}, // 0x0b DW_FORM_data1
166165
{1, 1}, // 0x0c DW_FORM_flag
167166
{0, 0}, // 0x0d DW_FORM_sdata
168-
{1, 4}, // 0x0e DW_FORM_strp
167+
{0, 0}, // 0x0e DW_FORM_strp (4 bytes for DWARF32, 8 bytes for DWARF64)
169168
{0, 0}, // 0x0f DW_FORM_udata
170169
{0, 0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes
171170
// for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
@@ -175,15 +174,15 @@ static FormSize g_form_sizes[] = {
175174
{1, 8}, // 0x14 DW_FORM_ref8
176175
{0, 0}, // 0x15 DW_FORM_ref_udata
177176
{0, 0}, // 0x16 DW_FORM_indirect
178-
{1, 4}, // 0x17 DW_FORM_sec_offset
177+
{0, 0}, // 0x17 DW_FORM_sec_offset (4 bytes for DWARF32,8 bytes for DWARF64)
179178
{0, 0}, // 0x18 DW_FORM_exprloc
180179
{1, 0}, // 0x19 DW_FORM_flag_present
181180
{0, 0}, // 0x1a DW_FORM_strx (ULEB128)
182181
{0, 0}, // 0x1b DW_FORM_addrx (ULEB128)
183182
{1, 4}, // 0x1c DW_FORM_ref_sup4
184183
{0, 0}, // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64)
185184
{1, 16}, // 0x1e DW_FORM_data16
186-
{1, 4}, // 0x1f DW_FORM_line_strp
185+
{0, 0}, // 0x1f DW_FORM_line_strp (4 bytes for DWARF32, 8 bytes for DWARF64)
187186
{1, 8}, // 0x20 DW_FORM_ref_sig8
188187
};
189188

@@ -246,13 +245,9 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
246245
return true;
247246

248247
case DW_FORM_ref_addr:
249-
ref_addr_size = 4;
250248
assert(unit); // Unit must be valid for DW_FORM_ref_addr objects or we will
251249
// get this wrong
252-
if (unit->GetVersion() <= 2)
253-
ref_addr_size = unit->GetAddressByteSize();
254-
else
255-
ref_addr_size = 4;
250+
ref_addr_size = unit->GetFormParams().getRefAddrByteSize();
256251
*offset_ptr += ref_addr_size;
257252
return true;
258253

@@ -288,7 +283,9 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
288283
case DW_FORM_sec_offset:
289284
case DW_FORM_strp:
290285
case DW_FORM_line_strp:
291-
*offset_ptr += 4;
286+
assert(unit);
287+
ref_addr_size = unit->GetFormParams().getDwarfOffsetByteSize();
288+
*offset_ptr += ref_addr_size;
292289
return true;
293290

294291
// 4 byte values

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

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,20 +1073,7 @@ const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const {
10731073
: m_dwarf.GetDWARFContext().getOrLoadDebugInfoData();
10741074
}
10751075

1076-
uint32_t DWARFUnit::GetHeaderByteSize() const {
1077-
switch (m_header.getUnitType()) {
1078-
case llvm::dwarf::DW_UT_compile:
1079-
case llvm::dwarf::DW_UT_partial:
1080-
return GetVersion() < 5 ? 11 : 12;
1081-
case llvm::dwarf::DW_UT_skeleton:
1082-
case llvm::dwarf::DW_UT_split_compile:
1083-
return 20;
1084-
case llvm::dwarf::DW_UT_type:
1085-
case llvm::dwarf::DW_UT_split_type:
1086-
return GetVersion() < 5 ? 23 : 24;
1087-
}
1088-
llvm_unreachable("invalid UnitType.");
1089-
}
1076+
uint32_t DWARFUnit::GetHeaderByteSize() const { return m_header.getSize(); }
10901077

10911078
std::optional<uint64_t>
10921079
DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ class DWARFUnit : public DWARFExpression::Delegate, public UserID {
119119
// Size of the CU data incl. header but without initial length.
120120
dw_offset_t GetLength() const { return m_header.getLength(); }
121121
uint16_t GetVersion() const override { return m_header.getVersion(); }
122+
const llvm::dwarf::FormParams &GetFormParams() const {
123+
return m_header.getFormParams();
124+
}
122125
const llvm::DWARFAbbreviationDeclarationSet *GetAbbreviations() const;
123126
dw_offset_t GetAbbrevOffset() const;
124127
uint8_t GetAddressByteSize() const override {

lldb/unittests/SymbolFile/DWARF/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ add_lldb_unittest(SymbolFileDWARFTests
66
DWARFUnitTest.cpp
77
SymbolFileDWARFTests.cpp
88
XcodeSDKModuleTests.cpp
9+
DWARF64UnitTest.cpp
910

1011
LINK_COMPONENTS
1112
Support
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//===-- DWARF64UnitTest.cpp------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
10+
#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
11+
#include "TestingSupport/Symbol/YAMLModuleTester.h"
12+
13+
using namespace lldb_private;
14+
using namespace lldb_private::dwarf;
15+
using namespace lldb_private::plugin::dwarf;
16+
17+
TEST(DWARF64UnitTest, DWARF64DebugInfoAndCU) {
18+
const char *yamldata = R"(
19+
--- !ELF
20+
FileHeader:
21+
Class: ELFCLASS64
22+
Data: ELFDATA2LSB
23+
Type: ET_EXEC
24+
Machine: EM_PPC64
25+
DWARF:
26+
debug_str:
27+
- 'clang version 18.1.8 (clang-18.1.8-1)'
28+
- 'main'
29+
debug_abbrev:
30+
- Table:
31+
- Code: 0x1
32+
Tag: DW_TAG_compile_unit
33+
Children: DW_CHILDREN_yes
34+
Attributes:
35+
- Attribute: DW_AT_producer
36+
Form: DW_FORM_strp
37+
- Attribute: DW_AT_language
38+
Form: DW_FORM_data2
39+
- Attribute: DW_AT_stmt_list
40+
Form: DW_FORM_sec_offset
41+
- Code: 0x02
42+
Tag: DW_TAG_subprogram
43+
Children: DW_CHILDREN_no
44+
Attributes:
45+
- Attribute: DW_AT_name
46+
Form: DW_FORM_strp
47+
debug_info:
48+
- Format: DWARF64
49+
Version: 4
50+
AbbrOffset: 0x0
51+
AddrSize: 8
52+
Entries:
53+
- AbbrCode: 0x1
54+
Values:
55+
- Value: 0x0
56+
- Value: 0x04
57+
- Value: 0x0
58+
- AbbrCode: 0x2
59+
Values:
60+
- Value: 0x1
61+
- AbbrCode: 0x0
62+
)";
63+
64+
YAMLModuleTester t(yamldata);
65+
auto *symbol_file =
66+
llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile());
67+
DWARFUnit *unit = symbol_file->DebugInfo().GetUnitAtIndex(0);
68+
ASSERT_TRUE(unit);
69+
ASSERT_EQ(unit->GetFormParams().Format, DwarfFormat::DWARF64);
70+
ASSERT_EQ(unit->GetVersion(), 4);
71+
ASSERT_EQ(unit->GetAddressByteSize(), 8);
72+
73+
DWARFFormValue form_value;
74+
const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
75+
ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
76+
ASSERT_EQ(unit->GetProducer(), eProducerClang);
77+
ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
78+
auto attrs = cu_entry->GetAttributes(unit, DWARFDebugInfoEntry::Recurse::yes);
79+
attrs.ExtractFormValueAtIndex(2, form_value); // Validate DW_AT_stmt_list
80+
ASSERT_EQ(form_value.Unsigned(), 0UL);
81+
82+
DWARFDIE cu_die(unit, cu_entry);
83+
auto declaration = cu_die.GetFirstChild();
84+
ASSERT_TRUE(declaration.IsValid());
85+
ASSERT_EQ(declaration.Tag(), DW_TAG_subprogram);
86+
}

llvm/docs/ReleaseNotes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ Changes to LLDB
304304
stop reason = SIGSEGV: sent by tkill system call (sender pid=649752, uid=2667987)
305305
```
306306
* ELF Cores can now have their siginfo structures inspected using `thread siginfo`.
307+
* LLDB now supports the `DWARF64` debugging information format.
307308

308309
### Changes to lldb-dap
309310

0 commit comments

Comments
 (0)