Skip to content

Commit 98747d9

Browse files
authored
DWARF support for multiple line tables (#2557)
Multiple tables appear to be emitted when linking files together. This fixes our support for that, which did not update their size properly. This required patching the YAML emitting code from LLVM in order to measure the size and then emit it, as that code is apparently not designed to handle changes in line table contents. Other minor fixes: * Set the flags for our dwarfdump command to emit the same as llvm-dwarfdump does with -v -all. * Add support for a few more opcodes, set_discriminator, set_basic_block, fixed_advance_pc, set_isa. * Handle a compile unit without abbreviations in the YAML code (again, apparently not something this LLVM code was intended to do). * Handle a compile unit with zero entries in the YAML code (ditto). * Properly set the AddressSize - we use the DWARFContext in a different way than LLVM expects, apparently. With this the emscripten test suite passes with -gforce_dwarf without crashing. My overall impression so from the the YAML code is that it probably isn't a long-term solution for us. Perhaps it may end up being scaffolding, that is, we can replace it with our own code eventually that is based on it, and remove most of the LLVM code. Before deciding that we should get everything working first, and this seems like the quickest path there.
1 parent 7732943 commit 98747d9

15 files changed

+2571
-31
lines changed

src/wasm/wasm-debug.cpp

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ struct BinaryenDWARFInfo {
6161
}
6262
// Parse debug sections.
6363
uint8_t addrSize = 4;
64-
context = llvm::DWARFContext::create(sections, addrSize);
64+
bool isLittleEndian = true;
65+
context = llvm::DWARFContext::create(sections, addrSize, isLittleEndian);
6566
}
6667
};
6768

@@ -76,6 +77,8 @@ void dumpDWARF(const Module& wasm) {
7677
}
7778
}
7879
llvm::DIDumpOptions options;
80+
options.DumpType = llvm::DIDT_All;
81+
options.ShowChildren = true;
7982
options.Verbose = true;
8083
info.context->dump(llvm::outs(), options);
8184
}
@@ -111,8 +114,8 @@ struct LineState {
111114
uint32_t line = 1;
112115
uint32_t col = 0;
113116
uint32_t file = 1;
114-
// TODO uint32_t isa = 0;
115-
// TODO Discriminator = 0;
117+
uint32_t isa = 0;
118+
uint32_t discriminator = 0;
116119
bool isStmt;
117120
bool basicBlock = false;
118121
// XXX these two should be just prologue, epilogue?
@@ -139,9 +142,17 @@ struct LineState {
139142
case llvm::dwarf::DW_LNE_end_sequence: {
140143
return true;
141144
}
145+
case llvm::dwarf::DW_LNE_set_discriminator: {
146+
discriminator = opcode.Data;
147+
break;
148+
}
149+
case llvm::dwarf::DW_LNE_define_file: {
150+
Fatal() << "TODO: DW_LNE_define_file";
151+
}
142152
default: {
143-
Fatal() << "unknown debug line sub-opcode: " << std::hex
144-
<< opcode.SubOpcode;
153+
// An unknown opcode, ignore.
154+
std::cerr << "warning: unknown subopcopde " << opcode.SubOpcode
155+
<< '\n';
145156
}
146157
}
147158
break;
@@ -174,13 +185,25 @@ struct LineState {
174185
isStmt = !isStmt;
175186
break;
176187
}
188+
case llvm::dwarf::DW_LNS_set_basic_block: {
189+
basicBlock = true;
190+
break;
191+
}
177192
case llvm::dwarf::DW_LNS_const_add_pc: {
178193
uint8_t AdjustOpcode = 255 - table.OpcodeBase;
179194
uint64_t AddrOffset =
180195
(AdjustOpcode / table.LineRange) * table.MinInstLength;
181196
addr += AddrOffset;
182197
break;
183198
}
199+
case llvm::dwarf::DW_LNS_fixed_advance_pc: {
200+
addr += opcode.Data;
201+
break;
202+
}
203+
case llvm::dwarf::DW_LNS_set_isa: {
204+
isa = opcode.Data;
205+
break;
206+
}
184207
default: {
185208
if (opcode.Opcode >= table.OpcodeBase) {
186209
// Special opcode: adjust line and addr, using some math.
@@ -239,11 +262,23 @@ struct LineState {
239262
item.Data = file;
240263
newOpcodes.push_back(item);
241264
}
265+
if (isa != old.isa) {
266+
auto item = makeItem(llvm::dwarf::DW_LNS_set_isa);
267+
item.Data = isa;
268+
newOpcodes.push_back(item);
269+
}
270+
if (discriminator != old.discriminator) {
271+
// len = 1 (subopcode) + 4 (wasm32 address)
272+
auto item = makeItem(llvm::dwarf::DW_LNE_set_discriminator, 5);
273+
item.Data = discriminator;
274+
newOpcodes.push_back(item);
275+
}
242276
if (isStmt != old.isStmt) {
243277
newOpcodes.push_back(makeItem(llvm::dwarf::DW_LNS_negate_stmt));
244278
}
245279
if (basicBlock != old.basicBlock) {
246-
Fatal() << "bb";
280+
assert(basicBlock);
281+
newOpcodes.push_back(makeItem(llvm::dwarf::DW_LNS_set_basic_block));
247282
}
248283
if (prologueEnd != old.prologueEnd) {
249284
assert(prologueEnd);
@@ -382,21 +417,6 @@ static void updateDebugLines(const Module& wasm,
382417
}
383418
}
384419

385-
static void fixEmittedSection(const std::string& name,
386-
std::vector<char>& data) {
387-
if (name == ".debug_line") {
388-
// The YAML code does not update the line section size. However, it is
389-
// trivial to do so after the fact, as the wasm section's additional size is
390-
// easy to compute: it is the emitted size - the 4 bytes of the size itself.
391-
uint32_t size = data.size() - 4;
392-
BufferWithRandomAccess buf;
393-
buf << size;
394-
for (int i = 0; i < 4; i++) {
395-
data[i] = buf[i];
396-
}
397-
}
398-
}
399-
400420
void writeDWARFSections(Module& wasm, const BinaryLocationsMap& newLocations) {
401421
BinaryenDWARFInfo info(wasm);
402422

@@ -411,7 +431,8 @@ void writeDWARFSections(Module& wasm, const BinaryLocationsMap& newLocations) {
411431
// TODO: Actually update, and remove sections we don't know how to update yet?
412432

413433
// Convert to binary sections.
414-
auto newSections = EmitDebugSections(data, true);
434+
auto newSections =
435+
EmitDebugSections(data, false /* EmitFixups for debug_info */);
415436

416437
// Update the custom sections in the wasm.
417438
// TODO: efficiency
@@ -422,7 +443,6 @@ void writeDWARFSections(Module& wasm, const BinaryLocationsMap& newLocations) {
422443
auto llvmData = newSections[llvmName]->getBuffer();
423444
section.data.resize(llvmData.size());
424445
std::copy(llvmData.begin(), llvmData.end(), section.data.data());
425-
fixEmittedSection(section.name, section.data);
426446
}
427447
}
428448
}

test/passes/dwarfdump.bin.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ Abbrev table for offset: 0x00000000
3939
DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005)
4040
DW_AT_high_pc [DW_FORM_data4] (0x00000002)
4141

42+
0x00000026: DW_TAG_subprogram [2]
43+
DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005)
44+
DW_AT_high_pc [DW_FORM_data4] (0x00000002)
45+
DW_AT_linkage_name [DW_FORM_strp] ( .debug_str[0x000000c8] = "_Z3foov")
46+
DW_AT_name [DW_FORM_strp] ( .debug_str[0x000000d0] = "foo")
47+
DW_AT_decl_file [DW_FORM_data1] ("/usr/local/google/home/azakai/Dev/emscripten/a.cpp")
48+
DW_AT_decl_line [DW_FORM_data1] (3)
49+
DW_AT_external [DW_FORM_flag_present] (true)
50+
51+
0x00000039: NULL
52+
4253
.debug_line contents:
4354
debug_line[0x00000000]
4455
Line table prologue:

test/passes/dwarfdump_roundtrip_dwarfdump.bin.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ Abbrev table for offset: 0x00000000
3939
DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005)
4040
DW_AT_high_pc [DW_FORM_data4] (0x00000002)
4141

42+
0x00000026: DW_TAG_subprogram [2]
43+
DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005)
44+
DW_AT_high_pc [DW_FORM_data4] (0x00000002)
45+
DW_AT_linkage_name [DW_FORM_strp] ( .debug_str[0x000000c8] = "_Z3foov")
46+
DW_AT_name [DW_FORM_strp] ( .debug_str[0x000000d0] = "foo")
47+
DW_AT_decl_file [DW_FORM_data1] ("/usr/local/google/home/azakai/Dev/emscripten/a.cpp")
48+
DW_AT_decl_line [DW_FORM_data1] (3)
49+
DW_AT_external [DW_FORM_flag_present] (true)
50+
51+
0x00000039: NULL
52+
4253
.debug_line contents:
4354
debug_line[0x00000000]
4455
Line table prologue:
@@ -129,6 +140,17 @@ Abbrev table for offset: 0x00000000
129140
DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005)
130141
DW_AT_high_pc [DW_FORM_data4] (0x00000002)
131142

143+
0x00000026: DW_TAG_subprogram [2]
144+
DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005)
145+
DW_AT_high_pc [DW_FORM_data4] (0x00000002)
146+
DW_AT_linkage_name [DW_FORM_strp] ( .debug_str[0x000000c8] = "_Z3foov")
147+
DW_AT_name [DW_FORM_strp] ( .debug_str[0x000000d0] = "foo")
148+
DW_AT_decl_file [DW_FORM_data1] ("/usr/local/google/home/azakai/Dev/emscripten/a.cpp")
149+
DW_AT_decl_line [DW_FORM_data1] (3)
150+
DW_AT_external [DW_FORM_flag_present] (true)
151+
152+
0x00000039: NULL
153+
132154
.debug_line contents:
133155
debug_line[0x00000000]
134156
Line table prologue:

0 commit comments

Comments
 (0)