| ... | ... | @@ -1138,8 +1138,7 @@ pub fn commitDeclState( |
| 1138 | 1138 | self.dbg_line_fn_first = src_fn; |
| 1139 | 1139 | self.dbg_line_fn_last = src_fn; |
| 1140 | 1140 | |
| 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{})); |
| 1143 | 1142 | } |
| 1144 | 1143 | |
| 1145 | 1144 | const last_src_fn = self.dbg_line_fn_last.?; |
| ... | ... | @@ -2277,6 +2276,8 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { |
| 2277 | 2276 | } |
| 2278 | 2277 | |
| 2279 | 2278 | pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void { |
| 2279 | const gpa = self.allocator; |
| 2280 | |
| 2280 | 2281 | const ptr_width_bytes: u8 = self.ptrWidthBytes(); |
| 2281 | 2282 | const target_endian = self.target.cpu.arch.endian(); |
| 2282 | 2283 | const init_len_size: usize = if (self.bin_file.tag == .macho) |
| ... | ... | @@ -2287,11 +2288,10 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void { |
| 2287 | 2288 | }; |
| 2288 | 2289 | |
| 2289 | 2290 | 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); |
| 2292 | 2292 | |
| 2293 | 2293 | // 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); |
| 2295 | 2295 | defer arena.deinit(); |
| 2296 | 2296 | const paths = try self.genIncludeDirsAndFileNames(arena.allocator(), module); |
| 2297 | 2297 | |
| ... | ... | @@ -2299,25 +2299,25 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void { |
| 2299 | 2299 | // files, and padding. We have a function to compute the upper bound size, however, |
| 2300 | 2300 | // because it's needed for determining where to put the offset of the first `SrcFn`. |
| 2301 | 2301 | 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); |
| 2303 | 2303 | defer di_buf.deinit(); |
| 2304 | 2304 | |
| 2305 | 2305 | // initial length - length of the .debug_line contribution for this compilation unit, |
| 2306 | 2306 | // 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; |
| 2309 | 2309 | |
| 2310 | 2310 | switch (self.bin_file.tag) { |
| 2311 | 2311 | .macho => { |
| 2312 | | mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, init_len)); |
| 2312 | mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, 0)); |
| 2313 | 2313 | }, |
| 2314 | 2314 | else => switch (self.ptr_width) { |
| 2315 | 2315 | .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); |
| 2317 | 2317 | }, |
| 2318 | 2318 | .p64 => { |
| 2319 | 2319 | 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); |
| 2321 | 2321 | }, |
| 2322 | 2322 | }, |
| 2323 | 2323 | } |
| ... | ... | @@ -2400,12 +2400,59 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void { |
| 2400 | 2400 | |
| 2401 | 2401 | assert(needed_bytes == di_buf.items.len); |
| 2402 | 2402 | |
| 2403 | | // We use NOPs because consumers empirically do not respect the header length field. |
| 2404 | 2403 | 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 | }, |
| 2407 | 2452 | } |
| 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; |
| 2409 | 2456 | switch (self.bin_file.tag) { |
| 2410 | 2457 | .elf => { |
| 2411 | 2458 | const elf_file = self.bin_file.cast(File.Elf).?; |