authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-18 23:14:23+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-19 21:56:47+02:00
log400faec10beed6c146bc562efab146be258471d7
tree19490d9fd5a0b66de4cb79974fc805d6c465314f
parent4f66efdc7f2158330b73f40a44b1f16b43c5318a

dwarf: introduce Dwarf.Format to be able to select 32/64bit format at whim


4 files changed, 115 insertions(+), 169 deletions(-)

src/link/Dwarf.zig+112-166
...@@ -1,32 +1,7 @@...@@ -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
26allocator: Allocator,1allocator: Allocator,
27bin_file: *File,2bin_file: *File,
3format: Format,
28ptr_width: PtrWidth,4ptr_width: PtrWidth,
29target: std.Target,
305
31/// A list of `Atom`s whose Line Number Programs have surplus capacity.6/// A list of `Atom`s whose Line Number Programs have surplus capacity.
32/// This is the same concept as `Section.free_list` in Elf; see those doc comments.7/// This is the same concept as `Section.free_list` in Elf; see those doc comments.
...@@ -983,17 +958,17 @@ const min_nop_size = 2;...@@ -983,17 +958,17 @@ const min_nop_size = 2;
983/// actual_capacity + (actual_capacity / ideal_factor)958/// actual_capacity + (actual_capacity / ideal_factor)
984const ideal_factor = 3;959const ideal_factor = 3;
985960
986pub fn init(allocator: Allocator, bin_file: *File, target: std.Target) Dwarf {961pub fn init(allocator: Allocator, bin_file: *File, format: Format) Dwarf {
987 const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {962 const ptr_width: PtrWidth = switch (bin_file.options.target.ptrBitWidth()) {
988 0...32 => .p32,963 0...32 => .p32,
989 33...64 => .p64,964 33...64 => .p64,
990 else => unreachable,965 else => unreachable,
991 };966 };
992 return Dwarf{967 return .{
993 .allocator = allocator,968 .allocator = allocator,
994 .bin_file = bin_file,969 .bin_file = bin_file,
970 .format = format,
995 .ptr_width = ptr_width,971 .ptr_width = ptr_width,
996 .target = target,
997 };972 };
998}973}
999974
...@@ -1129,7 +1104,7 @@ pub fn commitDeclState(...@@ -1129,7 +1104,7 @@ pub fn commitDeclState(
1129 const decl = mod.declPtr(decl_index);1104 const decl = mod.declPtr(decl_index);
1130 const ip = &mod.intern_pool;1105 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
1134 assert(decl.has_tv);1109 assert(decl.has_tv);
1135 switch (decl.ty.zigTypeTag(mod)) {1110 switch (decl.ty.zigTypeTag(mod)) {
...@@ -1837,12 +1812,10 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u...@@ -1837,12 +1812,10 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u
1837 var di_buf = try std.ArrayList(u8).initCapacity(self.allocator, needed_bytes);1812 var di_buf = try std.ArrayList(u8).initCapacity(self.allocator, needed_bytes);
1838 defer di_buf.deinit();1813 defer di_buf.deinit();
18391814
1840 const target_endian = self.target.cpu.arch.endian();1815 const target_endian = self.bin_file.options.target.cpu.arch.endian();
1841 const init_len_size: usize = if (self.bin_file.tag == .macho)1816 const init_len_size: usize = switch (self.format) {
1842 41817 .dwarf32 => 4,
1843 else switch (self.ptr_width) {1818 .dwarf64 => 12,
1844 .p32 => @as(usize, 4),
1845 .p64 => 12,
1846 };1819 };
18471820
1848 // initial length - length of the .debug_info contribution for this compilation unit,1821 // initial length - length of the .debug_info contribution for this compilation unit,
...@@ -1851,32 +1824,16 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u...@@ -1851,32 +1824,16 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u
1851 const after_init_len = di_buf.items.len + init_len_size;1824 const after_init_len = di_buf.items.len + init_len_size;
1852 const dbg_info_end = self.getDebugInfoEnd().?;1825 const dbg_info_end = self.getDebugInfoEnd().?;
1853 const init_len = dbg_info_end - after_init_len;1826 const init_len = dbg_info_end - after_init_len;
1854 if (self.bin_file.tag == .macho) {1827
1855 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(init_len)));1828 if (self.format == .dwarf64) di_buf.appendNTimesAssumeCapacity(0xff, 4);
1856 } else switch (self.ptr_width) {1829 self.writeOffsetAssumeCapacity(&di_buf, init_len);
1857 .p32 => {1830
1858 mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(init_len)), target_endian);
1859 },
1860 .p64 => {
1861 di_buf.appendNTimesAssumeCapacity(0xff, 4);
1862 mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), init_len, target_endian);
1863 },
1864 }
1865 mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 4, target_endian); // DWARF version1831 mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 4, target_endian); // DWARF version
1866 const abbrev_offset = self.abbrev_table_offset.?;1832 const abbrev_offset = self.abbrev_table_offset.?;
1867 if (self.bin_file.tag == .macho) {1833
1868 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(abbrev_offset)));1834 self.writeOffsetAssumeCapacity(&di_buf, abbrev_offset);
1869 di_buf.appendAssumeCapacity(8); // address size1835 di_buf.appendAssumeCapacity(self.ptrWidthBytes()); // address size
1870 } else switch (self.ptr_width) {1836
1871 .p32 => {
1872 mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(abbrev_offset)), target_endian);
1873 di_buf.appendAssumeCapacity(4); // address size
1874 },
1875 .p64 => {
1876 mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), abbrev_offset, target_endian);
1877 di_buf.appendAssumeCapacity(8); // address size
1878 },
1879 }
1880 // Write the form for the compile unit, which must match the abbrev table above.1837 // Write the form for the compile unit, which must match the abbrev table above.
1881 const name_strp = try self.strtab.insert(self.allocator, module.root_mod.root_src_path);1838 const name_strp = try self.strtab.insert(self.allocator, module.root_mod.root_src_path);
1882 var compile_unit_dir_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;1839 var compile_unit_dir_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
...@@ -1885,21 +1842,13 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u...@@ -1885,21 +1842,13 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u
1885 const producer_strp = try self.strtab.insert(self.allocator, link.producer_string);1842 const producer_strp = try self.strtab.insert(self.allocator, link.producer_string);
18861843
1887 di_buf.appendAssumeCapacity(@intFromEnum(AbbrevKind.compile_unit));1844 di_buf.appendAssumeCapacity(@intFromEnum(AbbrevKind.compile_unit));
1888 if (self.bin_file.tag == .macho) {1845 self.writeOffsetAssumeCapacity(&di_buf, 0); // DW.AT.stmt_list, DW.FORM.sec_offset
1889 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); // DW.AT.stmt_list, DW.FORM.sec_offset1846 self.writeAddrAssumeCapacity(&di_buf, low_pc);
1890 mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), low_pc);1847 self.writeAddrAssumeCapacity(&di_buf, high_pc);
1891 mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), high_pc);1848 self.writeOffsetAssumeCapacity(&di_buf, name_strp);
1892 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(name_strp)));1849 self.writeOffsetAssumeCapacity(&di_buf, comp_dir_strp);
1893 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(comp_dir_strp)));1850 self.writeOffsetAssumeCapacity(&di_buf, producer_strp);
1894 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(producer_strp)));1851
1895 } else {
1896 self.writeAddrAssumeCapacity(&di_buf, 0); // DW.AT.stmt_list, DW.FORM.sec_offset
1897 self.writeAddrAssumeCapacity(&di_buf, low_pc);
1898 self.writeAddrAssumeCapacity(&di_buf, high_pc);
1899 self.writeAddrAssumeCapacity(&di_buf, name_strp);
1900 self.writeAddrAssumeCapacity(&di_buf, comp_dir_strp);
1901 self.writeAddrAssumeCapacity(&di_buf, producer_strp);
1902 }
1903 // We are still waiting on dwarf-std.org to assign DW_LANG_Zig a number:1852 // We are still waiting on dwarf-std.org to assign DW_LANG_Zig a number:
1904 // http://dwarfstd.org/ShowIssue.php?issue=171115.11853 // http://dwarfstd.org/ShowIssue.php?issue=171115.1
1905 // Until then we say it is C99.1854 // Until then we say it is C99.
...@@ -1952,13 +1901,26 @@ fn resolveCompilationDir(module: *Module, buffer: *[std.fs.MAX_PATH_BYTES]u8) []...@@ -1952,13 +1901,26 @@ fn resolveCompilationDir(module: *Module, buffer: *[std.fs.MAX_PATH_BYTES]u8) []
1952}1901}
19531902
1954fn writeAddrAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), addr: u64) void {1903fn writeAddrAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), addr: u64) void {
1955 const target_endian = self.target.cpu.arch.endian();1904 const target_endian = self.bin_file.options.target.cpu.arch.endian();
1956 switch (self.ptr_width) {1905 switch (self.ptr_width) {
1957 .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(addr)), target_endian),1906 .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(addr)), target_endian),
1958 .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian),1907 .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian),
1959 }1908 }
1960}1909}
19611910
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
1962/// Writes to the file a buffer, prefixed and suffixed by the specified number of1924/// Writes to the file a buffer, prefixed and suffixed by the specified number of
1963/// bytes of NOPs. Asserts each padding size is at least `min_nop_size` and total padding bytes1925/// bytes of NOPs. Asserts each padding size is at least `min_nop_size` and total padding bytes
1964/// are less than 1044480 bytes (if this limit is ever reached, this function can be1926/// are less than 1044480 bytes (if this limit is ever reached, this function can be
...@@ -2174,13 +2136,7 @@ fn writeDbgInfoNopsToArrayList(...@@ -2174,13 +2136,7 @@ fn writeDbgInfoNopsToArrayList(
2174}2136}
21752137
2176pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {2138pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
2177 const target_endian = self.target.cpu.arch.endian();2139 const target_endian = self.bin_file.options.target.cpu.arch.endian();
2178 const init_len_size: usize = if (self.bin_file.tag == .macho)
2179 4
2180 else switch (self.ptr_width) {
2181 .p32 => @as(usize, 4),
2182 .p64 => 12,
2183 };
2184 const ptr_width_bytes = self.ptrWidthBytes();2140 const ptr_width_bytes = self.ptrWidthBytes();
21852141
2186 // Enough for all the data without resizing. When support for more compilation units2142 // Enough for all the data without resizing. When support for more compilation units
...@@ -2191,17 +2147,15 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {...@@ -2191,17 +2147,15 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
2191 // initial length - length of the .debug_aranges contribution for this compilation unit,2147 // initial length - length of the .debug_aranges contribution for this compilation unit,
2192 // not including the initial length itself.2148 // not including the initial length itself.
2193 // We have to come back and write it later after we know the size.2149 // We have to come back and write it later after we know the size.
2150 if (self.format == .dwarf64) di_buf.appendNTimesAssumeCapacity(0xff, 4);
2194 const init_len_index = di_buf.items.len;2151 const init_len_index = di_buf.items.len;
2195 di_buf.items.len += init_len_size;2152 self.writeOffsetAssumeCapacity(&di_buf, 0);
2196 const after_init_len = di_buf.items.len;2153 const after_init_len = di_buf.items.len;
2197 mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 2, target_endian); // version2154 mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 2, target_endian); // version
2155
2198 // When more than one compilation unit is supported, this will be the offset to it.2156 // When more than one compilation unit is supported, this will be the offset to it.
2199 // For now it is always at offset 0 in .debug_info.2157 // For now it is always at offset 0 in .debug_info.
2200 if (self.bin_file.tag == .macho) {2158 self.writeOffsetAssumeCapacity(&di_buf, 0); // .debug_info offset
2201 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); // __debug_info offset
2202 } else {
2203 self.writeAddrAssumeCapacity(&di_buf, 0); // .debug_info offset
2204 }
2205 di_buf.appendAssumeCapacity(ptr_width_bytes); // address_size2159 di_buf.appendAssumeCapacity(ptr_width_bytes); // address_size
2206 di_buf.appendAssumeCapacity(0); // segment_selector_size2160 di_buf.appendAssumeCapacity(0); // segment_selector_size
22072161
...@@ -2220,18 +2174,14 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {...@@ -2220,18 +2174,14 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
22202174
2221 // Go back and populate the initial length.2175 // Go back and populate the initial length.
2222 const init_len = di_buf.items.len - after_init_len;2176 const init_len = di_buf.items.len - after_init_len;
2223 if (self.bin_file.tag == .macho) {2177 switch (self.format) {
2224 mem.writeIntLittle(u32, di_buf.items[init_len_index..][0..4], @as(u32, @intCast(init_len)));2178 .dwarf32 => mem.writeInt(
2225 } else switch (self.ptr_width) {2179 u32,
2226 .p32 => {2180 di_buf.items[init_len_index..][0..4],
2227 mem.writeInt(u32, di_buf.items[init_len_index..][0..4], @as(u32, @intCast(init_len)), target_endian);2181 @as(u32, @intCast(init_len)),
2228 },2182 target_endian,
2229 .p64 => {2183 ),
2230 // initial length - length of the .debug_aranges contribution for this compilation unit,2184 .dwarf64 => mem.writeInt(u64, di_buf.items[init_len_index..][0..8], init_len, target_endian),
2231 // not including the initial length itself.
2232 di_buf.items[init_len_index..][0..4].* = [_]u8{ 0xff, 0xff, 0xff, 0xff };
2233 mem.writeInt(u64, di_buf.items[init_len_index + 4 ..][0..8], init_len, target_endian);
2234 },
2235 }2185 }
22362186
2237 const needed_size = @as(u32, @intCast(di_buf.items.len));2187 const needed_size = @as(u32, @intCast(di_buf.items.len));
...@@ -2265,12 +2215,10 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {...@@ -2265,12 +2215,10 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
2265pub fn writeDbgLineHeader(self: *Dwarf) !void {2215pub fn writeDbgLineHeader(self: *Dwarf) !void {
2266 const gpa = self.allocator;2216 const gpa = self.allocator;
22672217
2268 const target_endian = self.target.cpu.arch.endian();2218 const target_endian = self.bin_file.options.target.cpu.arch.endian();
2269 const init_len_size: usize = if (self.bin_file.tag == .macho)2219 const init_len_size: usize = switch (self.format) {
2270 42220 .dwarf32 => 4,
2271 else switch (self.ptr_width) {2221 .dwarf64 => 12,
2272 .p32 => @as(usize, 4),
2273 .p64 => 12,
2274 };2222 };
22752223
2276 const dbg_line_prg_off = self.getDebugLineProgramOff() orelse return;2224 const dbg_line_prg_off = self.getDebugLineProgramOff() orelse return;
...@@ -2288,20 +2236,8 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2288,20 +2236,8 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
2288 var di_buf = try std.ArrayList(u8).initCapacity(gpa, needed_bytes);2236 var di_buf = try std.ArrayList(u8).initCapacity(gpa, needed_bytes);
2289 defer di_buf.deinit();2237 defer di_buf.deinit();
22902238
2291 switch (self.bin_file.tag) {2239 if (self.format == .dwarf64) di_buf.appendNTimesAssumeCapacity(0xff, 4);
2292 .macho => {2240 self.writeOffsetAssumeCapacity(&di_buf, 0);
2293 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, 0));
2294 },
2295 else => switch (self.ptr_width) {
2296 .p32 => {
2297 mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, 0), target_endian);
2298 },
2299 .p64 => {
2300 di_buf.appendNTimesAssumeCapacity(0xff, 4);
2301 mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), @as(u64, 0), target_endian);
2302 },
2303 },
2304 }
23052241
2306 mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 4, target_endian); // version2242 mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 4, target_endian); // version
23072243
...@@ -2310,16 +2246,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2310,16 +2246,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
2310 // Therefore we rely on the NOP jump at the beginning of the Line Number Program for2246 // Therefore we rely on the NOP jump at the beginning of the Line Number Program for
2311 // padding rather than this field.2247 // padding rather than this field.
2312 const before_header_len = di_buf.items.len;2248 const before_header_len = di_buf.items.len;
23132249 self.writeOffsetAssumeCapacity(&di_buf, 0); // We will come back and write this.
2314 // We will come back and write this.
2315 switch (self.bin_file.tag) {
2316 .macho => di_buf.appendNTimesAssumeCapacity(0, 4),
2317 else => switch (self.ptr_width) {
2318 .p32 => di_buf.appendNTimesAssumeCapacity(0, 4),
2319 .p64 => di_buf.appendNTimesAssumeCapacity(0, 8),
2320 },
2321 }
2322
2323 const after_header_len = di_buf.items.len;2250 const after_header_len = di_buf.items.len;
23242251
2325 const opcode_base = DW.LNS.set_isa + 1;2252 const opcode_base = DW.LNS.set_isa + 1;
...@@ -2372,19 +2299,14 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2372,19 +2299,14 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
2372 di_buf.appendAssumeCapacity(0); // file names sentinel2299 di_buf.appendAssumeCapacity(0); // file names sentinel
23732300
2374 const header_len = di_buf.items.len - after_header_len;2301 const header_len = di_buf.items.len - after_header_len;
23752302 switch (self.format) {
2376 switch (self.bin_file.tag) {2303 .dwarf32 => mem.writeInt(
2377 .macho => {2304 u32,
2378 mem.writeIntLittle(u32, di_buf.items[before_header_len..][0..4], @as(u32, @intCast(header_len)));2305 di_buf.items[before_header_len..][0..4],
2379 },2306 @as(u32, @intCast(header_len)),
2380 else => switch (self.ptr_width) {2307 target_endian,
2381 .p32 => {2308 ),
2382 mem.writeInt(u32, di_buf.items[before_header_len..][0..4], @as(u32, @intCast(header_len)), target_endian);2309 .dwarf64 => mem.writeInt(u64, di_buf.items[before_header_len..][0..8], 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 },
2388 }2310 }
23892311
2390 assert(needed_bytes == di_buf.items.len);2312 assert(needed_bytes == di_buf.items.len);
...@@ -2453,17 +2375,12 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2453,17 +2375,12 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
24532375
2454 // Backpatch actual length of the debug line program2376 // Backpatch actual length of the debug line program
2455 const init_len = self.getDebugLineProgramEnd().? - init_len_size;2377 const init_len = self.getDebugLineProgramEnd().? - init_len_size;
2456 switch (self.bin_file.tag) {2378 switch (self.format) {
2457 .macho => {2379 .dwarf32 => {
2458 mem.writeIntLittle(u32, di_buf.items[0..4], @as(u32, @intCast(init_len)));2380 mem.writeInt(u32, di_buf.items[0..4], @as(u32, @intCast(init_len)), target_endian);
2459 },2381 },
2460 else => switch (self.ptr_width) {2382 .dwarf64 => {
2461 .p32 => {2383 mem.writeInt(u64, di_buf.items[4..][0..8], init_len, target_endian);
2462 mem.writeInt(u32, di_buf.items[0..4], @as(u32, @intCast(init_len)), target_endian);
2463 },
2464 .p64 => {
2465 mem.writeInt(u64, di_buf.items[4..][0..8], init_len, target_endian);
2466 },
2467 },2384 },
2468 }2385 }
24692386
...@@ -2524,17 +2441,14 @@ fn ptrWidthBytes(self: Dwarf) u8 {...@@ -2524,17 +2441,14 @@ fn ptrWidthBytes(self: Dwarf) u8 {
2524}2441}
25252442
2526fn dbgLineNeededHeaderBytes(self: Dwarf, dirs: []const []const u8, files: []const []const u8) u32 {2443fn dbgLineNeededHeaderBytes(self: Dwarf, dirs: []const []const u8, files: []const []const u8) u32 {
2527 var size = switch (self.bin_file.tag) { // length field2444 var size: usize = switch (self.format) { // length field
2528 .macho => @sizeOf(u32),2445 .dwarf32 => @as(usize, 4),
2529 else => switch (self.ptr_width) {2446 .dwarf64 => 12,
2530 .p32 => @as(usize, @sizeOf(u32)),
2531 .p64 => @sizeOf(u32) + @sizeOf(u64),
2532 },
2533 };2447 };
2534 size += @sizeOf(u16); // version field2448 size += @sizeOf(u16); // version field
2535 size += switch (self.bin_file.tag) { // offset to end-of-header2449 size += switch (self.format) { // offset to end-of-header
2536 .macho => @sizeOf(u32),2450 .dwarf32 => @as(usize, 4),
2537 else => self.ptrWidthBytes(),2451 .dwarf64 => 8,
2538 };2452 };
2539 size += 18; // opcodes2453 size += 18; // opcodes
25402454
...@@ -2570,6 +2484,8 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {...@@ -2570,6 +2484,8 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
2570}2484}
25712485
2572pub fn flushModule(self: *Dwarf, module: *Module) !void {2486pub fn flushModule(self: *Dwarf, module: *Module) !void {
2487 const target = self.bin_file.options.target;
2488
2573 if (self.global_abbrev_relocs.items.len > 0) {2489 if (self.global_abbrev_relocs.items.len > 0) {
2574 const gpa = self.allocator;2490 const gpa = self.allocator;
2575 var arena_alloc = std.heap.ArenaAllocator.init(gpa);2491 var arena_alloc = std.heap.ArenaAllocator.init(gpa);
...@@ -2581,7 +2497,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {...@@ -2581,7 +2497,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
2581 module,2497 module,
2582 Type.anyerror,2498 Type.anyerror,
2583 module.global_error_set.keys(),2499 module.global_error_set.keys(),
2584 self.target,2500 target,
2585 &dbg_info_buffer,2501 &dbg_info_buffer,
2586 );2502 );
25872503
...@@ -2610,7 +2526,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {...@@ -2610,7 +2526,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
2610 };2526 };
26112527
2612 var buf: [@sizeOf(u32)]u8 = undefined;2528 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
2615 while (self.global_abbrev_relocs.popOrNull()) |reloc| {2531 while (self.global_abbrev_relocs.popOrNull()) |reloc| {
2616 const atom = self.getAtom(.di_atom, reloc.atom_index);2532 const atom = self.getAtom(.di_atom, reloc.atom_index);
...@@ -2805,3 +2721,33 @@ fn getAtomPtr(self: *Dwarf, comptime kind: Kind, index: Atom.Index) *Atom {...@@ -2805,3 +2721,33 @@ fn getAtomPtr(self: *Dwarf, comptime kind: Kind, index: Atom.Index) *Atom {
2805 .di_atom => &self.di_atoms.items[index],2721 .di_atom => &self.di_atoms.items[index],
2806 };2722 };
2807}2723}
2724
2725pub const Format = enum {
2726 dwarf32,
2727 dwarf64,
2728};
2729
2730const Dwarf = @This();
2731
2732const std = @import("std");
2733const builtin = @import("builtin");
2734const assert = std.debug.assert;
2735const fs = std.fs;
2736const leb128 = std.leb;
2737const log = std.log.scoped(.dwarf);
2738const mem = std.mem;
2739
2740const link = @import("../link.zig");
2741const trace = @import("../tracy.zig").trace;
2742
2743const Allocator = mem.Allocator;
2744const DW = std.dwarf;
2745const File = link.File;
2746const LinkBlock = File.LinkBlock;
2747const LinkFn = File.LinkFn;
2748const LinkerLoad = @import("../codegen.zig").LinkerLoad;
2749const Module = @import("../Module.zig");
2750const InternPool = @import("../InternPool.zig");
2751const StringTable = @import("strtab.zig").StringTable;
2752const Type = @import("../type.zig").Type;
2753const 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...@@ -310,7 +310,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
310310
311 if (options.module != null and !options.use_llvm) {311 if (options.module != null and !options.use_llvm) {
312 if (!options.strip) {312 if (!options.strip) {
313 self.dwarf = Dwarf.init(allocator, &self.base, options.target);313 self.dwarf = Dwarf.init(allocator, &self.base, .dwarf32);
314 }314 }
315315
316 const index = @as(File.Index, @intCast(try self.files.addOne(allocator)));316 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 {...@@ -206,7 +206,7 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
206206
207 self.d_sym = .{207 self.d_sym = .{
208 .allocator = allocator,208 .allocator = allocator,
209 .dwarf = link.File.Dwarf.init(allocator, &self.base, options.target),209 .dwarf = link.File.Dwarf.init(allocator, &self.base, .dwarf32),
210 .file = d_sym_file,210 .file = d_sym_file,
211 };211 };
212 }212 }
src/link/Wasm.zig+1-1
...@@ -507,7 +507,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -507,7 +507,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
507 }507 }
508508
509 // if (!options.strip and options.module != null) {509 // 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);
511 // try wasm_bin.initDebugSections();511 // try wasm_bin.initDebugSections();
512 // }512 // }
513513