| ... | @@ -647,6 +647,8 @@ pub const File = struct { | ... | @@ -647,6 +647,8 @@ pub const File = struct { |
| 647 | } | 647 | } |
| 648 | | 648 | |
| 649 | fn allocatedSize(self: *Elf, start: u64) u64 { | 649 | fn allocatedSize(self: *Elf, start: u64) u64 { |
| | 650 | if (start == 0) |
| | 651 | return 0; |
| 650 | var min_pos: u64 = std.math.maxInt(u64); | 652 | var min_pos: u64 = std.math.maxInt(u64); |
| 651 | if (self.shdr_table_offset) |off| { | 653 | if (self.shdr_table_offset) |off| { |
| 652 | if (off > start and off < min_pos) min_pos = off; | 654 | if (off > start and off < min_pos) min_pos = off; |
| ... | @@ -1229,8 +1231,13 @@ pub const File = struct { | ... | @@ -1229,8 +1231,13 @@ pub const File = struct { |
| 1229 | 0, // segment_selector_size | 1231 | 0, // segment_selector_size |
| 1230 | }); | 1232 | }); |
| 1231 | | 1233 | |
| 1232 | const header_length = dbg_line_prg_off - (di_buf.items.len + ptr_width_bytes); | 1234 | // Empirically, debug info consumers do not respect this field, or otherwise |
| 1233 | self.writeDwarfAddrAssumeCapacity(&di_buf, header_length); | 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; |
| 1234 | | 1241 | |
| 1235 | const opcode_base = DW.LNS_set_isa + 1; | 1242 | const opcode_base = DW.LNS_set_isa + 1; |
| 1236 | di_buf.appendSliceAssumeCapacity(&[_]u8{ | 1243 | di_buf.appendSliceAssumeCapacity(&[_]u8{ |
| ... | @@ -1280,7 +1287,17 @@ pub const File = struct { | ... | @@ -1280,7 +1287,17 @@ pub const File = struct { |
| 1280 | self.writeDwarfAddrAssumeCapacity(&di_buf, root_src_file_strp); // DW.LNCT_path, DW.FORM_strp | 1287 | self.writeDwarfAddrAssumeCapacity(&di_buf, root_src_file_strp); // DW.LNCT_path, DW.FORM_strp |
| 1281 | di_buf.appendAssumeCapacity(0); // LNCT_directory_index, FORM_data1 | 1288 | di_buf.appendAssumeCapacity(0); // LNCT_directory_index, FORM_data1 |
| 1282 | | 1289 | |
| 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. |
| 1284 | const after_jmp = di_buf.items.len + 6; | 1301 | const after_jmp = di_buf.items.len + 6; |
| 1285 | if (after_jmp > dbg_line_prg_off) { | 1302 | if (after_jmp > dbg_line_prg_off) { |
| 1286 | // Move the first N files to the end to make more padding for the header. | 1303 | // Move the first N files to the end to make more padding for the header. |