authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-02 10:29:39-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-03 11:00:54-04:00
logabbec23e9cfb6549a2260fd447086dfd2935a350
treef11add52df2d829d9c2d4ed8052f40c1048732fc
parent6f746eef85c143ec559039bb4a70d15a05bcd2b5

Dwarf2: implement enough debug info to get line info working


3 files changed, 738 insertions(+), 338 deletions(-)

src/link.zig+11-11
......@@ -805,20 +805,20 @@ pub const File = struct {
805805 /// * `updateLineNumber`
806806 ///
807807 /// Asserts that the ZCU is not using the LLVM backend.
808 fn zcuFilesReady(base: *File) Error!void {
809 assert(base.comp.zcu.?.llvm_object == null);
808 fn zcuFilesReady(base: *File, zcu: *Zcu) Error!void {
809 assert(zcu.llvm_object == null);
810810 switch (base.tag) {
811811 else => {},
812812 inline .elf2 => |tag| {
813813 dev.check(tag.devFeature());
814 return @as(*tag.Type(), @fieldParentPtr("base", base)).zcuFilesReady();
814 return @as(*tag.Type(), @fieldParentPtr("base", base)).zcuFilesReady(zcu);
815815 },
816816 }
817817 }
818818
819819 /// Asserts that the ZCU is not using the LLVM backend.
820820 fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Error!void {
821 assert(base.comp.zcu.?.llvm_object == null);
821 assert(pt.zcu.llvm_object == null);
822822 const nav = pt.zcu.intern_pool.getNav(nav_index);
823823 assert(nav.resolved.?.value != .none);
824824
......@@ -834,7 +834,7 @@ pub const File = struct {
834834
835835 /// Never called when LLVM is codegenning the ZCU.
836836 fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Error!void {
837 assert(base.comp.zcu.?.llvm_object == null);
837 assert(pt.zcu.llvm_object == null);
838838 switch (base.tag) {
839839 .lld => unreachable,
840840 else => {},
......@@ -856,7 +856,7 @@ pub const File = struct {
856856 /// take ownership of an embedded slice and replace it with `&.{}` in `mir`.
857857 mir: *codegen.AnyMir,
858858 ) Error!void {
859 assert(base.comp.zcu.?.llvm_object == null);
859 assert(pt.zcu.llvm_object == null);
860860 switch (base.tag) {
861861 .lld => unreachable,
862862 .plan9 => unreachable,
......@@ -871,7 +871,7 @@ pub const File = struct {
871871 /// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`.
872872 /// Never called when LLVM is codegenning the ZCU.
873873 fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) Error!void {
874 assert(base.comp.zcu.?.llvm_object == null);
874 assert(pt.zcu.llvm_object == null);
875875 {
876876 const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?;
877877 const file = pt.zcu.fileByIndex(ti.file);
......@@ -996,7 +996,7 @@ pub const File = struct {
996996 pt: Zcu.PerThread,
997997 export_indices: []const Zcu.Export.Index,
998998 ) Error!void {
999 assert(base.comp.zcu.?.llvm_object == null);
999 assert(pt.zcu.llvm_object == null);
10001000
10011001 crash_report.LinkerOp.start(base, pt.tid);
10021002 defer crash_report.LinkerOp.stop(base, pt.tid);
......@@ -1031,7 +1031,7 @@ pub const File = struct {
10311031 /// the block/atom.
10321032 /// Never called when LLVM is codegenning the ZCU.
10331033 pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) Error!u64 {
1034 assert(base.comp.zcu.?.llvm_object == null);
1034 assert(pt.zcu.llvm_object == null);
10351035
10361036 switch (base.tag) {
10371037 .lld => unreachable,
......@@ -1054,7 +1054,7 @@ pub const File = struct {
10541054 decl_val: InternPool.Index,
10551055 decl_align: InternPool.Alignment,
10561056 ) Error!SymbolId {
1057 assert(base.comp.zcu.?.llvm_object == null);
1057 assert(pt.zcu.llvm_object == null);
10581058
10591059 switch (base.tag) {
10601060 .lld => unreachable,
......@@ -1635,7 +1635,7 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
16351635 .files_ready => {
16361636 if (zcu.llvm_object != null) return;
16371637 const lf = comp.bin_file orelse return;
1638 lf.zcuFilesReady() catch |err| switch (err) {
1638 lf.zcuFilesReady(zcu) catch |err| switch (err) {
16391639 error.Canceled => io.recancel(),
16401640 error.AlreadyReported => return,
16411641 error.OutOfMemory => return diags.setAllocFailure(),
src/link/Dwarf2.zig+366-113
......@@ -12,23 +12,28 @@ values: std.ArrayList(struct {
1212globals: std.array_hash_map.Auto(InternPool.Nav.Index, Global),
1313funcs: std.array_hash_map.Auto(InternPool.Nav.Index, Func),
1414
15debug_abbrev: DebugAbbrev,
15debug_abbrev: Abbrev,
1616frame: Frame,
17debug_info: DebugInfo,
18debug_line: DebugLine,
19debug_line_str: String,
20debug_str: String,
21debug_str_offsets: StringOffsets,
17debug_info: Info,
18debug_line: Line,
19debug_line_str: Str,
20debug_rnglists: Rnglists,
21debug_str: Str,
22debug_str_offsets: StrOffsets,
2223
2324pub const AddressSize = enum(u8) { @"32" = 4, @"64" = 8, _ };
2425
2526pub const Unit = struct {
27 files: std.array_hash_map.Auto(Zcu.File.Index, void),
28 files_changed: bool,
2629 frame_ni: MappedFile.Node.Index.Optional,
2730 cie_ni: MappedFile.Node.Index.Optional,
2831 debug_info_ni: MappedFile.Node.Index.Optional,
2932 debug_info_header_ni: MappedFile.Node.Index.Optional,
3033 debug_line_ni: MappedFile.Node.Index.Optional,
3134 debug_line_header_ni: MappedFile.Node.Index.Optional,
35 debug_rnglists_ni: MappedFile.Node.Index.Optional,
36 debug_rnglists_offset: usize,
3237
3338 pub const Index = enum(u32) {
3439 _,
......@@ -41,6 +46,30 @@ pub const Unit = struct {
4146 return &dwarf.units.values()[@backingInt(ui)];
4247 }
4348 };
49
50 pub const FileIndex = enum(u32) {
51 root = 0,
52 _,
53
54 fn get(fi: FileIndex, unit: *Unit) Zcu.File.Index {
55 return unit.files.keys()[@backingInt(fi)];
56 }
57 };
58
59 fn getFile(
60 unit: *Unit,
61 gpa: std.mem.Allocator,
62 zfi: Zcu.File.Index,
63 ) std.mem.Allocator.Error!FileIndex {
64 const file_gop = try unit.files.getOrPut(gpa, zfi);
65 if (!file_gop.found_existing) unit.files_changed = true;
66 return @fromBackingInt(@intCast(file_gop.index));
67 }
68
69 pub fn cleanFilesChanged(unit: *Unit) bool {
70 defer unit.files_changed = false;
71 return unit.files_changed;
72 }
4473};
4574
4675pub const Global = struct {
......@@ -90,15 +119,15 @@ pub const Frame = struct {
90119 pub const Format = std.debug.Dwarf.Unwind.Section;
91120};
92121
93pub const DebugAbbrev = struct {
122pub const Abbrev = struct {
94123 ni: MappedFile.Node.Index.Optional,
95124 offset: usize,
96125 set: std.enums.EnumSet(AbbrevCode),
97126};
98127
99pub const DebugInfo = struct {};
128pub const Info = struct {};
100129
101pub const DebugLine = struct {
130pub const Line = struct {
102131 header: Header,
103132
104133 pub const Header = struct {
......@@ -111,35 +140,51 @@ pub const DebugLine = struct {
111140 };
112141};
113142
114pub const String = struct {
143pub const Str = struct {
115144 ni: MappedFile.Node.Index.Optional,
116145 offset: usize,
117 map: std.AutoHashMapUnmanaged(usize, void),
146 map: std.HashMapUnmanaged(usize, void, Context, std.hash_map.default_max_load_percentage),
118147
119148 fn get(
120 s: *String,
149 s: *Str,
121150 gpa: std.mem.Allocator,
122151 mf: *MappedFile,
123 string: []const u8,
152 str: []const u8,
124153 ) MappedFile.Error!usize {
125154 const ni = s.ni.unwrap().?;
126 const gop = try s.map.getOrPutAdapted(gpa, string, Adapter{ .slice = ni.sliceConst(mf) });
155 const slice = ni.sliceConst(mf);
156 const gop = try s.map.getOrPutContextAdapted(
157 gpa,
158 str,
159 Adapter{ .slice = slice },
160 .{ .slice = slice },
161 );
127162 if (!gop.found_existing) {
128163 gop.key_ptr.* = s.offset;
129 try ni.ensureMinimumSize(mf, gpa, s.offset + string.len + 1);
164 try ni.ensureMinimumSize(mf, gpa, s.offset + str.len + 1);
130165 const slice_mut = ni.slice(mf);
131 @memcpy(slice_mut[s.offset..][0..string.len], string);
132 s.offset += string.len;
166 @memcpy(slice_mut[s.offset..][0..str.len], str);
167 s.offset += str.len;
133168 slice_mut[s.offset] = 0;
134169 s.offset += 1;
135170 }
136171 return gop.key_ptr.*;
137172 }
138173
174 const Context = struct {
175 slice: []const u8,
176 pub fn hash(context: Context, offset: usize) u64 {
177 return std.hash.Wyhash.hash(0, std.mem.sliceTo(context.slice[offset..], 0));
178 }
179 pub fn eql(_: Context, lhs_offset: usize, rhs_offset: usize) bool {
180 return lhs_offset == rhs_offset;
181 }
182 };
183
139184 const Adapter = struct {
140185 slice: []const u8,
141 pub fn hash(_: Adapter, key: []const u8) u32 {
142 return @truncate(std.hash.Wyhash.hash(0, key));
186 pub fn hash(_: Adapter, key: []const u8) u64 {
187 return std.hash.Wyhash.hash(0, key);
143188 }
144189 pub fn eql(adapter: Adapter, key: []const u8, rhs_offset: usize) bool {
145190 return std.mem.startsWith(u8, adapter.slice[rhs_offset..], key) and
......@@ -148,7 +193,9 @@ pub const String = struct {
148193 };
149194};
150195
151pub const StringOffsets = struct {
196pub const Rnglists = struct {};
197
198pub const StrOffsets = struct {
152199 ni: MappedFile.Node.Index.Optional,
153200 offset: usize,
154201};
......@@ -527,6 +574,7 @@ pub const WipNav = struct {
527574 high_pc: u32,
528575 }),
529576 info_writer: MappedFile.Node.Writer,
577 info_func_length_offset: usize,
530578 line_writer: MappedFile.Node.Writer,
531579
532580 pub fn deinit(debug: *Debug) void {
......@@ -538,13 +586,22 @@ pub const WipNav = struct {
538586 debug.* = undefined;
539587 }
540588
541 pub fn startDebugInfo(debug: *Debug) link.Error!void {
542 debug.startDebugInfoInner() catch |err| switch (err) {
589 pub fn genDebugFrame(debug: *Debug, loc: u32, cfa: Cfa) link.Error!void {
590 return debug.wip_nav.genDebugFrame(loc, cfa);
591 }
592
593 pub fn startFunc(debug: *Debug) link.Error!void {
594 assert(debug.wip_nav.func != null);
595 debug.startDebugInfo() catch |err| switch (err) {
543596 error.WriteFailed => return debug.wip_nav.reportWriteError(&debug.info_writer),
544597 else => |e| return e,
545598 };
599 debug.startDebugLine() catch |err| switch (err) {
600 error.WriteFailed => return debug.wip_nav.reportWriteError(&debug.line_writer),
601 else => |e| return e,
602 };
546603 }
547 fn startDebugInfoInner(debug: *Debug) link.EmitError!void {
604 fn startDebugInfo(debug: *Debug) link.EmitError!void {
548605 const dwarf = debug.wip_nav.dwarf;
549606 const ip = &debug.pt.zcu.intern_pool;
550607 const nav = ip.getNav(debug.wip_nav.func.?.nav(dwarf));
......@@ -552,29 +609,80 @@ pub const WipNav = struct {
552609 try diw.writeUleb128(try dwarf.refAbbrevCode(.decl_func));
553610 try debug.strp(nav.name.toSlice(ip));
554611 try debug.strp(nav.fqn.toSlice(ip));
612 try dwarf.symbolAddress(&debug.info_writer, debug.wip_nav.func_si, 0);
613 debug.info_func_length_offset = diw.end;
614 try diw.writeInt(u32, undefined, dwarf.endian);
555615 }
616 fn startDebugLine(debug: *Debug) link.EmitError!void {
617 const dwarf = debug.wip_nav.dwarf;
618 const zcu = debug.pt.zcu;
619 const ip = &zcu.intern_pool;
620 const nav = debug.wip_nav.func.?.nav(dwarf);
621 const func = zcu.funcInfo(zcu.navValue(nav).toIntern());
622 const zfi = zcu.navFileScopeIndex(nav);
623 const zf = zcu.fileByIndex(zfi);
624 const inst_info = ip.getNav(nav).srcInst(ip).resolveFull(ip).?;
625 const decl = zf.zir.?.getDeclaration(inst_info.inst);
626 const mod = zf.mod.?;
627 const dlw = &debug.line_writer.interface;
628 try dlw.writeByte(DW.LNS.extended_op);
629 if (zcu.comp.config.incremental) {
630 try dlw.writeUleb128(1 + @as(u7, switch (dwarf.format) {
631 .@"32" => 4,
632 .@"64" => 8,
633 }));
634 try dlw.writeByte(DW.LNE.ZIG_set_decl);
635 try dwarf.sectionOffset(&debug.line_writer, debug.info_writer.ni, 0);
556636
557 pub fn genDebugFrame(debug: *Debug, loc: u32, cfa: Cfa) link.Error!void {
558 return debug.wip_nav.genDebugFrame(loc, cfa);
637 try dlw.writeByte(DW.LNS.set_column);
638 try dlw.writeUleb128(func.lbrace_column + 1);
639
640 try debug.advancePcAndLine(func.lbrace_line, 0);
641 } else {
642 try dlw.writeUleb128(1 + @backingInt(dwarf.address_size));
643 try dlw.writeByte(DW.LNE.set_address);
644 try dwarf.symbolAddress(&debug.line_writer, debug.wip_nav.func_si, 0);
645
646 const fi = try dwarf.getUnit(mod).get(dwarf).getFile(zcu.gpa, zfi);
647 try dlw.writeByte(DW.LNS.set_file);
648 try dlw.writeUleb128(@backingInt(fi));
649
650 try dlw.writeByte(DW.LNS.set_column);
651 try dlw.writeUleb128(func.lbrace_column + 1);
652
653 try debug.advancePcAndLine(@intCast(decl.src_line + func.lbrace_line), 0);
654 }
559655 }
560656
561 pub fn finishFunc(debug: *Debug) link.Error!void {
657 pub fn finishFunc(debug: *Debug, func_length: u64) link.Error!void {
562658 assert(debug.wip_nav.func != null);
563 debug.finishDebugInfo() catch |err| switch (err) {
659 debug.finishDebugInfo(func_length) catch |err| switch (err) {
564660 error.WriteFailed => return debug.wip_nav.reportWriteError(&debug.info_writer),
565661 else => |e| return e,
566662 };
567 const dlw = &debug.line_writer.interface;
568 dlw.rebase(dlw.end, comptime 1 + uleb128Bytes(1) + 1) catch |err| switch (err) {
663 debug.finishDebugLine() catch |err| switch (err) {
569664 error.WriteFailed => return debug.wip_nav.reportWriteError(&debug.line_writer),
665 else => |e| return e,
570666 };
571667 }
572
573 fn finishDebugInfo(debug: *Debug) link.EmitError!void {
668 fn finishDebugInfo(debug: *Debug, func_length: u64) link.EmitError!void {
574669 const diw = &debug.info_writer.interface;
670 std.mem.writeInt(
671 u32,
672 diw.buffered()[debug.info_func_length_offset..][0..4],
673 @intCast(func_length),
674 debug.wip_nav.dwarf.endian,
675 );
575676 try diw.writeUleb128(@backingInt(AbbrevCode.null));
576677 try debug.wip_nav.dwarf.genDebugInfoPadding(diw, diw.unusedCapacityLen());
577678 }
679 fn finishDebugLine(debug: *Debug) link.EmitError!void {
680 const dlw = &debug.line_writer.interface;
681 try dlw.writeByte(DW.LNS.extended_op);
682 try dlw.writeUleb128(1);
683 try dlw.writeByte(DW.LNE.end_sequence);
684 try genDebugLinePadding(dlw, dlw.unusedCapacityLen());
685 }
578686
579687 pub const LocalVarTag = enum { arg, local_var };
580688 pub fn genLocalVarDebugInfo(
......@@ -666,7 +774,6 @@ pub const WipNav = struct {
666774 }
667775
668776 pub fn advancePcAndLine(debug: *Debug, delta_line: i33, delta_pc: u64) link.Error!void {
669 if (true) return;
670777 return debug.advancePcAndLineInner(delta_line, delta_pc) catch |err| switch (err) {
671778 error.WriteFailed => return debug.wip_nav.reportWriteError(&debug.line_writer),
672779 };
......@@ -707,7 +814,6 @@ pub const WipNav = struct {
707814 }
708815
709816 pub fn setColumn(debug: *Debug, column: u32) link.Error!void {
710 if (true) return;
711817 return debug.setColumnInner(column) catch |err| switch (err) {
712818 error.WriteFailed => return debug.wip_nav.reportWriteError(&debug.line_writer),
713819 };
......@@ -719,7 +825,6 @@ pub const WipNav = struct {
719825 }
720826
721827 pub fn negateStmt(debug: *Debug) link.Error!void {
722 if (true) return;
723828 return debug.negateStmtInner() catch |err| switch (err) {
724829 error.WriteFailed => return debug.wip_nav.reportWriteError(&debug.line_writer),
725830 };
......@@ -729,7 +834,6 @@ pub const WipNav = struct {
729834 }
730835
731836 pub fn setPrologueEnd(debug: *Debug) link.Error!void {
732 if (true) return;
733837 return debug.setPrologueEndInner() catch |err| switch (err) {
734838 error.WriteFailed => return debug.wip_nav.reportWriteError(&debug.line_writer),
735839 };
......@@ -739,7 +843,6 @@ pub const WipNav = struct {
739843 }
740844
741845 pub fn setEpilogueBegin(debug: *Debug) link.Error!void {
742 if (true) return;
743846 return debug.setEpilogueBeginInner() catch |err| switch (err) {
744847 error.WriteFailed => return debug.wip_nav.reportWriteError(&debug.line_writer),
745848 };
......@@ -749,13 +852,13 @@ pub const WipNav = struct {
749852 }
750853
751854 pub fn enterBlock(debug: *Debug, code_off: u64) link.Error!void {
752 if (true) return;
753855 return debug.enterBlockInner(code_off) catch |err| switch (err) {
754856 error.WriteFailed => return debug.wip_nav.reportWriteError(&debug.info_writer),
755857 else => |e| e,
756858 };
757859 }
758860 fn enterBlockInner(debug: *Debug, code_off: u64) link.EmitError!void {
861 if (true) return;
759862 const dwarf = debug.wip_nav.dwarf;
760863 const diw = &debug.info_writer.interface;
761864 const block = try debug.blocks.addOne(dwarf.lf.comp.gpa);
......@@ -943,15 +1046,6 @@ pub const WipNav = struct {
9431046 );
9441047 }
9451048
946 fn infoExternalReloc(debug: *Debug, reloc: struct {
947 source_off: u32 = 0,
948 target_si: link.File.SymbolId,
949 target_off: u64 = 0,
950 }) std.mem.Allocator.Error!void {
951 if (true) @panic("TODO");
952 try debug.wip_nav.externalReloc(&debug.wip_nav.dwarf.debug_frame.section, reloc);
953 }
954
9551049 fn infoSectionOffset(
9561050 debug: *Debug,
9571051 target_ni: MappedFile.Node.Index,
......@@ -996,18 +1090,8 @@ pub const WipNav = struct {
9961090 try loc.write(adapter);
9971091 }
9981092
999 fn infoAddrSym(
1000 debug: *Debug,
1001 si: link.File.SymbolId,
1002 sym_off: u64,
1003 ) link.EmitError!void {
1004 const diw = &debug.info_writer.interface;
1005 try debug.infoExternalReloc(.{
1006 .source_off = @bitCast(@as(u64, diw.end)),
1007 .target_si = si,
1008 .target_off = sym_off,
1009 });
1010 try diw.splatByteAll(0, @backingInt(debug.wip_nav.dwarf.address_size));
1093 fn infoAddrSym(debug: *Debug, si: link.File.SymbolId, addend: usize) link.EmitError!void {
1094 try debug.wip_nav.dwarf.symbolAddress(&debug.info_writer, si, addend);
10111095 }
10121096
10131097 fn refNav(debug: *Debug, nav_index: InternPool.Nav.Index) link.EmitError!void {
......@@ -1037,7 +1121,7 @@ pub const WipNav = struct {
10371121 const size = ty.abiSize(debug.pt.zcu);
10381122 try diw.writeUleb128(size);
10391123 if (size == 0) return;
1040 const old_end = diw.end;
1124 const offset = diw.end;
10411125 try codegen.generateSymbol(
10421126 debug.wip_nav.dwarf.lf,
10431127 debug.pt,
......@@ -1045,12 +1129,12 @@ pub const WipNav = struct {
10451129 diw,
10461130 .{ .debug_output = .{ .dwarf2 = debug } },
10471131 );
1048 if (old_end + size != diw.end) {
1132 if (offset + size != diw.end) {
10491133 std.debug.print("{f} [{}]: {} != {}\n", .{
10501134 ty.fmt(debug.pt),
10511135 ty.toIntern(),
10521136 size,
1053 diw.end - old_end,
1137 diw.end - offset,
10541138 });
10551139 unreachable;
10561140 }
......@@ -1210,7 +1294,8 @@ pub const WipNav = struct {
12101294 offset,
12111295 si,
12121296 @bitCast(sym_off),
1213 switch (dwarf.format) {
1297 switch (dwarf.address_size) {
1298 else => unreachable,
12141299 .@"32" => .abs32(elf),
12151300 .@"64" => .abs64(elf),
12161301 },
......@@ -1240,6 +1325,7 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {
12401325 },
12411326 .endian = target.cpu.arch.endian(),
12421327 .const_pool = .empty,
1328
12431329 .units = .empty,
12441330 .values = .empty,
12451331 .globals = .empty,
......@@ -1296,6 +1382,7 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {
12961382 .offset = 0,
12971383 .map = .empty,
12981384 },
1385 .debug_rnglists = .{},
12991386 .debug_str = .{
13001387 .ni = .none,
13011388 .offset = 0,
......@@ -1311,29 +1398,41 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {
13111398pub fn deinit(dwarf: *Dwarf) void {
13121399 const gpa = dwarf.lf.comp.gpa;
13131400 dwarf.const_pool.deinit(gpa);
1401 for (dwarf.units.values()) |*unit| unit.files.deinit(gpa);
13141402 dwarf.units.deinit(gpa);
13151403 dwarf.values.deinit(gpa);
13161404 dwarf.globals.deinit(gpa);
13171405 dwarf.funcs.deinit(gpa);
1406 dwarf.debug_line_str.map.deinit(gpa);
13181407 dwarf.debug_str.map.deinit(gpa);
13191408 dwarf.* = undefined;
13201409}
13211410
13221411pub fn initUnits(dwarf: *Dwarf, zcu: *Zcu) std.mem.Allocator.Error!void {
13231412 try dwarf.units.ensureTotalCapacity(zcu.gpa, zcu.module_roots.count());
1324 for (zcu.module_roots.keys(), zcu.module_roots.values()) |mod, root| switch (root) {
1325 .none => {},
1326 else => dwarf.units.putAssumeCapacityNoClobber(mod, .{
1413 for (zcu.module_roots.keys(), zcu.module_roots.values()) |mod, root| if (root.unwrap()) |root_zfi| {
1414 const unit_gop = dwarf.units.getOrPutAssumeCapacity(mod);
1415 assert(!unit_gop.found_existing);
1416 unit_gop.value_ptr.* = .{
1417 .files = .empty,
1418 .files_changed = true,
13271419 .frame_ni = .none,
13281420 .cie_ni = .none,
13291421 .debug_info_ni = .none,
13301422 .debug_info_header_ni = .none,
13311423 .debug_line_ni = .none,
13321424 .debug_line_header_ni = .none,
1333 }),
1425 .debug_rnglists_ni = .none,
1426 .debug_rnglists_offset = undefined,
1427 };
1428 assert(try unit_gop.value_ptr.getFile(zcu.gpa, root_zfi) == .root);
13341429 };
13351430}
13361431
1432pub fn getUnit(dwarf: *Dwarf, mod: *Module) Unit.Index {
1433 return @fromBackingInt(@intCast(dwarf.units.getIndex(mod).?));
1434}
1435
13371436fn getNavNode(dwarf: *Dwarf, nav_index: InternPool.Nav.Index) link.Error!MappedFile.Node.Index {
13381437 if (true) @panic("TODO");
13391438 const zcu = dwarf.linkFile().comp.zcu.?;
......@@ -1347,10 +1446,6 @@ fn getNavNode(dwarf: *Dwarf, nav_index: InternPool.Nav.Index) link.Error!MappedF
13471446 return .{ unit, entry };
13481447}
13491448
1350pub fn getUnit(dwarf: *Dwarf, mod: *Module) Unit.Index {
1351 return @fromBackingInt(@intCast(dwarf.units.getIndex(mod).?));
1352}
1353
13541449pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) std.mem.Allocator.Error!Func.Index {
13551450 const func_gop = try dwarf.funcs.getOrPut(dwarf.lf.comp.gpa, owner_nav);
13561451 if (!func_gop.found_existing) func_gop.value_ptr.* = .{
......@@ -1485,44 +1580,52 @@ pub fn updateEhFrameFde(dwarf: *Dwarf, fde: []u8, fde_offset: u64) void {
14851580
14861581pub fn genDebugInfoHeader(
14871582 dwarf: *Dwarf,
1488 nw: *MappedFile.Node.Writer,
1489 unit: Unit.Index,
1583 mod: *Module,
1584 unit: *Unit,
1585 dih_nw: *MappedFile.Node.Writer,
1586 debug_rnglists_offsets_table_offset: usize,
14901587 zcu: *Zcu,
14911588) link.EmitError!void {
14921589 const comp = zcu.comp;
1493 const mod = unit.mod(dwarf);
1494 const diw = &nw.interface;
1495 try dwarf.genUnitLength(diw);
1496 try diw.writeInt(u16, 5, dwarf.endian);
1497 try diw.writeByte(DW.UT.compile);
1498 try diw.writeByte(@backingInt(dwarf.address_size));
1499 try dwarf.sectionOffset(nw, dwarf.debug_abbrev.ni.unwrap().?, 0);
1500 const compile_unit_offset = diw.end;
1501 try diw.writeUleb128(try dwarf.refAbbrevCode(.compile_unit));
1502 try dwarf.strp(&dwarf.debug_str, nw, "zig " ++ @import("build_options").version);
1503 try diw.writeByte(DW.LANG.Zig);
1590 const dihw = &dih_nw.interface;
1591 try dwarf.genUnitLength(dihw);
1592 try dihw.writeInt(u16, 5, dwarf.endian);
1593 try dihw.writeByte(DW.UT.compile);
1594 try dihw.writeByte(@backingInt(dwarf.address_size));
1595 try dwarf.sectionOffset(dih_nw, dwarf.debug_abbrev.ni.unwrap().?, 0);
1596 const compile_unit_offset = dihw.end;
1597 try dihw.writeUleb128(try dwarf.refAbbrevCode(.compile_unit));
1598 try dihw.writeByte(DW.LANG.Zig);
1599 try dwarf.strp(&dwarf.debug_str, dih_nw, "zig " ++ @import("build_options").version);
15041600 const root_dir_path = try mod.root.toAbsolute(&comp.dirs, comp.gpa);
15051601 defer comp.gpa.free(root_dir_path);
1506 try dwarf.strp(&dwarf.debug_line_str, nw, root_dir_path);
1507 try dwarf.strp(&dwarf.debug_line_str, nw, mod.root_src_path);
1602 try dwarf.strp(&dwarf.debug_line_str, dih_nw, root_dir_path);
1603 try dwarf.strp(&dwarf.debug_line_str, dih_nw, mod.root_src_path);
15081604 try dwarf.sectionOffset(
1509 nw,
1605 dih_nw,
15101606 dwarf.getUnit(comp.root_mod).get(dwarf).debug_info_header_ni.unwrap().?,
15111607 compile_unit_offset,
15121608 );
1513 try dwarf.sectionOffset(nw, unit.get(dwarf).debug_line_header_ni.unwrap().?, 0);
1514 const module_offset = diw.end;
1515 try diw.writeUleb128(try dwarf.refAbbrevCode(.module));
1516 try dwarf.strp(&dwarf.debug_str, nw, mod.fully_qualified_name);
1609 try dwarf.sectionOffset(dih_nw, unit.debug_line_header_ni.unwrap().?, 0);
1610 try dwarf.sectionOffset(
1611 dih_nw,
1612 unit.debug_rnglists_ni.unwrap().?,
1613 debug_rnglists_offsets_table_offset,
1614 );
1615 try dihw.writeUleb128(0);
1616 const module_offset = dihw.end;
1617 try dihw.writeUleb128(try dwarf.refAbbrevCode(.module));
1618 try dwarf.strp(&dwarf.debug_str, dih_nw, mod.fully_qualified_name);
1619 try dihw.writeUleb128(0);
15171620 for ([_][]const u8{ "builtin", "root", "std" }, [_]*Module{
15181621 zcu.builtin_modules.get(mod.getBuiltinOptions(comp.config).hash()).?,
15191622 zcu.root_mod,
15201623 zcu.std_mod,
1521 }) |name, dep| try dwarf.genModuleDependency(nw, name, dep, module_offset);
1624 }) |name, dep| try dwarf.genModuleDependency(dih_nw, name, dep, module_offset);
15221625 for (mod.deps.keys(), mod.deps.values()) |name, dep|
1523 try dwarf.genModuleDependency(nw, name, dep, module_offset);
1626 try dwarf.genModuleDependency(dih_nw, name, dep, module_offset);
15241627 for ([2]AbbrevCode{ .pad_1, .pad_n }) |pad| _ = try dwarf.refAbbrevCode(pad);
1525 try dwarf.genDebugInfoPadding(diw, diw.unusedCapacityLen());
1628 try dwarf.genDebugInfoPadding(dihw, dihw.unusedCapacityLen());
15261629}
15271630
15281631fn genModuleDependency(
......@@ -1566,15 +1669,116 @@ pub fn genDebugInfoPadding(dwarf: *Dwarf, diw: *Writer, size: u64) Writer.Error!
15661669 }
15671670}
15681671
1569pub fn genDebugLineHeader(dwarf: *Dwarf, dlw: *Writer) Writer.Error!void {
1570 try dwarf.genUnitLength(dlw);
1571 @memset(dlw.unusedCapacitySlice(), 0xaa);
1672pub fn genDebugLineHeader(
1673 dwarf: *Dwarf,
1674 mod: *Module,
1675 unit: *Unit,
1676 dlh_nw: *MappedFile.Node.Writer,
1677 zcu: *Zcu,
1678) link.EmitError!void {
1679 const comp = zcu.comp;
1680 const dlhw = &dlh_nw.interface;
1681 try dwarf.genUnitLength(dlhw);
1682 try dlhw.writeInt(u16, 5, dwarf.endian);
1683 try dlhw.writeByte(@backingInt(dwarf.address_size));
1684 try dlhw.writeByte(0);
1685 const header_length_offset = dlhw.end;
1686 switch (dwarf.format) {
1687 .@"32" => try dlhw.writeInt(u32, undefined, dwarf.endian),
1688 .@"64" => try dlhw.writeInt(u64, undefined, dwarf.endian),
1689 }
1690 const header_start = dlhw.end;
1691 const StandardOpcode = DeclValEnum(DW.LNS);
1692 try dlhw.writeAll(&.{
1693 dwarf.debug_line.header.minimum_instruction_length,
1694 dwarf.debug_line.header.maximum_operations_per_instruction,
1695 @intFromBool(dwarf.debug_line.header.default_is_stmt),
1696 @bitCast(dwarf.debug_line.header.line_base),
1697 dwarf.debug_line.header.line_range,
1698 dwarf.debug_line.header.opcode_base,
1699 });
1700 try dlhw.writeAll(std.enums.EnumArray(StandardOpcode, u8).init(.{
1701 .extended_op = undefined,
1702 .copy = 0,
1703 .advance_pc = 1,
1704 .advance_line = 1,
1705 .set_file = 1,
1706 .set_column = 1,
1707 .negate_stmt = 0,
1708 .set_basic_block = 0,
1709 .const_add_pc = 0,
1710 .fixed_advance_pc = 1,
1711 .set_prologue_end = 0,
1712 .set_epilogue_begin = 0,
1713 .set_isa = 1,
1714 }).values[1..dwarf.debug_line.header.opcode_base]);
1715 try dlhw.writeByte(1);
1716 try dlhw.writeUleb128(DW.LNCT.path);
1717 try dlhw.writeUleb128(DW.FORM.line_strp);
1718 const dir_count = 1;
1719 const directory_index_form: DeclValEnum(DW.FORM) = if (dir_count <= 1 << 8)
1720 .data1
1721 else if (dir_count <= 1 << 16)
1722 .data2
1723 else
1724 .udata;
1725 try dlhw.writeUleb128(dir_count);
1726 {
1727 const root_dir_path = try mod.root.toAbsolute(&zcu.comp.dirs, comp.gpa);
1728 defer comp.gpa.free(root_dir_path);
1729 try dwarf.strp(&dwarf.debug_line_str, dlh_nw, root_dir_path);
1730 }
1731 try dlhw.writeByte(5);
1732 try dlhw.writeUleb128(DW.LNCT.path);
1733 try dlhw.writeUleb128(DW.FORM.line_strp);
1734 try dlhw.writeUleb128(DW.LNCT.directory_index);
1735 try dlhw.writeUleb128(@backingInt(directory_index_form));
1736 try dlhw.writeUleb128(DW.LNCT.timestamp);
1737 try dlhw.writeUleb128(DW.FORM.data8);
1738 try dlhw.writeUleb128(DW.LNCT.size);
1739 try dlhw.writeUleb128(DW.FORM.data8);
1740 try dlhw.writeUleb128(DW.LNCT.LLVM_source);
1741 try dlhw.writeUleb128(DW.FORM.line_strp);
1742 try dlhw.writeUleb128(unit.files.count());
1743 for (unit.files.keys()) |zfi| {
1744 const zcu_file = zcu.fileByIndex(zfi);
1745 try dwarf.strp(&dwarf.debug_line_str, dlh_nw, zcu_file.sub_file_path);
1746 switch (directory_index_form) {
1747 else => unreachable,
1748 .data1 => try dlhw.writeByte(0),
1749 .data2 => try dlhw.writeInt(u16, 0, dwarf.endian),
1750 .udata => try dlhw.writeUleb128(0),
1751 }
1752 try dlhw.writeInt(i64, @truncate(zcu_file.stat.mtime.nanoseconds), dwarf.endian);
1753 try dlhw.writeInt(u64, zcu_file.stat.size, dwarf.endian);
1754 try dwarf.strp(
1755 &dwarf.debug_line_str,
1756 dlh_nw,
1757 if (zcu_file.is_builtin) zcu_file.source.? else "",
1758 );
1759 }
1760 switch (dwarf.format) {
1761 .@"32" => std.mem.writeInt(
1762 u32,
1763 dlhw.buffer[header_length_offset..][0..4],
1764 @intCast(dlhw.end - header_start),
1765 dwarf.endian,
1766 ),
1767 .@"64" => std.mem.writeInt(
1768 u64,
1769 dlhw.buffer[header_length_offset..][0..8],
1770 dlhw.end - header_start,
1771 dwarf.endian,
1772 ),
1773 }
1774 try genDebugLinePadding(dlhw, dlhw.unusedCapacityLen());
15721775}
15731776
15741777pub fn genDebugLinePadding(dlw: *Writer, size: u64) Writer.Error!void {
15751778 switch (size) {
15761779 0 => {},
15771780 1 => try dlw.writeByte(DW.LNS.const_add_pc),
1781 2 => try dlw.writeAll(&.{ DW.LNS.negate_stmt, DW.LNS.negate_stmt }),
15781782 else => {
15791783 const extended_op_offset = dlw.end;
15801784 try dlw.writeByte(DW.LNS.extended_op);
......@@ -1590,10 +1794,48 @@ pub fn genDebugLinePadding(dlw: *Writer, size: u64) Writer.Error!void {
15901794 },
15911795 .gt => op_len_size += 1,
15921796 };
1797 try dlw.writeByte(DW.LNE.padding);
15931798 },
15941799 }
15951800}
15961801
1802pub fn genDebugRnglistsHeader(
1803 dwarf: *Dwarf,
1804 unit: *Unit,
1805 drh_nw: *MappedFile.Node.Writer,
1806) Writer.Error!usize {
1807 const drhw = &drh_nw.interface;
1808 try dwarf.genUnitLength(drhw);
1809 try drhw.writeInt(u16, 5, dwarf.endian);
1810 try drhw.writeByte(@backingInt(dwarf.address_size));
1811 try drhw.writeByte(0);
1812 try drhw.writeInt(u32, 1, dwarf.endian);
1813 const offsets_table_offset = drhw.end;
1814 switch (dwarf.format) {
1815 .@"32" => try drhw.writeInt(u32, 4, dwarf.endian),
1816 .@"64" => try drhw.writeInt(u64, 8, dwarf.endian),
1817 }
1818 unit.debug_rnglists_offset = drhw.end;
1819 try drhw.writeByte(DW.RLE.end_of_list);
1820 return offsets_table_offset;
1821}
1822
1823pub fn genDebugRnglists(
1824 dwarf: *Dwarf,
1825 unit: *Unit,
1826 dr_nw: *MappedFile.Node.Writer,
1827 func_si: link.File.SymbolId,
1828 func_length: u64,
1829) link.EmitError!void {
1830 const drw = &dr_nw.interface;
1831 drw.end = unit.debug_rnglists_offset;
1832 try drw.writeByte(DW.RLE.start_length);
1833 try dwarf.symbolAddress(dr_nw, func_si, 0);
1834 try drw.writeUleb128(func_length);
1835 unit.debug_rnglists_offset = drw.end;
1836 try drw.writeByte(DW.RLE.end_of_list);
1837}
1838
15971839fn refAbbrevCodeIfExists(
15981840 dwarf: *Dwarf,
15991841 abbrev_code: AbbrevCode,
......@@ -1638,19 +1880,30 @@ fn sectionOffset(
16381880 .@"32" => try nw.interface.writeInt(u32, 0, dwarf.endian),
16391881 .@"64" => try nw.interface.writeInt(u64, 0, dwarf.endian),
16401882 }
1641 try dwarf.lf.cast(.elf2).?.addNodeReloc(
1642 nw.ni,
1643 offset,
1644 target_ni,
1645 @bitCast(@as(u64, addend)),
1646 switch (dwarf.format) {
1647 .@"32" => .abs32,
1648 .@"64" => .abs64,
1649 },
1650 );
1883 const elf = dwarf.lf.cast(.elf2).?;
1884 try elf.addNodeReloc(nw.ni, offset, target_ni, @bitCast(@as(u64, addend)), switch (dwarf.format) {
1885 .@"32" => .abs32,
1886 .@"64" => .abs64,
1887 });
16511888}
16521889
1653fn strp(dwarf: *Dwarf, s: *String, nw: *MappedFile.Node.Writer, str: []const u8) link.EmitError!void {
1890fn symbolAddress(
1891 dwarf: *Dwarf,
1892 nw: *MappedFile.Node.Writer,
1893 target_si: link.File.SymbolId,
1894 addend: usize,
1895) link.EmitError!void {
1896 const offset = nw.interface.end;
1897 switch (dwarf.address_size) {
1898 else => unreachable,
1899 .@"32" => try nw.interface.writeInt(u32, 0, dwarf.endian),
1900 .@"64" => try nw.interface.writeInt(u64, 0, dwarf.endian),
1901 }
1902 const elf = dwarf.lf.cast(.elf2).?;
1903 try elf.addReloc(@bitCast(nw.ni), offset, target_si, @bitCast(@as(u64, addend)), .absAddr(elf));
1904}
1905
1906fn strp(dwarf: *Dwarf, s: *Str, nw: *MappedFile.Node.Writer, str: []const u8) link.EmitError!void {
16541907 const comp = dwarf.lf.comp;
16551908 const mf = &dwarf.lf.cast(.elf2).?.mf;
16561909 try dwarf.sectionOffset(nw, s.ni.unwrap().?, s.get(comp.gpa, mf, str) catch |err| switch (err) {
......@@ -1979,8 +2232,8 @@ pub const AbbrevCode = enum {
19792232 .attrs = decl_abbrev_common_attrs[4..] ++ .{
19802233 .{ .linkage_name, .strp },
19812234 //.{ .type, .ref_addr },
1982 //.{ .low_pc, .addr },
1983 //.{ .high_pc, .data4 },
2235 .{ .low_pc, .addr },
2236 .{ .high_pc, .data4 },
19842237 //.{ .alignment, .udata },
19852238 //.{ .external, .flag },
19862239 //.{ .noreturn, .flag },
......@@ -2200,14 +2453,14 @@ pub const AbbrevCode = enum {
22002453 .tag = .compile_unit,
22012454 .children = true,
22022455 .attrs = &.{
2203 .{ .producer, .strp },
22042456 .{ .language, .data1 },
2457 .{ .producer, .strp },
22052458 .{ .comp_dir, .line_strp },
22062459 .{ .name, .line_strp },
22072460 .{ .base_types, .ref_addr },
22082461 .{ .stmt_list, .sec_offset },
2209 //.{ .rnglists_base, .sec_offset },
2210 //.{ .ranges, .rnglistx },
2462 .{ .rnglists_base, .sec_offset },
2463 .{ .ranges, .rnglistx },
22112464 .{ .use_UTF8, .flag_present },
22122465 },
22132466 },
......@@ -2216,7 +2469,7 @@ pub const AbbrevCode = enum {
22162469 .children = true,
22172470 .attrs = &.{
22182471 .{ .name, .strp },
2219 //.{ .ranges, .rnglistx },
2472 .{ .ranges, .rnglistx },
22202473 },
22212474 },
22222475 .module_dependency = .{
src/link/Elf2.zig+361-214
......@@ -49,6 +49,7 @@ shndx: struct {
4949 debug_info: Section.Index,
5050 debug_line: Section.Index,
5151 debug_line_str: Section.Index,
52 debug_rnglists: Section.Index,
5253 debug_str: Section.Index,
5354 debug_str_offsets: Section.Index,
5455 // These sections are created only as needed, and are initially `.UNDEF`.
......@@ -212,6 +213,8 @@ dwarf_units: std.ArrayList(struct {
212213 debug_info_header_first_node_reloc: NodeReloc.Index,
213214 debug_line_header_first_target_reloc: NodeReloc.Index,
214215 debug_line_header_first_node_reloc: NodeReloc.Index,
216 debug_rnglists_first_target_reloc: NodeReloc.Index,
217 debug_rnglists_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void),
215218}),
216219dwarf_values: std.ArrayList(struct {
217220 debug_info_first_target_reloc: NodeReloc.Index,
......@@ -304,6 +307,7 @@ const Node = union(enum) {
304307 unit_debug_info_header: Dwarf.Unit.Index,
305308 unit_debug_line: Dwarf.Unit.Index,
306309 unit_debug_line_header: Dwarf.Unit.Index,
310 unit_debug_rnglists: Dwarf.Unit.Index,
307311
308312 value_debug_info: link.ConstPool.Index,
309313 global_debug_info: Dwarf.Global.Index,
......@@ -1808,9 +1812,14 @@ const NodeReloc = struct {
18081812 .none => {
18091813 const first_target_reloc = switch (elf.getNode(reloc.target)) {
18101814 else => unreachable,
1815 .debug_shared => |ss| &elf.dwarf_shared.getPtr(ss).first_target_reloc,
18111816 .unit_frame_cie => |ui| &elf.dwarf_units.items[@backingInt(ui)].frame_cie_first_target_reloc,
18121817 .unit_debug_info_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_target_reloc,
18131818 .unit_debug_line_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_target_reloc,
1819 .unit_debug_rnglists => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_rnglists_first_target_reloc,
1820 .value_debug_info => |vi| &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_target_reloc,
1821 .global_debug_info => |gi| &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_target_reloc,
1822 .func_debug_info => |fi| &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_target_reloc,
18141823 };
18151824 first_target_reloc.* = reloc.next;
18161825 },
......@@ -3258,6 +3267,7 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {
32583267 .unit_debug_info_header,
32593268 .unit_debug_line,
32603269 .unit_debug_line_header,
3270 .unit_debug_rnglists,
32613271 .value_debug_info,
32623272 .global_debug_info,
32633273 .func_frame_fde,
......@@ -3276,8 +3286,8 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {
32763286pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) link.Error!link.File.SymbolId {
32773287 const diags = &elf.base.comp.link_diags;
32783288 return elf.lazySymbolInner(lazy) catch |err| switch (err) {
3279 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
32803289 else => |e| return e,
3290 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
32813291 };
32823292}
32833293fn lazySymbolInner(elf: *Elf, lazy: link.File.LazySymbol) Error!link.File.SymbolId {
......@@ -3331,8 +3341,8 @@ pub const ExternSymbolOpts = struct {
33313341pub fn externSymbol(elf: *Elf, opts: ExternSymbolOpts) link.Error!link.File.SymbolId {
33323342 const diags = &elf.base.comp.link_diags;
33333343 return (elf.externSymbolInner(opts) catch |err| switch (err) {
3334 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
33353344 else => |e| return e,
3345 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
33363346 }).toTypeErased();
33373347}
33383348fn externSymbolInner(elf: *Elf, opts: ExternSymbolOpts) Error!Symbol.Id {
......@@ -3372,15 +3382,15 @@ pub fn addReloc(
33723382 const node: MappedFile.Node.Index = Node.fromAtom(atom);
33733383 const diags = &elf.base.comp.link_diags;
33743384 elf.ensureUnusedRelocCapacity(node, 1) catch |err| switch (err) {
3375 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
33763385 else => |e| return e,
3386 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
33773387 };
33783388 elf.addRelocAssumeCapacity(node, offset, .fromTypeErased(target), addend, @"type") catch |err| switch (err) {
3389 else => |e| return e,
33793390 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
33803391 error.UnknownRelocation => unreachable, // codegen bug
33813392 error.NonStaticRelocation => unreachable, // codegen bug
33823393 error.UnimplementedRelocation => unreachable, // codegen bug (asking Elf2 for a relocation it does not support)
3383 else => |e| return e,
33843394 };
33853395}
33863396pub fn addNodeReloc(
......@@ -3393,12 +3403,12 @@ pub fn addNodeReloc(
33933403) link.Error!void {
33943404 const diags = &elf.base.comp.link_diags;
33953405 elf.ensureUnusedRelocCapacity(node, 1) catch |err| switch (err) {
3396 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
33973406 else => |e| return e,
3407 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
33983408 };
33993409 elf.addNodeRelocAssumeCapacity(node, offset, target, addend, @"type") catch |err| switch (err) {
3400 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
34013410 else => |e| return e,
3411 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
34023412 };
34033413}
34043414pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.File.SymbolId {
......@@ -3416,8 +3426,8 @@ pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.Fil
34163426 });
34173427 }
34183428 const nmi = elf.navMapIndex(zcu, nav_index) catch |err| switch (err) {
3419 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
34203429 else => |e| return e,
3430 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
34213431 };
34223432 const s: Symbol.Id = .local(nmi.symbol(elf));
34233433 return s.toTypeErased();
......@@ -3429,8 +3439,8 @@ pub fn uavSymbol(
34293439) link.Error!link.File.SymbolId {
34303440 const diags = &elf.base.comp.link_diags;
34313441 const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) {
3432 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
34333442 else => |e| return e,
3443 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
34343444 };
34353445 const s: Symbol.Id = .local(umi.symbol(elf));
34363446 return s.toTypeErased();
......@@ -3470,8 +3480,8 @@ pub fn lowerUav(
34703480 _ = pt;
34713481 const diags = &elf.base.comp.link_diags;
34723482 const umi = elf.uavMapIndex(uav_val, uav_align) catch |err| switch (err) {
3473 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
34743483 else => |e| return e,
3484 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
34753485 };
34763486 const s: Symbol.Id = .local(umi.symbol(elf));
34773487 return s.toTypeErased();
......@@ -3705,6 +3715,7 @@ fn create(
37053715 .debug_info = .UNDEF,
37063716 .debug_line = .UNDEF,
37073717 .debug_line_str = .UNDEF,
3718 .debug_rnglists = .UNDEF,
37083719 .debug_str = .UNDEF,
37093720 .debug_str_offsets = .UNDEF,
37103721 .init_array = .UNDEF,
......@@ -3819,6 +3830,7 @@ pub fn deinit(elf: *Elf) void {
38193830 elf.changed_symtab_index.deinit(gpa);
38203831
38213832 elf.dwarf.deinit();
3833 for (elf.dwarf_units.items) |*dwarf_unit| dwarf_unit.debug_rnglists_symbol_relocs.deinit(gpa);
38223834 elf.dwarf_units.deinit(gpa);
38233835 elf.dwarf_values.deinit(gpa);
38243836 elf.dwarf_globals.deinit(gpa);
......@@ -3900,6 +3912,7 @@ fn initHeaders(
39003912 shnum += 1; // .debug_info
39013913 shnum += 1; // .debug_line
39023914 shnum += 1; // .debug_line_str
3915 shnum += 1; // .debug_rnglists
39033916 shnum += 1; // .debug_str
39043917 shnum += 1; // .debug_str_offsets
39053918 },
......@@ -4744,22 +4757,22 @@ fn initHeaders(
47444757 elf.plt_first_symbol_reloc = @fromBackingInt(@intCast(elf.symbol_relocs.items.len));
47454758 try elf.ensureUnusedRelocCapacity(plt_ni, 3);
47464759 elf.addRelocAssumeCapacity(plt_ni, 0, got_plt_sym, 0, .{ .LARCH = .PCALA_HI20 }) catch |err| switch (err) {
4760 else => |e| return e,
47474761 error.UnknownRelocation => unreachable,
47484762 error.NonStaticRelocation => unreachable,
47494763 error.UnimplementedRelocation => unreachable,
4750 else => |e| return e,
47514764 };
47524765 elf.addRelocAssumeCapacity(plt_ni, 8, got_plt_sym, 0, .{ .LARCH = .PCALA_LO12 }) catch |err| switch (err) {
4766 else => |e| return e,
47534767 error.UnknownRelocation => unreachable,
47544768 error.NonStaticRelocation => unreachable,
47554769 error.UnimplementedRelocation => unreachable,
4756 else => |e| return e,
47574770 };
47584771 elf.addRelocAssumeCapacity(plt_ni, 16, got_plt_sym, 0, .{ .LARCH = .PCALA_LO12 }) catch |err| switch (err) {
4772 else => |e| return e,
47594773 error.UnknownRelocation => unreachable,
47604774 error.NonStaticRelocation => unreachable,
47614775 error.UnimplementedRelocation => unreachable,
4762 else => |e| return e,
47634776 };
47644777 },
47654778 .SPARCV9 => {},
......@@ -5008,6 +5021,10 @@ fn initHeaders(
50085021 .name = ".debug_line_str",
50095022 .flags = .{ .MERGE = true, .STRINGS = true },
50105023 });
5024 elf.shndx.debug_rnglists = try elf.addSection(elf.ni.elf, .{
5025 .name = ".debug_rnglists",
5026 .node_align = elf.mf.flags.block_size,
5027 });
50115028 elf.shndx.debug_str = try elf.addSection(elf.ni.elf, .{
50125029 .name = ".debug_str",
50135030 .flags = .{ .MERGE = true, .STRINGS = true },
......@@ -5118,6 +5135,7 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
51185135 .unit_frame,
51195136 .unit_debug_info,
51205137 .unit_debug_line,
5138 .unit_debug_rnglists,
51215139 => elf.getNode(ni.parent(&elf.mf).unwrap().?).section,
51225140 .unit_frame_cie,
51235141 .unit_debug_info_header,
......@@ -5157,6 +5175,7 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
51575175 .unit_debug_info_header,
51585176 .unit_debug_line,
51595177 .unit_debug_line_header,
5178 .unit_debug_rnglists,
51605179 .value_debug_info,
51615180 .global_debug_info,
51625181 .func_frame_fde,
......@@ -5190,6 +5209,7 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
51905209 .unit_frame_cie,
51915210 .unit_debug_info_header,
51925211 .unit_debug_line_header,
5212 .unit_debug_rnglists,
51935213 .value_debug_info,
51945214 .global_debug_info,
51955215 .func_frame_fde,
......@@ -5210,7 +5230,12 @@ fn getNodeElfOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 {
52105230/// Asserts that `ni` must be a node which supports relocations (see `Elf.Node`). Does not support
52115231/// the special-case sections '.plt', '.dynamic', and '.eh_frame_hdr'.
52125232fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
5213 const symbol_relocs: ?*SymbolReloc.Index, const node_relocs: ?*NodeReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) {
5233 const opts: struct {
5234 ignore_node: MappedFile.Node.Index.Optional = .none,
5235 first_symbol_reloc: ?*SymbolReloc.Index = null,
5236 first_node_reloc: ?*NodeReloc.Index = null,
5237 first_got_reloc: ?*GotReloc.Index = null,
5238 } = switch (elf.getNode(ni)) {
52145239 .archive,
52155240 .archive_header,
52165241 .archive_input_member,
......@@ -5231,65 +5256,55 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
52315256 .section_manual_size,
52325257 => unreachable, // cannot contain relocs (.plt, .dynamic, and .eh_frame_hdr unsupported)
52335258 .input_section => |isi| .{
5234 &elf.input_sections.items[@backingInt(isi)].first_symbol_reloc,
5235 null,
5236 &elf.input_sections.items[@backingInt(isi)].first_got_reloc,
5259 .first_symbol_reloc = &elf.input_sections.items[@backingInt(isi)].first_symbol_reloc,
5260 .first_got_reloc = &elf.input_sections.items[@backingInt(isi)].first_got_reloc,
52375261 },
52385262 .nav => |nmi| .{
5239 &elf.navs.values()[@backingInt(nmi)].first_symbol_reloc,
5240 null,
5241 &elf.navs.values()[@backingInt(nmi)].first_got_reloc,
5263 .first_symbol_reloc = &elf.navs.values()[@backingInt(nmi)].first_symbol_reloc,
5264 .first_got_reloc = &elf.navs.values()[@backingInt(nmi)].first_got_reloc,
52425265 },
52435266 .uav => |umi| .{
5244 &elf.uavs.values()[@backingInt(umi)].first_symbol_reloc,
5245 null,
5246 null,
5267 .first_symbol_reloc = &elf.uavs.values()[@backingInt(umi)].first_symbol_reloc,
52475268 },
52485269 inline .lazy_code, .lazy_const_data => |lmi| .{
5249 &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_symbol_reloc,
5250 null,
5251 &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_got_reloc,
5270 .first_symbol_reloc = &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_symbol_reloc,
5271 .first_got_reloc = &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_got_reloc,
52525272 },
52535273 .unit_debug_info_header => |ui| .{
5254 null,
5255 &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_node_reloc,
5256 null,
5274 .first_node_reloc = &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_node_reloc,
52575275 },
52585276 .unit_debug_line_header => |ui| .{
5259 null,
5260 &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_node_reloc,
5261 null,
5277 .first_node_reloc = &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_node_reloc,
52625278 },
5279 .unit_debug_rnglists => unreachable, // unsupported
52635280 .value_debug_info => |vi| .{
5264 &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_symbol_reloc,
5265 &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_node_reloc,
5266 null,
5281 .first_symbol_reloc = &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_symbol_reloc,
5282 .first_node_reloc = &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_node_reloc,
52675283 },
52685284 .global_debug_info => |gi| .{
5269 &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_symbol_reloc,
5270 &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_node_reloc,
5271 null,
5285 .first_symbol_reloc = &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_symbol_reloc,
5286 .first_node_reloc = &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_node_reloc,
52725287 },
52735288 .func_frame_fde => |fi| .{
5274 &elf.dwarf_funcs.items[@backingInt(fi)].frame_fde_first_symbol_reloc,
5275 &elf.dwarf_funcs.items[@backingInt(fi)].frame_fde_first_node_reloc,
5276 null,
5289 .first_symbol_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].frame_fde_first_symbol_reloc,
5290 .first_node_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].frame_fde_first_node_reloc,
52775291 },
52785292 .func_debug_info => |fi| .{
5279 &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_symbol_reloc,
5280 &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_node_reloc,
5281 null,
5293 .ignore_node = fi.get(&elf.dwarf).debug_line_ni,
5294 .first_symbol_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_symbol_reloc,
5295 .first_node_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_node_reloc,
52825296 },
52835297 .func_debug_line => |fi| .{
5284 &elf.dwarf_funcs.items[@backingInt(fi)].debug_line_first_symbol_reloc,
5285 &elf.dwarf_funcs.items[@backingInt(fi)].debug_line_first_node_reloc,
5286 null,
5298 .ignore_node = fi.get(&elf.dwarf).debug_info_ni,
5299 .first_symbol_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].debug_line_first_symbol_reloc,
5300 .first_node_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].debug_line_first_node_reloc,
52875301 },
52885302 };
52895303
5290 if (symbol_relocs) |ptr| {
5304 if (opts.first_symbol_reloc) |ptr| {
52915305 if (ptr.* != .none) {
52925306 for (elf.symbol_relocs.items[@backingInt(ptr.*)..], @backingInt(ptr.*)..) |*reloc, index| {
5307 if (reloc.node.toOptional() == opts.ignore_node) continue;
52935308 if (reloc.node != ni) break;
52945309 reloc.delete(elf, @fromBackingInt(@intCast(index)));
52955310 }
......@@ -5297,9 +5312,10 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
52975312 ptr.* = @fromBackingInt(@intCast(elf.symbol_relocs.items.len));
52985313 }
52995314
5300 if (node_relocs) |ptr| {
5315 if (opts.first_node_reloc) |ptr| {
53015316 if (ptr.* != .none) {
53025317 for (elf.node_relocs.items[@backingInt(ptr.*)..]) |*reloc| {
5318 if (reloc.node.toOptional() == opts.ignore_node) continue;
53035319 if (reloc.node != ni) break;
53045320 reloc.delete(elf);
53055321 }
......@@ -5307,9 +5323,10 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
53075323 ptr.* = @fromBackingInt(@intCast(elf.node_relocs.items.len));
53085324 }
53095325
5310 if (got_relocs) |ptr| {
5326 if (opts.first_got_reloc) |ptr| {
53115327 if (ptr.* != .none) {
53125328 for (elf.got_relocs.items[@backingInt(ptr.*)..]) |*reloc| {
5329 if (reloc.node == opts.ignore_node) continue;
53135330 if (reloc.node != ni.toOptional()) break;
53145331 reloc.delete(elf);
53155332 }
......@@ -5324,12 +5341,16 @@ fn flushMovedNodeRelocs(
53245341 elf: *Elf,
53255342 node: MappedFile.Node.Index,
53265343 node_vaddr: u64,
5327 first_symbol_reloc: SymbolReloc.Index,
5328 first_node_reloc: NodeReloc.Index,
5329 first_got_reloc: GotReloc.Index,
5344 opts: struct {
5345 ignore_node: MappedFile.Node.Index.Optional = .none,
5346 first_symbol_reloc: SymbolReloc.Index = .none,
5347 first_node_reloc: NodeReloc.Index = .none,
5348 first_got_reloc: GotReloc.Index = .none,
5349 },
53305350) void {
5331 if (first_symbol_reloc != .none) {
5332 for (elf.symbol_relocs.items[@backingInt(first_symbol_reloc)..]) |*reloc| {
5351 if (opts.first_symbol_reloc != .none) {
5352 for (elf.symbol_relocs.items[@backingInt(opts.first_symbol_reloc)..]) |*reloc| {
5353 if (reloc.node.toOptional() == opts.ignore_node) continue;
53335354 if (reloc.node != node) break;
53345355 if (reloc.rela_index.unwrap()) |rela_index| {
53355356 // The node has moved, so the offset of the relocation within the section might have
......@@ -5345,8 +5366,9 @@ fn flushMovedNodeRelocs(
53455366 }
53465367 }
53475368
5348 if (first_node_reloc != .none) {
5349 for (elf.node_relocs.items[@backingInt(first_node_reloc)..]) |*reloc| {
5369 if (opts.first_node_reloc != .none) {
5370 for (elf.node_relocs.items[@backingInt(opts.first_node_reloc)..]) |*reloc| {
5371 if (reloc.node.toOptional() == opts.ignore_node) continue;
53505372 if (reloc.node != node) break;
53515373 if (reloc.rela_index.unwrap()) |rela_index| {
53525374 assert(elf.ehdrType() == .REL);
......@@ -5360,8 +5382,9 @@ fn flushMovedNodeRelocs(
53605382 }
53615383 }
53625384
5363 if (first_got_reloc != .none) {
5364 for (elf.got_relocs.items[@backingInt(first_got_reloc)..]) |*reloc| {
5385 if (opts.first_got_reloc != .none) {
5386 for (elf.got_relocs.items[@backingInt(opts.first_got_reloc)..]) |*reloc| {
5387 if (reloc.node == opts.ignore_node) continue;
53655388 if (reloc.node != node.toOptional()) break;
53665389 reloc.apply(elf);
53675390 }
......@@ -5814,6 +5837,7 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node
58145837 })) |shndx| {
58155838 break :section shndx;
58165839 } else |err| switch (err) {
5840 else => |e| return e,
58175841 error.StripSection,
58185842 error.TlsSectionUnavailable,
58195843 error.UnsupportedSectionFlags,
......@@ -5821,7 +5845,6 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node
58215845 error.SectionFlagsConflict,
58225846 => {}, // fall back to default behavior below
58235847
5824 else => |e| return e,
58255848 }
58265849 }
58275850 if (elf.base.comp.config.any_non_single_threaded and nav.resolved.?.@"threadlocal") {
......@@ -6074,8 +6097,8 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load
60746097 strtab.clearRetainingCapacity();
60756098 try strtab.ensureTotalCapacityPrecise(size);
60766099 r.streamExact(&strtab.writer, size) catch |err| switch (err) {
6077 error.WriteFailed => return error.OutOfMemory,
60786100 else => |e| return e,
6101 error.WriteFailed => return error.OutOfMemory,
60796102 };
60806103 continue;
60816104 }
......@@ -6106,8 +6129,8 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load
61066129 }
61076130 try fr.seekTo(std.mem.alignForward(u64, offset + size, 2));
61086131 } else |err| switch (err) {
6109 error.EndOfStream => if (!fr.atEnd()) return error.EndOfStream,
61106132 else => |e| return e,
6133 error.EndOfStream => if (!fr.atEnd()) return error.EndOfStream,
61116134 }
61126135}
61136136fn fmtMemberString(member: ?[]const u8) std.fmt.Alt(?[]const u8, memberStringEscape) {
......@@ -6273,6 +6296,7 @@ fn loadObject(
62736296 .flags = section.shdr.flags.shf,
62746297 .entsize = section.shdr.entsize,
62756298 }) catch |err| switch (err) {
6299 else => |e| return e,
62766300 error.StripSection => continue,
62776301 error.TlsSectionUnavailable => return diags.failParse(
62786302 path,
......@@ -6303,7 +6327,6 @@ fn loadObject(
63036327 "flags of section '{s}' conflict with other inputs",
63046328 .{name},
63056329 ),
6306 else => |e| return e,
63076330 };
63086331 if (section.shdr.flags.shf.COMPRESSED) {
63096332 // SHF_COMPRESSED is only allowed on non-alloc sections.
......@@ -6585,6 +6608,7 @@ fn loadObject(
65856608 rel.addend,
65866609 rt,
65876610 ) catch |err| switch (err) {
6611 else => |e| return e,
65886612 error.UnknownRelocation => diags.addParseError(
65896613 path,
65906614 "unknown relocation type '{f}'",
......@@ -6600,7 +6624,6 @@ fn loadObject(
66006624 "TODO(Elf2): unimplemented relocation type '{f}'",
66016625 .{rt.fmt(elf)},
66026626 ),
6603 else => |e| return e,
66046627 };
66056628 }
66066629 },
......@@ -6997,7 +7020,7 @@ pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) link.Error!void {
69977020fn prelinkInner(elf: *Elf) Error!void {
69987021 const comp = elf.base.comp;
69997022 const gpa = comp.gpa;
7000 if (comp.zcu) |zcu| self_hosted_codegen: {
7023 if (comp.zcu) |_| self_hosted_codegen: {
70017024 if (comp.config.use_llvm) break :self_hosted_codegen;
70027025
70037026 // We're using self-hosted codegen---add an input representing the Zig "object".
......@@ -7019,15 +7042,32 @@ fn prelinkInner(elf: *Elf) Error!void {
70197042 .extra = .{ .file_symbol = zcu_file_symbol },
70207043 };
70217044 elf.input_pending_index += 1;
7045 }
7046}
7047
7048pub fn zcuFilesReady(elf: *Elf, zcu: *Zcu) link.Error!void {
7049 elf.zcuFilesReadyInner(zcu) catch |err| switch (err) {
7050 else => |e| return e,
7051 error.MappedFileIo => return elf.base.comp.link_diags.fail(
7052 "failed to write output file: {t}",
7053 .{elf.mf.io_err.?},
7054 ),
7055 };
7056}
7057fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void {
7058 const gpa = zcu.gpa;
70227059
7060 if (elf.dwarf.units.count() == 0) {
70237061 try elf.dwarf.initUnits(zcu);
7024 try elf.nodes.ensureUnusedCapacity(gpa, 4 + 4 + (4 + 4) * elf.dwarf.units.count());
7062 try elf.nodes.ensureUnusedCapacity(gpa, 4 + 5 + 5 * elf.dwarf.units.count());
70257063 try elf.dwarf_units.appendNTimes(gpa, .{
70267064 .frame_cie_first_target_reloc = .none,
70277065 .debug_info_header_first_target_reloc = .none,
70287066 .debug_info_header_first_node_reloc = .none,
70297067 .debug_line_header_first_target_reloc = .none,
70307068 .debug_line_header_first_node_reloc = .none,
7069 .debug_rnglists_first_target_reloc = .none,
7070 .debug_rnglists_symbol_relocs = .empty,
70317071 }, elf.dwarf.units.count());
70327072
70337073 elf.dwarf.debug_abbrev.ni =
......@@ -7046,11 +7086,12 @@ fn prelinkInner(elf: *Elf) Error!void {
70467086 .wrap(try elf.shndx.debug_str_offsets.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}));
70477087 elf.nodes.appendAssumeCapacity(.{ .debug_shared = .debug_str_offsets });
70487088
7049 for ([4]Section.Index{
7089 for ([5]Section.Index{
70507090 elf.shndx.eh_frame,
70517091 elf.shndx.debug_frame,
70527092 elf.shndx.debug_info,
70537093 elf.shndx.debug_line,
7094 elf.shndx.debug_rnglists,
70547095 }) |debug_shndx| {
70557096 if (debug_shndx == .UNDEF) continue;
70567097 const debug_ni = debug_shndx.get(elf).ni;
......@@ -7085,7 +7126,6 @@ fn prelinkInner(elf: *Elf) Error!void {
70857126 const debug_info_ni =
70867127 try debug_info_shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{
70877128 .alignment = elf.mf.flags.block_size,
7088 .next_moved = true,
70897129 .enable_next_moved = true,
70907130 });
70917131 unit.debug_info_ni = .wrap(debug_info_ni);
......@@ -7105,7 +7145,6 @@ fn prelinkInner(elf: *Elf) Error!void {
71057145 const debug_line_ni =
71067146 try debug_line_shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{
71077147 .alignment = elf.mf.flags.block_size,
7108 .next_moved = true,
71097148 .enable_next_moved = true,
71107149 });
71117150 unit.debug_line_ni = .wrap(debug_line_ni);
......@@ -7113,43 +7152,72 @@ fn prelinkInner(elf: *Elf) Error!void {
71137152
71147153 unit.debug_line_header_ni =
71157154 .wrap(try debug_line_ni.addOnlyHeaderChild(&elf.mf, gpa, .{
7116 .next_moved = true,
7155 // Idle tasks are going to try to keep this up to date before we are able to
7156 // write out the full header, so just reserve space for them to do so.
7157 .size = elf.dwarf.unitLengthSize(),
71177158 .enable_next_moved = true,
71187159 }));
71197160 elf.nodes.appendAssumeCapacity(.{ .unit_debug_line_header = ui });
71207161 },
71217162 }
7163 switch (elf.shndx.debug_rnglists) {
7164 .UNDEF => {},
7165 else => |debug_rnglists_shndx| {
7166 unit.debug_rnglists_ni =
7167 .wrap(try debug_rnglists_shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{
7168 .next_moved = true,
7169 .enable_next_moved = true,
7170 }));
7171 elf.nodes.appendAssumeCapacity(.{ .unit_debug_rnglists = ui });
7172 },
7173 }
71227174 }
71237175
7124 for (0.., elf.dwarf.units.values()) |unit_index, *unit| {
7125 const ui: Dwarf.Unit.Index = @fromBackingInt(@intCast(unit_index));
7126 if (elf.shndx.debug_info != .UNDEF) {
7127 var header_nw: MappedFile.Node.Writer = undefined;
7128 const debug_info_header_ni = unit.debug_info_header_ni.unwrap().?;
7129 debug_info_header_ni.writer(&elf.mf, gpa, &header_nw);
7130 defer header_nw.deinit();
7131 elf.resetNodeRelocs(debug_info_header_ni);
7132 elf.dwarf.genDebugInfoHeader(&header_nw, ui, zcu) catch |err| switch (err) {
7133 error.WriteFailed => return header_nw.err.?,
7176 for (elf.dwarf.units.keys(), elf.dwarf.units.values()) |mod, *unit| {
7177 var drh_nw: MappedFile.Node.Writer = undefined;
7178 unit.debug_rnglists_ni.unwrap().?.writer(&elf.mf, gpa, &drh_nw);
7179 defer drh_nw.deinit();
7180 const debug_rnglists_offsets_table_offset =
7181 elf.dwarf.genDebugRnglistsHeader(unit, &drh_nw) catch |err| switch (err) {
71347182 else => |e| return e,
7183 error.WriteFailed => return drh_nw.err.?,
71357184 };
7136 }
7137 if (elf.shndx.debug_line != .UNDEF) {
7138 var header_nw: MappedFile.Node.Writer = undefined;
7139 const debug_line_header_ni = unit.debug_line_header_ni.unwrap().?;
7140 debug_line_header_ni.writer(&elf.mf, gpa, &header_nw);
7141 defer header_nw.deinit();
7142 elf.resetNodeRelocs(debug_line_header_ni);
7143 elf.dwarf.genDebugLineHeader(&header_nw.interface) catch |err| switch (err) {
7144 error.WriteFailed => return header_nw.err.?,
7145 };
7146 }
7185
7186 var dih_nw: MappedFile.Node.Writer = undefined;
7187 const debug_info_header_ni = unit.debug_info_header_ni.unwrap().?;
7188 debug_info_header_ni.writer(&elf.mf, gpa, &dih_nw);
7189 defer dih_nw.deinit();
7190 elf.resetNodeRelocs(debug_info_header_ni);
7191 elf.dwarf.genDebugInfoHeader(
7192 mod,
7193 unit,
7194 &dih_nw,
7195 debug_rnglists_offsets_table_offset,
7196 zcu,
7197 ) catch |err| switch (err) {
7198 else => |e| return e,
7199 error.WriteFailed => return dih_nw.err.?,
7200 };
71477201 }
71487202 }
71497203}
71507204
7151pub fn zcuFilesReady(elf: *Elf) link.Error!void {
7152 _ = elf; // TODO jacobly
7205fn flushFiles(elf: *Elf) Error!void {
7206 const gpa = elf.base.comp.gpa;
7207 if (elf.shndx.debug_line != .UNDEF) for (elf.dwarf.units.keys(), elf.dwarf.units.values()) |mod, *unit| {
7208 if (!unit.cleanFilesChanged()) continue;
7209 const debug_line_header_ni = unit.debug_line_header_ni.unwrap().?;
7210 try debug_line_header_ni.moved(gpa, &elf.mf);
7211 try debug_line_header_ni.nextMoved(gpa, &elf.mf);
7212 var dlh_nw: MappedFile.Node.Writer = undefined;
7213 debug_line_header_ni.writer(&elf.mf, gpa, &dlh_nw);
7214 defer dlh_nw.deinit();
7215 elf.resetNodeRelocs(debug_line_header_ni);
7216 elf.dwarf.genDebugLineHeader(mod, unit, &dlh_nw, elf.base.comp.zcu.?) catch |err| switch (err) {
7217 else => |e| return e,
7218 error.WriteFailed => return dlh_nw.err.?,
7219 };
7220 };
71537221}
71547222
71557223fn prepareDynamic(elf: *Elf) Error!void {
......@@ -7952,6 +8020,10 @@ fn addNodeRelocAssumeCapacity(
79528020 .unit_frame_cie => |ui| &elf.dwarf_units.items[@backingInt(ui)].frame_cie_first_target_reloc,
79538021 .unit_debug_info_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_target_reloc,
79548022 .unit_debug_line_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_target_reloc,
8023 .unit_debug_rnglists => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_rnglists_first_target_reloc,
8024 .value_debug_info => |vi| &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_target_reloc,
8025 .global_debug_info => |gi| &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_target_reloc,
8026 .func_debug_info => |fi| &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_target_reloc,
79558027 };
79568028 const next = first_target_reloc.*;
79578029 const ri: NodeReloc.Index = @fromBackingInt(@intCast(elf.node_relocs.items.len));
......@@ -8052,6 +8124,7 @@ fn addGotRelocAssumeCapacity(
80528124 .unit_debug_info_header,
80538125 .unit_debug_line,
80548126 .unit_debug_line_header,
8127 .unit_debug_rnglists,
80558128 .value_debug_info,
80568129 .global_debug_info,
80578130 .func_frame_fde,
......@@ -8331,10 +8404,12 @@ fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) Error!bool {
83318404}
83328405
83338406pub fn updateNav(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) link.Error!void {
8334 const diags = &elf.base.comp.link_diags;
83358407 elf.updateNavInner(pt, nav_index) catch |err| switch (err) {
8336 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
83378408 else => |e| return e,
8409 error.MappedFileIo => return elf.base.comp.link_diags.fail(
8410 "failed to write output file: {t}",
8411 .{elf.mf.io_err.?},
8412 ),
83388413 };
83398414}
83408415fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Error!void {
......@@ -8365,8 +8440,8 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
83658440 &nw.interface,
83668441 .{ .atom_index = Node.toAtom(ni) },
83678442 ) catch |err| switch (err) {
8368 error.WriteFailed => return nw.err.?,
83698443 else => |e| return e,
8444 error.WriteFailed => return nw.err.?,
83708445 };
83718446 switch (elf.symPtr(nmi.symbol(elf).index())) {
83728447 inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)),
......@@ -8383,10 +8458,12 @@ pub fn updateFunc(
83838458 func_index: InternPool.Index,
83848459 mir: *const codegen.AnyMir,
83858460) link.Error!void {
8386 const diags = &elf.base.comp.link_diags;
83878461 elf.updateFuncInner(pt, func_index, mir) catch |err| switch (err) {
8388 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
83898462 else => |e| return e,
8463 error.MappedFileIo => return elf.base.comp.link_diags.fail(
8464 "failed to write output file: {t}",
8465 .{elf.mf.io_err.?},
8466 ),
83908467 };
83918468}
83928469fn updateFuncInner(
......@@ -8403,7 +8480,8 @@ fn updateFuncInner(
84038480
84048481 const nmi = try elf.navMapIndex(zcu, func.owner_nav);
84058482 log.debug("updateFunc({f}) = {d}", .{ nav.fqn.fmt(ip), nmi.symbol(elf) });
8406 const ni = nmi.symbol(elf).index().ptr(elf).node.unwrap().?;
8483 const lsi = nmi.symbol(elf);
8484 const ni = lsi.index().ptr(elf).node.unwrap().?;
84078485
84088486 // Ensure the NAV is marked as moved so that once we're done, `flushMoved` will eventually be
84098487 // called to apply the NAV's new relocations.
......@@ -8421,7 +8499,7 @@ fn updateFuncInner(
84218499 if (mod.strip and mod.unwind_tables == .none) break :debug_output .{ .none, undefined };
84228500
84238501 try elf.nodes.ensureUnusedCapacity(gpa, 5);
8424 const dwarf_func_index = try dwarf.getFunc(func.owner_nav);
8502 const dwarf_fi = try dwarf.getFunc(func.owner_nav);
84258503 try elf.dwarf_funcs.appendNTimes(gpa, .{
84268504 .frame_fde_first_symbol_reloc = .none,
84278505 .frame_fde_first_node_reloc = .none,
......@@ -8430,14 +8508,14 @@ fn updateFuncInner(
84308508 .debug_info_first_node_reloc = .none,
84318509 .debug_line_first_symbol_reloc = .none,
84328510 .debug_line_first_node_reloc = .none,
8433 }, @backingInt(dwarf_func_index) + 1 -| elf.dwarf_funcs.items.len);
8511 }, @backingInt(dwarf_fi) + 1 -| elf.dwarf_funcs.items.len);
84348512
84358513 const wip_nav = &debug_output_buf.wip_nav;
84368514 wip_nav.* = .{
84378515 .dwarf = dwarf,
84388516 .unit = dwarf.getUnit(mod),
8439 .func = dwarf_func_index,
8440 .func_si = Symbol.Id.local(nmi.symbol(elf)).toTypeErased(),
8517 .func = dwarf_fi,
8518 .func_si = Symbol.Id.local(lsi).toTypeErased(),
84418519 .cfi = .{
84428520 .loc = 0,
84438521 .cfa = dwarf.frame.header.initial_instructions[0].def_cfa,
......@@ -8462,7 +8540,6 @@ fn updateFuncInner(
84628540 .eh_frame => elf.shndx.eh_frame,
84638541 }.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{
84648542 .alignment = frame_align.max(elf.mf.flags.block_size),
8465 .next_moved = true,
84668543 .enable_next_moved = true,
84678544 });
84688545 unit.frame_ni = .wrap(frame_ni);
......@@ -8487,7 +8564,7 @@ fn updateFuncInner(
84878564 error.WriteFailed => return cie_nw.err.?,
84888565 };
84898566 };
8490 const dwarf_func = dwarf_func_index.get(dwarf);
8567 const dwarf_func = dwarf_fi.get(dwarf);
84918568 const fde_ni = if (dwarf_func.fde_ni.unwrap()) |fde_ni| fde_ni: {
84928569 try fde_ni.moved(gpa, &elf.mf);
84938570 try fde_ni.nextMoved(gpa, &elf.mf);
......@@ -8510,24 +8587,34 @@ fn updateFuncInner(
85108587 debug.pt = pt;
85118588 debug.any_children = false;
85128589 debug.blocks = .empty;
8513 const debug_info_ni = dwarf_func.debug_info_ni.unwrap() orelse debug_info_ni: {
8590 const debug_info_ni = if (dwarf_func.debug_info_ni.unwrap()) |debug_info_ni| debug_info_ni: {
8591 try debug_info_ni.moved(gpa, &elf.mf);
8592 try debug_info_ni.nextMoved(gpa, &elf.mf);
8593 break :debug_info_ni debug_info_ni;
8594 } else debug_info_ni: {
85148595 const debug_info_ni =
85158596 try unit.debug_info_ni.unwrap().?.addFloatingChild(&elf.mf, gpa, .{
8597 .moved = true,
85168598 .next_moved = true,
85178599 .enable_next_moved = true,
85188600 });
85198601 dwarf_func.debug_info_ni = .wrap(debug_info_ni);
8520 elf.nodes.appendAssumeCapacity(.{ .func_debug_info = dwarf_func_index });
8602 elf.nodes.appendAssumeCapacity(.{ .func_debug_info = dwarf_fi });
85218603 break :debug_info_ni debug_info_ni;
85228604 };
85238605 debug_info_ni.writer(&elf.mf, gpa, &debug.info_writer);
8524 const debug_line_ni = dwarf_func.debug_line_ni.unwrap() orelse debug_line_ni: {
8606 const debug_line_ni = if (dwarf_func.debug_line_ni.unwrap()) |debug_line_ni| debug_line_ni: {
8607 try debug_line_ni.moved(gpa, &elf.mf);
8608 try debug_line_ni.nextMoved(gpa, &elf.mf);
8609 break :debug_line_ni debug_line_ni;
8610 } else debug_line_ni: {
85258611 const debug_line_ni =
85268612 try unit.debug_line_ni.unwrap().?.addFloatingChild(&elf.mf, gpa, .{
8613 .moved = true,
85278614 .next_moved = true,
85288615 .enable_next_moved = true,
85298616 });
8530 elf.nodes.appendAssumeCapacity(.{ .func_debug_line = dwarf_func_index });
8617 elf.nodes.appendAssumeCapacity(.{ .func_debug_line = dwarf_fi });
85318618 break :debug_line_ni debug_line_ni;
85328619 };
85338620 debug_line_ni.writer(&elf.mf, gpa, &debug.line_writer);
......@@ -8549,7 +8636,8 @@ fn updateFuncInner(
85498636 elf.resetNodeRelocs(dwarf_func.fde_ni.unwrap().?);
85508637 try debug.wip_nav.genDebugFrameHeader();
85518638 elf.resetNodeRelocs(dwarf_func.debug_info_ni.unwrap().?);
8552 try debug.startDebugInfo();
8639 elf.resetNodeRelocs(dwarf_func.debug_line_ni.unwrap().?);
8640 try debug.startFunc();
85538641 },
85548642 .none => {},
85558643 }
......@@ -8563,10 +8651,8 @@ fn updateFuncInner(
85638651 &nw.interface,
85648652 debug_output,
85658653 ) catch |err| switch (err) {
8566 error.WriteFailed => {
8567 if (nw.err) |e| return e;
8568 },
85698654 else => |e| return e,
8655 error.WriteFailed => if (nw.err) |e| return e,
85708656 };
85718657 const func_length = nw.interface.end;
85728658 switch (elf.symPtr(nmi.symbol(elf).index())) {
......@@ -8591,19 +8677,44 @@ fn updateFuncInner(
85918677 }
85928678 },
85938679 .dwarf2 => |debug| {
8594 try debug.finishFunc();
8595 for ([2]Section.Index{
8680 try debug.finishFunc(func_length);
8681 for ([3]Section.Index{
85968682 elf.shndx.debug_info,
85978683 elf.shndx.debug_line,
8684 elf.shndx.debug_rnglists,
85988685 }) |debug_shndx| try debug_shndx.get(elf).ni.trimStart(&elf.mf, gpa);
8686 const unit = debug.wip_nav.unit.get(debug.wip_nav.dwarf);
85998687 {
8600 const debug_info_ni =
8601 debug.wip_nav.unit.get(debug.wip_nav.dwarf).debug_info_ni.unwrap().?;
8688 const debug_info_ni = unit.debug_info_ni.unwrap().?;
86028689 const last_offset, const last_size =
86038690 debug_info_ni.last(&elf.mf).unwrap().?.location(&elf.mf).resolve(&elf.mf);
86048691 try debug_info_ni.ensureMinimumSize(&elf.mf, gpa, last_offset + last_size +
86058692 comptime Dwarf.uleb128Bytes(@backingInt(Dwarf.AbbrevCode.null)) * 2);
86068693 }
8694 {
8695 var dr_nw: MappedFile.Node.Writer = undefined;
8696 unit.debug_rnglists_ni.unwrap().?.writer(&elf.mf, gpa, &dr_nw);
8697 defer dr_nw.deinit();
8698 const first_symbol_reloc = elf.symbol_relocs.items.len;
8699 debug.wip_nav.dwarf.genDebugRnglists(
8700 unit,
8701 &dr_nw,
8702 debug.wip_nav.func_si,
8703 func_length,
8704 ) catch |err| switch (err) {
8705 else => |e| return e,
8706 error.WriteFailed => return dr_nw.err.?,
8707 };
8708 const symbol_relocs = &elf.dwarf_units.items[@backingInt(debug.wip_nav.unit)]
8709 .debug_rnglists_symbol_relocs;
8710 try symbol_relocs.ensureUnusedCapacity(gpa, elf.symbol_relocs.items.len -
8711 first_symbol_reloc);
8712 for (first_symbol_reloc..elf.symbol_relocs.items.len) |symbol_ri|
8713 symbol_relocs.putAssumeCapacityNoClobber(
8714 @fromBackingInt(@intCast(symbol_ri)),
8715 {},
8716 );
8717 }
86078718 continue :debug_output .{ .eh_frame = &debug.wip_nav };
86088719 },
86098720 .none => {},
......@@ -8615,13 +8726,15 @@ fn updateFuncInner(
86158726}
86168727
86178728pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) link.Error!void {
8618 const diags = &elf.base.comp.link_diags;
86198729 elf.genLazy(pt, .{
86208730 .kind = .const_data,
86218731 .index = @intCast(elf.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return),
86228732 }) catch |err| switch (err) {
8623 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
86248733 else => |e| return e,
8734 error.MappedFileIo => return elf.base.comp.link_diags.fail(
8735 "failed to write output file: {t}",
8736 .{elf.mf.io_err.?},
8737 ),
86258738 };
86268739}
86278740
......@@ -8632,8 +8745,11 @@ pub fn flush(
86328745 prog_node: std.Progress.Node,
86338746) link.Error!void {
86348747 elf.flushInner(arena, tid, prog_node) catch |err| switch (err) {
8635 error.MappedFileIo => return elf.base.comp.link_diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
86368748 else => |e| return e,
8749 error.MappedFileIo => return elf.base.comp.link_diags.fail(
8750 "failed to write output file: {t}",
8751 .{elf.mf.io_err.?},
8752 ),
86378753 };
86388754}
86398755fn flushInner(
......@@ -8649,6 +8765,8 @@ fn flushInner(
86498765 const sub_prog_node = prog_node.start("ELF Flush", 0);
86508766 defer sub_prog_node.end();
86518767
8768 try elf.flushFiles();
8769
86528770 if (comp.config.output_mode == .Exe) {
86538771 var any_undef = false;
86548772 for (elf.globals.strong_undef.keys()) |name| {
......@@ -8714,7 +8832,7 @@ fn flushInner(
87148832
87158833 if (elf.options.enable_link_snapshots)
87168834 elf.dumpStderr(tid) catch |err|
8717 return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err});
8835 return diags.fail("dumping link snapshot failed: {t}", .{err});
87188836}
87198837
87208838pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
......@@ -8737,8 +8855,8 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
87378855 const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(ii.node(elf)));
87388856 defer sub_prog_node.end();
87398857 elf.flushInput(ii) catch |err| switch (err) {
8740 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
87418858 else => |e| return e,
8859 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
87428860 };
87438861 break :task;
87448862 }
......@@ -8748,8 +8866,8 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
87488866 const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.node(elf)));
87498867 defer sub_prog_node.end();
87508868 elf.flushInputSection(isi) catch |err| switch (err) {
8751 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
87528869 else => |e| return e,
8870 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
87538871 };
87548872 break :task;
87558873 }
......@@ -8907,11 +9025,12 @@ fn idleProgNode(
89079025 .unit_debug_info_header,
89089026 .unit_debug_line,
89099027 .unit_debug_line_header,
9028 .unit_debug_rnglists,
89109029 => |ui, tag| std.mem.print(&name, "{s} info for {s}", .{
89119030 switch (tag) {
89129031 else => unreachable,
89139032 .unit_frame, .unit_frame_cie => "unwind",
8914 .unit_debug_info, .unit_debug_info_header => "debug",
9033 .unit_debug_info, .unit_debug_info_header, .unit_debug_rnglists => "debug",
89159034 .unit_debug_line, .unit_debug_line_header => "line",
89169035 },
89179036 ui.mod(&elf.dwarf).fully_qualified_name,
......@@ -8996,8 +9115,8 @@ fn genUav(
89969115 &nw.interface,
89979116 .{ .atom_index = Node.toAtom(ni) },
89989117 ) catch |err| switch (err) {
8999 error.WriteFailed => return nw.err.?,
90009118 else => |e| return e,
9119 error.WriteFailed => return nw.err.?,
90019120 };
90029121 switch (elf.symPtr(umi.symbol(elf).index())) {
90039122 inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)),
......@@ -9032,8 +9151,8 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void {
90329151 .none,
90339152 .{ .atom_index = Node.toAtom(ni) },
90349153 ) catch |err| switch (err) {
9035 error.WriteFailed => return nw.err.?,
90369154 else => |e| return e,
9155 error.WriteFailed => return nw.err.?,
90379156 };
90389157 switch (elf.symPtr(lmr.symbol(elf).index())) {
90399158 inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)),
......@@ -9241,14 +9360,18 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
92419360 reloc.apply(elf);
92429361 }
92439362 } else if (shndx == elf.shndx.plt) {
9244 elf.flushMovedNodeRelocs(ni, addr, elf.plt_first_symbol_reloc, .none, .none);
9363 elf.flushMovedNodeRelocs(ni, addr, .{
9364 .first_symbol_reloc = elf.plt_first_symbol_reloc,
9365 });
92459366 elf.flushMovedPltSection(.plt, old_addr, addr);
92469367 } else if (shndx == elf.shndx.got_plt) {
92479368 elf.flushMovedPltSection(.got_plt, old_addr, addr);
92489369 } else if (shndx == elf.shndx.plt_sec) {
92499370 elf.flushMovedPltSection(.plt_sec, old_addr, addr);
92509371 } else if (shndx == elf.shndx.eh_frame_hdr) {
9251 elf.flushMovedNodeRelocs(ni, addr, elf.eh_frame_hdr_first_symbol_reloc, .none, .none);
9372 elf.flushMovedNodeRelocs(ni, addr, .{
9373 .first_symbol_reloc = elf.eh_frame_hdr_first_symbol_reloc,
9374 });
92529375 }
92539376 },
92549377 .input_section => |isi| {
......@@ -9295,13 +9418,10 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
92959418 }
92969419 }
92979420
9298 elf.flushMovedNodeRelocs(
9299 ni,
9300 new_section_addr,
9301 isi.ptrConst(elf).first_symbol_reloc,
9302 .none,
9303 isi.ptrConst(elf).first_got_reloc,
9304 );
9421 elf.flushMovedNodeRelocs(ni, new_section_addr, .{
9422 .first_symbol_reloc = isi.ptrConst(elf).first_symbol_reloc,
9423 .first_got_reloc = isi.ptrConst(elf).first_got_reloc,
9424 });
93059425 },
93069426 .copied_global => |global_name| {
93079427 const copied_global = elf.copied_globals.getPtr(global_name) orelse {
......@@ -9327,13 +9447,10 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
93279447 name = elf.globalByName(name).?.next_in_node;
93289448 }
93299449 }
9330 elf.flushMovedNodeRelocs(
9331 ni,
9332 new_addr,
9333 mi.firstSymbolReloc(elf),
9334 .none,
9335 mi.firstGotReloc(elf),
9336 );
9450 elf.flushMovedNodeRelocs(ni, new_addr, .{
9451 .first_symbol_reloc = mi.firstSymbolReloc(elf),
9452 .first_got_reloc = mi.firstGotReloc(elf),
9453 });
93379454 },
93389455 .debug_shared => |ss| {
93399456 var target_ri = elf.dwarf_shared.getPtr(ss).first_target_reloc;
......@@ -9364,13 +9481,9 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
93649481 target_reloc.apply(elf);
93659482 target_ri = target_reloc.next;
93669483 }
9367 elf.flushMovedNodeRelocs(
9368 ni,
9369 elf.computeNodeVAddr(ni),
9370 .none,
9371 dwarf_unit.debug_info_header_first_node_reloc,
9372 .none,
9373 );
9484 elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{
9485 .first_node_reloc = dwarf_unit.debug_info_header_first_node_reloc,
9486 });
93749487 },
93759488 .unit_debug_line_header => |ui| {
93769489 const dwarf_unit = &elf.dwarf_units.items[@backingInt(ui)];
......@@ -9381,13 +9494,32 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
93819494 target_reloc.apply(elf);
93829495 target_ri = target_reloc.next;
93839496 }
9384 elf.flushMovedNodeRelocs(
9385 ni,
9386 elf.computeNodeVAddr(ni),
9387 .none,
9388 dwarf_unit.debug_line_header_first_node_reloc,
9389 .none,
9390 );
9497 elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{
9498 .first_node_reloc = dwarf_unit.debug_line_header_first_node_reloc,
9499 });
9500 },
9501 .unit_debug_rnglists => |ui| {
9502 const dwarf_unit = &elf.dwarf_units.items[@backingInt(ui)];
9503 var target_ri = dwarf_unit.debug_rnglists_first_target_reloc;
9504 while (target_ri != .none) {
9505 const target_reloc = target_ri.get(elf);
9506 assert(target_reloc.target == ni);
9507 target_reloc.apply(elf);
9508 target_ri = target_reloc.next;
9509 }
9510 const node_vaddr = elf.computeNodeVAddr(ni);
9511 for (dwarf_unit.debug_rnglists_symbol_relocs.keys()) |symbol_ri| {
9512 const symbol_reloc = symbol_ri.get(elf);
9513 assert(symbol_reloc.node == ni);
9514 if (symbol_reloc.rela_index.unwrap()) |rela_index| {
9515 // The node has moved, so the offset of the relocation within the section might have
9516 // changed, so update the `offset` field of the `ElfN.Rela` entry.
9517 symbol_reloc.relaSection(elf).relaSetOffset(elf, rela_index, node_vaddr + symbol_reloc.offset);
9518 }
9519 if (elf.ehdrType() != .REL) {
9520 symbol_reloc.apply(elf);
9521 }
9522 }
93919523 },
93929524 .value_debug_info => |vi| {
93939525 const dwarf_value = &elf.dwarf_values.items[@backingInt(vi)];
......@@ -9398,13 +9530,10 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
93989530 target_reloc.apply(elf);
93999531 target_ri = target_reloc.next;
94009532 }
9401 elf.flushMovedNodeRelocs(
9402 ni,
9403 elf.computeNodeVAddr(ni),
9404 dwarf_value.debug_info_first_symbol_reloc,
9405 dwarf_value.debug_info_first_node_reloc,
9406 .none,
9407 );
9533 elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{
9534 .first_symbol_reloc = dwarf_value.debug_info_first_symbol_reloc,
9535 .first_node_reloc = dwarf_value.debug_info_first_node_reloc,
9536 });
94089537 },
94099538 .global_debug_info => |vi| {
94109539 const dwarf_global = &elf.dwarf_globals.items[@backingInt(vi)];
......@@ -9415,13 +9544,10 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
94159544 target_reloc.apply(elf);
94169545 target_ri = target_reloc.next;
94179546 }
9418 elf.flushMovedNodeRelocs(
9419 ni,
9420 elf.computeNodeVAddr(ni),
9421 dwarf_global.debug_info_first_symbol_reloc,
9422 dwarf_global.debug_info_first_node_reloc,
9423 .none,
9424 );
9547 elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{
9548 .first_symbol_reloc = dwarf_global.debug_info_first_symbol_reloc,
9549 .first_node_reloc = dwarf_global.debug_info_first_node_reloc,
9550 });
94259551 },
94269552 .func_frame_fde => |fi| {
94279553 const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)];
......@@ -9433,13 +9559,10 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
94339559 elf.dwarf.updateEhFrameFde(ni.slice(&elf.mf), offset);
94349560 },
94359561 }
9436 elf.flushMovedNodeRelocs(
9437 ni,
9438 elf.computeNodeVAddr(ni),
9439 dwarf_func.frame_fde_first_symbol_reloc,
9440 dwarf_func.frame_fde_first_node_reloc,
9441 .none,
9442 );
9562 elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{
9563 .first_symbol_reloc = dwarf_func.frame_fde_first_symbol_reloc,
9564 .first_node_reloc = dwarf_func.frame_fde_first_node_reloc,
9565 });
94439566 },
94449567 .func_debug_info => |fi| {
94459568 const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)];
......@@ -9450,23 +9573,19 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
94509573 target_reloc.apply(elf);
94519574 target_ri = target_reloc.next;
94529575 }
9453 elf.flushMovedNodeRelocs(
9454 ni,
9455 elf.computeNodeVAddr(ni),
9456 dwarf_func.debug_info_first_symbol_reloc,
9457 dwarf_func.debug_info_first_node_reloc,
9458 .none,
9459 );
9576 elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{
9577 .ignore_node = fi.get(&elf.dwarf).debug_line_ni,
9578 .first_symbol_reloc = dwarf_func.debug_info_first_symbol_reloc,
9579 .first_node_reloc = dwarf_func.debug_info_first_node_reloc,
9580 });
94609581 },
94619582 .func_debug_line => |fi| {
94629583 const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)];
9463 elf.flushMovedNodeRelocs(
9464 ni,
9465 elf.computeNodeVAddr(ni),
9466 dwarf_func.debug_line_first_symbol_reloc,
9467 dwarf_func.debug_line_first_node_reloc,
9468 .none,
9469 );
9584 elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{
9585 .ignore_node = fi.get(&elf.dwarf).debug_info_ni,
9586 .first_symbol_reloc = dwarf_func.debug_line_first_symbol_reloc,
9587 .first_node_reloc = dwarf_func.debug_line_first_node_reloc,
9588 });
94709589 },
94719590 }
94729591 try ni.childrenMoved(elf.base.comp.gpa, &elf.mf);
......@@ -9712,6 +9831,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
97129831 .unit_debug_info_header,
97139832 .unit_debug_line,
97149833 .unit_debug_line_header,
9834 .unit_debug_rnglists,
97159835 .value_debug_info,
97169836 .global_debug_info,
97179837 .func_frame_fde,
......@@ -9774,6 +9894,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
97749894 .unit_frame_cie,
97759895 .unit_debug_info_header,
97769896 .unit_debug_line_header,
9897 .unit_debug_rnglists,
97779898 .value_debug_info,
97789899 .global_debug_info,
97799900 .func_frame_fde,
......@@ -9788,15 +9909,15 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
97889909 break :slice parent_slice[@intCast(offset)..@intCast(next_offset)];
97899910 } else slice: switch (tag) {
97909911 else => unreachable,
9791 .unit_padding => {
9792 const frame_slice = parent_ni.slicePadding(&elf.mf);
9912 .unit_padding, .unit_debug_rnglists => {
9913 const parent_slice = parent_ni.slicePadding(&elf.mf);
97939914 switch (elf.getNode(parent_ni).section.debugFrameFormat(elf) orelse .debug_frame) {
97949915 .eh_frame => {
9795 const end = frame_slice.len - 4;
9796 std.mem.writeInt(u32, frame_slice[end..][0..4], 0, elf.dwarf.endian);
9797 break :slice frame_slice[@intCast(offset)..end];
9916 const end = parent_slice.len - 4;
9917 std.mem.writeInt(u32, parent_slice[end..][0..4], 0, elf.dwarf.endian);
9918 break :slice parent_slice[@intCast(offset)..end];
97989919 },
9799 .debug_frame => break :slice frame_slice[@intCast(offset)..],
9920 .debug_frame => break :slice parent_slice[@intCast(offset)..],
98009921 }
98019922 },
98029923 .unit_frame_cie, .func_frame_fde => {
......@@ -9840,36 +9961,64 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
98409961 break :debug_end @intCast(parent_next_offset);
98419962 } else debug_slice.len]);
98429963 fw.end = @intCast(offset + size);
9843 for (0..2) |_| fw.writeUleb128(@backingInt(Dwarf.AbbrevCode.null)) catch
9844 unreachable; // ensured by `updateFunc`
9845 elf.dwarf.updateUnitLength(fw.buffer, fw.end);
9964 switch (tag) {
9965 else => unreachable,
9966 .unit_debug_info_header,
9967 .value_debug_info,
9968 .global_debug_info,
9969 .func_debug_info,
9970 => for (0..2) |_| fw.writeUleb128(@backingInt(Dwarf.AbbrevCode.null)) catch unreachable,
9971 .unit_debug_line_header, .func_debug_line => {},
9972 }
9973 const unit_padding_offset = fw.end;
98469974 const unit_padding = fw.unusedCapacitySlice();
98479975 elf.dwarf.genUnitPadding(&fw) catch |err| switch (err) {
98489976 error.WriteFailed => {
9849 comptime assert(Dwarf.uleb128Bytes(@backingInt(Dwarf.AbbrevCode.null)) == 1);
9850 @memset(fw.buffer, @backingInt(Dwarf.AbbrevCode.null));
9977 fw.end = unit_padding_offset;
9978 elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len);
9979 switch (tag) {
9980 else => unreachable,
9981 .unit_debug_info_header, .value_debug_info, .global_debug_info, .func_debug_info => {
9982 comptime assert(Dwarf.uleb128Bytes(@backingInt(Dwarf.AbbrevCode.null)) == 1);
9983 @memset(fw.unusedCapacitySlice(), @backingInt(Dwarf.AbbrevCode.null));
9984 },
9985 .unit_debug_line_header, .func_debug_line => Dwarf.genDebugLinePadding(&fw, fw.unusedCapacityLen()) catch
9986 unreachable,
9987 }
9988 return;
98519989 },
98529990 };
9991 elf.dwarf.updateUnitLength(fw.buffer, unit_padding_offset);
98539992 elf.dwarf.updateUnitLength(unit_padding, unit_padding.len);
98549993 return;
98559994 },
98569995 };
9996 var fw: Io.Writer = .fixed(slice[@intCast(size)..]);
98579997 switch (tag) {
98589998 else => unreachable,
98599999 .unit_padding => elf.dwarf.updateUnitLength(slice, slice.len),
986010000 .unit_frame_cie, .func_frame_fde => {
986110001 elf.dwarf.updateUnitLength(slice, slice.len);
9862 @memset(slice[@intCast(size)..], std.dwarf.CFA.nop);
10002 @memset(fw.buffer, std.dwarf.CFA.nop);
986310003 },
986410004 .unit_debug_info_header,
9865 .unit_debug_line_header,
986610005 .value_debug_info,
986710006 .global_debug_info,
986810007 .func_debug_info,
10008 => elf.dwarf.genDebugInfoPadding(&fw, fw.buffer.len) catch unreachable,
10009 .unit_debug_line_header,
986910010 .func_debug_line,
9870 => {
9871 var fw: Io.Writer = .fixed(slice[@intCast(size)..]);
9872 elf.dwarf.genDebugInfoPadding(&fw, fw.unusedCapacityLen()) catch unreachable;
10011 => Dwarf.genDebugLinePadding(&fw, fw.buffer.len) catch unreachable,
10012 .unit_debug_rnglists => {
10013 elf.dwarf.genUnitPadding(&fw) catch |err| switch (err) {
10014 error.WriteFailed => {
10015 elf.dwarf.updateUnitLength(slice, slice.len);
10016 @memset(fw.buffer, std.dwarf.RLE.end_of_list);
10017 return;
10018 },
10019 };
10020 elf.dwarf.updateUnitLength(slice, size);
10021 elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len);
987310022 },
987410023 }
987510024 },
......@@ -10229,11 +10378,10 @@ pub fn updateExports(
1022910378 pt: Zcu.PerThread,
1023010379 export_indices: []const Zcu.Export.Index,
1023110380) link.Error!void {
10232 const diags = &elf.base.comp.link_diags;
1023310381 for (export_indices) |export_index| {
1023410382 elf.updateExportInner(pt, export_index) catch |err| switch (err) {
1023510383 else => |e| return e,
10236 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
10384 error.MappedFileIo => return elf.base.comp.link_diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
1023710385 };
1023810386 }
1023910387}
......@@ -10377,7 +10525,7 @@ pub fn printNode(
1037710525 const ip = &zcu.intern_pool;
1037810526 const nav = ip.getNav(nmi.navIndex(elf));
1037910527 try w.print("({f}, {f})", .{
10380 Type.fromInterned(ip.typeOf(nav.resolved.?.value)).fmt(.{ .zcu = zcu, .tid = tid }),
10528 Type.fromInterned(nav.resolved.?.type).fmt(.{ .zcu = zcu, .tid = tid }),
1038110529 nav.fqn.fmt(ip),
1038210530 });
1038310531 },
......@@ -10402,9 +10550,8 @@ pub fn printNode(
1040210550 .unit_debug_info_header,
1040310551 .unit_debug_line,
1040410552 .unit_debug_line_header,
10405 => |ui| try w.print("({s})", .{
10406 ui.mod(&elf.dwarf).fully_qualified_name,
10407 }),
10553 .unit_debug_rnglists,
10554 => |ui| try w.print("({s})", .{ui.mod(&elf.dwarf).fully_qualified_name}),
1040810555 .value_debug_info => |cpi| try w.print("({f})", .{
1040910556 Value.fromInterned(cpi.val(&elf.dwarf.const_pool))
1041010557 .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
......@@ -10414,7 +10561,7 @@ pub fn printNode(
1041410561 const ip = &zcu.intern_pool;
1041510562 const nav = ip.getNav(gi.nav(&elf.dwarf));
1041610563 try w.print("({f}, {f})", .{
10417 Type.fromInterned(ip.typeOf(nav.resolved.?.value)).fmt(.{ .zcu = zcu, .tid = tid }),
10564 Type.fromInterned(nav.resolved.?.type).fmt(.{ .zcu = zcu, .tid = tid }),
1041810565 nav.fqn.fmt(ip),
1041910566 });
1042010567 },
......@@ -10423,7 +10570,7 @@ pub fn printNode(
1042310570 const ip = &zcu.intern_pool;
1042410571 const nav = ip.getNav(fi.nav(&elf.dwarf));
1042510572 try w.print("({f}, {f})", .{
10426 Type.fromInterned(ip.typeOf(nav.resolved.?.value)).fmt(.{ .zcu = zcu, .tid = tid }),
10573 Type.fromInterned(nav.resolved.?.type).fmt(.{ .zcu = zcu, .tid = tid }),
1042710574 nav.fqn.fmt(ip),
1042810575 });
1042910576 },