authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-21 16:14:40+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-10-21 16:14:40+02:00
log809e7aa4fc0e613752f8c7a4319ac4157089ea84
tree52b38d59672519e0901e65d487d1013335ed7348
parent3d6e63337164b42fec4df55687071be38d33dce9
parentf4f5e9edd69d3ca8f4d523ca6949487721a4e166
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17638 from ziglang/elf-dwarf-fixes

dwarf: decouple DWARF formats from target pointer size + misc fixes

4 files changed, 133 insertions(+), 190 deletions(-)

src/link/Dwarf.zig+130-187
......@@ -1,32 +1,7 @@
1const Dwarf = @This();
2
3const std = @import("std");
4const builtin = @import("builtin");
5const assert = std.debug.assert;
6const fs = std.fs;
7const leb128 = std.leb;
8const log = std.log.scoped(.dwarf);
9const mem = std.mem;
10
11const link = @import("../link.zig");
12const trace = @import("../tracy.zig").trace;
13
14const Allocator = mem.Allocator;
15const DW = std.dwarf;
16const File = link.File;
17const LinkBlock = File.LinkBlock;
18const LinkFn = File.LinkFn;
19const LinkerLoad = @import("../codegen.zig").LinkerLoad;
20const Module = @import("../Module.zig");
21const InternPool = @import("../InternPool.zig");
22const StringTable = @import("strtab.zig").StringTable;
23const Type = @import("../type.zig").Type;
24const Value = @import("../value.zig").Value;
25
261allocator: Allocator,
272bin_file: *File,
3format: Format,
284ptr_width: PtrWidth,
29target: std.Target,
305
316/// A list of `Atom`s whose Line Number Programs have surplus capacity.
327/// This is the same concept as `Section.free_list` in Elf; see those doc comments.
......@@ -983,17 +958,17 @@ const min_nop_size = 2;
983958/// actual_capacity + (actual_capacity / ideal_factor)
984959const ideal_factor = 3;
985960
986pub fn init(allocator: Allocator, bin_file: *File, target: std.Target) Dwarf {
987 const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {
961pub fn init(allocator: Allocator, bin_file: *File, format: Format) Dwarf {
962 const ptr_width: PtrWidth = switch (bin_file.options.target.ptrBitWidth()) {
988963 0...32 => .p32,
989964 33...64 => .p64,
990965 else => unreachable,
991966 };
992 return Dwarf{
967 return .{
993968 .allocator = allocator,
994969 .bin_file = bin_file,
970 .format = format,
995971 .ptr_width = ptr_width,
996 .target = target,
997972 };
998973}
999974
......@@ -1129,7 +1104,7 @@ pub fn commitDeclState(
11291104 const decl = mod.declPtr(decl_index);
11301105 const ip = &mod.intern_pool;
11311106
1132 const target_endian = self.target.cpu.arch.endian();
1107 const target_endian = self.bin_file.options.target.cpu.arch.endian();
11331108
11341109 assert(decl.has_tv);
11351110 switch (decl.ty.zigTypeTag(mod)) {
......@@ -1788,8 +1763,6 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
17881763 DW.AT.count, DW.FORM.udata,
17891764 0,
17901765 0, // table sentinel
1791 0,
1792 0,
17931766 0, // section sentinel
17941767 };
17951768 const abbrev_offset = 0;
......@@ -1839,12 +1812,10 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u
18391812 var di_buf = try std.ArrayList(u8).initCapacity(self.allocator, needed_bytes);
18401813 defer di_buf.deinit();
18411814
1842 const target_endian = self.target.cpu.arch.endian();
1843 const init_len_size: usize = if (self.bin_file.tag == .macho)
1844 4
1845 else switch (self.ptr_width) {
1846 .p32 => @as(usize, 4),
1847 .p64 => 12,
1815 const target_endian = self.bin_file.options.target.cpu.arch.endian();
1816 const init_len_size: usize = switch (self.format) {
1817 .dwarf32 => 4,
1818 .dwarf64 => 12,
18481819 };
18491820
18501821 // initial length - length of the .debug_info contribution for this compilation unit,
......@@ -1852,33 +1823,17 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u
18521823 // We have to come back and write it later after we know the size.
18531824 const after_init_len = di_buf.items.len + init_len_size;
18541825 const dbg_info_end = self.getDebugInfoEnd().?;
1855 const init_len = dbg_info_end - after_init_len;
1856 if (self.bin_file.tag == .macho) {
1857 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(init_len)));
1858 } else switch (self.ptr_width) {
1859 .p32 => {
1860 mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(init_len)), target_endian);
1861 },
1862 .p64 => {
1863 di_buf.appendNTimesAssumeCapacity(0xff, 4);
1864 mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), init_len, target_endian);
1865 },
1866 }
1826 const init_len = dbg_info_end - after_init_len + 1;
1827
1828 if (self.format == .dwarf64) di_buf.appendNTimesAssumeCapacity(0xff, 4);
1829 self.writeOffsetAssumeCapacity(&di_buf, init_len);
1830
18671831 mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 4, target_endian); // DWARF version
18681832 const abbrev_offset = self.abbrev_table_offset.?;
1869 if (self.bin_file.tag == .macho) {
1870 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(abbrev_offset)));
1871 di_buf.appendAssumeCapacity(8); // address size
1872 } else switch (self.ptr_width) {
1873 .p32 => {
1874 mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(abbrev_offset)), target_endian);
1875 di_buf.appendAssumeCapacity(4); // address size
1876 },
1877 .p64 => {
1878 mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), abbrev_offset, target_endian);
1879 di_buf.appendAssumeCapacity(8); // address size
1880 },
1881 }
1833
1834 self.writeOffsetAssumeCapacity(&di_buf, abbrev_offset);
1835 di_buf.appendAssumeCapacity(self.ptrWidthBytes()); // address size
1836
18821837 // Write the form for the compile unit, which must match the abbrev table above.
18831838 const name_strp = try self.strtab.insert(self.allocator, module.root_mod.root_src_path);
18841839 var compile_unit_dir_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
......@@ -1887,21 +1842,13 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u
18871842 const producer_strp = try self.strtab.insert(self.allocator, link.producer_string);
18881843
18891844 di_buf.appendAssumeCapacity(@intFromEnum(AbbrevKind.compile_unit));
1890 if (self.bin_file.tag == .macho) {
1891 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); // DW.AT.stmt_list, DW.FORM.sec_offset
1892 mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), low_pc);
1893 mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), high_pc);
1894 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(name_strp)));
1895 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(comp_dir_strp)));
1896 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(producer_strp)));
1897 } else {
1898 self.writeAddrAssumeCapacity(&di_buf, 0); // DW.AT.stmt_list, DW.FORM.sec_offset
1899 self.writeAddrAssumeCapacity(&di_buf, low_pc);
1900 self.writeAddrAssumeCapacity(&di_buf, high_pc);
1901 self.writeAddrAssumeCapacity(&di_buf, name_strp);
1902 self.writeAddrAssumeCapacity(&di_buf, comp_dir_strp);
1903 self.writeAddrAssumeCapacity(&di_buf, producer_strp);
1904 }
1845 self.writeOffsetAssumeCapacity(&di_buf, 0); // DW.AT.stmt_list, DW.FORM.sec_offset
1846 self.writeAddrAssumeCapacity(&di_buf, low_pc);
1847 self.writeAddrAssumeCapacity(&di_buf, high_pc);
1848 self.writeOffsetAssumeCapacity(&di_buf, name_strp);
1849 self.writeOffsetAssumeCapacity(&di_buf, comp_dir_strp);
1850 self.writeOffsetAssumeCapacity(&di_buf, producer_strp);
1851
19051852 // We are still waiting on dwarf-std.org to assign DW_LANG_Zig a number:
19061853 // http://dwarfstd.org/ShowIssue.php?issue=171115.1
19071854 // Until then we say it is C99.
......@@ -1954,13 +1901,26 @@ fn resolveCompilationDir(module: *Module, buffer: *[std.fs.MAX_PATH_BYTES]u8) []
19541901}
19551902
19561903fn writeAddrAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), addr: u64) void {
1957 const target_endian = self.target.cpu.arch.endian();
1904 const target_endian = self.bin_file.options.target.cpu.arch.endian();
19581905 switch (self.ptr_width) {
19591906 .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(addr)), target_endian),
19601907 .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian),
19611908 }
19621909}
19631910
1911fn writeOffsetAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), off: u64) void {
1912 const target_endian = self.bin_file.options.target.cpu.arch.endian();
1913 switch (self.format) {
1914 .dwarf32 => mem.writeInt(
1915 u32,
1916 buf.addManyAsArrayAssumeCapacity(4),
1917 @as(u32, @intCast(off)),
1918 target_endian,
1919 ),
1920 .dwarf64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), off, target_endian),
1921 }
1922}
1923
19641924/// Writes to the file a buffer, prefixed and suffixed by the specified number of
19651925/// bytes of NOPs. Asserts each padding size is at least `min_nop_size` and total padding bytes
19661926/// are less than 1044480 bytes (if this limit is ever reached, this function can be
......@@ -2176,13 +2136,7 @@ fn writeDbgInfoNopsToArrayList(
21762136}
21772137
21782138pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
2179 const target_endian = self.target.cpu.arch.endian();
2180 const init_len_size: usize = if (self.bin_file.tag == .macho)
2181 4
2182 else switch (self.ptr_width) {
2183 .p32 => @as(usize, 4),
2184 .p64 => 12,
2185 };
2139 const target_endian = self.bin_file.options.target.cpu.arch.endian();
21862140 const ptr_width_bytes = self.ptrWidthBytes();
21872141
21882142 // Enough for all the data without resizing. When support for more compilation units
......@@ -2193,17 +2147,15 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
21932147 // initial length - length of the .debug_aranges contribution for this compilation unit,
21942148 // not including the initial length itself.
21952149 // We have to come back and write it later after we know the size.
2150 if (self.format == .dwarf64) di_buf.appendNTimesAssumeCapacity(0xff, 4);
21962151 const init_len_index = di_buf.items.len;
2197 di_buf.items.len += init_len_size;
2152 self.writeOffsetAssumeCapacity(&di_buf, 0);
21982153 const after_init_len = di_buf.items.len;
21992154 mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 2, target_endian); // version
2155
22002156 // When more than one compilation unit is supported, this will be the offset to it.
22012157 // For now it is always at offset 0 in .debug_info.
2202 if (self.bin_file.tag == .macho) {
2203 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); // __debug_info offset
2204 } else {
2205 self.writeAddrAssumeCapacity(&di_buf, 0); // .debug_info offset
2206 }
2158 self.writeOffsetAssumeCapacity(&di_buf, 0); // .debug_info offset
22072159 di_buf.appendAssumeCapacity(ptr_width_bytes); // address_size
22082160 di_buf.appendAssumeCapacity(0); // segment_selector_size
22092161
......@@ -2222,18 +2174,14 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
22222174
22232175 // Go back and populate the initial length.
22242176 const init_len = di_buf.items.len - after_init_len;
2225 if (self.bin_file.tag == .macho) {
2226 mem.writeIntLittle(u32, di_buf.items[init_len_index..][0..4], @as(u32, @intCast(init_len)));
2227 } else switch (self.ptr_width) {
2228 .p32 => {
2229 mem.writeInt(u32, di_buf.items[init_len_index..][0..4], @as(u32, @intCast(init_len)), target_endian);
2230 },
2231 .p64 => {
2232 // initial length - length of the .debug_aranges contribution for this compilation unit,
2233 // not including the initial length itself.
2234 di_buf.items[init_len_index..][0..4].* = [_]u8{ 0xff, 0xff, 0xff, 0xff };
2235 mem.writeInt(u64, di_buf.items[init_len_index + 4 ..][0..8], init_len, target_endian);
2236 },
2177 switch (self.format) {
2178 .dwarf32 => mem.writeInt(
2179 u32,
2180 di_buf.items[init_len_index..][0..4],
2181 @as(u32, @intCast(init_len)),
2182 target_endian,
2183 ),
2184 .dwarf64 => mem.writeInt(u64, di_buf.items[init_len_index..][0..8], init_len, target_endian),
22372185 }
22382186
22392187 const needed_size = @as(u32, @intCast(di_buf.items.len));
......@@ -2267,13 +2215,10 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
22672215pub fn writeDbgLineHeader(self: *Dwarf) !void {
22682216 const gpa = self.allocator;
22692217
2270 const ptr_width_bytes: u8 = self.ptrWidthBytes();
2271 const target_endian = self.target.cpu.arch.endian();
2272 const init_len_size: usize = if (self.bin_file.tag == .macho)
2273 4
2274 else switch (self.ptr_width) {
2275 .p32 => @as(usize, 4),
2276 .p64 => 12,
2218 const target_endian = self.bin_file.options.target.cpu.arch.endian();
2219 const init_len_size: usize = switch (self.format) {
2220 .dwarf32 => 4,
2221 .dwarf64 => 12,
22772222 };
22782223
22792224 const dbg_line_prg_off = self.getDebugLineProgramOff() orelse return;
......@@ -2291,25 +2236,8 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
22912236 var di_buf = try std.ArrayList(u8).initCapacity(gpa, needed_bytes);
22922237 defer di_buf.deinit();
22932238
2294 // initial length - length of the .debug_line contribution for this compilation unit,
2295 // not including the initial length itself.
2296 // We will backpatch this value later so just remember where we need to write it.
2297 const before_init_len = di_buf.items.len;
2298
2299 switch (self.bin_file.tag) {
2300 .macho => {
2301 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, 0));
2302 },
2303 else => switch (self.ptr_width) {
2304 .p32 => {
2305 mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, 0), target_endian);
2306 },
2307 .p64 => {
2308 di_buf.appendNTimesAssumeCapacity(0xff, 4);
2309 mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), @as(u64, 0), target_endian);
2310 },
2311 },
2312 }
2239 if (self.format == .dwarf64) di_buf.appendNTimesAssumeCapacity(0xff, 4);
2240 self.writeOffsetAssumeCapacity(&di_buf, 0);
23132241
23142242 mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 4, target_endian); // version
23152243
......@@ -2318,12 +2246,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
23182246 // Therefore we rely on the NOP jump at the beginning of the Line Number Program for
23192247 // padding rather than this field.
23202248 const before_header_len = di_buf.items.len;
2321
2322 di_buf.items.len += switch (self.bin_file.tag) { // We will come back and write this.
2323 .macho => @sizeOf(u32),
2324 else => ptr_width_bytes,
2325 };
2326
2249 self.writeOffsetAssumeCapacity(&di_buf, 0); // We will come back and write this.
23272250 const after_header_len = di_buf.items.len;
23282251
23292252 const opcode_base = DW.LNS.set_isa + 1;
......@@ -2360,7 +2283,11 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
23602283
23612284 for (paths.files, 0..) |file, i| {
23622285 const dir_index = paths.files_dirs_indexes[i];
2363 log.debug("adding new file name at {d} of '{s}' referencing directory {d}", .{ i + 1, file, dir_index + 1 });
2286 log.debug("adding new file name at {d} of '{s}' referencing directory {d}", .{
2287 i + 1,
2288 file,
2289 dir_index + 1,
2290 });
23642291 di_buf.appendSliceAssumeCapacity(file);
23652292 di_buf.appendSliceAssumeCapacity(&[_]u8{
23662293 0, // null byte for the relative path name
......@@ -2372,19 +2299,14 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
23722299 di_buf.appendAssumeCapacity(0); // file names sentinel
23732300
23742301 const header_len = di_buf.items.len - after_header_len;
2375
2376 switch (self.bin_file.tag) {
2377 .macho => {
2378 mem.writeIntLittle(u32, di_buf.items[before_header_len..][0..4], @as(u32, @intCast(header_len)));
2379 },
2380 else => switch (self.ptr_width) {
2381 .p32 => {
2382 mem.writeInt(u32, di_buf.items[before_header_len..][0..4], @as(u32, @intCast(header_len)), target_endian);
2383 },
2384 .p64 => {
2385 mem.writeInt(u64, di_buf.items[before_header_len..][0..8], header_len, target_endian);
2386 },
2387 },
2302 switch (self.format) {
2303 .dwarf32 => mem.writeInt(
2304 u32,
2305 di_buf.items[before_header_len..][0..4],
2306 @as(u32, @intCast(header_len)),
2307 target_endian,
2308 ),
2309 .dwarf64 => mem.writeInt(u64, di_buf.items[before_header_len..][0..8], header_len, target_endian),
23882310 }
23892311
23902312 assert(needed_bytes == di_buf.items.len);
......@@ -2452,18 +2374,13 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
24522374 }
24532375
24542376 // Backpatch actual length of the debug line program
2455 const init_len = self.getDebugLineProgramEnd().? - before_init_len - init_len_size;
2456 switch (self.bin_file.tag) {
2457 .macho => {
2458 mem.writeIntLittle(u32, di_buf.items[before_init_len..][0..4], @as(u32, @intCast(init_len)));
2377 const init_len = self.getDebugLineProgramEnd().? - init_len_size;
2378 switch (self.format) {
2379 .dwarf32 => {
2380 mem.writeInt(u32, di_buf.items[0..4], @as(u32, @intCast(init_len)), target_endian);
24592381 },
2460 else => switch (self.ptr_width) {
2461 .p32 => {
2462 mem.writeInt(u32, di_buf.items[before_init_len..][0..4], @as(u32, @intCast(init_len)), target_endian);
2463 },
2464 .p64 => {
2465 mem.writeInt(u64, di_buf.items[before_init_len + 4 ..][0..8], init_len, target_endian);
2466 },
2382 .dwarf64 => {
2383 mem.writeInt(u64, di_buf.items[4..][0..8], init_len, target_endian);
24672384 },
24682385 }
24692386
......@@ -2500,7 +2417,7 @@ fn getDebugInfoOff(self: Dwarf) ?u32 {
25002417fn getDebugInfoEnd(self: Dwarf) ?u32 {
25012418 const last_index = self.di_atom_last_index orelse return null;
25022419 const last = self.getAtom(.di_atom, last_index);
2503 return last.off + last.len + 1;
2420 return last.off + last.len;
25042421}
25052422
25062423fn getDebugLineProgramOff(self: Dwarf) ?u32 {
......@@ -2524,17 +2441,14 @@ fn ptrWidthBytes(self: Dwarf) u8 {
25242441}
25252442
25262443fn dbgLineNeededHeaderBytes(self: Dwarf, dirs: []const []const u8, files: []const []const u8) u32 {
2527 var size = switch (self.bin_file.tag) { // length field
2528 .macho => @sizeOf(u32),
2529 else => switch (self.ptr_width) {
2530 .p32 => @as(usize, @sizeOf(u32)),
2531 .p64 => @sizeOf(u32) + @sizeOf(u64),
2532 },
2444 var size: usize = switch (self.format) { // length field
2445 .dwarf32 => @as(usize, 4),
2446 .dwarf64 => 12,
25332447 };
25342448 size += @sizeOf(u16); // version field
2535 size += switch (self.bin_file.tag) { // offset to end-of-header
2536 .macho => @sizeOf(u32),
2537 else => self.ptrWidthBytes(),
2449 size += switch (self.format) { // offset to end-of-header
2450 .dwarf32 => @as(usize, 4),
2451 .dwarf64 => 8,
25382452 };
25392453 size += 18; // opcodes
25402454
......@@ -2570,6 +2484,8 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
25702484}
25712485
25722486pub fn flushModule(self: *Dwarf, module: *Module) !void {
2487 const target = self.bin_file.options.target;
2488
25732489 if (self.global_abbrev_relocs.items.len > 0) {
25742490 const gpa = self.allocator;
25752491 var arena_alloc = std.heap.ArenaAllocator.init(gpa);
......@@ -2581,7 +2497,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
25812497 module,
25822498 Type.anyerror,
25832499 module.global_error_set.keys(),
2584 self.target,
2500 target,
25852501 &dbg_info_buffer,
25862502 );
25872503
......@@ -2610,7 +2526,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
26102526 };
26112527
26122528 var buf: [@sizeOf(u32)]u8 = undefined;
2613 mem.writeInt(u32, &buf, self.getAtom(.di_atom, di_atom_index).off, self.target.cpu.arch.endian());
2529 mem.writeInt(u32, &buf, self.getAtom(.di_atom, di_atom_index).off, target.cpu.arch.endian());
26142530
26152531 while (self.global_abbrev_relocs.popOrNull()) |reloc| {
26162532 const atom = self.getAtom(.di_atom, reloc.atom_index);
......@@ -2670,21 +2586,18 @@ fn genIncludeDirsAndFileNames(self: *Dwarf, arena: Allocator) !struct {
26702586 try files_dir_indexes.ensureTotalCapacity(self.di_files.count());
26712587
26722588 for (self.di_files.keys()) |dif| {
2673 const dir_path = d: {
2674 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
2675 const dir_path = try dif.mod.root.joinString(arena, dif.mod.root.sub_path);
2676 const abs_dir_path = if (std.fs.path.isAbsolute(dir_path))
2677 dir_path
2678 else
2679 std.os.realpath(dir_path, &buffer) catch dir_path; // If realpath fails, fallback to whatever dir_path was
2680 break :d try std.fs.path.join(arena, &.{
2681 abs_dir_path, std.fs.path.dirname(dif.sub_file_path) orelse "",
2682 });
2683 };
2684 const sub_file_path = try arena.dupe(u8, std.fs.path.basename(dif.sub_file_path));
2589 const full_path = try dif.mod.root.joinString(arena, dif.sub_file_path);
2590 const dir_path = std.fs.path.dirname(full_path) orelse ".";
2591 const sub_file_path = std.fs.path.basename(full_path);
2592 // TODO re-investigate if realpath is needed here
2593 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
2594 const resolved = if (!std.fs.path.isAbsolute(dir_path))
2595 std.os.realpath(dir_path, &buffer) catch dir_path
2596 else
2597 dir_path;
26852598
26862599 const dir_index: u28 = blk: {
2687 const dirs_gop = dirs.getOrPutAssumeCapacity(dir_path);
2600 const dirs_gop = dirs.getOrPutAssumeCapacity(try arena.dupe(u8, resolved));
26882601 break :blk @as(u28, @intCast(dirs_gop.index + 1));
26892602 };
26902603
......@@ -2813,3 +2726,33 @@ fn getAtomPtr(self: *Dwarf, comptime kind: Kind, index: Atom.Index) *Atom {
28132726 .di_atom => &self.di_atoms.items[index],
28142727 };
28152728}
2729
2730pub const Format = enum {
2731 dwarf32,
2732 dwarf64,
2733};
2734
2735const Dwarf = @This();
2736
2737const std = @import("std");
2738const builtin = @import("builtin");
2739const assert = std.debug.assert;
2740const fs = std.fs;
2741const leb128 = std.leb;
2742const log = std.log.scoped(.dwarf);
2743const mem = std.mem;
2744
2745const link = @import("../link.zig");
2746const trace = @import("../tracy.zig").trace;
2747
2748const Allocator = mem.Allocator;
2749const DW = std.dwarf;
2750const File = link.File;
2751const LinkBlock = File.LinkBlock;
2752const LinkFn = File.LinkFn;
2753const LinkerLoad = @import("../codegen.zig").LinkerLoad;
2754const Module = @import("../Module.zig");
2755const InternPool = @import("../InternPool.zig");
2756const StringTable = @import("strtab.zig").StringTable;
2757const Type = @import("../type.zig").Type;
2758const Value = @import("../value.zig").Value;
src/link/Elf.zig+1-1
......@@ -310,7 +310,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
310310
311311 if (options.module != null and !options.use_llvm) {
312312 if (!options.strip) {
313 self.dwarf = Dwarf.init(allocator, &self.base, options.target);
313 self.dwarf = Dwarf.init(allocator, &self.base, .dwarf32);
314314 }
315315
316316 const index = @as(File.Index, @intCast(try self.files.addOne(allocator)));
src/link/MachO.zig+1-1
......@@ -206,7 +206,7 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
206206
207207 self.d_sym = .{
208208 .allocator = allocator,
209 .dwarf = link.File.Dwarf.init(allocator, &self.base, options.target),
209 .dwarf = link.File.Dwarf.init(allocator, &self.base, .dwarf32),
210210 .file = d_sym_file,
211211 };
212212 }
src/link/Wasm.zig+1-1
......@@ -507,7 +507,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
507507 }
508508
509509 // if (!options.strip and options.module != null) {
510 // wasm_bin.dwarf = Dwarf.init(allocator, &wasm_bin.base, options.target);
510 // wasm_bin.dwarf = Dwarf.init(allocator, &wasm_bin.base, .dwarf32);
511511 // try wasm_bin.initDebugSections();
512512 // }
513513