authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-08-12 22:46:34-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-03 12:59:38-04:00
log3dd202df0101e9ac9380a1aa5a813555241e8c3d
treeac3e5b0637fc3c5eb5e24412161b33b08839c325
parentfd9f45c358837b0091b795fad1c75f4efc8f4fc4

Dwarf2: implement enough debug info for incremental line info to work


6 files changed, 379 insertions(+), 141 deletions(-)

src/Compilation.zig+8-1
...@@ -3710,8 +3710,15 @@ pub fn saveState(comp: *Compilation) !void {...@@ -3710,8 +3710,15 @@ pub fn saveState(comp: *Compilation) !void {
37103710
3711 // linker state3711 // linker state
3712 switch (lf.tag) {3712 switch (lf.tag) {
3713 .elf => {},
3714 .elf2 => {
3715 const elf = lf.cast(.elf2).?;
3716 try bufs.ensureUnusedCapacity(3);
3717 addBuf(&bufs, @ptrCast(elf.mf.nodes.items));
3718 addBuf(&bufs, @ptrCast(&elf.mf.free_ni));
3719 addBuf(&bufs, @ptrCast(elf.mf.large.items));
3720 },
3713 .wasm => {3721 .wasm => {
3714 dev.check(link.File.Tag.wasm.devFeature());
3715 const wasm = lf.cast(.wasm).?;3722 const wasm = lf.cast(.wasm).?;
3716 const is_obj = comp.config.output_mode == .Obj;3723 const is_obj = comp.config.output_mode == .Obj;
3717 try bufs.ensureUnusedCapacity(85);3724 try bufs.ensureUnusedCapacity(85);
src/codegen/llvm.zig+2-2
...@@ -1431,7 +1431,7 @@ pub const Object = struct {...@@ -1431,7 +1431,7 @@ pub const Object = struct {
14311431
1432 pub fn getDebugType(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Metadata {1432 pub fn getDebugType(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Metadata {
1433 assert(!o.builder.strip);1433 assert(!o.builder.strip);
1434 const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern());1434 const index = o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()) catch |err| return @errorCast(err);
1435 return o.debug_types.items[@backingInt(index)];1435 return o.debug_types.items[@backingInt(index)];
1436 }1436 }
14371437
...@@ -4108,7 +4108,7 @@ pub const Object = struct {...@@ -4108,7 +4108,7 @@ pub const Object = struct {
4108 }4108 }
41094109
4110 pub fn lazyAbiAlignment(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Alignment.Lazy {4110 pub fn lazyAbiAlignment(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Alignment.Lazy {
4111 const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern());4111 const index = o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()) catch |err| return @errorCast(err);
4112 return o.lazy_abi_aligns.items[@backingInt(index)];4112 return o.lazy_abi_aligns.items[@backingInt(index)];
4113 }4113 }
41144114
src/link/C.zig+3-3
...@@ -209,7 +209,7 @@ pub fn addConst(...@@ -209,7 +209,7 @@ pub fn addConst(
209 pt: Zcu.PerThread,209 pt: Zcu.PerThread,
210 pool_index: link.ConstPool.Index,210 pool_index: link.ConstPool.Index,
211 val: InternPool.Index,211 val: InternPool.Index,
212) Allocator.Error!void {212) link.Error!void {
213 const zcu = pt.zcu;213 const zcu = pt.zcu;
214 const gpa = zcu.comp.gpa;214 const gpa = zcu.comp.gpa;
215 assert(zcu.intern_pool.typeOf(val) == .type_type);215 assert(zcu.intern_pool.typeOf(val) == .type_type);
...@@ -310,7 +310,7 @@ pub fn updateConst(...@@ -310,7 +310,7 @@ pub fn updateConst(
310 pt: Zcu.PerThread,310 pt: Zcu.PerThread,
311 index: link.ConstPool.Index,311 index: link.ConstPool.Index,
312 val: InternPool.Index,312 val: InternPool.Index,
313) Allocator.Error!void {313) link.Error!void {
314 const zcu = pt.zcu;314 const zcu = pt.zcu;
315 const gpa = zcu.comp.gpa;315 const gpa = zcu.comp.gpa;
316316
...@@ -1344,7 +1344,7 @@ fn addCTypeDependencies(...@@ -1344,7 +1344,7 @@ fn addCTypeDependencies(
1344 c: *C,1344 c: *C,
1345 pt: Zcu.PerThread,1345 pt: Zcu.PerThread,
1346 deps: *const codegen.CType.Dependencies,1346 deps: *const codegen.CType.Dependencies,
1347) Allocator.Error!CTypeDependencies {1347) link.Error!CTypeDependencies {
1348 const gpa = pt.zcu.comp.gpa;1348 const gpa = pt.zcu.comp.gpa;
13491349
1350 try c.bigint_types.ensureUnusedCapacity(gpa, deps.bigint.count());1350 try c.bigint_types.ensureUnusedCapacity(gpa, deps.bigint.count());
src/link/ConstPool.zig+2-2
...@@ -59,7 +59,7 @@ pub const User = union(enum) {...@@ -59,7 +59,7 @@ pub const User = union(enum) {
59 pt: Zcu.PerThread,59 pt: Zcu.PerThread,
60 index: Index,60 index: Index,
61 val: InternPool.Index,61 val: InternPool.Index,
62 ) Allocator.Error!void {62 ) link.Error!void {
63 switch (user) {63 switch (user) {
64 inline else => |impl| return impl.addConst(pt, index, val),64 inline else => |impl| return impl.addConst(pt, index, val),
65 }65 }
...@@ -144,7 +144,7 @@ pub fn updateContainerType(...@@ -144,7 +144,7 @@ pub fn updateContainerType(
144144
145/// After this is called, there may be a constant for which debug information (complete or not) has145/// After this is called, there may be a constant for which debug information (complete or not) has
146/// not yet been emitted, so the user must call `flushPending` at some point after this call.146/// not yet been emitted, so the user must call `flushPending` at some point after this call.
147pub fn get(pool: *ConstPool, pt: Zcu.PerThread, user: User, val: InternPool.Index) Allocator.Error!ConstPool.Index {147pub fn get(pool: *ConstPool, pt: Zcu.PerThread, user: User, val: InternPool.Index) link.Error!ConstPool.Index {
148 const zcu = pt.zcu;148 const zcu = pt.zcu;
149 const ip = &zcu.intern_pool;149 const ip = &zcu.intern_pool;
150 const gpa = zcu.comp.gpa;150 const gpa = zcu.comp.gpa;
src/link/Dwarf2.zig+260-61
...@@ -6,7 +6,7 @@ const_pool: link.ConstPool,...@@ -6,7 +6,7 @@ const_pool: link.ConstPool,
66
7units: std.array_hash_map.Auto(*Module, Unit),7units: std.array_hash_map.Auto(*Module, Unit),
8/// Indices are `link.ConstPool.Index`.8/// Indices are `link.ConstPool.Index`.
9values: std.ArrayList(Value),9consts: std.ArrayList(Const),
10globals: std.array_hash_map.Auto(InternPool.Nav.Index, Global),10globals: std.array_hash_map.Auto(InternPool.Nav.Index, Global),
11funcs: std.array_hash_map.Auto(InternPool.Nav.Index, Func),11funcs: std.array_hash_map.Auto(InternPool.Nav.Index, Func),
12decls: std.array_hash_map.Auto(InternPool.TrackedInst.Index, MappedFile.Node.Index),12decls: std.array_hash_map.Auto(InternPool.TrackedInst.Index, MappedFile.Node.Index),
...@@ -92,20 +92,12 @@ pub const Unit = struct {...@@ -92,20 +92,12 @@ pub const Unit = struct {
92 }92 }
93};93};
9494
95pub const Value = struct {95pub const Const = struct {
96 debug_info_ni: MappedFile.Node.Index,96 debug_info_ni: MappedFile.Node.Index.Optional,
97
98 pub const Index = enum(u32) {
99 _,
100
101 pub fn cpi(vi: Value.Index, dwarf: *Dwarf) link.ConstPool.Index {
102 return dwarf.values[@backingInt(vi)];
103 }
10497
105 pub fn get(vi: Value.Index, dwarf: *Dwarf) *Global {98 pub fn get(cpi: link.ConstPool.Index, dwarf: *Dwarf) *Const {
106 return &dwarf.values[@backingInt(vi)];99 return &dwarf.consts.items[@backingInt(cpi)];
107 }100 }
108 };
109};101};
110102
111pub const Global = struct {103pub const Global = struct {
...@@ -626,14 +618,14 @@ pub const WipNav = struct {...@@ -626,14 +618,14 @@ pub const WipNav = struct {
626 return debug.wip_nav.genDebugFrame(loc, cfa);618 return debug.wip_nav.genDebugFrame(loc, cfa);
627 }619 }
628620
629 pub fn startDebugInfo(debug: *Debug) link.Error!void {621 pub fn startFuncDebugInfo(debug: *Debug) link.Error!void {
630 assert(debug.wip_nav.func != .none);622 assert(debug.wip_nav.func != .none);
631 debug.startDebugInfoInner() catch |err| switch (err) {623 debug.startFuncDebugInfoInner() catch |err| switch (err) {
632 error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer),624 error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer),
633 else => |e| return e,625 else => |e| return e,
634 };626 };
635 }627 }
636 fn startDebugInfoInner(debug: *Debug) link.EmitError!void {628 fn startFuncDebugInfoInner(debug: *Debug) link.EmitError!void {
637 const dwarf = debug.wip_nav.dwarf;629 const dwarf = debug.wip_nav.dwarf;
638 const zcu = debug.pt.zcu;630 const zcu = debug.pt.zcu;
639 const ip = &zcu.intern_pool;631 const ip = &zcu.intern_pool;
...@@ -644,6 +636,7 @@ pub const WipNav = struct {...@@ -644,6 +636,7 @@ pub const WipNav = struct {
644 const nav = ip.getNav(func.owner_nav);636 const nav = ip.getNav(func.owner_nav);
645 const diw = &debug.info_writer.interface;637 const diw = &debug.info_writer.interface;
646 try diw.writeUleb128(try dwarf.refAbbrevCode(.decl_func));638 try diw.writeUleb128(try dwarf.refAbbrevCode(.decl_func));
639 try debug.refType(.fromInterned(zcu.fileRootType(inst_info.file)));
647 try diw.writeInt(u32, decl.src_line + 1, dwarf.endian);640 try diw.writeInt(u32, decl.src_line + 1, dwarf.endian);
648 try diw.writeUleb128(decl.src_column + 1);641 try diw.writeUleb128(decl.src_column + 1);
649 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);642 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);
...@@ -730,7 +723,7 @@ pub const WipNav = struct {...@@ -730,7 +723,7 @@ pub const WipNav = struct {
730 debug: *Debug,723 debug: *Debug,
731 tag: LocalVarTag,724 tag: LocalVarTag,
732 opt_name: ?[]const u8,725 opt_name: ?[]const u8,
733 ty: ZigType,726 ty: Type,
734 loc: Loc,727 loc: Loc,
735 ) link.Error!void {728 ) link.Error!void {
736 return debug.genLocalVarDebugInfoInner(tag, opt_name, ty, loc) catch |err| switch (err) {729 return debug.genLocalVarDebugInfoInner(tag, opt_name, ty, loc) catch |err| switch (err) {
...@@ -742,7 +735,7 @@ pub const WipNav = struct {...@@ -742,7 +735,7 @@ pub const WipNav = struct {
742 debug: *Debug,735 debug: *Debug,
743 tag: LocalVarTag,736 tag: LocalVarTag,
744 opt_name: ?[]const u8,737 opt_name: ?[]const u8,
745 ty: ZigType,738 ty: Type,
746 loc: Loc,739 loc: Loc,
747 ) link.EmitError!void {740 ) link.EmitError!void {
748 assert(debug.wip_nav.func != .none);741 assert(debug.wip_nav.func != .none);
...@@ -761,7 +754,7 @@ pub const WipNav = struct {...@@ -761,7 +754,7 @@ pub const WipNav = struct {
761 debug: *Debug,754 debug: *Debug,
762 tag: LocalConstTag,755 tag: LocalConstTag,
763 opt_name: ?[]const u8,756 opt_name: ?[]const u8,
764 val: ZigValue,757 val: Value,
765 ) link.Error!void {758 ) link.Error!void {
766 return debug.genLocalConstDebugInfoInner(tag, opt_name, val) catch |err| switch (err) {759 return debug.genLocalConstDebugInfoInner(tag, opt_name, val) catch |err| switch (err) {
767 error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer),760 error.WriteFailed => return debug.wip_nav.dwarf.reportWriteError(&debug.info_writer),
...@@ -772,7 +765,7 @@ pub const WipNav = struct {...@@ -772,7 +765,7 @@ pub const WipNav = struct {
772 debug: *Debug,765 debug: *Debug,
773 tag: LocalConstTag,766 tag: LocalConstTag,
774 opt_name: ?[]const u8,767 opt_name: ?[]const u8,
775 val: ZigValue,768 val: Value,
776 ) link.EmitError!void {769 ) link.EmitError!void {
777 assert(debug.wip_nav.func != .none);770 assert(debug.wip_nav.func != .none);
778 const zcu = debug.pt.zcu;771 const zcu = debug.pt.zcu;
...@@ -1059,11 +1052,11 @@ pub const WipNav = struct {...@@ -1059,11 +1052,11 @@ pub const WipNav = struct {
10591052
1060 const old_owner_nav = zcu.funcInfo(debug.wip_nav.func).owner_nav;1053 const old_owner_nav = zcu.funcInfo(debug.wip_nav.func).owner_nav;
1061 const old_inst_info = ip.getNav(old_owner_nav).srcInst(ip).resolveFull(ip).?;1054 const old_inst_info = ip.getNav(old_owner_nav).srcInst(ip).resolveFull(ip).?;
1062 const old_file = zcu.fileByIndex(old_inst_info.file);1055 const old_zf = zcu.fileByIndex(old_inst_info.file);
1063 const new_inst_info = ip.getNav(new_owner_nav).srcInst(ip).resolveFull(ip).?;1056 const new_inst_info = ip.getNav(new_owner_nav).srcInst(ip).resolveFull(ip).?;
1064 const new_file = zcu.fileByIndex(new_inst_info.file);1057 const new_zf = zcu.fileByIndex(new_inst_info.file);
1065 if (old_inst_info.file != new_inst_info.file) {1058 if (old_inst_info.file != new_inst_info.file) {
1066 const new_ui = dwarf.getUnit(new_file.mod.?);1059 const new_ui = dwarf.getUnit(new_zf.mod.?);
1067 _, const new_fi =1060 _, const new_fi =
1068 try debug.wip_nav.unit.get(dwarf).getFile(zcu.gpa, new_ui, new_inst_info.file);1061 try debug.wip_nav.unit.get(dwarf).getFile(zcu.gpa, new_ui, new_inst_info.file);
10691062
...@@ -1071,8 +1064,8 @@ pub const WipNav = struct {...@@ -1071,8 +1064,8 @@ pub const WipNav = struct {
1071 try dlw.writeUleb128(@backingInt(new_fi));1064 try dlw.writeUleb128(@backingInt(new_fi));
1072 }1065 }
10731066
1074 const old_src_line: i33 = old_file.zir.?.getDeclaration(old_inst_info.inst).src_line;1067 const old_src_line: i33 = old_zf.zir.?.getDeclaration(old_inst_info.inst).src_line;
1075 const new_src_line: i33 = new_file.zir.?.getDeclaration(new_inst_info.inst).src_line;1068 const new_src_line: i33 = new_zf.zir.?.getDeclaration(new_inst_info.inst).src_line;
1076 if (new_src_line != old_src_line) {1069 if (new_src_line != old_src_line) {
1077 try dlw.writeByte(DW.LNS.advance_line);1070 try dlw.writeByte(DW.LNS.advance_line);
1078 try dlw.writeSleb128(new_src_line - old_src_line);1071 try dlw.writeSleb128(new_src_line - old_src_line);
...@@ -1137,27 +1130,21 @@ pub const WipNav = struct {...@@ -1137,27 +1130,21 @@ pub const WipNav = struct {
1137 );1130 );
1138 }1131 }
11391132
1140 fn refType(debug: *Debug, ty: ZigType) link.EmitError!void {1133 fn refType(debug: *Debug, ty: Type) link.EmitError!void {
1141 return debug.refValue(ty.toValue());1134 return debug.refValue(ty.toValue());
1142 }1135 }
11431136
1144 fn refValue(debug: *Debug, value: ZigValue) link.EmitError!void {1137 fn refValue(debug: *Debug, val: Value) link.EmitError!void {
1145 try debug.wip_nav.dwarf.sectionOffset(&debug.info_writer, try debug.getValueNode(value), 0);
1146 }
1147
1148 fn getValueNode(debug: *Debug, value: ZigValue) link.Error!MappedFile.Node.Index {
1149 const zcu = debug.pt.zcu;
1150 if (value.typeOf(zcu).toIntern() != .type_type) {
1151 assert(value.typeOf(zcu).comptimeOnly(zcu));
1152 }
1153 const dwarf = debug.wip_nav.dwarf;1138 const dwarf = debug.wip_nav.dwarf;
1154 const index = try dwarf.const_pool.get(debug.pt, .{1139 const cpi = try dwarf.getConst(debug.pt, val);
1155 .elf2 = dwarf.lf.cast(.elf2).?,1140 try dwarf.sectionOffset(
1156 }, value.toIntern());1141 &debug.info_writer,
1157 return dwarf.values.items[@backingInt(index)].debug_info_ni;1142 Const.get(cpi, dwarf).debug_info_ni.unwrap().?,
1143 0,
1144 );
1158 }1145 }
11591146
1160 fn blockValue(debug: *Debug, val: ZigValue) link.EmitError!void {1147 fn blockValue(debug: *Debug, val: Value) link.EmitError!void {
1161 const ty = val.typeOf(debug.pt.zcu);1148 const ty = val.typeOf(debug.pt.zcu);
1162 const diw = &debug.info_writer.interface;1149 const diw = &debug.info_writer.interface;
1163 const size = ty.abiSize(debug.pt.zcu);1150 const size = ty.abiSize(debug.pt.zcu);
...@@ -1355,7 +1342,7 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {...@@ -1355,7 +1342,7 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {
1355 .const_pool = .empty,1342 .const_pool = .empty,
13561343
1357 .units = .empty,1344 .units = .empty,
1358 .values = .empty,1345 .consts = .empty,
1359 .globals = .empty,1346 .globals = .empty,
1360 .funcs = .empty,1347 .funcs = .empty,
1361 .decls = .empty,1348 .decls = .empty,
...@@ -1429,9 +1416,10 @@ pub fn deinit(dwarf: *Dwarf) void {...@@ -1429,9 +1416,10 @@ pub fn deinit(dwarf: *Dwarf) void {
1429 dwarf.const_pool.deinit(gpa);1416 dwarf.const_pool.deinit(gpa);
1430 for (dwarf.units.values()) |*unit| unit.deinit(gpa);1417 for (dwarf.units.values()) |*unit| unit.deinit(gpa);
1431 dwarf.units.deinit(gpa);1418 dwarf.units.deinit(gpa);
1432 dwarf.values.deinit(gpa);1419 dwarf.consts.deinit(gpa);
1433 dwarf.globals.deinit(gpa);1420 dwarf.globals.deinit(gpa);
1434 dwarf.funcs.deinit(gpa);1421 dwarf.funcs.deinit(gpa);
1422 dwarf.decls.deinit(gpa);
1435 dwarf.debug_line_str.map.deinit(gpa);1423 dwarf.debug_line_str.map.deinit(gpa);
1436 dwarf.debug_str.map.deinit(gpa);1424 dwarf.debug_str.map.deinit(gpa);
1437 dwarf.* = undefined;1425 dwarf.* = undefined;
...@@ -1471,6 +1459,13 @@ pub fn getUnit(dwarf: *Dwarf, mod: *Module) Unit.Index {...@@ -1471,6 +1459,13 @@ pub fn getUnit(dwarf: *Dwarf, mod: *Module) Unit.Index {
1471 return @fromBackingInt(@intCast(dwarf.units.getIndex(mod).?));1459 return @fromBackingInt(@intCast(dwarf.units.getIndex(mod).?));
1472}1460}
14731461
1462pub fn getConst(dwarf: *Dwarf, pt: Zcu.PerThread, val: Value) link.Error!link.ConstPool.Index {
1463 const zcu = pt.zcu;
1464 const ty = val.typeOf(zcu);
1465 if (ty.toIntern() != .type_type) assert(ty.comptimeOnly(zcu));
1466 return dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, val.toIntern());
1467}
1468
1474pub fn getGlobal(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Global.Index {1469pub fn getGlobal(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Global.Index {
1475 const comp = dwarf.lf.comp;1470 const comp = dwarf.lf.comp;
1476 const gpa = comp.gpa;1471 const gpa = comp.gpa;
...@@ -1483,10 +1478,9 @@ pub fn getGlobal(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Global.Ind...@@ -1483,10 +1478,9 @@ pub fn getGlobal(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Global.Ind
1483 const elf = dwarf.lf.cast(.elf2).?;1478 const elf = dwarf.lf.cast(.elf2).?;
1484 try elf.nodes.ensureUnusedCapacity(gpa, 1);1479 try elf.nodes.ensureUnusedCapacity(gpa, 1);
1485 try elf.dwarf_globals.ensureUnusedCapacity(gpa, 1);1480 try elf.dwarf_globals.ensureUnusedCapacity(gpa, 1);
1486 const unit = dwarf.getUnit(comp.zcu.?.zcu.navFileScope(nav).mod.?).get(dwarf);1481 const unit = dwarf.getUnit(comp.zcu.?.navFileScope(nav).mod.?).get(dwarf);
1487 assert(unit.debug_info_ni != .none);1482 global_gop.value_ptr.debug_info_ni = .wrap(elf.addNodeAssumeCapacity(
1488 global_gop.value_ptr.debug_info_ni = elf.addNodeAssumeCapacity(1483 unit.debug_info_ni.unwrap().?.addFloatingChild(gpa, &elf.mf, .{
1489 elf.mf.addLastChildNode(gpa, unit.debug_info_ni, .{
1490 .enable_next_moved = true,1484 .enable_next_moved = true,
1491 }) catch |err| switch (err) {1485 }) catch |err| switch (err) {
1492 else => |e| return e,1486 else => |e| return e,
...@@ -1495,7 +1489,7 @@ pub fn getGlobal(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Global.Ind...@@ -1495,7 +1489,7 @@ pub fn getGlobal(dwarf: *Dwarf, nav: InternPool.Nav.Index) link.Error!Global.Ind
1495 }),1489 }),
1496 },1490 },
1497 .{ .global_debug_info = gi },1491 .{ .global_debug_info = gi },
1498 );1492 ));
1499 elf.dwarf_globals.addOneAssumeCapacity().* = .{1493 elf.dwarf_globals.addOneAssumeCapacity().* = .{
1500 .debug_info_first_target_reloc = .none,1494 .debug_info_first_target_reloc = .none,
1501 .debug_info_first_node_reloc = .none,1495 .debug_info_first_node_reloc = .none,
...@@ -1773,7 +1767,6 @@ pub fn genDebugInfoPadding(dwarf: *Dwarf, diw: *Writer, size: u64) Writer.Error!...@@ -1773,7 +1767,6 @@ pub fn genDebugInfoPadding(dwarf: *Dwarf, diw: *Writer, size: u64) Writer.Error!
17731767
1774pub fn genDebugLineHeader(1768pub fn genDebugLineHeader(
1775 dwarf: *Dwarf,1769 dwarf: *Dwarf,
1776 mod: *Module,
1777 unit: *Unit,1770 unit: *Unit,
1778 dlh_nw: *MappedFile.Node.Writer,1771 dlh_nw: *MappedFile.Node.Writer,
1779 zcu: *Zcu,1772 zcu: *Zcu,
...@@ -1817,7 +1810,7 @@ pub fn genDebugLineHeader(...@@ -1817,7 +1810,7 @@ pub fn genDebugLineHeader(
1817 try dlhw.writeByte(1);1810 try dlhw.writeByte(1);
1818 try dlhw.writeUleb128(DW.LNCT.path);1811 try dlhw.writeUleb128(DW.LNCT.path);
1819 try dlhw.writeUleb128(DW.FORM.line_strp);1812 try dlhw.writeUleb128(DW.FORM.line_strp);
1820 const dir_count = 1;1813 const dir_count = unit.dirs.count();
1821 const directory_index_form: DeclValEnum(DW.FORM) = if (dir_count <= 1 << 8)1814 const directory_index_form: DeclValEnum(DW.FORM) = if (dir_count <= 1 << 8)
1822 .data11815 .data1
1823 else if (dir_count <= 1 << 16)1816 else if (dir_count <= 1 << 16)
...@@ -1825,8 +1818,8 @@ pub fn genDebugLineHeader(...@@ -1825,8 +1818,8 @@ pub fn genDebugLineHeader(
1825 else1818 else
1826 .udata;1819 .udata;
1827 try dlhw.writeUleb128(dir_count);1820 try dlhw.writeUleb128(dir_count);
1828 {1821 for (unit.dirs.keys()) |ui| {
1829 const root_dir_path = try mod.root.toAbsolute(&zcu.comp.dirs, comp.gpa);1822 const root_dir_path = try ui.mod(dwarf).root.toAbsolute(&zcu.comp.dirs, comp.gpa);
1830 defer comp.gpa.free(root_dir_path);1823 defer comp.gpa.free(root_dir_path);
1831 try dwarf.strp(&dwarf.debug_line_str, dlh_nw, root_dir_path);1824 try dwarf.strp(&dwarf.debug_line_str, dlh_nw, root_dir_path);
1832 }1825 }
...@@ -1845,11 +1838,12 @@ pub fn genDebugLineHeader(...@@ -1845,11 +1838,12 @@ pub fn genDebugLineHeader(
1845 for (unit.files.keys()) |zfi| {1838 for (unit.files.keys()) |zfi| {
1846 const zf = zcu.fileByIndex(zfi);1839 const zf = zcu.fileByIndex(zfi);
1847 try dwarf.strp(&dwarf.debug_line_str, dlh_nw, zf.sub_file_path);1840 try dwarf.strp(&dwarf.debug_line_str, dlh_nw, zf.sub_file_path);
1841 const di = unit.dirs.getIndex(dwarf.getUnit(zf.mod.?)).?;
1848 switch (directory_index_form) {1842 switch (directory_index_form) {
1849 else => unreachable,1843 else => unreachable,
1850 .data1 => try dlhw.writeByte(0),1844 .data1 => try dlhw.writeByte(@intCast(di)),
1851 .data2 => try dlhw.writeInt(u16, 0, dwarf.endian),1845 .data2 => try dlhw.writeInt(u16, @intCast(di), dwarf.endian),
1852 .udata => try dlhw.writeUleb128(0),1846 .udata => try dlhw.writeUleb128(di),
1853 }1847 }
1854 try dlhw.writeInt(i64, @truncate(zf.stat.mtime.nanoseconds), dwarf.endian);1848 try dlhw.writeInt(i64, @truncate(zf.stat.mtime.nanoseconds), dwarf.endian);
1855 try dlhw.writeInt(u64, zf.stat.size, dwarf.endian);1849 try dlhw.writeInt(u64, zf.stat.size, dwarf.endian);
...@@ -1938,6 +1932,209 @@ pub fn genDebugRnglists(...@@ -1938,6 +1932,209 @@ pub fn genDebugRnglists(
1938 try drw.writeByte(DW.RLE.end_of_list);1932 try drw.writeByte(DW.RLE.end_of_list);
1939}1933}
19401934
1935pub fn updateComptimeNav(
1936 dwarf: *Dwarf,
1937 pt: Zcu.PerThread,
1938 nav_index: InternPool.Nav.Index,
1939) link.Error!void {
1940 const zcu = dwarf.lf.comp.zcu.?;
1941 const ip = &zcu.intern_pool;
1942 const nav = ip.getNav(nav_index);
1943 const inst_info = nav.srcInst(ip).resolveFull(ip).?;
1944 const nav_val: Value = .fromInterned(nav.resolved.?.value);
1945 const file = zcu.fileByIndex(inst_info.file);
1946 const zir = &file.zir.?;
1947 const decl = zir.getDeclaration(inst_info.inst);
1948 switch (decl.kind) {
1949 .unnamed_test, .@"test", .decltest => return,
1950 .@"comptime", .@"const", .@"var" => {},
1951 }
1952 emit: switch (ip.indexToKey(nav_val.toIntern())) {
1953 .struct_type => {
1954 const loaded_struct = ip.loadStructType(nav_val.toIntern());
1955 if (nav_index.toOptional() == loaded_struct.name_nav) {
1956 _ = try dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, nav_val.toIntern());
1957 break :emit;
1958 }
1959 },
1960 .enum_type => {
1961 const loaded_enum = ip.loadEnumType(nav_val.toIntern());
1962 if (nav_index.toOptional() == loaded_enum.name_nav) {
1963 _ = try dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, nav_val.toIntern());
1964 break :emit;
1965 }
1966 },
1967 .union_type => {
1968 const loaded_union = ip.loadUnionType(nav_val.toIntern());
1969 if (nav_index.toOptional() == loaded_union.name_nav) {
1970 _ = try dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, nav_val.toIntern());
1971 break :emit;
1972 }
1973 },
1974 .opaque_type => {
1975 const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern());
1976 if (nav_index.toOptional() == loaded_opaque.name_nav) {
1977 _ = try dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, nav_val.toIntern());
1978 break :emit;
1979 }
1980 },
1981 .func => |func| if (func.owner_nav == nav_index and func.generic_owner == .none) {
1982 const fi = try dwarf.getFunc(func.owner_nav);
1983 const f = fi.get(dwarf);
1984 if (f.fde_ni != .none or f.debug_line_ni != .none) return;
1985 var di_nw: MappedFile.Node.Writer = undefined;
1986 f.debug_info_ni.unwrap().?.writer(zcu.gpa, &dwarf.lf.cast(.elf2).?.mf, &di_nw);
1987 defer di_nw.deinit();
1988 const parent_cpi = try dwarf.getConst(pt, .fromInterned(zcu.fileRootType(inst_info.file)));
1989 dwarf.genDeclFuncGeneric(
1990 &di_nw,
1991 zir,
1992 parent_cpi,
1993 &decl,
1994 &ip.indexToKey(func.ty).func_type,
1995 nav.name.toSlice(ip),
1996 zir.getParamBody(func.zir_body_inst.resolve(ip).?),
1997 ) catch |err| switch (err) {
1998 else => |e| return e,
1999 error.WriteFailed => return dwarf.reportWriteError(&di_nw),
2000 };
2001 } else return,
2002
2003 else => return,
2004
2005 // memoization, not values
2006 .memoized_call => unreachable,
2007 }
2008 try dwarf.const_pool.flushPending(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? });
2009}
2010fn genDeclFuncGeneric(
2011 dwarf: *Dwarf,
2012 di_nw: *MappedFile.Node.Writer,
2013 zir: *const std.zig.Zir,
2014 parent_cpi: link.ConstPool.Index,
2015 decl: *const std.zig.Zir.Inst.Declaration.Unwrapped,
2016 fn_ty: *const InternPool.Key.FuncType,
2017 name: []const u8,
2018 param_body: []const std.zig.Zir.Inst.Index,
2019) link.EmitError!void {
2020 const diw = &di_nw.interface;
2021 try diw.writeUleb128(try dwarf.refAbbrevCode(.decl_func_generic));
2022 try dwarf.sectionOffset(di_nw, Const.get(parent_cpi, dwarf).debug_info_ni.unwrap().?, 0);
2023 try diw.writeInt(u32, decl.src_line + 1, dwarf.endian);
2024 try diw.writeUleb128(decl.src_column + 1);
2025 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);
2026 try dwarf.strp(&dwarf.debug_str, di_nw, name);
2027 for (param_body) |param_inst| switch (zir.getParamName(param_inst) orelse continue) {
2028 .empty => {
2029 try diw.writeUleb128(try dwarf.refAbbrevCode(.unnamed_arg));
2030 try diw.writeUleb128(0);
2031 },
2032 else => |param_name| {
2033 try diw.writeUleb128(try dwarf.refAbbrevCode(.arg));
2034 try dwarf.strp(&dwarf.debug_str, di_nw, zir.nullTerminatedString(param_name));
2035 try diw.writeUleb128(0);
2036 },
2037 };
2038 if (fn_ty.is_var_args) try diw.writeUleb128(try dwarf.refAbbrevCode(.is_var_args));
2039 try diw.writeUleb128(@backingInt(AbbrevCode.null));
2040 try dwarf.genDebugInfoPadding(diw, diw.unusedCapacityLen());
2041}
2042
2043pub fn addConst(dwarf: *Dwarf, cpi: link.ConstPool.Index, val: InternPool.Index) link.Error!void {
2044 const comp = dwarf.lf.comp;
2045 const zcu = comp.zcu.?;
2046 const ip = &zcu.intern_pool;
2047 try dwarf.consts.ensureUnusedCapacity(comp.gpa, 1);
2048
2049 assert(@backingInt(cpi) == dwarf.consts.items.len);
2050 dwarf.consts.appendAssumeCapacity(.{
2051 .debug_info_ni = switch (ip.indexToKey(val)) {
2052 else => .none,
2053 .struct_type, .union_type, .enum_type, .opaque_type => |_, tag| debug_info_ni: {
2054 if (switch (tag) {
2055 .struct_type => ip.loadStructType(val).name_nav,
2056 .union_type => ip.loadUnionType(val).name_nav,
2057 .enum_type => ip.loadEnumType(val).name_nav,
2058 .opaque_type => ip.loadOpaqueType(val).name_nav,
2059 else => unreachable,
2060 }.unwrap()) |name_nav| {
2061 const name_gi = try dwarf.getGlobal(name_nav);
2062 break :debug_info_ni name_gi.get(dwarf).debug_info_ni.unwrap().?;
2063 }
2064 const elf = dwarf.lf.cast(.elf2).?;
2065 try elf.nodes.ensureUnusedCapacity(comp.gpa, 1);
2066 try elf.dwarf_consts.ensureUnusedCapacity(comp.gpa, 1);
2067 const src_inst = Type.fromInterned(val).typeDeclInstAllowGeneratedTag(zcu).?;
2068 const unit = dwarf.getUnit(zcu.fileByIndex(src_inst.resolveFile(ip)).mod.?).get(dwarf);
2069 const debug_info_ni = elf.addNodeAssumeCapacity(
2070 unit.debug_info_ni.unwrap().?.addFloatingChild(comp.gpa, &elf.mf, .{
2071 .enable_next_moved = true,
2072 }) catch |err| switch (err) {
2073 else => |e| return e,
2074 error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{
2075 elf.mf.io_err.?,
2076 }),
2077 },
2078 .{ .const_debug_info = cpi },
2079 );
2080 elf.dwarf_consts.putAssumeCapacity(cpi, .{
2081 .debug_info_first_target_reloc = .none,
2082 .debug_info_first_symbol_reloc = .none,
2083 .debug_info_first_node_reloc = .none,
2084 });
2085
2086 break :debug_info_ni debug_info_ni;
2087 }.toOptional(),
2088 },
2089 });
2090}
2091
2092pub fn updateConst(dwarf: *Dwarf, cpi: link.ConstPool.Index, val: InternPool.Index) void {
2093 _ = dwarf;
2094 _ = cpi;
2095 _ = val;
2096}
2097
2098pub fn updateConstIncomplete(
2099 dwarf: *Dwarf,
2100 di_nw: *MappedFile.Node.Writer,
2101 val: InternPool.Index,
2102) link.Error!void {
2103 dwarf.updateConstIncompleteInner(di_nw, val) catch |err| switch (err) {
2104 else => |e| return e,
2105 error.WriteFailed => return dwarf.reportWriteError(di_nw),
2106 };
2107}
2108fn updateConstIncompleteInner(
2109 dwarf: *Dwarf,
2110 di_nw: *MappedFile.Node.Writer,
2111 val: InternPool.Index,
2112) link.EmitError!void {
2113 const comp = dwarf.lf.comp;
2114 const zcu = comp.zcu.?;
2115 const ip = &zcu.intern_pool;
2116 const diw = &di_nw.interface;
2117 emit: switch (ip.indexToKey(val)) {
2118 .struct_type => {
2119 const loaded_struct = ip.loadStructType(val);
2120 if (loaded_struct.zir_index.resolveFull(ip)) |src_inst| switch (src_inst.inst) {
2121 .main_struct_inst => {
2122 const ui = dwarf.getUnit(comp.zcu.?.fileByIndex(src_inst.file).mod.?);
2123 _, const fi = try ui.get(dwarf).getFile(comp.gpa, ui, src_inst.file);
2124 try diw.writeUleb128(try dwarf.refAbbrevCode(.empty_file));
2125 try diw.writeUleb128(@backingInt(fi));
2126 try dwarf.strp(&dwarf.debug_str, di_nw, loaded_struct.name.toSlice(ip));
2127 break :emit;
2128 },
2129 else => return,
2130 };
2131 return;
2132 },
2133 else => return,
2134 }
2135 try dwarf.genDebugInfoPadding(diw, diw.unusedCapacityLen());
2136}
2137
1941pub fn updateLineNumber(2138pub fn updateLineNumber(
1942 dwarf: *Dwarf,2139 dwarf: *Dwarf,
1943 mf: *MappedFile,2140 mf: *MappedFile,
...@@ -2221,7 +2418,7 @@ pub const AbbrevCode = enum {...@@ -2221,7 +2418,7 @@ pub const AbbrevCode = enum {
2221 DeclValEnum(DW.FORM),2418 DeclValEnum(DW.FORM),
2222 };2419 };
2223 const decl_attrs = &[_]Attr{2420 const decl_attrs = &[_]Attr{
2224 //.{ .ZIG_parent, .ref_addr },2421 .{ .ZIG_parent, .ref_addr },
2225 .{ .decl_line, .data4 },2422 .{ .decl_line, .data4 },
2226 .{ .decl_column, .udata },2423 .{ .decl_column, .udata },
2227 .{ .accessibility, .data1 },2424 .{ .accessibility, .data1 },
...@@ -2233,7 +2430,7 @@ pub const AbbrevCode = enum {...@@ -2233,7 +2430,7 @@ pub const AbbrevCode = enum {
2233 };2430 };
22342431
2235 const decl_instance_attrs = &[_]Attr{2432 const decl_instance_attrs = &[_]Attr{
2236 //.{ .ZIG_parent, .ref_addr },2433 .{ .ZIG_parent, .ref_addr },
2237 .{ .specification, .ref_addr },2434 .{ .specification, .ref_addr },
2238 };2435 };
22392436
...@@ -2387,14 +2584,16 @@ pub const AbbrevCode = enum {...@@ -2387,14 +2584,16 @@ pub const AbbrevCode = enum {
2387 .decl_nullary_func_generic = .{2584 .decl_nullary_func_generic = .{
2388 .tag = .subprogram,2585 .tag = .subprogram,
2389 .attrs = decl_attrs ++ .{2586 .attrs = decl_attrs ++ .{
2390 .{ .type, .ref_addr },2587 //.{ .type, .ref_addr },
2588 //.{ .noreturn, .flag },
2391 },2589 },
2392 },2590 },
2393 .decl_func_generic = .{2591 .decl_func_generic = .{
2394 .tag = .subprogram,2592 .tag = .subprogram,
2395 .children = true,2593 .children = true,
2396 .attrs = decl_attrs ++ .{2594 .attrs = decl_attrs ++ .{
2397 .{ .type, .ref_addr },2595 //.{ .type, .ref_addr },
2596 //.{ .noreturn, .flag },
2398 },2597 },
2399 },2598 },
2400 .decl_extern_nullary_func = .{2599 .decl_extern_nullary_func = .{
...@@ -3304,7 +3503,7 @@ const link = @import("../link.zig");...@@ -3304,7 +3503,7 @@ const link = @import("../link.zig");
3304const MappedFile = @import("MappedFile.zig");3503const MappedFile = @import("MappedFile.zig");
3305const Module = @import("../Module.zig");3504const Module = @import("../Module.zig");
3306const std = @import("std");3505const std = @import("std");
3307const ZigType = @import("../Type.zig");3506const Type = @import("../Type.zig");
3308const ZigValue = @import("../Value.zig");3507const Value = @import("../Value.zig");
3309const Writer = std.Io.Writer;3508const Writer = std.Io.Writer;
3310const Zcu = @import("../Zcu.zig");3509const Zcu = @import("../Zcu.zig");
src/link/Elf2.zig+104-72
...@@ -224,7 +224,7 @@ dwarf_units: std.ArrayList(struct {...@@ -224,7 +224,7 @@ dwarf_units: std.ArrayList(struct {
224 debug_rnglists_first_target_reloc: NodeReloc.Index,224 debug_rnglists_first_target_reloc: NodeReloc.Index,
225 debug_rnglists_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void),225 debug_rnglists_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void),
226}),226}),
227dwarf_values: std.ArrayList(struct {227dwarf_consts: std.array_hash_map.Auto(link.ConstPool.Index, struct {
228 debug_info_first_target_reloc: NodeReloc.Index,228 debug_info_first_target_reloc: NodeReloc.Index,
229 debug_info_first_symbol_reloc: SymbolReloc.Index,229 debug_info_first_symbol_reloc: SymbolReloc.Index,
230 debug_info_first_node_reloc: NodeReloc.Index,230 debug_info_first_node_reloc: NodeReloc.Index,
...@@ -318,7 +318,7 @@ const Node = union(enum) {...@@ -318,7 +318,7 @@ const Node = union(enum) {
318 unit_debug_line_header: Dwarf.Unit.Index,318 unit_debug_line_header: Dwarf.Unit.Index,
319 unit_debug_rnglists: Dwarf.Unit.Index,319 unit_debug_rnglists: Dwarf.Unit.Index,
320320
321 value_debug_info: link.ConstPool.Index,321 const_debug_info: link.ConstPool.Index,
322 global_debug_info: Dwarf.Global.Index,322 global_debug_info: Dwarf.Global.Index,
323 func_frame_fde: Dwarf.Func.Index,323 func_frame_fde: Dwarf.Func.Index,
324 func_debug_info: Dwarf.Func.Index,324 func_debug_info: Dwarf.Func.Index,
...@@ -1142,7 +1142,8 @@ const SymbolReloc = struct {...@@ -1142,7 +1142,8 @@ const SymbolReloc = struct {
1142 /// * An input section1142 /// * An input section
1143 /// * A section1143 /// * A section
1144 /// * A NAV, UAV, or lazy code/data1144 /// * A NAV, UAV, or lazy code/data
1145 node: MappedFile.Node.Index,1145 /// * `.none`, if this relocation was deleted (in which case it should be ignored)
1146 node: MappedFile.Node.Index.Optional,
1146 /// The offset of the relocation inside of `node`.1147 /// The offset of the relocation inside of `node`.
1147 offset: u64,1148 offset: u64,
1148 /// A symbol used to compute the relocated value. Precise meaning depends on `@"type"`.1149 /// A symbol used to compute the relocated value. Precise meaning depends on `@"type"`.
...@@ -1182,7 +1183,7 @@ const SymbolReloc = struct {...@@ -1182,7 +1183,7 @@ const SymbolReloc = struct {
1182 /// because relocations in the GOTPLT are handled specially, without `SymbolReloc` entries.1183 /// because relocations in the GOTPLT are handled specially, without `SymbolReloc` entries.
1183 fn relaSection(sr: *const SymbolReloc, elf: *Elf) Section.Index {1184 fn relaSection(sr: *const SymbolReloc, elf: *Elf) Section.Index {
1184 const shndx = switch (elf.ehdrType()) {1185 const shndx = switch (elf.ehdrType()) {
1185 .REL => elf.getNodeShndx(sr.node).get(elf).rela.shndx,1186 .REL => elf.getNodeShndx(sr.node.unwrap().?).get(elf).rela.shndx,
1186 .EXEC, .DYN => elf.shndx.rela_dyn,1187 .EXEC, .DYN => elf.shndx.rela_dyn,
1187 };1188 };
1188 assert(shndx != .UNDEF);1189 assert(shndx != .UNDEF);
...@@ -1619,7 +1620,8 @@ const SymbolReloc = struct {...@@ -1619,7 +1620,8 @@ const SymbolReloc = struct {
16191620
1620 fn apply(reloc: *SymbolReloc, elf: *Elf) void {1621 fn apply(reloc: *SymbolReloc, elf: *Elf) void {
1621 assert(elf.ehdrType() != .REL);1622 assert(elf.ehdrType() != .REL);
1622 if (reloc.node.hasMoved(&elf.mf) or reloc.target.hasMoved(elf)) {1623 const node = reloc.node.unwrap() orelse return; // deleted
1624 if (node.hasMoved(&elf.mf) or reloc.target.hasMoved(elf)) {
1623 // There's no point applying the relocation now, because it will be re-applied by1625 // There's no point applying the relocation now, because it will be re-applied by
1624 // `flushMoved` at some point anyway.1626 // `flushMoved` at some point anyway.
1625 return;1627 return;
...@@ -1644,8 +1646,9 @@ const SymbolReloc = struct {...@@ -1644,8 +1646,9 @@ const SymbolReloc = struct {
1644 }1646 }
1645 }1647 }
1646 fn applyInner(reloc: *const SymbolReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void {1648 fn applyInner(reloc: *const SymbolReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void {
1647 const dest_vaddr = elf.getNodeVAddr(reloc.node) + reloc.offset;1649 const node = reloc.node.unwrap().?;
1648 const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..];1650 const dest_vaddr = elf.getNodeVAddr(node) + reloc.offset;
1651 const dest_slice = node.slice(&elf.mf)[@intCast(reloc.offset)..];
16491652
1650 const addend: u64 = @bitCast(reloc.addend);1653 const addend: u64 = @bitCast(reloc.addend);
1651 const target_val: u64 = type: switch (reloc.type.target) {1654 const target_val: u64 = type: switch (reloc.type.target) {
...@@ -1737,6 +1740,7 @@ const SymbolReloc = struct {...@@ -1737,6 +1740,7 @@ const SymbolReloc = struct {
1737 }1740 }
17381741
1739 reloc.* = undefined;1742 reloc.* = undefined;
1743 reloc.node = .none;
1740 }1744 }
17411745
1742 /// If `reloc.rela_index` is populated, reset it to `.none` and delete the relocation, updating1746 /// If `reloc.rela_index` is populated, reset it to `.none` and delete the relocation, updating
...@@ -1746,7 +1750,7 @@ const SymbolReloc = struct {...@@ -1746,7 +1750,7 @@ const SymbolReloc = struct {
1746 reloc.relaSection(elf).relaDeleteOne(elf, rela_index);1750 reloc.relaSection(elf).relaDeleteOne(elf, rela_index);
1747 switch (elf.ehdrType()) {1751 switch (elf.ehdrType()) {
1748 .REL => {},1752 .REL => {},
1749 .EXEC, .DYN => switch (elf.nodeWantsDsoRelocation(reloc.node)) {1753 .EXEC, .DYN => switch (elf.nodeWantsDsoRelocation(reloc.node.unwrap().?)) {
1750 .no => unreachable, // there *was* a dynamic relocation!1754 .no => unreachable, // there *was* a dynamic relocation!
1751 .yes => {},1755 .yes => {},
1752 .yes_textrel => elf.textrel_count -= 1,1756 .yes_textrel => elf.textrel_count -= 1,
...@@ -1760,7 +1764,7 @@ const SymbolReloc = struct {...@@ -1760,7 +1764,7 @@ const SymbolReloc = struct {
1760/// This represents a symbol reloc against the section symbol containing the node1764/// This represents a symbol reloc against the section symbol containing the node
1761/// with a variable addend that changes when the target node moves.1765/// with a variable addend that changes when the target node moves.
1762const NodeReloc = struct {1766const NodeReloc = struct {
1763 node: MappedFile.Node.Index,1767 node: MappedFile.Node.Index.Optional,
1764 offset: u64,1768 offset: u64,
1765 target: MappedFile.Node.Index,1769 target: MappedFile.Node.Index,
1766 addend: i64,1770 addend: i64,
...@@ -1786,7 +1790,7 @@ const NodeReloc = struct {...@@ -1786,7 +1790,7 @@ const NodeReloc = struct {
1786 assert(elf.ehdrType() == .REL);1790 assert(elf.ehdrType() == .REL);
1787 // The node has moved, so the offset of the relocation within the section might have1791 // The node has moved, so the offset of the relocation within the section might have
1788 // changed, so update the `offset` field of the `ElfN.Rela` entry.1792 // changed, so update the `offset` field of the `ElfN.Rela` entry.
1789 elf.getNodeShndx(reloc.node).get(elf).rela.shndx.relaSetOffset(elf, rela_index, node_vaddr + reloc.offset);1793 elf.getNodeShndx(reloc.node.unwrap().?).get(elf).rela.shndx.relaSetOffset(elf, rela_index, node_vaddr + reloc.offset);
1790 } else {1794 } else {
1791 assert(elf.ehdrType() != .REL);1795 assert(elf.ehdrType() != .REL);
1792 reloc.apply(elf);1796 reloc.apply(elf);
...@@ -1797,7 +1801,7 @@ const NodeReloc = struct {...@@ -1797,7 +1801,7 @@ const NodeReloc = struct {
1797 if (reloc.rela_index.unwrap()) |rela_index| {1801 if (reloc.rela_index.unwrap()) |rela_index| {
1798 assert(elf.ehdrType() == .REL);1802 assert(elf.ehdrType() == .REL);
1799 // The target has moved, so the `addend` field of the `ElfN.Rela` entry needs to be updated.1803 // The target has moved, so the `addend` field of the `ElfN.Rela` entry needs to be updated.
1800 elf.getNodeShndx(reloc.node).get(elf).rela.shndx.relaSetAddend(elf, rela_index, target_section_offset +% @as(u64, @bitCast(reloc.addend)));1804 elf.getNodeShndx(reloc.node.unwrap().?).get(elf).rela.shndx.relaSetAddend(elf, rela_index, target_section_offset +% @as(u64, @bitCast(reloc.addend)));
1801 } else {1805 } else {
1802 assert(elf.ehdrType() != .REL);1806 assert(elf.ehdrType() != .REL);
1803 reloc.apply(elf);1807 reloc.apply(elf);
...@@ -1805,12 +1809,13 @@ const NodeReloc = struct {...@@ -1805,12 +1809,13 @@ const NodeReloc = struct {
1805 }1809 }
18061810
1807 fn apply(reloc: *NodeReloc, elf: *Elf) void {1811 fn apply(reloc: *NodeReloc, elf: *Elf) void {
1812 const node = reloc.node.unwrap() orelse return; // deleted
1808 if (reloc.rela_index.unwrap()) |rela_index| {1813 if (reloc.rela_index.unwrap()) |rela_index| {
1809 assert(elf.ehdrType() == .REL);1814 assert(elf.ehdrType() == .REL);
1810 _ = rela_index;1815 _ = rela_index;
1811 } else {1816 } else {
1812 assert(elf.ehdrType() != .REL);1817 assert(elf.ehdrType() != .REL);
1813 if (reloc.node.hasMoved(&elf.mf) or reloc.target.hasMoved(&elf.mf)) {1818 if (node.hasMoved(&elf.mf) or reloc.target.hasMoved(&elf.mf)) {
1814 // There's no point applying the relocation now, because it will be re-applied by1819 // There's no point applying the relocation now, because it will be re-applied by
1815 // `flushMoved` at some point anyway.1820 // `flushMoved` at some point anyway.
1816 return;1821 return;
...@@ -1842,7 +1847,7 @@ const NodeReloc = struct {...@@ -1842,7 +1847,7 @@ const NodeReloc = struct {
1842 }, .cast = .unsigned, .shift = .@"0" };1847 }, .cast = .unsigned, .shift = .@"0" };
1843 const addend: u64 = @bitCast(reloc.addend);1848 const addend: u64 = @bitCast(reloc.addend);
1844 const target_val = elf.getNodeVAddr(reloc.target) +% addend;1849 const target_val = elf.getNodeVAddr(reloc.target) +% addend;
1845 const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..];1850 const dest_slice = reloc.node.unwrap().?.slice(&elf.mf)[@intCast(reloc.offset)..];
1846 try simple.write(target_val, dest_slice, elf.targetEndian());1851 try simple.write(target_val, dest_slice, elf.targetEndian());
1847 }1852 }
18481853
...@@ -1858,7 +1863,7 @@ const NodeReloc = struct {...@@ -1858,7 +1863,7 @@ const NodeReloc = struct {
1858 .unit_debug_info_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_target_reloc,1863 .unit_debug_info_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_target_reloc,
1859 .unit_debug_line_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_target_reloc,1864 .unit_debug_line_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_target_reloc,
1860 .unit_debug_rnglists => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_rnglists_first_target_reloc,1865 .unit_debug_rnglists => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_rnglists_first_target_reloc,
1861 .value_debug_info => |vi| &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_target_reloc,1866 .const_debug_info => |cpi| &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_target_reloc,
1862 .global_debug_info => |gi| &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_target_reloc,1867 .global_debug_info => |gi| &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_target_reloc,
1863 .func_debug_info => |fi| &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_target_reloc,1868 .func_debug_info => |fi| &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_target_reloc,
1864 };1869 };
...@@ -1877,13 +1882,14 @@ const NodeReloc = struct {...@@ -1877,13 +1882,14 @@ const NodeReloc = struct {
1877 }1882 }
18781883
1879 reloc.* = undefined;1884 reloc.* = undefined;
1885 reloc.node = .none;
1880 }1886 }
18811887
1882 /// If `reloc.rela_index` is populated, reset it to `.none` and delete the relocation.1888 /// If `reloc.rela_index` is populated, reset it to `.none` and delete the relocation.
1883 fn deleteOutputRel(reloc: *NodeReloc, elf: *Elf) void {1889 fn deleteOutputRel(reloc: *NodeReloc, elf: *Elf) void {
1884 const rela_index = reloc.rela_index.unwrap() orelse return;1890 const rela_index = reloc.rela_index.unwrap() orelse return;
1885 assert(elf.ehdrType() == .REL);1891 assert(elf.ehdrType() == .REL);
1886 elf.getNodeShndx(reloc.node).get(elf).rela.shndx.relaDeleteOne(elf, rela_index);1892 elf.getNodeShndx(reloc.node.unwrap().?).get(elf).rela.shndx.relaDeleteOne(elf, rela_index);
1887 reloc.rela_index = .none;1893 reloc.rela_index = .none;
1888 }1894 }
1889};1895};
...@@ -3175,7 +3181,8 @@ const Symbol = struct {...@@ -3175,7 +3181,8 @@ const Symbol = struct {
3175 .abs, .pltabs => {},3181 .abs, .pltabs => {},
3176 }3182 }
3177 if (!reloc.type.action.simple.dest.isAddr(elf)) continue;3183 if (!reloc.type.action.simple.dest.isAddr(elf)) continue;
3178 switch (elf.nodeWantsDsoRelocation(reloc.node)) {3184 const node = reloc.node.unwrap().?;
3185 switch (elf.nodeWantsDsoRelocation(node)) {
3179 .no => continue,3186 .no => continue,
3180 .yes_textrel => elf.textrel_count += 1,3187 .yes_textrel => elf.textrel_count += 1,
3181 .yes => {},3188 .yes => {},
...@@ -3183,7 +3190,7 @@ const Symbol = struct {...@@ -3183,7 +3190,7 @@ const Symbol = struct {
3183 // There is capacity for a relocation because we just deleted one earlier.3190 // There is capacity for a relocation because we just deleted one earlier.
3184 reloc.rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{3191 reloc.rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{
3185 .type = .relative(elf),3192 .type = .relative(elf),
3186 .offset = elf.getNodeVAddr(reloc.node) + reloc.offset,3193 .offset = elf.getNodeVAddr(node) + reloc.offset,
3187 .raw_sym_index = 0,3194 .raw_sym_index = 0,
3188 .addend = 0,3195 .addend = 0,
3189 }).toOptional();3196 }).toOptional();
...@@ -3310,7 +3317,7 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {...@@ -3310,7 +3317,7 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {
3310 .unit_debug_line,3317 .unit_debug_line,
3311 .unit_debug_line_header,3318 .unit_debug_line_header,
3312 .unit_debug_rnglists,3319 .unit_debug_rnglists,
3313 .value_debug_info,3320 .const_debug_info,
3314 .global_debug_info,3321 .global_debug_info,
3315 .func_frame_fde,3322 .func_frame_fde,
3316 .func_debug_info,3323 .func_debug_info,
...@@ -3823,7 +3830,7 @@ fn create(...@@ -3823,7 +3830,7 @@ fn create(
3823 .first_target_reloc = .none,3830 .first_target_reloc = .none,
3824 }),3831 }),
3825 .dwarf_units = .empty,3832 .dwarf_units = .empty,
3826 .dwarf_values = .empty,3833 .dwarf_consts = .empty,
3827 .dwarf_globals = .empty,3834 .dwarf_globals = .empty,
3828 .dwarf_funcs = .empty,3835 .dwarf_funcs = .empty,
38293836
...@@ -3878,7 +3885,7 @@ pub fn deinit(elf: *Elf) void {...@@ -3878,7 +3885,7 @@ pub fn deinit(elf: *Elf) void {
3878 elf.dwarf.deinit();3885 elf.dwarf.deinit();
3879 for (elf.dwarf_units.items) |*dwarf_unit| dwarf_unit.debug_rnglists_symbol_relocs.deinit(gpa);3886 for (elf.dwarf_units.items) |*dwarf_unit| dwarf_unit.debug_rnglists_symbol_relocs.deinit(gpa);
3880 elf.dwarf_units.deinit(gpa);3887 elf.dwarf_units.deinit(gpa);
3881 elf.dwarf_values.deinit(gpa);3888 elf.dwarf_consts.deinit(gpa);
3882 elf.dwarf_globals.deinit(gpa);3889 elf.dwarf_globals.deinit(gpa);
3883 elf.dwarf_funcs.deinit(gpa);3890 elf.dwarf_funcs.deinit(gpa);
38843891
...@@ -5176,7 +5183,7 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {...@@ -5176,7 +5183,7 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
5176 .unit_frame_cie,5183 .unit_frame_cie,
5177 .unit_debug_info_header,5184 .unit_debug_info_header,
5178 .unit_debug_line_header,5185 .unit_debug_line_header,
5179 .value_debug_info,5186 .const_debug_info,
5180 .global_debug_info,5187 .global_debug_info,
5181 .func_frame_fde,5188 .func_frame_fde,
5182 .func_debug_info,5189 .func_debug_info,
...@@ -5213,7 +5220,7 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {...@@ -5213,7 +5220,7 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
5213 .unit_debug_line,5220 .unit_debug_line,
5214 .unit_debug_line_header,5221 .unit_debug_line_header,
5215 .unit_debug_rnglists,5222 .unit_debug_rnglists,
5216 .value_debug_info,5223 .const_debug_info,
5217 .global_debug_info,5224 .global_debug_info,
5218 .func_frame_fde,5225 .func_frame_fde,
5219 .func_debug_info,5226 .func_debug_info,
...@@ -5252,7 +5259,7 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {...@@ -5252,7 +5259,7 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
5252 .unit_debug_info_header,5259 .unit_debug_info_header,
5253 .unit_debug_line_header,5260 .unit_debug_line_header,
5254 .unit_debug_rnglists,5261 .unit_debug_rnglists,
5255 .value_debug_info,5262 .const_debug_info,
5256 .global_debug_info,5263 .global_debug_info,
5257 .func_frame_fde,5264 .func_frame_fde,
5258 .func_debug_info,5265 .func_debug_info,
...@@ -5287,7 +5294,7 @@ fn computeNodeSectionOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 {...@@ -5287,7 +5294,7 @@ fn computeNodeSectionOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 {
5287 .unit_debug_info_header,5294 .unit_debug_info_header,
5288 .unit_debug_line_header,5295 .unit_debug_line_header,
5289 .unit_debug_rnglists,5296 .unit_debug_rnglists,
5290 .value_debug_info,5297 .const_debug_info,
5291 .global_debug_info,5298 .global_debug_info,
5292 .func_frame_fde,5299 .func_frame_fde,
5293 .func_debug_info,5300 .func_debug_info,
...@@ -5356,9 +5363,9 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {...@@ -5356,9 +5363,9 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
5356 .first_node_reloc = &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_node_reloc,5363 .first_node_reloc = &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_node_reloc,
5357 },5364 },
5358 .unit_debug_rnglists => unreachable, // unsupported5365 .unit_debug_rnglists => unreachable, // unsupported
5359 .value_debug_info => |vi| .{5366 .const_debug_info => |cpi| .{
5360 .first_symbol_reloc = &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_symbol_reloc,5367 .first_symbol_reloc = &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_symbol_reloc,
5361 .first_node_reloc = &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_node_reloc,5368 .first_node_reloc = &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_node_reloc,
5362 },5369 },
5363 .global_debug_info => |gi| .{5370 .global_debug_info => |gi| .{
5364 .first_symbol_reloc = &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_symbol_reloc,5371 .first_symbol_reloc = &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_symbol_reloc,
...@@ -5387,8 +5394,11 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {...@@ -5387,8 +5394,11 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
5387 if (opts.first_symbol_reloc) |ptr| {5394 if (opts.first_symbol_reloc) |ptr| {
5388 if (ptr.* != .none) {5395 if (ptr.* != .none) {
5389 for (elf.symbol_relocs.items[@backingInt(ptr.*)..], @backingInt(ptr.*)..) |*reloc, index| {5396 for (elf.symbol_relocs.items[@backingInt(ptr.*)..], @backingInt(ptr.*)..) |*reloc, index| {
5390 if (reloc.node.toOptional() == opts.skip_symbol_relocs) continue;5397 if (reloc.node != ni.toOptional()) {
5391 if (reloc.node != ni) break;5398 if (reloc.node == .none) continue;
5399 if (reloc.node == opts.skip_symbol_relocs) continue;
5400 break;
5401 }
5392 reloc.delete(elf, @fromBackingInt(@intCast(index)));5402 reloc.delete(elf, @fromBackingInt(@intCast(index)));
5393 }5403 }
5394 }5404 }
...@@ -5398,8 +5408,11 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {...@@ -5398,8 +5408,11 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
5398 if (opts.first_node_reloc) |ptr| {5408 if (opts.first_node_reloc) |ptr| {
5399 if (ptr.* != .none) {5409 if (ptr.* != .none) {
5400 for (elf.node_relocs.items[@backingInt(ptr.*)..]) |*reloc| {5410 for (elf.node_relocs.items[@backingInt(ptr.*)..]) |*reloc| {
5401 if (reloc.node.toOptional() == opts.skip_node_relocs) continue;5411 if (reloc.node != ni.toOptional()) {
5402 if (reloc.node != ni) break;5412 if (reloc.node == .none) continue;
5413 if (reloc.node == opts.skip_node_relocs) continue;
5414 break;
5415 }
5403 reloc.delete(elf);5416 reloc.delete(elf);
5404 }5417 }
5405 }5418 }
...@@ -5409,7 +5422,10 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {...@@ -5409,7 +5422,10 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
5409 if (opts.first_got_reloc) |ptr| {5422 if (opts.first_got_reloc) |ptr| {
5410 if (ptr.* != .none) {5423 if (ptr.* != .none) {
5411 for (elf.got_relocs.items[@backingInt(ptr.*)..]) |*reloc| {5424 for (elf.got_relocs.items[@backingInt(ptr.*)..]) |*reloc| {
5412 if (reloc.node != ni.toOptional()) break;5425 if (reloc.node != ni.toOptional()) {
5426 if (reloc.node == .none) continue;
5427 break;
5428 }
5413 reloc.delete(elf);5429 reloc.delete(elf);
5414 }5430 }
5415 }5431 }
...@@ -5433,23 +5449,32 @@ fn flushMovedNodeRelocs(...@@ -5433,23 +5449,32 @@ fn flushMovedNodeRelocs(
5433) void {5449) void {
5434 if (opts.first_symbol_reloc != .none) {5450 if (opts.first_symbol_reloc != .none) {
5435 for (elf.symbol_relocs.items[@backingInt(opts.first_symbol_reloc)..]) |*reloc| {5451 for (elf.symbol_relocs.items[@backingInt(opts.first_symbol_reloc)..]) |*reloc| {
5436 if (reloc.node.toOptional() == opts.skip_symbol_relocs) continue;5452 if (reloc.node != node.toOptional()) {
5437 if (reloc.node != node) break;5453 if (reloc.node == .none) continue;
5454 if (reloc.node == opts.skip_symbol_relocs) continue;
5455 break;
5456 }
5438 reloc.flushMovedNode(elf, node_vaddr);5457 reloc.flushMovedNode(elf, node_vaddr);
5439 }5458 }
5440 }5459 }
54415460
5442 if (opts.first_node_reloc != .none) {5461 if (opts.first_node_reloc != .none) {
5443 for (elf.node_relocs.items[@backingInt(opts.first_node_reloc)..]) |*reloc| {5462 for (elf.node_relocs.items[@backingInt(opts.first_node_reloc)..]) |*reloc| {
5444 if (reloc.node.toOptional() == opts.skip_node_relocs) continue;5463 if (reloc.node != node.toOptional()) {
5445 if (reloc.node != node) break;5464 if (reloc.node == .none) continue;
5465 if (reloc.node == opts.skip_node_relocs) continue;
5466 break;
5467 }
5446 reloc.flushMovedNode(elf, node_vaddr);5468 reloc.flushMovedNode(elf, node_vaddr);
5447 }5469 }
5448 }5470 }
54495471
5450 if (opts.first_got_reloc != .none) {5472 if (opts.first_got_reloc != .none) {
5451 for (elf.got_relocs.items[@backingInt(opts.first_got_reloc)..]) |*reloc| {5473 for (elf.got_relocs.items[@backingInt(opts.first_got_reloc)..]) |*reloc| {
5452 if (reloc.node != node.toOptional()) break;5474 if (reloc.node != node.toOptional()) {
5475 if (reloc.node == .none) continue;
5476 break;
5477 }
5453 reloc.apply(elf);5478 reloc.apply(elf);
5454 }5479 }
5455 }5480 }
...@@ -7277,7 +7302,7 @@ fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void {...@@ -7277,7 +7302,7 @@ fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void {
72777302
7278fn flushFiles(elf: *Elf) Error!void {7303fn flushFiles(elf: *Elf) Error!void {
7279 const gpa = elf.base.comp.gpa;7304 const gpa = elf.base.comp.gpa;
7280 if (elf.shndx.debug_line != .UNDEF) for (elf.dwarf.units.keys(), elf.dwarf.units.values()) |mod, *unit| {7305 if (elf.shndx.debug_line != .UNDEF) for (elf.dwarf.units.values()) |*unit| {
7281 if (!unit.cleanDebugLineHeaderChanged()) continue;7306 if (!unit.cleanDebugLineHeaderChanged()) continue;
7282 const debug_line_header_ni = unit.debug_line_header_ni.unwrap().?;7307 const debug_line_header_ni = unit.debug_line_header_ni.unwrap().?;
7283 try debug_line_header_ni.parent(&elf.mf).unwrap().?.nextMoved(gpa, &elf.mf);7308 try debug_line_header_ni.parent(&elf.mf).unwrap().?.nextMoved(gpa, &elf.mf);
...@@ -7287,7 +7312,7 @@ fn flushFiles(elf: *Elf) Error!void {...@@ -7287,7 +7312,7 @@ fn flushFiles(elf: *Elf) Error!void {
7287 debug_line_header_ni.writer(gpa, &elf.mf, &dlh_nw);7312 debug_line_header_ni.writer(gpa, &elf.mf, &dlh_nw);
7288 defer dlh_nw.deinit();7313 defer dlh_nw.deinit();
7289 elf.resetNodeRelocs(debug_line_header_ni);7314 elf.resetNodeRelocs(debug_line_header_ni);
7290 elf.dwarf.genDebugLineHeader(mod, unit, &dlh_nw, elf.base.comp.zcu.?) catch |err| switch (err) {7315 elf.dwarf.genDebugLineHeader(unit, &dlh_nw, elf.base.comp.zcu.?) catch |err| switch (err) {
7291 else => |e| return e,7316 else => |e| return e,
7292 error.WriteFailed => return dlh_nw.err.?,7317 error.WriteFailed => return dlh_nw.err.?,
7293 };7318 };
...@@ -7629,7 +7654,7 @@ fn addRelocAssumeCapacity(...@@ -7629,7 +7654,7 @@ fn addRelocAssumeCapacity(
7629 first_target_reloc.* = ri;7654 first_target_reloc.* = ri;
7630 if (next != .none) next.get(elf).prev = ri;7655 if (next != .none) next.get(elf).prev = ri;
7631 elf.symbol_relocs.appendAssumeCapacity(.{7656 elf.symbol_relocs.appendAssumeCapacity(.{
7632 .node = node,7657 .node = node.toOptional(),
7633 .offset = offset,7658 .offset = offset,
7634 .type = undefined,7659 .type = undefined,
7635 .target = target,7660 .target = target,
...@@ -8067,7 +8092,7 @@ fn addSymbolRelocAssumeCapacity(...@@ -8067,7 +8092,7 @@ fn addSymbolRelocAssumeCapacity(
8067 first_target_reloc.* = ri;8092 first_target_reloc.* = ri;
8068 if (next != .none) next.get(elf).prev = ri;8093 if (next != .none) next.get(elf).prev = ri;
8069 elf.symbol_relocs.appendAssumeCapacity(.{8094 elf.symbol_relocs.appendAssumeCapacity(.{
8070 .node = node,8095 .node = node.toOptional(),
8071 .offset = offset,8096 .offset = offset,
8072 .target = target,8097 .target = target,
8073 .addend = addend,8098 .addend = addend,
...@@ -8101,7 +8126,7 @@ fn addNodeRelocAssumeCapacity(...@@ -8101,7 +8126,7 @@ fn addNodeRelocAssumeCapacity(
8101 .unit_debug_info_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_target_reloc,8126 .unit_debug_info_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_target_reloc,
8102 .unit_debug_line_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_target_reloc,8127 .unit_debug_line_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_target_reloc,
8103 .unit_debug_rnglists => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_rnglists_first_target_reloc,8128 .unit_debug_rnglists => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_rnglists_first_target_reloc,
8104 .value_debug_info => |vi| &elf.dwarf_values.items[@backingInt(vi)].debug_info_first_target_reloc,8129 .const_debug_info => |cpi| &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_target_reloc,
8105 .global_debug_info => |gi| &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_target_reloc,8130 .global_debug_info => |gi| &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_target_reloc,
8106 .func_debug_info => |fi| &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_target_reloc,8131 .func_debug_info => |fi| &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_target_reloc,
8107 };8132 };
...@@ -8151,7 +8176,7 @@ fn addNodeRelocAssumeCapacity(...@@ -8151,7 +8176,7 @@ fn addNodeRelocAssumeCapacity(
8151 .addend = 0,8176 .addend = 0,
8152 });8177 });
8153 elf.node_relocs.appendAssumeCapacity(.{8178 elf.node_relocs.appendAssumeCapacity(.{
8154 .node = node,8179 .node = node.toOptional(),
8155 .offset = offset,8180 .offset = offset,
8156 .type = undefined,8181 .type = undefined,
8157 .target = target,8182 .target = target,
...@@ -8164,7 +8189,7 @@ fn addNodeRelocAssumeCapacity(...@@ -8164,7 +8189,7 @@ fn addNodeRelocAssumeCapacity(
8164 },8189 },
8165 .DYN, .EXEC => {8190 .DYN, .EXEC => {
8166 elf.node_relocs.appendAssumeCapacity(.{8191 elf.node_relocs.appendAssumeCapacity(.{
8167 .node = node,8192 .node = node.toOptional(),
8168 .offset = offset,8193 .offset = offset,
8169 .target = target,8194 .target = target,
8170 .addend = addend,8195 .addend = addend,
...@@ -8209,7 +8234,7 @@ fn addGotRelocAssumeCapacity(...@@ -8209,7 +8234,7 @@ fn addGotRelocAssumeCapacity(
8209 .unit_debug_line,8234 .unit_debug_line,
8210 .unit_debug_line_header,8235 .unit_debug_line_header,
8211 .unit_debug_rnglists,8236 .unit_debug_rnglists,
8212 .value_debug_info,8237 .const_debug_info,
8213 .global_debug_info,8238 .global_debug_info,
8214 .func_frame_fde,8239 .func_frame_fde,
8215 .func_debug_info,8240 .func_debug_info,
...@@ -8502,7 +8527,8 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)...@@ -8502,7 +8527,8 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
85028527
8503 const nav = ip.getNav(nav_index);8528 const nav = ip.getNav(nav_index);
8504 if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return;8529 if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return;
8505 if (!Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) return;8530 if (!Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu))
8531 return elf.dwarf.updateComptimeNav(pt, nav_index);
85068532
8507 const nmi = try elf.navMapIndex(zcu, nav_index);8533 const nmi = try elf.navMapIndex(zcu, nav_index);
8508 const ni = nmi.symbol(elf).index().ptr(elf).node.unwrap().?;8534 const ni = nmi.symbol(elf).index().ptr(elf).node.unwrap().?;
...@@ -8546,11 +8572,11 @@ pub fn updateContainerType(...@@ -8546,11 +8572,11 @@ pub fn updateContainerType(
85468572
8547pub fn addConst(8573pub fn addConst(
8548 elf: *Elf,8574 elf: *Elf,
8549 pt: Zcu.PerThread,8575 _: Zcu.PerThread,
8550 index: link.ConstPool.Index,8576 index: link.ConstPool.Index,
8551 val: InternPool.Index,8577 val: InternPool.Index,
8552) std.mem.Allocator.Error!void {8578) link.Error!void {
8553 if (false) try elf.dwarf.addConst(pt, index, val);8579 try elf.dwarf.addConst(index, val);
8554}8580}
85558581
8556pub fn updateConst(8582pub fn updateConst(
...@@ -8570,7 +8596,7 @@ fn updateConstInner(...@@ -8570,7 +8596,7 @@ fn updateConstInner(
8570) link.Error!void {8596) link.Error!void {
8571 var lazy_it = elf.lazy.iterator();8597 var lazy_it = elf.lazy.iterator();
8572 while (lazy_it.next()) |lazy| if (lazy.value.getIndex(cpi)) |li| {8598 while (lazy_it.next()) |lazy| if (lazy.value.getIndex(cpi)) |li| {
8573 const lazy_ty: Type = .fromInterned(cpi.val(&elf.dwarf.const_pool));8599 const lazy_ty: Type = .fromInterned(val);
8574 var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;8600 var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;
8575 const prog_name: []const u8 = switch (lazy_ty.zigTypeTag(pt.zcu)) {8601 const prog_name: []const u8 = switch (lazy_ty.zigTypeTag(pt.zcu)) {
8576 .@"enum" => std.mem.print(&prog_name_buf, "@tagName({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,8602 .@"enum" => std.mem.print(&prog_name_buf, "@tagName({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,
...@@ -8590,16 +8616,20 @@ fn updateConstInner(...@@ -8590,16 +8616,20 @@ fn updateConstInner(
8590 ),8616 ),
8591 };8617 };
8592 };8618 };
8593 if (false) try elf.dwarf.updateConst(pt, cpi, val);8619 elf.dwarf.updateConst(cpi, val);
8594}8620}
85958621
8596pub fn updateConstIncomplete(8622pub fn updateConstIncomplete(
8597 elf: *Elf,8623 elf: *Elf,
8598 pt: Zcu.PerThread,8624 _: Zcu.PerThread,
8599 cpi: link.ConstPool.Index,8625 cpi: link.ConstPool.Index,
8600 val: InternPool.Index,8626 val: InternPool.Index,
8601) link.Error!void {8627) link.Error!void {
8602 if (false) try elf.dwarf.updateConstIncomplete(pt, cpi, val);8628 const debug_info_ni = Dwarf.Const.get(cpi, &elf.dwarf).debug_info_ni.unwrap().?;
8629 var di_nw: MappedFile.Node.Writer = undefined;
8630 debug_info_ni.writer(elf.base.comp.gpa, &elf.mf, &di_nw);
8631 defer di_nw.deinit();
8632 try elf.dwarf.updateConstIncomplete(&di_nw, val);
8603}8633}
86048634
8605pub fn updateFunc(8635pub fn updateFunc(
...@@ -8770,7 +8800,7 @@ fn updateFuncInner(...@@ -8770,7 +8800,7 @@ fn updateFuncInner(
8770 elf.resetNodeRelocs(dwarf_func.debug_line_ni.unwrap().?);8800 elf.resetNodeRelocs(dwarf_func.debug_line_ni.unwrap().?);
8771 try debug.startDebugLine();8801 try debug.startDebugLine();
8772 elf.resetNodeRelocs(dwarf_func.debug_info_ni.unwrap().?);8802 elf.resetNodeRelocs(dwarf_func.debug_info_ni.unwrap().?);
8773 try debug.startDebugInfo();8803 try debug.startFuncDebugInfo();
8774 },8804 },
8775 .none => {},8805 .none => {},
8776 }8806 }
...@@ -9187,7 +9217,7 @@ fn idleProgNode(...@@ -9187,7 +9217,7 @@ fn idleProgNode(
9187 },9217 },
9188 ui.mod(&elf.dwarf).fully_qualified_name,9218 ui.mod(&elf.dwarf).fully_qualified_name,
9189 }) catch &name,9219 }) catch &name,
9190 .value_debug_info => |cpi| std.mem.print(&name, "debug info for {f}", .{9220 .const_debug_info => |cpi| std.mem.print(&name, "debug info for {f}", .{
9191 Value.fromInterned(cpi.val(&elf.dwarf.const_pool))9221 Value.fromInterned(cpi.val(&elf.dwarf.const_pool))
9192 .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),9222 .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
9193 }) catch &name,9223 }) catch &name,
...@@ -9648,14 +9678,14 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -9648,14 +9678,14 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
9648 const node_vaddr = elf.computeNodeVAddr(ni);9678 const node_vaddr = elf.computeNodeVAddr(ni);
9649 for (dwarf_unit.debug_rnglists_symbol_relocs.keys()) |symbol_ri| {9679 for (dwarf_unit.debug_rnglists_symbol_relocs.keys()) |symbol_ri| {
9650 const symbol_reloc = symbol_ri.get(elf);9680 const symbol_reloc = symbol_ri.get(elf);
9651 assert(symbol_reloc.node == ni);9681 assert(symbol_reloc.node.unwrap().? == ni);
9652 symbol_reloc.flushMovedNode(elf, node_vaddr);9682 symbol_reloc.flushMovedNode(elf, node_vaddr);
9653 }9683 }
9654 },9684 },
9655 .value_debug_info => |vi| {9685 .const_debug_info => |cpi| {
9656 const dwarf_value = &elf.dwarf_values.items[@backingInt(vi)];9686 const dwarf_const = &elf.dwarf_consts.get(cpi).?;
9657 const target_section_offset = elf.computeNodeSectionOffset(ni);9687 const target_section_offset = elf.computeNodeSectionOffset(ni);
9658 var target_ri = dwarf_value.debug_info_first_target_reloc;9688 var target_ri = dwarf_const.debug_info_first_target_reloc;
9659 while (target_ri != .none) {9689 while (target_ri != .none) {
9660 const target_reloc = target_ri.get(elf);9690 const target_reloc = target_ri.get(elf);
9661 assert(target_reloc.target == ni);9691 assert(target_reloc.target == ni);
...@@ -9663,12 +9693,12 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -9663,12 +9693,12 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
9663 target_ri = target_reloc.next;9693 target_ri = target_reloc.next;
9664 }9694 }
9665 elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{9695 elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{
9666 .first_symbol_reloc = dwarf_value.debug_info_first_symbol_reloc,9696 .first_symbol_reloc = dwarf_const.debug_info_first_symbol_reloc,
9667 .first_node_reloc = dwarf_value.debug_info_first_node_reloc,9697 .first_node_reloc = dwarf_const.debug_info_first_node_reloc,
9668 });9698 });
9669 },9699 },
9670 .global_debug_info => |vi| {9700 .global_debug_info => |gi| {
9671 const dwarf_global = &elf.dwarf_globals.items[@backingInt(vi)];9701 const dwarf_global = &elf.dwarf_globals.items[@backingInt(gi)];
9672 const target_section_offset = elf.computeNodeSectionOffset(ni);9702 const target_section_offset = elf.computeNodeSectionOffset(ni);
9673 var target_ri = dwarf_global.debug_info_first_target_reloc;9703 var target_ri = dwarf_global.debug_info_first_target_reloc;
9674 while (target_ri != .none) {9704 while (target_ri != .none) {
...@@ -9972,7 +10002,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo...@@ -9972,7 +10002,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
9972 .unit_debug_line,10002 .unit_debug_line,
9973 .unit_debug_line_header,10003 .unit_debug_line_header,
9974 .unit_debug_rnglists,10004 .unit_debug_rnglists,
9975 .value_debug_info,10005 .const_debug_info,
9976 .global_debug_info,10006 .global_debug_info,
9977 .func_frame_fde,10007 .func_frame_fde,
9978 .func_debug_info,10008 .func_debug_info,
...@@ -10036,7 +10066,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!...@@ -10036,7 +10066,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
10036 .unit_debug_info_header,10066 .unit_debug_info_header,
10037 .unit_debug_line_header,10067 .unit_debug_line_header,
10038 .unit_debug_rnglists,10068 .unit_debug_rnglists,
10039 .value_debug_info,10069 .const_debug_info,
10040 .global_debug_info,10070 .global_debug_info,
10041 .func_frame_fde,10071 .func_frame_fde,
10042 .func_debug_info,10072 .func_debug_info,
...@@ -10089,7 +10119,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!...@@ -10089,7 +10119,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
10089 },10119 },
10090 .unit_debug_info_header,10120 .unit_debug_info_header,
10091 .unit_debug_line_header,10121 .unit_debug_line_header,
10092 .value_debug_info,10122 .const_debug_info,
10093 .global_debug_info,10123 .global_debug_info,
10094 .func_debug_info,10124 .func_debug_info,
10095 .func_debug_line,10125 .func_debug_line,
...@@ -10105,7 +10135,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!...@@ -10105,7 +10135,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
10105 switch (tag) {10135 switch (tag) {
10106 else => unreachable,10136 else => unreachable,
10107 .unit_debug_info_header,10137 .unit_debug_info_header,
10108 .value_debug_info,10138 .const_debug_info,
10109 .global_debug_info,10139 .global_debug_info,
10110 .func_debug_info,10140 .func_debug_info,
10111 => for (0..2) |_| fw.writeUleb128(@backingInt(Dwarf.AbbrevCode.null)) catch unreachable,10141 => for (0..2) |_| fw.writeUleb128(@backingInt(Dwarf.AbbrevCode.null)) catch unreachable,
...@@ -10119,7 +10149,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!...@@ -10119,7 +10149,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
10119 elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len);10149 elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len);
10120 switch (tag) {10150 switch (tag) {
10121 else => unreachable,10151 else => unreachable,
10122 .unit_debug_info_header, .value_debug_info, .global_debug_info, .func_debug_info => {10152 .unit_debug_info_header, .const_debug_info, .global_debug_info, .func_debug_info => {
10123 comptime assert(Dwarf.uleb128Size(@backingInt(Dwarf.AbbrevCode.null)) == 1);10153 comptime assert(Dwarf.uleb128Size(@backingInt(Dwarf.AbbrevCode.null)) == 1);
10124 @memset(fw.unusedCapacitySlice(), @backingInt(Dwarf.AbbrevCode.null));10154 @memset(fw.unusedCapacitySlice(), @backingInt(Dwarf.AbbrevCode.null));
10125 },10155 },
...@@ -10143,7 +10173,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!...@@ -10143,7 +10173,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
10143 @memset(fw.buffer, std.dwarf.CFA.nop);10173 @memset(fw.buffer, std.dwarf.CFA.nop);
10144 },10174 },
10145 .unit_debug_info_header,10175 .unit_debug_info_header,
10146 .value_debug_info,10176 .const_debug_info,
10147 .global_debug_info,10177 .global_debug_info,
10148 .func_debug_info,10178 .func_debug_info,
10149 => elf.dwarf.genDebugInfoPadding(&fw, fw.buffer.len) catch unreachable,10179 => elf.dwarf.genDebugInfoPadding(&fw, fw.buffer.len) catch unreachable,
...@@ -10693,9 +10723,11 @@ pub fn printNode(...@@ -10693,9 +10723,11 @@ pub fn printNode(
10693 .unit_debug_line_header,10723 .unit_debug_line_header,
10694 .unit_debug_rnglists,10724 .unit_debug_rnglists,
10695 => |ui| try w.print("({s})", .{ui.mod(&elf.dwarf).fully_qualified_name}),10725 => |ui| try w.print("({s})", .{ui.mod(&elf.dwarf).fully_qualified_name}),
10696 .value_debug_info => |cpi| try w.print("({f})", .{10726 .const_debug_info => |cpi| try w.print("({f})", .{
10697 Value.fromInterned(cpi.val(&elf.dwarf.const_pool))10727 Value.fromInterned(cpi.val(&elf.dwarf.const_pool)).fmtValue(.{
10698 .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),10728 .zcu = elf.base.comp.zcu.?,
10729 .tid = tid,
10730 }),
10699 }),10731 }),
10700 .global_debug_info => |gi| {10732 .global_debug_info => |gi| {
10701 const zcu = elf.base.comp.zcu.?;10733 const zcu = elf.base.comp.zcu.?;