authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-12-08 00:20:19+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-12-09 09:24:25+01:00
log4c38ba7d1b64ac69bbb7cc612503bd32661cbbe5
treeee295aa5e94e549129b02cb539d9826773cb8b17
parentbe2b85f670d5fd1d3a8b5cea60bfc8a7b5f2e1e0

dwarf: move SrcFns if debug_line header exceeded its padding


1 files changed, 62 insertions(+), 15 deletions(-)

src/link/Dwarf.zig+62-15
......@@ -1138,8 +1138,7 @@ pub fn commitDeclState(
11381138 self.dbg_line_fn_first = src_fn;
11391139 self.dbg_line_fn_last = src_fn;
11401140
1141 // TODO TEXME JK
1142 src_fn.off = padToIdeal(self.dbgLineNeededHeaderBytes(&[0][]u8{}, &[0][]u8{}) * 100);
1141 src_fn.off = padToIdeal(self.dbgLineNeededHeaderBytes(&[0][]u8{}, &[0][]u8{}));
11431142 }
11441143
11451144 const last_src_fn = self.dbg_line_fn_last.?;
......@@ -2277,6 +2276,8 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
22772276}
22782277
22792278pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void {
2279 const gpa = self.allocator;
2280
22802281 const ptr_width_bytes: u8 = self.ptrWidthBytes();
22812282 const target_endian = self.target.cpu.arch.endian();
22822283 const init_len_size: usize = if (self.bin_file.tag == .macho)
......@@ -2287,11 +2288,10 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void {
22872288 };
22882289
22892290 const dbg_line_prg_off = self.getDebugLineProgramOff() orelse return;
2290 const dbg_line_prg_end = self.getDebugLineProgramEnd().?;
2291 assert(dbg_line_prg_end != 0);
2291 assert(self.getDebugLineProgramEnd().? != 0);
22922292
22932293 // Convert all input DI files into a set of include dirs and file names.
2294 var arena = std.heap.ArenaAllocator.init(self.allocator);
2294 var arena = std.heap.ArenaAllocator.init(gpa);
22952295 defer arena.deinit();
22962296 const paths = try self.genIncludeDirsAndFileNames(arena.allocator(), module);
22972297
......@@ -2299,25 +2299,25 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void {
22992299 // files, and padding. We have a function to compute the upper bound size, however,
23002300 // because it's needed for determining where to put the offset of the first `SrcFn`.
23012301 const needed_bytes = self.dbgLineNeededHeaderBytes(paths.dirs, paths.files);
2302 var di_buf = try std.ArrayList(u8).initCapacity(self.allocator, needed_bytes);
2302 var di_buf = try std.ArrayList(u8).initCapacity(gpa, needed_bytes);
23032303 defer di_buf.deinit();
23042304
23052305 // initial length - length of the .debug_line contribution for this compilation unit,
23062306 // not including the initial length itself.
2307 const after_init_len = di_buf.items.len + init_len_size;
2308 const init_len = dbg_line_prg_end - after_init_len;
2307 // We will backpatch this value later so just remember where we need to write it.
2308 const before_init_len = di_buf.items.len;
23092309
23102310 switch (self.bin_file.tag) {
23112311 .macho => {
2312 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, init_len));
2312 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, 0));
23132313 },
23142314 else => switch (self.ptr_width) {
23152315 .p32 => {
2316 mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, init_len), target_endian);
2316 mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, 0), target_endian);
23172317 },
23182318 .p64 => {
23192319 di_buf.appendNTimesAssumeCapacity(0xff, 4);
2320 mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), init_len, target_endian);
2320 mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), @as(u64, 0), target_endian);
23212321 },
23222322 },
23232323 }
......@@ -2400,12 +2400,59 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void {
24002400
24012401 assert(needed_bytes == di_buf.items.len);
24022402
2403 // We use NOPs because consumers empirically do not respect the header length field.
24042403 if (di_buf.items.len > dbg_line_prg_off) {
2405 // Move the first N files to the end to make more padding for the header.
2406 @panic("TODO: handle .debug_line header exceeding its padding");
2404 const needed_with_padding = padToIdeal(needed_bytes);
2405 const delta = needed_with_padding - dbg_line_prg_off;
2406
2407 const macho_file = self.bin_file.cast(File.MachO).?;
2408 const d_sym = &macho_file.d_sym.?;
2409 const debug_line_sect = &d_sym.sections.items[d_sym.debug_line_section_index.?];
2410 const needed_size = debug_line_sect.size + delta;
2411
2412 if (needed_size > d_sym.allocatedSize(debug_line_sect.offset)) {
2413 @panic("TODO grow debug_line section");
2414 }
2415
2416 var src_fn = self.dbg_line_fn_first.?;
2417 const last_fn = self.dbg_line_fn_last.?;
2418 const file_pos = debug_line_sect.offset + src_fn.off;
2419
2420 var buffer = try gpa.alloc(u8, last_fn.off + last_fn.len - src_fn.off);
2421 defer gpa.free(buffer);
2422 const amt = try d_sym.file.preadAll(buffer, file_pos);
2423 if (amt != buffer.len) return error.InputOutput;
2424
2425 try d_sym.file.pwriteAll(buffer, file_pos + delta);
2426
2427 debug_line_sect.size = needed_size;
2428
2429 while (true) {
2430 src_fn.off += delta;
2431
2432 if (src_fn.next) |next| {
2433 src_fn = next;
2434 } else break;
2435 }
2436 }
2437
2438 // Backpatch actual length of the debug line program
2439 const init_len = self.getDebugLineProgramEnd().? - before_init_len - init_len_size;
2440 switch (self.bin_file.tag) {
2441 .macho => {
2442 mem.writeIntLittle(u32, di_buf.items[before_init_len..][0..4], @intCast(u32, init_len));
2443 },
2444 else => switch (self.ptr_width) {
2445 .p32 => {
2446 mem.writeInt(u32, di_buf.items[before_init_len..][0..4], @intCast(u32, init_len), target_endian);
2447 },
2448 .p64 => {
2449 mem.writeInt(u64, di_buf.items[before_init_len + 4 ..][0..8], init_len, target_endian);
2450 },
2451 },
24072452 }
2408 const jmp_amt = dbg_line_prg_off - di_buf.items.len;
2453
2454 // We use NOPs because consumers empirically do not respect the header length field.
2455 const jmp_amt = self.getDebugLineProgramOff().? - di_buf.items.len;
24092456 switch (self.bin_file.tag) {
24102457 .elf => {
24112458 const elf_file = self.bin_file.cast(File.Elf).?;