authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-02 19:57:42-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-02 19:57:42-07:00
log1ce6e201aa818b05f6637438d1c0b460ea817e3f
tree6e4dee6d2077b442703ca3a0ba8bfb14daa5745d
parent1a3f250f195d4ed5455795d4fa6e4b0cf97cb6ce

.debug_line: don't rely on header_length field

Empirically, debug info consumers do not respect this field, or otherwise consider it to be an error when it does not point exactly to the end of the header. Therefore we rely on the NOP jump at the beginning of the Line Number Program for padding rather than this field. llvm-dwarfdump says the line number data is fine; gdb and binutils-readelf crap out.

1 files changed, 20 insertions(+), 3 deletions(-)

src-self-hosted/link.zig+20-3
......@@ -647,6 +647,8 @@ pub const File = struct {
647647 }
648648
649649 fn allocatedSize(self: *Elf, start: u64) u64 {
650 if (start == 0)
651 return 0;
650652 var min_pos: u64 = std.math.maxInt(u64);
651653 if (self.shdr_table_offset) |off| {
652654 if (off > start and off < min_pos) min_pos = off;
......@@ -1229,8 +1231,13 @@ pub const File = struct {
12291231 0, // segment_selector_size
12301232 });
12311233
1232 const header_length = dbg_line_prg_off - (di_buf.items.len + ptr_width_bytes);
1233 self.writeDwarfAddrAssumeCapacity(&di_buf, header_length);
1234 // Empirically, debug info consumers do not respect this field, or otherwise
1235 // consider it to be an error when it does not point exactly to the end of the header.
1236 // Therefore we rely on the NOP jump at the beginning of the Line Number Program for
1237 // padding rather than this field.
1238 const before_header_len = di_buf.items.len;
1239 di_buf.items.len += ptr_width_bytes; // We will come back and write this.
1240 const after_header_len = di_buf.items.len;
12341241
12351242 const opcode_base = DW.LNS_set_isa + 1;
12361243 di_buf.appendSliceAssumeCapacity(&[_]u8{
......@@ -1280,7 +1287,17 @@ pub const File = struct {
12801287 self.writeDwarfAddrAssumeCapacity(&di_buf, root_src_file_strp); // DW.LNCT_path, DW.FORM_strp
12811288 di_buf.appendAssumeCapacity(0); // LNCT_directory_index, FORM_data1
12821289
1283 // Add a redundant NOP in case the consumer ignores header_length.
1290 const header_len = di_buf.items.len - after_header_len;
1291 switch (self.ptr_width) {
1292 .p32 => {
1293 mem.writeInt(u32, di_buf.items[before_header_len..][0..4], @intCast(u32, header_len), target_endian);
1294 },
1295 .p64 => {
1296 mem.writeInt(u64, di_buf.items[before_header_len..][0..8], header_len, target_endian);
1297 },
1298 }
1299
1300 // We use a NOP jmp because consumers empirically do not respect the header length field.
12841301 const after_jmp = di_buf.items.len + 6;
12851302 if (after_jmp > dbg_line_prg_off) {
12861303 // Move the first N files to the end to make more padding for the header.