From 1ce6e201aa818b05f6637438d1c0b460ea817e3f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 2 Aug 2020 19:57:42 -0700 Subject: [PATCH] .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. --- src-self-hosted/link.zig | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index ca12e59ee6d45eb3ab03c01c7243199dcf2b416f..96a15cadeeae4d2f9b8f32551fb922e0804e20fc 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -647,6 +647,8 @@ pub const File = struct { } fn allocatedSize(self: *Elf, start: u64) u64 { + if (start == 0) + return 0; var min_pos: u64 = std.math.maxInt(u64); if (self.shdr_table_offset) |off| { if (off > start and off < min_pos) min_pos = off; @@ -1229,8 +1231,13 @@ pub const File = struct { 0, // segment_selector_size }); - const header_length = dbg_line_prg_off - (di_buf.items.len + ptr_width_bytes); - self.writeDwarfAddrAssumeCapacity(&di_buf, header_length); + // 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. + const before_header_len = di_buf.items.len; + di_buf.items.len += ptr_width_bytes; // We will come back and write this. + const after_header_len = di_buf.items.len; const opcode_base = DW.LNS_set_isa + 1; di_buf.appendSliceAssumeCapacity(&[_]u8{ @@ -1280,7 +1287,17 @@ pub const File = struct { self.writeDwarfAddrAssumeCapacity(&di_buf, root_src_file_strp); // DW.LNCT_path, DW.FORM_strp di_buf.appendAssumeCapacity(0); // LNCT_directory_index, FORM_data1 - // Add a redundant NOP in case the consumer ignores header_length. + const header_len = di_buf.items.len - after_header_len; + switch (self.ptr_width) { + .p32 => { + mem.writeInt(u32, di_buf.items[before_header_len..][0..4], @intCast(u32, header_len), target_endian); + }, + .p64 => { + mem.writeInt(u64, di_buf.items[before_header_len..][0..8], header_len, target_endian); + }, + } + + // We use a NOP jmp because consumers empirically do not respect the header length field. const after_jmp = di_buf.items.len + 6; if (after_jmp > dbg_line_prg_off) { // Move the first N files to the end to make more padding for the header. -- 2.54.0