| ... | @@ -1138,8 +1138,7 @@ pub fn commitDeclState( | ... | @@ -1138,8 +1138,7 @@ pub fn commitDeclState( |
| 1138 | self.dbg_line_fn_first = src_fn; | 1138 | self.dbg_line_fn_first = src_fn; |
| 1139 | self.dbg_line_fn_last = src_fn; | 1139 | self.dbg_line_fn_last = src_fn; |
| 1140 | | 1140 | |
| 1141 | // TODO TEXME JK | 1141 | src_fn.off = padToIdeal(self.dbgLineNeededHeaderBytes(&[0][]u8{}, &[0][]u8{})); |
| 1142 | src_fn.off = padToIdeal(self.dbgLineNeededHeaderBytes(&[0][]u8{}, &[0][]u8{}) * 100); | | |
| 1143 | } | 1142 | } |
| 1144 | | 1143 | |
| 1145 | const last_src_fn = self.dbg_line_fn_last.?; | 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,6 +2276,8 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { |
| 2277 | } | 2276 | } |
| 2278 | | 2277 | |
| 2279 | pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void { | 2278 | pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void { |
| | 2279 | const gpa = self.allocator; |
| | 2280 | |
| 2280 | const ptr_width_bytes: u8 = self.ptrWidthBytes(); | 2281 | const ptr_width_bytes: u8 = self.ptrWidthBytes(); |
| 2281 | const target_endian = self.target.cpu.arch.endian(); | 2282 | const target_endian = self.target.cpu.arch.endian(); |
| 2282 | const init_len_size: usize = if (self.bin_file.tag == .macho) | 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,11 +2288,10 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void { |
| 2287 | }; | 2288 | }; |
| 2288 | | 2289 | |
| 2289 | const dbg_line_prg_off = self.getDebugLineProgramOff() orelse return; | 2290 | const dbg_line_prg_off = self.getDebugLineProgramOff() orelse return; |
| 2290 | const dbg_line_prg_end = self.getDebugLineProgramEnd().?; | 2291 | assert(self.getDebugLineProgramEnd().? != 0); |
| 2291 | assert(dbg_line_prg_end != 0); | | |
| 2292 | | 2292 | |
| 2293 | // Convert all input DI files into a set of include dirs and file names. | 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 | defer arena.deinit(); | 2295 | defer arena.deinit(); |
| 2296 | const paths = try self.genIncludeDirsAndFileNames(arena.allocator(), module); | 2296 | const paths = try self.genIncludeDirsAndFileNames(arena.allocator(), module); |
| 2297 | | 2297 | |
| ... | @@ -2299,25 +2299,25 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void { | ... | @@ -2299,25 +2299,25 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void { |
| 2299 | // files, and padding. We have a function to compute the upper bound size, however, | 2299 | // files, and padding. We have a function to compute the upper bound size, however, |
| 2300 | // because it's needed for determining where to put the offset of the first `SrcFn`. | 2300 | // because it's needed for determining where to put the offset of the first `SrcFn`. |
| 2301 | const needed_bytes = self.dbgLineNeededHeaderBytes(paths.dirs, paths.files); | 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 | defer di_buf.deinit(); | 2303 | defer di_buf.deinit(); |
| 2304 | | 2304 | |
| 2305 | // initial length - length of the .debug_line contribution for this compilation unit, | 2305 | // initial length - length of the .debug_line contribution for this compilation unit, |
| 2306 | // not including the initial length itself. | 2306 | // not including the initial length itself. |
| 2307 | const after_init_len = di_buf.items.len + init_len_size; | 2307 | // We will backpatch this value later so just remember where we need to write it. |
| 2308 | const init_len = dbg_line_prg_end - after_init_len; | 2308 | const before_init_len = di_buf.items.len; |
| 2309 | | 2309 | |
| 2310 | switch (self.bin_file.tag) { | 2310 | switch (self.bin_file.tag) { |
| 2311 | .macho => { | 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 | else => switch (self.ptr_width) { | 2314 | else => switch (self.ptr_width) { |
| 2315 | .p32 => { | 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 | .p64 => { | 2318 | .p64 => { |
| 2319 | di_buf.appendNTimesAssumeCapacity(0xff, 4); | 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,12 +2400,59 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void { |
| 2400 | | 2400 | |
| 2401 | assert(needed_bytes == di_buf.items.len); | 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 | if (di_buf.items.len > dbg_line_prg_off) { | 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. | 2404 | const needed_with_padding = padToIdeal(needed_bytes); |
| 2406 | @panic("TODO: handle .debug_line header exceeding its padding"); | 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 | switch (self.bin_file.tag) { | 2456 | switch (self.bin_file.tag) { |
| 2410 | .elf => { | 2457 | .elf => { |
| 2411 | const elf_file = self.bin_file.cast(File.Elf).?; | 2458 | const elf_file = self.bin_file.cast(File.Elf).?; |