| ... | ... | @@ -44,6 +44,11 @@ abbrev_table_offset: ?u64 = null, |
| 44 | 44 | /// Table of debug symbol names. |
| 45 | 45 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 46 | 46 | |
| 47 | file_names_buffer: std.ArrayListUnmanaged(u8) = .{}, |
| 48 | file_names: std.ArrayListUnmanaged(u32) = .{}, |
| 49 | file_names_free_list: std.ArrayListUnmanaged(u28) = .{}, |
| 50 | file_names_lookup: std.AutoHashMapUnmanaged(*Module.File, u28) = .{}, |
| 51 | |
| 47 | 52 | /// List of atoms that are owned directly by the DWARF module. |
| 48 | 53 | /// TODO convert links in DebugInfoAtom into indices and make |
| 49 | 54 | /// sure every atom is owned by this module. |
| ... | ... | @@ -906,6 +911,10 @@ pub fn deinit(self: *Dwarf) void { |
| 906 | 911 | self.dbg_line_fn_free_list.deinit(gpa); |
| 907 | 912 | self.atom_free_list.deinit(gpa); |
| 908 | 913 | self.strtab.deinit(gpa); |
| 914 | self.file_names_buffer.deinit(gpa); |
| 915 | self.file_names.deinit(gpa); |
| 916 | self.file_names_free_list.deinit(gpa); |
| 917 | self.file_names_lookup.deinit(gpa); |
| 909 | 918 | self.global_abbrev_relocs.deinit(gpa); |
| 910 | 919 | |
| 911 | 920 | for (self.managed_atoms.items) |atom| { |
| ... | ... | @@ -968,8 +977,12 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) |
| 968 | 977 | assert(self.getRelocDbgFileIndex() == dbg_line_buffer.items.len); |
| 969 | 978 | // Once we support more than one source file, this will have the ability to be more |
| 970 | 979 | // than one possible value. |
| 971 | | const file_index = 1; |
| 972 | | leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), file_index); |
| 980 | const file_index = try self.addFileName(mod, decl_index); |
| 981 | leb128.writeUnsignedFixed( |
| 982 | 4, |
| 983 | dbg_line_buffer.addManyAsArrayAssumeCapacity(4), |
| 984 | file_index + 1, |
| 985 | ); |
| 973 | 986 | |
| 974 | 987 | // Emit a line for the begin curly with prologue_end=false. The codegen will |
| 975 | 988 | // do the work of setting prologue_end=true and epilogue_begin=true. |
| ... | ... | @@ -1132,7 +1145,8 @@ pub fn commitDeclState( |
| 1132 | 1145 | self.dbg_line_fn_first = src_fn; |
| 1133 | 1146 | self.dbg_line_fn_last = src_fn; |
| 1134 | 1147 | |
| 1135 | | src_fn.off = padToIdeal(self.dbgLineNeededHeaderBytes(module)); |
| 1148 | // TODO TEXME JK |
| 1149 | src_fn.off = padToIdeal(self.dbgLineNeededHeaderBytes(module) * 100); |
| 1136 | 1150 | } |
| 1137 | 1151 | |
| 1138 | 1152 | const last_src_fn = self.dbg_line_fn_last.?; |
| ... | ... | @@ -2271,6 +2285,7 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void { |
| 2271 | 2285 | // files, and padding. We have a function to compute the upper bound size, however, |
| 2272 | 2286 | // because it's needed for determining where to put the offset of the first `SrcFn`. |
| 2273 | 2287 | const needed_bytes = self.dbgLineNeededHeaderBytes(module); |
| 2288 | log.debug("dbg_line_prg_off = {x}, needed_bytes = {x}", .{ dbg_line_prg_off, needed_bytes }); |
| 2274 | 2289 | var di_buf = try std.ArrayList(u8).initCapacity(self.allocator, needed_bytes); |
| 2275 | 2290 | defer di_buf.deinit(); |
| 2276 | 2291 | |
| ... | ... | @@ -2325,15 +2340,28 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void { |
| 2325 | 2340 | 1, // `DW.LNS.set_isa` |
| 2326 | 2341 | 0, // include_directories (none except the compilation unit cwd) |
| 2327 | 2342 | }); |
| 2328 | | // file_names[0] |
| 2329 | | di_buf.appendSliceAssumeCapacity(module.root_pkg.root_src_path); // relative path name |
| 2330 | | di_buf.appendSliceAssumeCapacity(&[_]u8{ |
| 2331 | | 0, // null byte for the relative path name |
| 2332 | | 0, // directory_index |
| 2333 | | 0, // mtime (TODO supply this) |
| 2334 | | 0, // file size bytes (TODO supply this) |
| 2335 | | 0, // file_names sentinel |
| 2336 | | }); |
| 2343 | // // file_names[0] |
| 2344 | // di_buf.appendSliceAssumeCapacity(module.root_pkg.root_src_path); // relative path name |
| 2345 | // di_buf.appendSliceAssumeCapacity(&[_]u8{ |
| 2346 | // 0, // null byte for the relative path name |
| 2347 | // 0, // directory_index |
| 2348 | // 0, // mtime (TODO supply this) |
| 2349 | // 0, // file size bytes (TODO supply this) |
| 2350 | // 0, // file_names sentinel |
| 2351 | // }); |
| 2352 | |
| 2353 | for (self.file_names.items) |off, i| { |
| 2354 | const file_name = self.getFileName(off); |
| 2355 | log.debug("file_name[{d}] = {s}", .{ i + 1, file_name }); |
| 2356 | di_buf.appendSliceAssumeCapacity(file_name); |
| 2357 | di_buf.appendSliceAssumeCapacity(&[_]u8{ |
| 2358 | 0, // null byte for the relative path name |
| 2359 | 0, // directory_index |
| 2360 | 0, // mtime (TODO supply this) |
| 2361 | 0, // file size bytes (TODO supply this) |
| 2362 | }); |
| 2363 | } |
| 2364 | di_buf.appendAssumeCapacity(0); // file names sentinel |
| 2337 | 2365 | |
| 2338 | 2366 | const header_len = di_buf.items.len - after_header_len; |
| 2339 | 2367 | if (self.tag == .macho) { |
| ... | ... | @@ -2405,18 +2433,18 @@ fn ptrWidthBytes(self: Dwarf) u8 { |
| 2405 | 2433 | } |
| 2406 | 2434 | |
| 2407 | 2435 | fn dbgLineNeededHeaderBytes(self: Dwarf, module: *Module) u32 { |
| 2408 | | _ = self; |
| 2409 | 2436 | const directory_entry_format_count = 1; |
| 2410 | 2437 | const file_name_entry_format_count = 1; |
| 2411 | 2438 | const directory_count = 1; |
| 2412 | | const file_name_count = 1; |
| 2439 | const file_name_count = self.file_names.items.len; |
| 2413 | 2440 | const root_src_dir_path_len = if (module.root_pkg.root_src_directory.path) |p| p.len else 1; // "." |
| 2441 | |
| 2414 | 2442 | return @intCast(u32, 53 + directory_entry_format_count * 2 + file_name_entry_format_count * 2 + |
| 2415 | 2443 | directory_count * 8 + file_name_count * 8 + |
| 2416 | 2444 | // These are encoded as DW.FORM.string rather than DW.FORM.strp as we would like |
| 2417 | 2445 | // because of a workaround for readelf and gdb failing to understand DWARFv5 correctly. |
| 2418 | 2446 | root_src_dir_path_len + |
| 2419 | | module.root_pkg.root_src_path.len); |
| 2447 | self.file_names_buffer.items.len); |
| 2420 | 2448 | } |
| 2421 | 2449 | |
| 2422 | 2450 | /// The reloc offset for the line offset of a function from the previous function's line. |
| ... | ... | @@ -2527,6 +2555,47 @@ pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void { |
| 2527 | 2555 | } |
| 2528 | 2556 | } |
| 2529 | 2557 | |
| 2558 | fn allocateFileIndex(self: *Dwarf) !u28 { |
| 2559 | try self.file_names.ensureUnusedCapacity(self.allocator, 1); |
| 2560 | |
| 2561 | const index = blk: { |
| 2562 | if (self.file_names_free_list.popOrNull()) |index| { |
| 2563 | log.debug(" (reusing file name index {d})", .{index}); |
| 2564 | break :blk index; |
| 2565 | } else { |
| 2566 | const index = @intCast(u28, self.file_names.items.len); |
| 2567 | log.debug(" (allocating file name index {d})", .{index}); |
| 2568 | _ = self.file_names.addOneAssumeCapacity(); |
| 2569 | break :blk index; |
| 2570 | } |
| 2571 | }; |
| 2572 | |
| 2573 | return index; |
| 2574 | } |
| 2575 | |
| 2576 | fn addFileName(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) !u28 { |
| 2577 | const decl = mod.declPtr(decl_index); |
| 2578 | const file_scope = decl.getFileScope(); |
| 2579 | if (self.file_names_lookup.get(file_scope)) |file_index| { |
| 2580 | return file_index; |
| 2581 | } |
| 2582 | const index = try self.allocateFileIndex(); |
| 2583 | const file_name = try file_scope.fullPath(self.allocator); |
| 2584 | defer self.allocator.free(file_name); |
| 2585 | try self.file_names_buffer.ensureUnusedCapacity(self.allocator, file_name.len + 1); |
| 2586 | const off = @intCast(u32, self.file_names_buffer.items.len); |
| 2587 | self.file_names_buffer.appendSliceAssumeCapacity(file_name); |
| 2588 | self.file_names_buffer.appendAssumeCapacity(0); |
| 2589 | self.file_names.items[index] = off; |
| 2590 | try self.file_names_lookup.putNoClobber(self.allocator, file_scope, index); |
| 2591 | return index; |
| 2592 | } |
| 2593 | |
| 2594 | fn getFileName(self: Dwarf, off: u32) []const u8 { |
| 2595 | assert(off < self.file_names_buffer.items.len); |
| 2596 | return mem.sliceTo(@ptrCast([*:0]const u8, self.file_names_buffer.items.ptr) + off, 0); |
| 2597 | } |
| 2598 | |
| 2530 | 2599 | fn addDbgInfoErrorSet( |
| 2531 | 2600 | arena: Allocator, |
| 2532 | 2601 | module: *Module, |