authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-07 19:37:01-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-07 19:53:17-04:00
loga059c9a5e57164338bf4b99728905882b0d6323c
treef88220844871861ef457de9ca3ed8aaf17a87089
parent5637ede041a9b8b0a050343be5392f97994f6777

Dwarf2: use indexed addresses

This saves another ~70MB.

3 files changed, 229 insertions(+), 59 deletions(-)

src/codegen/x86_64/Emit.zig+18-13
......@@ -552,9 +552,9 @@ pub fn emitMir(emit: *Emit) Error!void {
552552 .pseudo_dbg_var_m,
553553 => switch (emit.debug_output) {
554554 inline .dwarf, .dwarf2 => |dwarf, tag| {
555 const DwarfLoc = switch (tag) {
556 .dwarf => link.File.Dwarf.Loc,
557 .dwarf2 => link.File.Dwarf2.Loc,
555 const DwarfLoc, const addr_loc = switch (tag) {
556 .dwarf => .{ link.File.Dwarf.Loc, "addr_reloc" },
557 .dwarf2 => .{ link.File.Dwarf2.Loc, "addrx_sym" },
558558 .eh_frame, .none => comptime unreachable,
559559 };
560560 var loc_buf: [2]DwarfLoc = undefined;
......@@ -597,16 +597,21 @@ pub fn emitMir(emit: *Emit) Error!void {
597597 .none => .{ .constu = 0 },
598598 .reg => |reg| .{ .breg = reg.dwarfNum() },
599599 .frame, .table, .rip_inst => unreachable,
600 .nav => |nav| .{ .addr_reloc = try codegen.genNavRef(
601 emit.bin_file,
602 emit.pt,
603 nav,
604 ) },
605 .uav => |uav| .{ .addr_reloc = try emit.bin_file.lowerUav(
606 emit.pt,
607 uav.val,
608 Type.fromInterned(uav.orig_ty).ptrAlignment(emit.pt.zcu),
609 ) },
600 .nav => |nav| @unionInit(
601 DwarfLoc,
602 addr_loc,
603 try codegen.genNavRef(emit.bin_file, emit.pt, nav),
604 ),
605 .uav => |uav| @unionInit(
606 DwarfLoc,
607 addr_loc,
608 try emit.bin_file.lowerUav(
609 emit.pt,
610 uav.val,
611 Type.fromInterned(uav.orig_ty)
612 .ptrAlignment(emit.pt.zcu),
613 ),
614 ),
610615 .lazy_sym, .extern_func => unreachable,
611616 };
612617 break :base &loc_buf[0];
src/link/Dwarf2.zig+108-28
......@@ -13,6 +13,7 @@ decls: std.array_hash_map.Auto(InternPool.TrackedInst.Index, Decl),
1313pending_decl: struct { di: Decl.Index, instance: Decl.Instance },
1414
1515debug_abbrev: Abbrev,
16debug_addr: Addr,
1617frame: Frame,
1718debug_info: Info,
1819debug_line: Line,
......@@ -182,6 +183,29 @@ pub const Abbrev = struct {
182183 set: std.enums.EnumSet(AbbrevCode),
183184};
184185
186pub const Addr = struct {
187 ni: link.MappedFile.Node.Index.Optional,
188 pending_index: usize,
189 map: std.array_hash_map.Auto(link.File.SymbolId, void),
190
191 fn get(a: *Addr, gpa: std.mem.Allocator, si: link.File.SymbolId) std.mem.Allocator.Error!usize {
192 const gop = try a.map.getOrPut(gpa, si);
193 return gop.index;
194 }
195
196 fn tableOffset(dwarf: *Dwarf) usize {
197 return dwarf.unitLengthSize() + 2 + 1 + 1;
198 }
199
200 pub fn size(a: *Addr, dwarf: *Dwarf) usize {
201 return tableOffset(dwarf) + @backingInt(dwarf.address_size) * a.pending_index;
202 }
203
204 pub fn anyPending(a: *Addr) bool {
205 return a.map.count() - a.pending_index > 0;
206 }
207};
208
185209pub const Info = struct {};
186210
187211pub const Line = struct {
......@@ -274,12 +298,14 @@ pub const StrOffsets = struct {
274298 ) link.Error!usize {
275299 const comp = dwarf.lf.comp;
276300 try so.map.ensureUnusedCapacity(comp.gpa, 1);
277 return so.map.getOrPutAssumeCapacity(s.get(comp.gpa, mf, str) catch |err| switch (err) {
301 const offset = s.get(comp.gpa, mf, str) catch |err| switch (err) {
278302 else => |e| return e,
279303 error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{
280304 mf.io_err.?,
281305 }),
282 }).index;
306 };
307 const gop = so.map.getOrPutAssumeCapacity(offset);
308 return gop.index;
283309 }
284310
285311 fn tableOffset(dwarf: *Dwarf) usize {
......@@ -289,13 +315,20 @@ pub const StrOffsets = struct {
289315 pub fn size(so: *StrOffsets, dwarf: *Dwarf) usize {
290316 return tableOffset(dwarf) + dwarf.secOffsetSize() * so.pending_index;
291317 }
318
319 pub fn anyPending(so: *StrOffsets) bool {
320 return so.map.count() - so.pending_index > 0;
321 }
292322};
293323
294324pub const SharedSection = enum { debug_abbrev, debug_line_str, debug_str };
295325
296326pub const Loc = union(enum) {
297327 empty,
298 addr_reloc: link.File.SymbolId,
328 addr_sym: struct {
329 si: link.File.SymbolId,
330 offset: usize = 0,
331 },
299332 deref: *const Loc,
300333 constu: u64,
301334 consts: i64,
......@@ -314,6 +347,8 @@ pub const Loc = union(enum) {
314347 node: link.MappedFile.Node.Index,
315348 offset: i65 = 0,
316349 },
350 addrx_sym: link.File.SymbolId,
351 constx_sym: link.File.SymbolId,
317352 wasm_ext: union(enum) {
318353 local: u32,
319354 global: u32,
......@@ -356,11 +391,11 @@ pub const Loc = union(enum) {
356391 };
357392 switch (loc) {
358393 .empty => {},
359 .addr_reloc => |si| {
394 .addr_sym => |sym| {
360395 try w.writeByte(DW.OP.addr);
361396 switch (writer) {
362397 .io => try dwarf.addrPlaceholder(w),
363 .mf => |nw| try dwarf.addrSym(nw, si, 0),
398 .mf => |nw| try dwarf.addrSym(nw, sym.si, sym.offset),
364399 }
365400 },
366401 .deref => |addr| {
......@@ -479,6 +514,14 @@ pub const Loc = union(enum) {
479514 }
480515 try w.writeSleb128(implicit_pointer.offset);
481516 },
517 .addrx_sym => |si| {
518 try w.writeByte(DW.OP.addrx);
519 try dwarf.addrxSym(w, si);
520 },
521 .constx_sym => |si| {
522 try w.writeByte(DW.OP.constx);
523 try dwarf.addrxSym(w, si);
524 },
482525 .wasm_ext => |wasm_ext| {
483526 try w.writeByte(DW.OP.WASM_location);
484527 switch (wasm_ext) {
......@@ -731,14 +774,16 @@ pub const WipFunc = struct {
731774 .@"extern", .@"export" => nav.name,
732775 }.toSlice(ip));
733776 try dwarf.refType(pt, di_nw, .fromInterned(func_type.return_type));
734 try dwarf.addrSym(di_nw, debug.wip_func.func_si, 0);
777 try dwarf.addrxSym(di_w, debug.wip_func.func_si);
735778 debug.info_func_length_offset = di_w.end;
736779 try di_w.writeInt(u32, undefined, dwarf.endian);
737780 try di_w.writeUleb128(
738781 target_info.minFunctionAlignment(target).max(nav.resolved.?.@"align").toByteUnits().?,
739782 );
740 try di_w.writeByte(@intFromBool(decl.linkage != .normal));
741 try di_w.writeByte(@intFromBool(Type.fromInterned(func_type.return_type).isNoReturn(zcu)));
783 try di_w.writeAll(&.{
784 @intFromBool(decl.linkage != .normal),
785 @intFromBool(Type.fromInterned(func_type.return_type).isNoReturn(zcu)),
786 });
742787 }
743788
744789 pub fn startDebugLine(debug: *Debug) link.Error!void {
......@@ -1284,6 +1329,11 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {
12841329 .end = 0,
12851330 .set = .empty,
12861331 },
1332 .debug_addr = .{
1333 .ni = .none,
1334 .pending_index = 0,
1335 .map = .empty,
1336 },
12871337 .frame = .{
12881338 .header = if (target.cpu.arch == .x86_64 and target.ofmt == .elf) header: {
12891339 dev.checkAny(&.{ .llvm_backend, .x86_64_backend });
......@@ -1353,6 +1403,7 @@ pub fn deinit(dwarf: *Dwarf) void {
13531403 dwarf.globals.deinit(gpa);
13541404 dwarf.funcs.deinit(gpa);
13551405 dwarf.decls.deinit(gpa);
1406 dwarf.debug_addr.map.deinit(gpa);
13561407 dwarf.debug_line_str.map.deinit(gpa);
13571408 dwarf.debug_str.map.deinit(gpa);
13581409 dwarf.debug_str_offsets.map.deinit(gpa);
......@@ -1620,6 +1671,24 @@ pub fn genUnitPadding(dwarf: *Dwarf, w: *std.Io.Writer) std.Io.Writer.Error!void
16201671 try w.writeInt(u16, 0, dwarf.endian);
16211672}
16221673
1674pub fn genDebugAddrHeader(dwarf: *Dwarf, dah_w: *std.Io.Writer) std.Io.Writer.Error!void {
1675 try dwarf.genUnitLength(dah_w);
1676 try dah_w.writeInt(u16, 5, dwarf.endian);
1677 try dah_w.writeAll(&.{ @backingInt(dwarf.address_size), 0 });
1678 assert(dah_w.end == Addr.tableOffset(dwarf));
1679}
1680
1681pub fn genPendingDebugAddr(dwarf: *Dwarf, da_nw: *link.MappedFile.Node.Writer) link.Error!void {
1682 da_nw.interface.end = dwarf.debug_addr.size(dwarf);
1683 for (dwarf.debug_addr.map.keys()[dwarf.debug_addr.pending_index..]) |si| {
1684 dwarf.addrSym(da_nw, si, 0) catch |err| switch (err) {
1685 else => |e| return e,
1686 error.WriteFailed => return dwarf.reportWriteError(da_nw),
1687 };
1688 dwarf.debug_addr.pending_index += 1;
1689 }
1690}
1691
16231692pub const EhFrameHdr = extern struct {
16241693 version: u8,
16251694 eh_frame_ptr_enc: std.dwarf.EH.PE,
......@@ -1675,11 +1744,7 @@ pub fn genDebugFrameCie(
16751744 const Register = @import("../codegen/x86_64/bits.zig").Register;
16761745 switch (format) {
16771746 .eh_frame => try df_w.writeAll("zR\x00"),
1678 .debug_frame => {
1679 try df_w.writeAll("\x00");
1680 try df_w.writeByte(@backingInt(dwarf.address_size));
1681 try df_w.writeByte(0);
1682 },
1747 .debug_frame => try df_w.writeAll("\x00" ++ .{ @backingInt(dwarf.address_size), 0 }),
16831748 }
16841749 try df_w.writeUleb128(dwarf.frame.header.code_alignment_factor);
16851750 try df_w.writeSleb128(dwarf.frame.header.data_alignment_factor);
......@@ -1726,8 +1791,7 @@ pub fn genDebugInfoHeader(
17261791 if (!unit.alive) return dwarf.genUnitPadding(dih_w);
17271792 try dwarf.genUnitLength(dih_w);
17281793 try dih_w.writeInt(u16, 5, dwarf.endian);
1729 try dih_w.writeByte(DW.UT.compile);
1730 try dih_w.writeByte(@backingInt(dwarf.address_size));
1794 try dih_w.writeAll(&.{ DW.UT.compile, @backingInt(dwarf.address_size) });
17311795 try dwarf.secOffset(dih_nw, dwarf.debug_abbrev.ni.unwrap().?, 0);
17321796 const compile_unit_offset = dih_w.end;
17331797 try dwarf.abbrevCode(dih_nw, .compile_unit);
......@@ -1738,6 +1802,7 @@ pub fn genDebugInfoHeader(
17381802 compile_unit_offset,
17391803 );
17401804 try dwarf.secOffset(dih_nw, unit.debug_line_header_ni.unwrap().?, 0);
1805 try dwarf.secOffset(dih_nw, dwarf.debug_addr.ni.unwrap().?, Addr.tableOffset(dwarf));
17411806 try dwarf.secOffset(dih_nw, unit.debug_rnglists_ni.unwrap().?, Rnglists.tableOffset(dwarf));
17421807 try dwarf.secOffset(dih_nw, dwarf.debug_str_offsets.ni.unwrap().?, StrOffsets.tableOffset(dwarf));
17431808 try dwarf.strx1(dih_nw, "zig " ++ @import("build_options").version);
......@@ -1818,8 +1883,7 @@ pub fn genDebugLineHeader(
18181883 const dlh_w = &dlh_nw.interface;
18191884 try dwarf.genUnitLength(dlh_w);
18201885 try dlh_w.writeInt(u16, 5, dwarf.endian);
1821 try dlh_w.writeByte(@backingInt(dwarf.address_size));
1822 try dlh_w.writeByte(0);
1886 try dlh_w.writeAll(&.{ @backingInt(dwarf.address_size), 0 });
18231887 const header_length_offset = dlh_w.end;
18241888 switch (dwarf.format) {
18251889 .@"32" => try dlh_w.writeInt(u32, undefined, dwarf.endian),
......@@ -1950,8 +2014,7 @@ pub fn genDebugRnglistsHeader(
19502014 const drh_w = &drh_nw.interface;
19512015 try dwarf.genUnitLength(drh_w);
19522016 try drh_w.writeInt(u16, 5, dwarf.endian);
1953 try drh_w.writeByte(@backingInt(dwarf.address_size));
1954 try drh_w.writeByte(0);
2017 try drh_w.writeAll(&.{ @backingInt(dwarf.address_size), 0 });
19552018 try drh_w.writeInt(u32, 1, dwarf.endian);
19562019 assert(drh_w.end == Rnglists.tableOffset(dwarf));
19572020 switch (dwarf.format) {
......@@ -1971,8 +2034,8 @@ pub fn genDebugRnglistsRange(
19712034) link.EmitError!void {
19722035 const dr_w = &dr_nw.interface;
19732036 dr_w.end = unit.debug_rnglists_end;
1974 try dr_w.writeByte(DW.RLE.start_length);
1975 try dwarf.addrSym(dr_nw, func_si, 0);
2037 try dr_w.writeByte(DW.RLE.startx_length);
2038 try dwarf.addrxSym(dr_w, func_si);
19762039 try dr_w.writeUleb128(func_length);
19772040 unit.debug_rnglists_end = dr_w.end;
19782041 try dr_w.writeByte(DW.RLE.end_of_list);
......@@ -1986,9 +2049,10 @@ pub fn genDebugStrOffsetsHeader(dwarf: *Dwarf, dsoh_w: *std.Io.Writer) std.Io.Wr
19862049}
19872050
19882051pub fn genPendingDebugStrOffsets(dwarf: *Dwarf, dso_nw: *link.MappedFile.Node.Writer) link.Error!void {
2052 const debug_str_ni = dwarf.debug_str.ni.unwrap().?;
19892053 dso_nw.interface.end = dwarf.debug_str_offsets.size(dwarf);
19902054 for (dwarf.debug_str_offsets.map.keys()[dwarf.debug_str_offsets.pending_index..]) |offset| {
1991 dwarf.secOffset(dso_nw, dwarf.debug_str.ni.unwrap().?, offset) catch |err| switch (err) {
2055 dwarf.secOffset(dso_nw, debug_str_ni, offset) catch |err| switch (err) {
19922056 else => |e| return e,
19932057 error.WriteFailed => return dwarf.reportWriteError(dso_nw),
19942058 };
......@@ -2081,7 +2145,7 @@ fn updateExternInner(
20812145 if (func_type.is_var_args) try dwarf.abbrevCode(di_nw, .is_var_args);
20822146 if (!is_empty) try di_w.writeUleb128(@backingInt(AbbrevCode.null));
20832147 } else {
2084 const addr: Loc = .{ .addr_reloc = si };
2148 const addr: Loc = .{ .addr_sym = .{ .si = si } };
20852149 const loc: Loc = if (nav_threadlocal) switch (arch) {
20862150 .x86_64 => .{ .form_tls_address = &addr },
20872151 else => unreachable,
......@@ -2169,7 +2233,7 @@ fn updateGlobalInner(
21692233 .@"extern" => unreachable,
21702234 .@"export" => nav.name,
21712235 }.toSlice(ip));
2172 const addr: Loc = .{ .addr_reloc = si };
2236 const addr: Loc = .{ .addr_sym = .{ .si = si } };
21732237 const loc: Loc = if (nav_threadlocal) switch (arch) {
21742238 .x86_64 => .{ .form_tls_address = &addr },
21752239 else => unreachable,
......@@ -4403,6 +4467,21 @@ fn addrSym(
44034467 .absAddr(elf),
44044468 ) else unreachable;
44054469}
4470fn addrxSym(dwarf: *Dwarf, w: *std.Io.Writer, si: link.File.SymbolId) link.EmitError!void {
4471 try w.writeUleb128(try dwarf.debug_addr.get(dwarf.lf.comp.gpa, si));
4472}
4473fn addrx1Sym(dwarf: *Dwarf, w: *std.Io.Writer, si: link.File.SymbolId) link.EmitError!void {
4474 try w.writeByte(@intCast(try dwarf.debug_addr.get(dwarf.lf.comp.gpa, si)));
4475}
4476fn addrx2Sym(dwarf: *Dwarf, w: *std.Io.Writer, si: link.File.SymbolId) link.EmitError!void {
4477 try w.writeInt(u16, @intCast(try dwarf.debug_addr.get(dwarf.lf.comp.gpa, si)), dwarf.endian);
4478}
4479fn addrx3Sym(dwarf: *Dwarf, w: *std.Io.Writer, si: link.File.SymbolId) link.EmitError!void {
4480 try w.writeInt(u24, @intCast(try dwarf.debug_addr.get(dwarf.lf.comp.gpa, si)), dwarf.endian);
4481}
4482fn addrx4Sym(dwarf: *Dwarf, w: *std.Io.Writer, si: link.File.SymbolId) link.EmitError!void {
4483 try w.writeInt(u32, @intCast(try dwarf.debug_addr.get(dwarf.lf.comp.gpa, si)), dwarf.endian);
4484}
44064485
44074486fn blockConst(
44084487 dwarf: *Dwarf,
......@@ -5072,7 +5151,7 @@ pub const AbbrevCode = enum {
50725151 .attrs = decl_attrs ++ .{
50735152 .{ .linkage_name, .strx },
50745153 .{ .type, .ref_addr },
5075 .{ .low_pc, .addr },
5154 .{ .low_pc, .addrx },
50765155 .{ .high_pc, .data4 },
50775156 .{ .alignment, .udata },
50785157 .{ .external, .flag },
......@@ -5085,7 +5164,7 @@ pub const AbbrevCode = enum {
50855164 .attrs = decl_attrs ++ .{
50865165 .{ .linkage_name, .strx },
50875166 .{ .type, .ref_addr },
5088 .{ .low_pc, .addr },
5167 .{ .low_pc, .addrx },
50895168 .{ .high_pc, .data4 },
50905169 .{ .alignment, .udata },
50915170 .{ .external, .flag },
......@@ -5353,7 +5432,7 @@ pub const AbbrevCode = enum {
53535432 .attrs = decl_instance_attrs ++ .{
53545433 .{ .linkage_name, .strx },
53555434 .{ .type, .ref_addr },
5356 .{ .low_pc, .addr },
5435 .{ .low_pc, .addrx },
53575436 .{ .high_pc, .data4 },
53585437 .{ .alignment, .udata },
53595438 .{ .external, .flag },
......@@ -5366,7 +5445,7 @@ pub const AbbrevCode = enum {
53665445 .attrs = decl_instance_attrs ++ .{
53675446 .{ .linkage_name, .strx },
53685447 .{ .type, .ref_addr },
5369 .{ .low_pc, .addr },
5448 .{ .low_pc, .addrx },
53705449 .{ .high_pc, .data4 },
53715450 .{ .alignment, .udata },
53725451 .{ .external, .flag },
......@@ -6020,6 +6099,7 @@ pub const AbbrevCode = enum {
60206099 .{ .language, .data1 },
60216100 .{ .base_types, .ref_addr },
60226101 .{ .stmt_list, .sec_offset },
6102 .{ .addr_base, .sec_offset },
60236103 .{ .rnglists_base, .sec_offset },
60246104 .{ .str_offsets_base, .sec_offset },
60256105 .{ .producer, .strx1 },
src/link/Elf2.zig+103-18
......@@ -53,6 +53,7 @@ shndx: struct {
5353 rela_dyn: Section.Index,
5454 rela_plt: Section.Index,
5555 debug_abbrev: Section.Index,
56 debug_addr: Section.Index,
5657 eh_frame_hdr: Section.Index,
5758 eh_frame: Section.Index,
5859 debug_frame: Section.Index,
......@@ -215,6 +216,7 @@ textrel_count: u32,
215216
216217dwarf: Dwarf,
217218dwarf_shared: std.enums.EnumArray(Dwarf.SharedSection, dwarf_relocs.Shared),
219dwarf_addr: dwarf_relocs.Addr,
218220dwarf_str_offsets: dwarf_relocs.StrOffsets,
219221dwarf_units: []dwarf_relocs.Unit,
220222dwarf_consts: std.array_hash_map.Auto(link.ConstPool.Index, dwarf_relocs.Const),
......@@ -287,6 +289,7 @@ const Node = union(enum) {
287289 lazy_const_data: LazyMapRef.Index(.const_data),
288290
289291 debug_shared: Dwarf.SharedSection,
292 debug_addr,
290293 eh_frame_footer,
291294 debug_str_offsets,
292295 unit_padding,
......@@ -882,6 +885,10 @@ const dwarf_relocs = struct {
882885 const Shared = struct {
883886 first_target_reloc: NodeReloc.Index,
884887 };
888 const Addr = struct {
889 first_target_reloc: NodeReloc.Index,
890 symbol_relocs: std.ArrayList(SymbolReloc.Index),
891 };
885892 const StrOffsets = struct {
886893 first_target_reloc: NodeReloc.Index,
887894 node_relocs: std.ArrayList(NodeReloc.Index),
......@@ -3352,6 +3359,7 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {
33523359 .input_section,
33533360 .copied_global,
33543361 .debug_shared,
3362 .debug_addr,
33553363 .eh_frame_footer,
33563364 .debug_str_offsets,
33573365 .unit_padding,
......@@ -3807,6 +3815,7 @@ fn create(
38073815 .rela_dyn = .UNDEF,
38083816 .rela_plt = .UNDEF,
38093817 .debug_abbrev = .UNDEF,
3818 .debug_addr = .UNDEF,
38103819 .eh_frame_hdr = .UNDEF,
38113820 .eh_frame = .UNDEF,
38123821 .debug_frame = .UNDEF,
......@@ -3873,6 +3882,10 @@ fn create(
38733882 .dwarf_shared = comptime .initFill(.{
38743883 .first_target_reloc = .none,
38753884 }),
3885 .dwarf_addr = .{
3886 .first_target_reloc = .none,
3887 .symbol_relocs = .empty,
3888 },
38763889 .dwarf_str_offsets = .{
38773890 .first_target_reloc = .none,
38783891 .node_relocs = .empty,
......@@ -3932,6 +3945,7 @@ pub fn deinit(elf: *Elf) void {
39323945 elf.changed_symtab_index.deinit(gpa);
39333946
39343947 elf.dwarf.deinit();
3948 elf.dwarf_addr.symbol_relocs.deinit(gpa);
39353949 elf.dwarf_str_offsets.node_relocs.deinit(gpa);
39363950 for (elf.dwarf_units) |*dwarf_unit| dwarf_unit.debug_rnglists_symbol_relocs.deinit(gpa);
39373951 gpa.free(elf.dwarf_units);
......@@ -4012,6 +4026,7 @@ fn initHeaders(
40124026 .strip => {},
40134027 .dwarf => {
40144028 shnum += 1; // .debug_abbrev
4029 shnum += 1; // .debug_addr
40154030 shnum += @intFromBool(have_debug_frame); // .debug_frame
40164031 shnum += 1; // .debug_info
40174032 shnum += 1; // .debug_line
......@@ -5116,6 +5131,11 @@ fn initHeaders(
51165131 .strip => {},
51175132 .dwarf => {
51185133 elf.shndx.debug_abbrev = try elf.addSection(elf.ni.elf, .{ .name = ".debug_abbrev" });
5134 elf.shndx.debug_addr = try elf.addSection(elf.ni.elf, .{
5135 .name = ".debug_addr",
5136 .addralign = addr_align,
5137 .node_align = elf.mf.flags.block_size,
5138 });
51195139 if (have_debug_frame) elf.shndx.debug_frame = try elf.addSection(elf.ni.elf, .{
51205140 .name = ".debug_frame",
51215141 .addralign = addr_align,
......@@ -5144,7 +5164,10 @@ fn initHeaders(
51445164 });
51455165 elf.shndx.debug_str_offsets = try elf.addSection(elf.ni.elf, .{
51465166 .name = ".debug_str_offsets",
5147 .addralign = addr_align,
5167 .addralign = switch (elf.dwarf.format) {
5168 .@"32" => .@"4",
5169 .@"64" => .@"8",
5170 },
51485171 .node_align = elf.mf.flags.block_size,
51495172 });
51505173 },
......@@ -5240,6 +5263,7 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
52405263 .lazy_code,
52415264 .lazy_const_data,
52425265 .debug_shared,
5266 .debug_addr,
52435267 .eh_frame_footer,
52445268 .debug_str_offsets,
52455269 .unit_padding,
......@@ -5288,6 +5312,7 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
52885312 .lazy_const_data,
52895313 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
52905314 .debug_shared,
5315 .debug_addr,
52915316 .eh_frame_footer,
52925317 .debug_str_offsets,
52935318 .unit_padding,
......@@ -5329,7 +5354,7 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
53295354 .lazy_code,
53305355 .lazy_const_data,
53315356 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
5332 .debug_shared, .eh_frame_footer, .debug_str_offsets, .unit_padding => unreachable,
5357 .debug_shared, .debug_addr, .eh_frame_footer, .debug_str_offsets, .unit_padding => unreachable,
53335358 .unit_frame, .unit_debug_info, .unit_debug_line => {
53345359 const section_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);
53355360 break :parent_vaddr elf.getNodeShndx(parent_ni).vaddr(elf) + section_offset;
......@@ -5366,7 +5391,7 @@ fn computeNodeSectionOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 {
53665391 .section, .section_manual_size => 0,
53675392 .input_section, .copied_global => unreachable,
53685393 .nav, .uav, .lazy_code, .lazy_const_data => unreachable,
5369 .debug_shared, .eh_frame_footer, .debug_str_offsets, .unit_padding => unreachable,
5394 .debug_shared, .debug_addr, .eh_frame_footer, .debug_str_offsets, .unit_padding => unreachable,
53705395 .unit_frame, .unit_debug_info, .unit_debug_line => {
53715396 const parent_section_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);
53725397 break :parent_section_offset parent_section_offset;
......@@ -5415,6 +5440,7 @@ pub fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
54155440 .segment,
54165441 .copied_global,
54175442 .debug_shared,
5443 .debug_addr,
54185444 .eh_frame_footer,
54195445 .debug_str_offsets,
54205446 .unit_padding,
......@@ -7215,8 +7241,14 @@ fn prelinkInner(elf: *Elf) Error!void {
72157241 };
72167242 elf.input_pending_index += 1;
72177243
7218 try elf.nodes.ensureUnusedCapacity(gpa, 6 + 4);
7219 for ([6]Section.Index{
7244 const addr_align: Alignment = switch (elf.identClass()) {
7245 .NONE, _ => unreachable,
7246 .@"32" => .@"4",
7247 .@"64" => .@"8",
7248 };
7249 try elf.nodes.ensureUnusedCapacity(gpa, 7 + 5);
7250 for ([7]Section.Index{
7251 elf.shndx.debug_addr,
72207252 elf.shndx.eh_frame,
72217253 elf.shndx.debug_frame,
72227254 elf.shndx.debug_info,
......@@ -7238,11 +7270,7 @@ fn prelinkInner(elf: *Elf) Error!void {
72387270 };
72397271 break :last_header_oni last_header_oni;
72407272 }, .{
7241 .alignment = if (frame_format) |_| switch (elf.identClass()) {
7242 .NONE, _ => unreachable,
7243 .@"32" => .@"4",
7244 .@"64" => .@"8",
7245 } else .@"1",
7273 .alignment = if (frame_format) |_| addr_align else .@"1",
72467274 .next_moved = true,
72477275 .enable_next_moved = true,
72487276 }),
......@@ -7258,6 +7286,28 @@ fn prelinkInner(elf: *Elf) Error!void {
72587286 error.WriteFailed => return debug_nw.err.?,
72597287 };
72607288 }
7289 switch (elf.shndx.debug_addr) {
7290 .UNDEF => {},
7291 else => |debug_addr_shndx| {
7292 const debug_addr_ni = elf.addNodeAssumeCapacity(
7293 try debug_addr_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{
7294 .alignment = addr_align,
7295 .next_moved = true,
7296 .enable_next_moved = true,
7297 }),
7298 .debug_addr,
7299 );
7300 elf.dwarf.debug_addr.ni = .wrap(debug_addr_ni);
7301
7302 var dah_nw: link.MappedFile.Node.Writer = undefined;
7303 debug_addr_ni.writer(gpa, &elf.mf, &dah_nw);
7304 defer dah_nw.deinit();
7305 elf.dwarf.genDebugAddrHeader(&dah_nw.interface) catch |err| switch (err) {
7306 else => |e| return e,
7307 error.WriteFailed => return dah_nw.err.?,
7308 };
7309 },
7310 }
72617311 switch (elf.shndx.debug_abbrev) {
72627312 .UNDEF => {},
72637313 else => |debug_abbrev_shndx| elf.dwarf.debug_abbrev.ni = .wrap(elf.addNodeAssumeCapacity(
......@@ -7430,7 +7480,7 @@ fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void {
74307480 error.WriteFailed => return dih_nw.err.?,
74317481 };
74327482 }
7433 try elf.genPendingDebugStrings(gpa);
7483 try elf.genPendingDebug(gpa);
74347484}
74357485
74367486fn flushFiles(elf: *Elf) Error!void {
......@@ -8255,6 +8305,7 @@ fn addNodeRelocAssumeCapacity(
82558305 const first_target_reloc = switch (elf.getNode(target)) {
82568306 else => unreachable,
82578307 .debug_shared => |ss| &elf.dwarf_shared.getPtr(ss).first_target_reloc,
8308 .debug_addr => &elf.dwarf_addr.first_target_reloc,
82588309 .debug_str_offsets => &elf.dwarf_str_offsets.first_target_reloc,
82598310 .unit_frame_cie => |ui| &elf.dwarf_units[@backingInt(ui)].frame_cie_first_target_reloc,
82608311 .unit_debug_info_header => |ui| &elf.dwarf_units[@backingInt(ui)].debug_info_header_first_target_reloc,
......@@ -8361,6 +8412,7 @@ fn addGotRelocAssumeCapacity(
83618412 .segment,
83628413 .copied_global,
83638414 .debug_shared,
8415 .debug_addr,
83648416 .eh_frame_footer,
83658417 .debug_str_offsets,
83668418 .unit_padding,
......@@ -9211,7 +9263,8 @@ fn flushInner(
92119263 assert(elf.input_section_pending_index == elf.input_sections.items.len);
92129264 assert(elf.pending_uavs.items.len == 0);
92139265 assert(elf.dwarf.const_pool.pending.items.len == 0);
9214 assert(elf.dwarf.debug_str_offsets.pending_index == elf.dwarf.debug_str_offsets.map.count());
9266 assert(!elf.dwarf.debug_addr.anyPending());
9267 assert(!elf.dwarf.debug_str_offsets.anyPending());
92159268
92169269 // We've done the final `idle` loop, so everything is at its final place in the file. We have a
92179270 // few more things to check and write now that addresses and offsets are finalized.
......@@ -9536,9 +9589,22 @@ fn genPending(elf: *Elf, pt: Zcu.PerThread) link.Error!void {
95369589 },
95379590 .code_view => unreachable,
95389591 }
9539 try elf.genPendingDebugStrings(gpa);
9540}
9541fn genPendingDebugStrings(elf: *Elf, gpa: std.mem.Allocator) link.Error!void {
9592 try elf.genPendingDebug(gpa);
9593}
9594fn genPendingDebug(elf: *Elf, gpa: std.mem.Allocator) link.Error!void {
9595 while (elf.dwarf.debug_addr.map.count() - elf.dwarf.debug_addr.pending_index > 0) {
9596 const debug_addr_ni = elf.dwarf.debug_addr.ni.unwrap().?;
9597 try debug_addr_ni.moved(gpa, &elf.mf);
9598 var da_nw: link.MappedFile.Node.Writer = undefined;
9599 debug_addr_ni.writer(gpa, &elf.mf, &da_nw);
9600 defer da_nw.deinit();
9601 const first_symbol_ri = elf.symbol_relocs.items.len;
9602 try elf.dwarf.genPendingDebugAddr(&da_nw);
9603 const symbol_relocs = &elf.dwarf_addr.symbol_relocs;
9604 try symbol_relocs.ensureUnusedCapacity(gpa, elf.symbol_relocs.items.len - first_symbol_ri);
9605 for (first_symbol_ri..elf.symbol_relocs.items.len) |symbol_ri|
9606 symbol_relocs.appendAssumeCapacity(@fromBackingInt(@intCast(symbol_ri)));
9607 }
95429608 while (elf.dwarf.debug_str_offsets.map.count() - elf.dwarf.debug_str_offsets.pending_index > 0) {
95439609 const debug_str_offsets_ni = elf.dwarf.debug_str_offsets.ni.unwrap().?;
95449610 try debug_str_offsets_ni.moved(gpa, &elf.mf);
......@@ -9958,6 +10024,22 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
995810024 .unit_debug_info,
995910025 .unit_debug_line,
996010026 => {},
10027 .debug_addr => {
10028 const target_section_offset = elf.computeNodeSectionOffset(ni);
10029 var target_ri = elf.dwarf_addr.first_target_reloc;
10030 while (target_ri != .none) {
10031 const target_reloc = target_ri.get(elf);
10032 assert(target_reloc.target == ni);
10033 target_reloc.flushMovedTarget(elf, target_section_offset);
10034 target_ri = target_reloc.next;
10035 }
10036 const node_vaddr = elf.computeNodeVAddr(ni);
10037 for (elf.dwarf_addr.symbol_relocs.items) |symbol_ri| {
10038 const symbol_reloc = symbol_ri.get(elf);
10039 assert(symbol_reloc.node.unwrap().? == ni);
10040 symbol_reloc.flushMovedNode(elf, node_vaddr);
10041 }
10042 },
996110043 .debug_str_offsets => {
996210044 const target_section_offset = elf.computeNodeSectionOffset(ni);
996310045 var target_ri = elf.dwarf_str_offsets.first_target_reloc;
......@@ -10356,6 +10438,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
1035610438 .lazy_code,
1035710439 .lazy_const_data,
1035810440 .debug_shared,
10441 .debug_addr,
1035910442 .eh_frame_footer,
1036010443 .debug_str_offsets,
1036110444 .unit_padding,
......@@ -10430,6 +10513,7 @@ fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
1043010513 error.NoSpaceLeft => archive.strtab_member_too_big = true,
1043110514 }
1043210515 },
10516 .debug_addr,
1043310517 .debug_str_offsets,
1043410518 .unit_padding,
1043510519 .unit_frame_cie,
......@@ -10447,6 +10531,7 @@ fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
1044710531 const offset, const size = ni.location(&elf.mf).resolve(&elf.mf);
1044810532 break :location .{ offset, switch (node) {
1044910533 else => unreachable,
10534 .debug_addr => elf.dwarf.debug_addr.size(&elf.dwarf),
1045010535 .debug_str_offsets => elf.dwarf.debug_str_offsets.size(&elf.dwarf),
1045110536 .unit_padding,
1045210537 .unit_frame_cie,
......@@ -10475,7 +10560,7 @@ fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
1047510560 };
1047610561 switch (node) {
1047710562 else => unreachable,
10478 .debug_str_offsets, .unit_padding, .unit_debug_rnglists => {
10563 .debug_addr, .debug_str_offsets, .unit_padding, .unit_debug_rnglists => {
1047910564 const parent_slice = parent_ni.slicePadding(&elf.mf);
1048010565 const frame_shndx = elf.getNodeShndx(parent_ni);
1048110566 const frame_format = frame_shndx.debugFrameFormat(elf) orelse
......@@ -10600,13 +10685,13 @@ fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
1060010685 var fw: Io.Writer = .fixed(slice[@intCast(size)..]);
1060110686 switch (node) {
1060210687 else => unreachable,
10603 .debug_str_offsets, .unit_debug_rnglists => {
10688 .debug_addr, .debug_str_offsets, .unit_debug_rnglists => {
1060410689 elf.dwarf.genUnitPadding(&fw) catch |err| switch (err) {
1060510690 error.WriteFailed => {
1060610691 elf.dwarf.updateUnitLength(slice, slice.len);
1060710692 @memset(fw.buffer, switch (node) {
1060810693 else => unreachable,
10609 .debug_str_offsets => std.math.maxInt(u8),
10694 .debug_addr, .debug_str_offsets => std.math.maxInt(u8),
1061010695 .unit_debug_rnglists => std.dwarf.RLE.end_of_list,
1061110696 });
1061210697 return;