authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-08-09 15:26:09-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-03 11:00:54-04:00
logc5c037808e30d2c632bd3bd08ed17eef7fdd373e
tree810bbbbc99beb142b38f24eb5fee981eb93ecd35
parent2375b0063da554eeb1ed4b0b8dbe8dad485c5f6a

Dwarf2: start emitting some dwarf debug info


4 files changed, 1081 insertions(+), 451 deletions(-)

lib/std/Io/Writer.zig+4-7
......@@ -487,7 +487,7 @@ pub fn writableSliceGreedyPreserve(w: *Writer, preserve: usize, minimum_len: usi
487487 @branchHint(.likely);
488488 return w.buffer[w.end..];
489489 }
490 try rebase(w, preserve, minimum_len);
490 try w.vtable.rebase(w, preserve, minimum_len);
491491 assert(w.buffer.len >= preserve + minimum_len);
492492 return w.buffer[w.end..];
493493}
......@@ -845,13 +845,10 @@ pub fn writeByte(w: *Writer, byte: u8) Error!void {
845845///
846846/// Asserts buffer capacity is at least `preserve`.
847847pub fn writeBytePreserve(w: *Writer, preserve: usize, byte: u8) Error!void {
848 if (w.buffer.len - w.end != 0) {
849 @branchHint(.likely);
850 w.buffer[w.end] = byte;
851 w.end += 1;
852 return;
848 if (w.buffer.len - w.end == 0) {
849 @branchHint(.unlikely);
850 try w.vtable.rebase(w, preserve -| 1, 1);
853851 }
854 try w.vtable.rebase(w, preserve -| 1, 1);
855852 w.buffer[w.end] = byte;
856853 w.end += 1;
857854}
src/codegen/x86_64/Emit.zig+15-13
......@@ -36,7 +36,7 @@ pub fn emitMir(emit: *Emit) Error!void {
3636 if (lowered_inst.prefix == .directive) {
3737 const start_offset: u32 = @intCast(emit.w.end);
3838 switch (emit.debug_output) {
39 inline .dwarf, .eh_frame, .dwarf2 => |dwarf| switch (lowered_inst.encoding.mnemonic) {
39 inline .dwarf, .dwarf2, .eh_frame => |dwarf| switch (lowered_inst.encoding.mnemonic) {
4040 .@".cfi_def_cfa" => try dwarf.genDebugFrame(start_offset, .{ .def_cfa = .{
4141 .reg = lowered_inst.ops[0].reg.dwarfNum(),
4242 .off = lowered_inst.ops[1].imm.signed,
......@@ -475,15 +475,17 @@ pub fn emitMir(emit: *Emit) Error!void {
475475 .column = mir_inst.data.line_column.column,
476476 .is_stmt = false,
477477 }),
478 .pseudo_dbg_epilogue_begin_none => switch (emit.debug_output) {
479 inline .dwarf, .dwarf2 => |dwarf| {
480 try dwarf.setEpilogueBegin();
481 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
482 emit.prev_di_loc.line, emit.prev_di_loc.column,
483 });
484 try emit.dbgAdvancePcAndLine(emit.prev_di_loc);
485 },
486 .eh_frame, .none => {},
478 .pseudo_dbg_epilogue_begin_none => {
479 switch (emit.debug_output) {
480 inline .dwarf, .dwarf2 => |dwarf| {
481 try dwarf.setEpilogueBegin();
482 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
483 emit.prev_di_loc.line, emit.prev_di_loc.column,
484 });
485 },
486 .eh_frame, .none => {},
487 }
488 try emit.dbgAdvancePcAndLine(emit.prev_di_loc);
487489 },
488490 .pseudo_dbg_enter_block_none => switch (emit.debug_output) {
489491 inline .dwarf, .dwarf2 => |dwarf| {
......@@ -976,11 +978,11 @@ const Loc = struct {
976978};
977979
978980fn dbgAdvancePcAndLine(emit: *Emit, loc: Loc) Error!void {
979 const delta_line = @as(i33, loc.line) - @as(i33, emit.prev_di_loc.line);
980 const delta_pc: usize = emit.w.end - emit.prev_di_pc;
981 log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line });
982981 switch (emit.debug_output) {
983982 inline .dwarf, .dwarf2 => |dwarf| {
983 const delta_line = @as(i33, loc.line) - @as(i33, emit.prev_di_loc.line);
984 const delta_pc: usize = emit.w.end - emit.prev_di_pc;
985 log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line });
984986 if (loc.is_stmt != emit.prev_di_loc.is_stmt) try dwarf.negateStmt();
985987 if (loc.column != emit.prev_di_loc.column) try dwarf.setColumn(loc.column);
986988 try dwarf.advancePcAndLine(delta_line, delta_pc);
src/link/Dwarf2.zig+427-208
......@@ -1,4 +1,4 @@
1tag: link.File.Tag,
1lf: *link.File,
22format: DW.Format,
33endian: std.lang.Endian,
44address_size: AddressSize,
......@@ -12,15 +12,23 @@ 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,
1516frame: Frame,
1617debug_info: DebugInfo,
1718debug_line: DebugLine,
19debug_line_str: String,
20debug_str: String,
21debug_str_offsets: StringOffsets,
1822
1923pub const AddressSize = enum(u8) { @"32" = 4, @"64" = 8, _ };
2024
2125pub const Unit = struct {
2226 frame_ni: MappedFile.Node.Index.Optional,
2327 cie_ni: MappedFile.Node.Index.Optional,
28 debug_info_ni: MappedFile.Node.Index.Optional,
29 debug_info_header_ni: MappedFile.Node.Index.Optional,
30 debug_line_ni: MappedFile.Node.Index.Optional,
31 debug_line_header_ni: MappedFile.Node.Index.Optional,
2432
2533 pub const Index = enum(u32) {
2634 _,
......@@ -71,7 +79,6 @@ pub const Func = struct {
7179
7280pub const Frame = struct {
7381 header: Header,
74 section_index: SectionIndex,
7582
7683 pub const Header = struct {
7784 code_alignment_factor: u32,
......@@ -83,13 +90,16 @@ pub const Frame = struct {
8390 pub const Format = std.debug.Dwarf.Unwind.Section;
8491};
8592
86pub const DebugInfo = struct {
87 section_index: SectionIndex,
93pub const DebugAbbrev = struct {
94 ni: MappedFile.Node.Index.Optional,
95 offset: usize,
96 set: std.enums.EnumSet(AbbrevCode),
8897};
8998
99pub const DebugInfo = struct {};
100
90101pub const DebugLine = struct {
91102 header: Header,
92 section_index: SectionIndex,
93103
94104 pub const Header = struct {
95105 minimum_instruction_length: u8,
......@@ -101,7 +111,49 @@ pub const DebugLine = struct {
101111 };
102112};
103113
104pub const SectionIndex = enum(u32) { none = std.math.maxInt(u32), _ };
114pub const String = struct {
115 ni: MappedFile.Node.Index.Optional,
116 offset: usize,
117 map: std.AutoHashMapUnmanaged(usize, void),
118
119 fn get(
120 s: *String,
121 gpa: std.mem.Allocator,
122 mf: *MappedFile,
123 string: []const u8,
124 ) MappedFile.Error!usize {
125 const ni = s.ni.unwrap().?;
126 const gop = try s.map.getOrPutAdapted(gpa, string, Adapter{ .slice = ni.sliceConst(mf) });
127 if (!gop.found_existing) {
128 gop.key_ptr.* = s.offset;
129 try ni.ensureMinimumSize(mf, gpa, s.offset + string.len + 1);
130 const slice_mut = ni.slice(mf);
131 @memcpy(slice_mut[s.offset..][0..string.len], string);
132 s.offset += string.len;
133 slice_mut[s.offset] = 0;
134 s.offset += 1;
135 }
136 return gop.key_ptr.*;
137 }
138
139 const Adapter = struct {
140 slice: []const u8,
141 pub fn hash(_: Adapter, key: []const u8) u32 {
142 return @truncate(std.hash.Wyhash.hash(0, key));
143 }
144 pub fn eql(adapter: Adapter, key: []const u8, rhs_offset: usize) bool {
145 return std.mem.startsWith(u8, adapter.slice[rhs_offset..], key) and
146 adapter.slice[rhs_offset + key.len] == 0;
147 }
148 };
149};
150
151pub const StringOffsets = struct {
152 ni: MappedFile.Node.Index.Optional,
153 offset: usize,
154};
155
156pub const SharedSection = enum { debug_abbrev, debug_line_str, debug_str, debug_str_offsets };
105157
106158pub const Loc = union(enum) {
107159 empty,
......@@ -463,7 +515,7 @@ pub const WipNav = struct {
463515 },
464516 frame_format: Frame.Format,
465517 fde_writer: MappedFile.Node.Writer,
466 frame_func_length_offset: usize,
518 frame_func_length: struct { offset: usize, size: AddressSize },
467519
468520 pub const Debug = struct {
469521 wip_nav: WipNav,
......@@ -477,22 +529,53 @@ pub const WipNav = struct {
477529 info_writer: MappedFile.Node.Writer,
478530 line_writer: MappedFile.Node.Writer,
479531
480 pub fn deinit(debug: *Debug, gpa: Allocator) void {
532 pub fn deinit(debug: *Debug) void {
533 const gpa = debug.pt.zcu.gpa;
481534 debug.line_writer.deinit();
482535 debug.info_writer.deinit();
483536 debug.blocks.deinit(gpa);
484 debug.wip_nav.deinit(gpa);
537 debug.wip_nav.deinit();
485538 debug.* = undefined;
486539 }
487540
488 pub fn genFuncHeaders(debug: *Debug) link.Error!void {
489 try debug.wip_nav.genFuncHeaders();
541 pub fn startDebugInfo(debug: *Debug) link.Error!void {
542 debug.startDebugInfoInner() catch |err| switch (err) {
543 error.WriteFailed => return debug.wip_nav.reportWriteError(&debug.info_writer),
544 else => |e| return e,
545 };
546 }
547 fn startDebugInfoInner(debug: *Debug) link.EmitError!void {
548 const dwarf = debug.wip_nav.dwarf;
549 const ip = &debug.pt.zcu.intern_pool;
550 const nav = ip.getNav(debug.wip_nav.func.?.nav(dwarf));
551 const diw = &debug.info_writer.interface;
552 try diw.writeUleb128(try dwarf.refAbbrevCode(.decl_func));
553 try debug.strp(nav.name.toSlice(ip));
554 try debug.strp(nav.fqn.toSlice(ip));
490555 }
491556
492557 pub fn genDebugFrame(debug: *Debug, loc: u32, cfa: Cfa) link.Error!void {
493558 return debug.wip_nav.genDebugFrame(loc, cfa);
494559 }
495560
561 pub fn finishFunc(debug: *Debug) link.Error!void {
562 assert(debug.wip_nav.func != null);
563 debug.finishDebugInfo() catch |err| switch (err) {
564 error.WriteFailed => return debug.wip_nav.reportWriteError(&debug.info_writer),
565 else => |e| return e,
566 };
567 const dlw = &debug.line_writer.interface;
568 dlw.rebase(dlw.end, comptime 1 + uleb128Bytes(1) + 1) catch |err| switch (err) {
569 error.WriteFailed => return debug.wip_nav.reportWriteError(&debug.line_writer),
570 };
571 }
572
573 fn finishDebugInfo(debug: *Debug) link.EmitError!void {
574 const diw = &debug.info_writer.interface;
575 try diw.writeUleb128(@backingInt(AbbrevCode.null));
576 try debug.wip_nav.dwarf.genDebugInfoPadding(diw, diw.unusedCapacityLen());
577 }
578
496579 pub const LocalVarTag = enum { arg, local_var };
497580 pub fn genLocalVarDebugInfo(
498581 debug: *Debug,
......@@ -675,7 +758,7 @@ pub const WipNav = struct {
675758 fn enterBlockInner(debug: *Debug, code_off: u64) link.EmitError!void {
676759 const dwarf = debug.wip_nav.dwarf;
677760 const diw = &debug.info_writer.interface;
678 const block = try debug.blocks.addOne(dwarf.linkFile().comp.gpa);
761 const block = try debug.blocks.addOne(dwarf.lf.comp.gpa);
679762
680763 block.abbrev_code = @intCast(diw.end);
681764 try debug.abbrevCode(.block);
......@@ -767,17 +850,18 @@ pub const WipNav = struct {
767850 const dwarf = debug.wip_nav.dwarf;
768851 const inlined_func_bytes = comptime uleb128Bytes(@backingInt(AbbrevCode.inlined_func));
769852 const block = debug.blocks.pop().?;
853 const diw = &debug.info_writer.interface;
770854 if (debug.any_children)
771 try debug.info_writer.interface.writeUleb128(@backingInt(AbbrevCode.null))
855 try diw.writeUleb128(@backingInt(AbbrevCode.null))
772856 else
773857 std.leb.writeUnsignedFixed(
774858 inlined_func_bytes,
775 debug.info_writer.interface.buffered()[block.abbrev_code..][0..inlined_func_bytes],
859 diw.buffered()[block.abbrev_code..][0..inlined_func_bytes],
776860 @intCast(try dwarf.refAbbrevCode(.empty_inlined_func)),
777861 );
778862 std.mem.writeInt(
779863 u32,
780 debug.info_writer.interface.buffered()[block.high_pc..][0..4],
864 diw.buffered()[block.high_pc..][0..4],
781865 @intCast(code_off - block.low_pc_off),
782866 dwarf.endian,
783867 );
......@@ -806,7 +890,7 @@ pub const WipNav = struct {
806890
807891 const dlw = &debug.line_writer.interface;
808892 if (zcu.comp.config.incremental) {
809 const new_func_gop = try dwarf.funcs.getOrPut(dwarf.gpa, new_func_info.owner_nav);
893 const new_func_gop = try dwarf.funcs.getOrPut(zcu.gpa, new_func_info.owner_nav);
810894 errdefer _ = if (!new_func_gop.found_existing) dwarf.funcs.pop();
811895 if (!new_func_gop.found_existing) new_func_gop.value_ptr.* = .{
812896 .frame_node = .none,
......@@ -822,8 +906,8 @@ pub const WipNav = struct {
822906 try dlw.writeByte(DW.LNS.extended_op);
823907 try dlw.writeUleb128(1 + section_offset_size);
824908 try dlw.writeByte(DW.LNE.ZIG_set_decl);
825 try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{
826 .source_off = @intCast(dlw.end),
909 try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(zcu.gpa, .{
910 .source_off = @bitCast(@as(u64, dlw.end)),
827911 .target_sec = .debug_info,
828912 .target_unit = new_unit,
829913 .target_entry = new_func_gop.value_ptr.toOptional(),
......@@ -836,8 +920,8 @@ pub const WipNav = struct {
836920 const old_file = zcu.navFileScopeIndex(old_func_info.owner_nav);
837921 if (old_file != new_file) {
838922 const mod_info = dwarf.getModInfo(wip_nav.unit);
839 try mod_info.dirs.put(dwarf.gpa, new_unit, {});
840 const file_gop = try mod_info.files.getOrPut(dwarf.gpa, new_file);
923 try mod_info.dirs.put(zcu.gpa, new_unit, {});
924 const file_gop = try mod_info.files.getOrPut(zcu.gpa, new_file);
841925
842926 try dlw.writeByte(DW.LNS.set_file);
843927 try dlw.writeUleb128(file_gop.index);
......@@ -854,57 +938,38 @@ pub const WipNav = struct {
854938 }
855939
856940 fn abbrevCode(debug: *Debug, abbrev_code: AbbrevCode) link.EmitError!void {
857 try debug.info_writer.interface.writeUleb128(try debug.wip_nav.dwarf.refAbbrevCode(abbrev_code));
941 try debug.info_writer.interface.writeUleb128(
942 try debug.wip_nav.dwarf.refAbbrevCode(abbrev_code),
943 );
858944 }
859945
860946 fn infoExternalReloc(debug: *Debug, reloc: struct {
861947 source_off: u32 = 0,
862948 target_si: link.File.SymbolId,
863949 target_off: u64 = 0,
864 }) Allocator.Error!void {
950 }) std.mem.Allocator.Error!void {
865951 if (true) @panic("TODO");
866952 try debug.wip_nav.externalReloc(&debug.wip_nav.dwarf.debug_frame.section, reloc);
867953 }
868954
869955 fn infoSectionOffset(
870956 debug: *Debug,
871 target: MappedFile.Node.Index,
957 target_ni: MappedFile.Node.Index,
872958 addend: i64,
873959 ) link.EmitError!void {
874 const dwarf = debug.wip_nav.dwarf;
875 const diw = &debug.info_writer.interface;
876 const offset = diw.end;
877 switch (dwarf.format) {
878 .@"32" => try diw.writeInt(u32, 0, dwarf.endian),
879 .@"64" => try diw.writeInt(u64, 0, dwarf.endian),
880 }
881 try dwarf.linkFile().cast(.elf2).?.addNodeReloc(
882 debug.info_writer.ni,
883 offset,
884 target,
885 addend,
886 switch (dwarf.format) {
887 .@"32" => .abs32,
888 .@"64" => .abs64,
889 },
890 );
960 try debug.wip_nav.dwarf.sectionOffset(&debug.info_writer, target_ni, addend);
891961 }
892962
893963 fn strp(debug: *Debug, str: []const u8) link.EmitError!void {
894 if (true) @panic("TODO");
895964 const dwarf = debug.wip_nav.dwarf;
896 try debug.infoSectionOffset(.debug_str, try dwarf.debug_str.addString(dwarf, str), 0);
965 try dwarf.strp(&dwarf.debug_str, &debug.info_writer, str);
897966 }
898967
899 fn strpFmt(
900 debug: *Debug,
901 comptime fmt: []const u8,
902 args: anytype,
903 ) link.EmitError!void {
904 const gpa = &debug.wip_nav.dwarf.gpa;
968 fn strpFmt(debug: *Debug, comptime fmt: []const u8, args: anytype) link.EmitError!void {
969 const gpa = debug.pt.zcu.gpa;
905970 const str = try std.fmt.allocPrint(gpa, fmt, args);
906971 defer gpa.free(str);
907 return debug.strp(str);
972 try debug.strp(str);
908973 }
909974
910975 fn infoExprLoc(debug: *Debug, loc: Loc) link.EmitError!void {
......@@ -923,10 +988,7 @@ pub const WipNav = struct {
923988 fn addrSym(ctx: @This(), si: link.File.SymbolId) link.EmitError!void {
924989 try ctx.debug.infoAddrSym(si, 0);
925990 }
926 fn infoEntry(
927 ctx: @This(),
928 node: MappedFile.Node.Index,
929 ) link.EmitError!void {
991 fn infoEntry(ctx: @This(), node: MappedFile.Node.Index) link.EmitError!void {
930992 try ctx.debug.infoSectionOffset(node, 0);
931993 }
932994 } = .{ .debug = debug };
......@@ -941,7 +1003,7 @@ pub const WipNav = struct {
9411003 ) link.EmitError!void {
9421004 const diw = &debug.info_writer.interface;
9431005 try debug.infoExternalReloc(.{
944 .source_off = @intCast(diw.end),
1006 .source_off = @bitCast(@as(u64, diw.end)),
9451007 .target_si = si,
9461008 .target_off = sym_off,
9471009 });
......@@ -957,7 +1019,6 @@ pub const WipNav = struct {
9571019 }
9581020
9591021 fn refValue(debug: *Debug, value: Value) link.EmitError!void {
960 if (true) @panic("TODO");
9611022 try debug.infoSectionOffset(.debug_info, try debug.getValueNode(value), 0);
9621023 }
9631024
......@@ -978,7 +1039,7 @@ pub const WipNav = struct {
9781039 if (size == 0) return;
9791040 const old_end = diw.end;
9801041 try codegen.generateSymbol(
981 debug.wip_nav.dwarf.linkFile(),
1042 debug.wip_nav.dwarf.lf,
9821043 debug.pt,
9831044 val,
9841045 diw,
......@@ -996,37 +1057,29 @@ pub const WipNav = struct {
9961057 }
9971058 };
9981059
999 pub fn deinit(wip_nav: *WipNav, gpa: Allocator) void {
1000 _ = gpa;
1060 pub fn deinit(wip_nav: *WipNav) void {
10011061 wip_nav.fde_writer.deinit();
10021062 wip_nav.* = undefined;
10031063 }
10041064
1005 pub fn genFuncHeaders(wip_nav: *WipNav) link.Error!void {
1006 wip_nav.genDebugFrameHeader() catch |err| switch (err) {
1065 pub fn genDebugFrameHeader(wip_nav: *WipNav) link.Error!void {
1066 wip_nav.genDebugFrameHeaderInner() catch |err| switch (err) {
10071067 error.WriteFailed => return wip_nav.reportWriteError(&wip_nav.fde_writer),
10081068 else => |e| return e,
10091069 };
10101070 }
1011 fn genDebugFrameHeader(wip_nav: *WipNav) link.EmitError!void {
1071 fn genDebugFrameHeaderInner(wip_nav: *WipNav) link.EmitError!void {
10121072 assert(wip_nav.func != null);
10131073 const dwarf = wip_nav.dwarf;
10141074 const dfw = &wip_nav.fde_writer.interface;
1015 switch (dwarf.format) {
1016 .@"32" => try dfw.writeInt(u32, undefined, dwarf.endian),
1017 .@"64" => {
1018 try dfw.writeInt(u32, std.math.maxInt(u32), dwarf.endian);
1019 try dfw.writeInt(u64, undefined, dwarf.endian);
1020 },
1021 }
1022 const unit = wip_nav.unit.get(dwarf);
1075 try dwarf.genUnitLength(dfw);
10231076 switch (wip_nav.frame_format) {
10241077 .eh_frame => {
10251078 try dfw.writeInt(u32, undefined, dwarf.endian);
10261079 {
10271080 const offset = dfw.end;
10281081 try dfw.writeInt(u32, 0, dwarf.endian);
1029 const elf = dwarf.linkFile().cast(.elf2).?;
1082 const elf = dwarf.lf.cast(.elf2).?;
10301083 try elf.addReloc(
10311084 @bitCast(wip_nav.fde_writer.ni),
10321085 offset,
......@@ -1035,14 +1088,14 @@ pub const WipNav = struct {
10351088 .rel32(elf),
10361089 );
10371090 }
1038 wip_nav.frame_func_length_offset = dfw.end;
1091 wip_nav.frame_func_length = .{ .offset = dfw.end, .size = .@"32" };
10391092 try dfw.writeInt(u32, undefined, dwarf.endian);
10401093 try dfw.writeUleb128(0);
10411094 },
10421095 .debug_frame => {
1043 try wip_nav.frameSectionOffset(unit.cie_ni.unwrap().?, 0);
1096 try wip_nav.frameSectionOffset(wip_nav.unit.get(dwarf).cie_ni.unwrap().?, 0);
10441097 try wip_nav.frameAddrSym(wip_nav.func_si, 0);
1045 wip_nav.frame_func_length_offset = dfw.end;
1098 wip_nav.frame_func_length = .{ .offset = dfw.end, .size = dwarf.address_size };
10461099 try dfw.splatByteAll(undefined, @backingInt(dwarf.address_size));
10471100 },
10481101 }
......@@ -1063,30 +1116,23 @@ pub const WipNav = struct {
10631116
10641117 pub fn finishDebugFrameFde(wip_nav: *WipNav, func_length: u64) void {
10651118 const dwarf = wip_nav.dwarf;
1066 const fde = wip_nav.fde_writer.interface.buffer;
1067 switch (wip_nav.frame_format) {
1068 .eh_frame => std.mem.writeInt(
1119 const dfw = &wip_nav.fde_writer.interface;
1120 switch (wip_nav.frame_func_length.size) {
1121 _ => unreachable,
1122 .@"32" => std.mem.writeInt(
10691123 u32,
1070 fde[wip_nav.frame_func_length_offset..][0..4],
1124 dfw.buffered()[wip_nav.frame_func_length.offset..][0..4],
10711125 @intCast(func_length),
10721126 dwarf.endian,
10731127 ),
1074 .debug_frame => switch (dwarf.address_size) {
1075 _ => unreachable,
1076 .@"32" => std.mem.writeInt(
1077 u32,
1078 fde[wip_nav.frame_func_length_offset..][0..4],
1079 @intCast(func_length),
1080 dwarf.endian,
1081 ),
1082 .@"64" => std.mem.writeInt(
1083 u64,
1084 fde[wip_nav.frame_func_length_offset..][0..8],
1085 func_length,
1086 dwarf.endian,
1087 ),
1088 },
1128 .@"64" => std.mem.writeInt(
1129 u64,
1130 dfw.buffered()[wip_nav.frame_func_length.offset..][0..8],
1131 func_length,
1132 dwarf.endian,
1133 ),
10891134 }
1135 @memset(dfw.unusedCapacitySlice(), DW.CFA.nop);
10901136 }
10911137
10921138 const ExprLocCounter = struct {
......@@ -1119,26 +1165,10 @@ pub const WipNav = struct {
11191165
11201166 fn frameSectionOffset(
11211167 wip_nav: *WipNav,
1122 target: MappedFile.Node.Index,
1123 addend: i64,
1168 target_ni: MappedFile.Node.Index,
1169 addend: usize,
11241170 ) link.EmitError!void {
1125 const dwarf = wip_nav.dwarf;
1126 const dfw = &wip_nav.fde_writer.interface;
1127 const offset = dfw.end;
1128 switch (dwarf.format) {
1129 .@"32" => try dfw.writeInt(u32, 0, dwarf.endian),
1130 .@"64" => try dfw.writeInt(u64, 0, dwarf.endian),
1131 }
1132 try dwarf.linkFile().cast(.elf2).?.addNodeReloc(
1133 wip_nav.fde_writer.ni,
1134 offset,
1135 target,
1136 addend,
1137 switch (dwarf.format) {
1138 .@"32" => .abs32,
1139 .@"64" => .abs64,
1140 },
1141 );
1171 try wip_nav.dwarf.sectionOffset(&wip_nav.fde_writer, target_ni, addend);
11421172 }
11431173
11441174 fn frameExprLoc(wip_nav: *WipNav, loc: Loc) link.EmitError!void {
......@@ -1174,7 +1204,7 @@ pub const WipNav = struct {
11741204 const dfw = &wip_nav.fde_writer.interface;
11751205 const offset = dfw.end;
11761206 try dfw.splatByteAll(0, @backingInt(dwarf.address_size));
1177 const elf = dwarf.linkFile().cast(.elf2).?;
1207 const elf = dwarf.lf.cast(.elf2).?;
11781208 try elf.addReloc(
11791209 @bitCast(wip_nav.fde_writer.ni),
11801210 offset,
......@@ -1190,7 +1220,7 @@ pub const WipNav = struct {
11901220 fn reportWriteError(wip_nav: *WipNav, mfnw: *const MappedFile.Node.Writer) link.Error {
11911221 switch (mfnw.err.?) {
11921222 else => |e| return e,
1193 error.MappedFileIo => return wip_nav.dwarf.linkFile().comp.link_diags.fail(
1223 error.MappedFileIo => return wip_nav.dwarf.lf.comp.link_diags.fail(
11941224 "failed to write output file: {t}",
11951225 .{mfnw.mf.io_err.?},
11961226 ),
......@@ -1199,10 +1229,9 @@ pub const WipNav = struct {
11991229};
12001230
12011231pub fn init(lf: *link.File, format: DW.Format) Dwarf {
1202 const comp = lf.comp;
1203 const target = &comp.root_mod.resolved_target.result;
1232 const target = &lf.comp.root_mod.resolved_target.result;
12041233 return .{
1205 .tag = lf.tag,
1234 .lf = lf,
12061235 .format = format,
12071236 .address_size = switch (target.ptrBitWidth()) {
12081237 0...32 => .@"32",
......@@ -1216,9 +1245,32 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {
12161245 .globals = .empty,
12171246 .funcs = .empty,
12181247
1219 .debug_info = .{
1220 .section_index = .none,
1248 .debug_abbrev = .{
1249 .ni = .none,
1250 .offset = 0,
1251 .set = .empty,
1252 },
1253 .frame = .{
1254 .header = if (target.cpu.arch == .x86_64 and target.ofmt == .elf) header: {
1255 dev.check(.x86_64_backend);
1256 const Register = @import("../codegen/x86_64/bits.zig").Register;
1257 break :header comptime .{
1258 .code_alignment_factor = 1,
1259 .data_alignment_factor = -8,
1260 .return_address_register = Register.rip.dwarfNum(),
1261 .initial_instructions = &.{
1262 .{ .def_cfa = .{ .reg = Register.rsp.dwarfNum(), .off = 8 } },
1263 .{ .offset = .{ .reg = Register.rip.dwarfNum(), .off = -8 } },
1264 },
1265 };
1266 } else .{
1267 .code_alignment_factor = undefined,
1268 .data_alignment_factor = undefined,
1269 .return_address_register = undefined,
1270 .initial_instructions = &.{},
1271 },
12211272 },
1273 .debug_info = .{},
12221274 .debug_line = .{
12231275 .header = switch (target.cpu.arch) {
12241276 .x86_64, .aarch64 => .{
......@@ -1238,55 +1290,46 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {
12381290 .opcode_base = DW.LNS.set_isa + 1,
12391291 },
12401292 },
1241 .section_index = .none,
12421293 },
1243 .frame = .{
1244 .header = if (target.cpu.arch == .x86_64 and target.ofmt == .elf) header: {
1245 dev.check(.x86_64_backend);
1246 const Register = @import("../codegen/x86_64/bits.zig").Register;
1247 break :header comptime .{
1248 .code_alignment_factor = 1,
1249 .data_alignment_factor = -8,
1250 .return_address_register = Register.rip.dwarfNum(),
1251 .initial_instructions = &.{
1252 .{ .def_cfa = .{ .reg = Register.rsp.dwarfNum(), .off = 8 } },
1253 .{ .offset = .{ .reg = Register.rip.dwarfNum(), .off = -8 } },
1254 },
1255 };
1256 } else .{
1257 .code_alignment_factor = undefined,
1258 .data_alignment_factor = undefined,
1259 .return_address_register = undefined,
1260 .initial_instructions = &.{},
1261 },
1262 .section_index = .none,
1294 .debug_line_str = .{
1295 .ni = .none,
1296 .offset = 0,
1297 .map = .empty,
1298 },
1299 .debug_str = .{
1300 .ni = .none,
1301 .offset = 0,
1302 .map = .empty,
1303 },
1304 .debug_str_offsets = .{
1305 .ni = .none,
1306 .offset = 0,
12631307 },
12641308 };
12651309}
12661310
1267pub fn deinit(dwarf: *Dwarf, gpa: Allocator) void {
1311pub fn deinit(dwarf: *Dwarf) void {
1312 const gpa = dwarf.lf.comp.gpa;
12681313 dwarf.const_pool.deinit(gpa);
12691314 dwarf.units.deinit(gpa);
12701315 dwarf.values.deinit(gpa);
12711316 dwarf.globals.deinit(gpa);
12721317 dwarf.funcs.deinit(gpa);
1318 dwarf.debug_str.map.deinit(gpa);
12731319 dwarf.* = undefined;
12741320}
12751321
1276fn linkFile(dwarf: *Dwarf) *link.File {
1277 return switch (dwarf.tag) {
1278 else => unreachable,
1279 .elf2 => |tag| &@as(*tag.Type(), @alignCast(@fieldParentPtr("dwarf", dwarf))).base,
1280 };
1281}
1282
1283pub fn initUnits(dwarf: *Dwarf, zcu: *Zcu) Allocator.Error!void {
1322pub fn initUnits(dwarf: *Dwarf, zcu: *Zcu) std.mem.Allocator.Error!void {
12841323 try dwarf.units.ensureTotalCapacity(zcu.gpa, zcu.module_roots.count());
12851324 for (zcu.module_roots.keys(), zcu.module_roots.values()) |mod, root| switch (root) {
12861325 .none => {},
12871326 else => dwarf.units.putAssumeCapacityNoClobber(mod, .{
12881327 .frame_ni = .none,
12891328 .cie_ni = .none,
1329 .debug_info_ni = .none,
1330 .debug_info_header_ni = .none,
1331 .debug_line_ni = .none,
1332 .debug_line_header_ni = .none,
12901333 }),
12911334 };
12921335}
......@@ -1308,8 +1351,8 @@ pub fn getUnit(dwarf: *Dwarf, mod: *Module) Unit.Index {
13081351 return @fromBackingInt(@intCast(dwarf.units.getIndex(mod).?));
13091352}
13101353
1311pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) Allocator.Error!Func.Index {
1312 const func_gop = try dwarf.funcs.getOrPut(dwarf.linkFile().comp.gpa, owner_nav);
1354pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) std.mem.Allocator.Error!Func.Index {
1355 const func_gop = try dwarf.funcs.getOrPut(dwarf.lf.comp.gpa, owner_nav);
13131356 if (!func_gop.found_existing) func_gop.value_ptr.* = .{
13141357 .fde_ni = .none,
13151358 .debug_info_ni = .none,
......@@ -1318,6 +1361,21 @@ pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) Allocator.Error!F
13181361 return @fromBackingInt(@intCast(func_gop.index));
13191362}
13201363
1364pub fn unitLengthSize(dwarf: *Dwarf) usize {
1365 return switch (dwarf.format) {
1366 .@"32" => 4,
1367 .@"64" => 12,
1368 };
1369}
1370pub fn genUnitLength(dwarf: *Dwarf, w: *Writer) Writer.Error!void {
1371 switch (dwarf.format) {
1372 .@"32" => try w.writeInt(u32, undefined, dwarf.endian),
1373 .@"64" => {
1374 try w.writeInt(u32, std.math.maxInt(u32), dwarf.endian);
1375 try w.writeInt(u64, undefined, dwarf.endian);
1376 },
1377 }
1378}
13211379pub fn updateUnitLength(dwarf: *Dwarf, header: []u8, unit_length: u64) void {
13221380 switch (dwarf.format) {
13231381 .@"32" => std.mem.writeInt(u32, header[0..4], @intCast(unit_length - 4), dwarf.endian),
......@@ -1325,6 +1383,11 @@ pub fn updateUnitLength(dwarf: *Dwarf, header: []u8, unit_length: u64) void {
13251383 }
13261384}
13271385
1386pub fn genUnitPadding(dwarf: *Dwarf, w: *Writer) Writer.Error!void {
1387 try dwarf.genUnitLength(w);
1388 try w.writeInt(u16, 0, dwarf.endian);
1389}
1390
13281391pub const EhFrameHdr = extern struct {
13291392 version: u8,
13301393 eh_frame_ptr_enc: std.dwarf.EH.PE,
......@@ -1345,7 +1408,7 @@ pub fn genEhFrameHdr(
13451408 .table_enc = .omit,
13461409 .eh_frame_ptr = undefined,
13471410 };
1348 const elf = dwarf.linkFile().cast(.elf2).?;
1411 const elf = dwarf.lf.cast(.elf2).?;
13491412 try elf.addReloc(
13501413 eh_frame_hdr_ai,
13511414 @offsetOf(EhFrameHdr, "eh_frame_ptr"),
......@@ -1357,26 +1420,20 @@ pub fn genEhFrameHdr(
13571420
13581421pub fn genDebugFrameCie(
13591422 dwarf: *Dwarf,
1360 w: *Writer,
1423 dfw: *Writer,
13611424 /// `null` means to generate an architecture-agnostic padding cie
13621425 arch: ?std.Target.Cpu.Arch,
13631426 format: Frame.Format,
13641427) Writer.Error!void {
1365 switch (dwarf.format) {
1366 .@"32" => try w.writeInt(u32, undefined, dwarf.endian),
1367 .@"64" => {
1368 try w.writeInt(u32, std.math.maxInt(u32), dwarf.endian);
1369 try w.writeInt(u64, undefined, dwarf.endian);
1370 },
1371 }
1428 try dwarf.genUnitLength(dfw);
13721429 switch (format) {
1373 .eh_frame => try w.writeInt(u32, 0, dwarf.endian),
1430 .eh_frame => try dfw.writeInt(u32, 0, dwarf.endian),
13741431 .debug_frame => switch (dwarf.format) {
1375 .@"32" => try w.writeInt(u32, std.math.maxInt(u32), dwarf.endian),
1376 .@"64" => try w.writeInt(u64, std.math.maxInt(u64), dwarf.endian),
1432 .@"32" => try dfw.writeInt(u32, std.math.maxInt(u32), dwarf.endian),
1433 .@"64" => try dfw.writeInt(u64, std.math.maxInt(u64), dwarf.endian),
13771434 },
13781435 }
1379 try w.writeByte(if (arch) |_| switch (format) {
1436 try dfw.writeByte(if (arch) |_| switch (format) {
13801437 .eh_frame => 1,
13811438 .debug_frame => 4,
13821439 } else 0);
......@@ -1386,40 +1443,38 @@ pub fn genDebugFrameCie(
13861443 dev.check(.x86_64_backend);
13871444 const Register = @import("../codegen/x86_64/bits.zig").Register;
13881445 switch (format) {
1389 .eh_frame => try w.writeAll("zR\x00"),
1446 .eh_frame => try dfw.writeAll("zR\x00"),
13901447 .debug_frame => {
1391 try w.writeAll("\x00");
1392 try w.writeByte(@backingInt(dwarf.address_size));
1393 try w.writeByte(0);
1448 try dfw.writeAll("\x00");
1449 try dfw.writeByte(@backingInt(dwarf.address_size));
1450 try dfw.writeByte(0);
13941451 },
13951452 }
1396 try w.writeUleb128(dwarf.frame.header.code_alignment_factor);
1397 try w.writeSleb128(dwarf.frame.header.data_alignment_factor);
1453 try dfw.writeUleb128(dwarf.frame.header.code_alignment_factor);
1454 try dfw.writeSleb128(dwarf.frame.header.data_alignment_factor);
13981455 switch (format) {
1399 .eh_frame => try w.writeByte(@intCast(dwarf.frame.header.return_address_register)),
1400 .debug_frame => try w.writeUleb128(dwarf.frame.header.return_address_register),
1456 .eh_frame => try dfw.writeByte(@intCast(dwarf.frame.header.return_address_register)),
1457 .debug_frame => try dfw.writeUleb128(dwarf.frame.header.return_address_register),
14011458 }
14021459 switch (format) {
14031460 .eh_frame => {
1404 try w.writeUleb128(1);
1405 try w.writeByte(@bitCast(@as(DW.EH.PE, .{ .type = .sdata4, .rel = .pcrel })));
1461 try dfw.writeUleb128(1);
1462 try dfw.writeByte(@bitCast(@as(DW.EH.PE, .{ .type = .sdata4, .rel = .pcrel })));
14061463 },
14071464 .debug_frame => {},
14081465 }
1409 try w.writeByte(DW.CFA.def_cfa_sf);
1410 try w.writeUleb128(Register.rsp.dwarfNum());
1411 try w.writeSleb128(-1);
1412 try w.writeByte(@as(u8, DW.CFA.offset) + Register.rip.dwarfNum());
1413 try w.writeUleb128(1);
1466 try dfw.writeByte(DW.CFA.def_cfa_sf);
1467 try dfw.writeUleb128(Register.rsp.dwarfNum());
1468 try dfw.writeSleb128(-1);
1469 try dfw.writeByte(@as(u8, DW.CFA.offset) + Register.rip.dwarfNum());
1470 try dfw.writeUleb128(1);
14141471 },
14151472 }
1473 @memset(dfw.unusedCapacitySlice(), DW.CFA.nop);
14161474}
14171475
14181476pub fn updateEhFrameFde(dwarf: *Dwarf, fde: []u8, fde_offset: u64) void {
1419 const cie_pointer_offset: usize = switch (dwarf.format) {
1420 .@"32" => 4,
1421 .@"64" => 12,
1422 };
1477 const cie_pointer_offset = dwarf.unitLengthSize();
14231478 std.mem.writeInt(
14241479 u32,
14251480 fde[cie_pointer_offset..][0..4],
......@@ -1428,27 +1483,182 @@ pub fn updateEhFrameFde(dwarf: *Dwarf, fde: []u8, fde_offset: u64) void {
14281483 );
14291484}
14301485
1486pub fn genDebugInfoHeader(
1487 dwarf: *Dwarf,
1488 nw: *MappedFile.Node.Writer,
1489 unit: Unit.Index,
1490 zcu: *Zcu,
1491) link.EmitError!void {
1492 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);
1504 const root_dir_path = try mod.root.toAbsolute(&comp.dirs, comp.gpa);
1505 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);
1508 try dwarf.sectionOffset(
1509 nw,
1510 dwarf.getUnit(comp.root_mod).get(dwarf).debug_info_header_ni.unwrap().?,
1511 compile_unit_offset,
1512 );
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);
1517 for ([_][]const u8{ "builtin", "root", "std" }, [_]*Module{
1518 zcu.builtin_modules.get(mod.getBuiltinOptions(comp.config).hash()).?,
1519 zcu.root_mod,
1520 zcu.std_mod,
1521 }) |name, dep| try dwarf.genModuleDependency(nw, name, dep, module_offset);
1522 for (mod.deps.keys(), mod.deps.values()) |name, dep|
1523 try dwarf.genModuleDependency(nw, name, dep, module_offset);
1524 for ([2]AbbrevCode{ .pad_1, .pad_n }) |pad| _ = try dwarf.refAbbrevCode(pad);
1525 try dwarf.genDebugInfoPadding(diw, diw.unusedCapacityLen());
1526}
1527
1528fn genModuleDependency(
1529 dwarf: *Dwarf,
1530 nw: *MappedFile.Node.Writer,
1531 name: []const u8,
1532 dep: *Module,
1533 module_offset: usize,
1534) link.EmitError!void {
1535 const diw = &nw.interface;
1536 try diw.writeUleb128(try dwarf.refAbbrevCode(.module_dependency));
1537 try diw.writeAll(name);
1538 try diw.writeByte(0);
1539 try dwarf.sectionOffset(
1540 nw,
1541 dwarf.getUnit(dep).get(dwarf).debug_info_header_ni.unwrap().?,
1542 module_offset,
1543 );
1544}
1545
1546pub fn genDebugInfoPadding(dwarf: *Dwarf, diw: *Writer, size: u64) Writer.Error!void {
1547 switch (size) {
1548 0 => {},
1549 1 => try diw.writeUleb128(dwarf.refAbbrevCodeIfExists(.pad_1).?),
1550 else => {
1551 const abbrev_code_offset = diw.end;
1552 try diw.writeUleb128(dwarf.refAbbrevCodeIfExists(.pad_n).?);
1553 const abbrev_code_size = diw.end - abbrev_code_offset;
1554 var block_len_size: u5 = 1;
1555 while (true) switch (std.math.order(size - abbrev_code_size - block_len_size, @as(u64, 1) << 7 * block_len_size)) {
1556 .lt => break try diw.writeUleb128(size - abbrev_code_size - block_len_size),
1557 .eq => {
1558 // no length will ever work, so undercount and futz with the leb encoding to make up the missing byte
1559 block_len_size += 1;
1560 std.leb.writeUnsignedExtended(try diw.writableSlice(block_len_size), size - abbrev_code_size - block_len_size);
1561 break;
1562 },
1563 .gt => block_len_size += 1,
1564 };
1565 },
1566 }
1567}
1568
1569pub fn genDebugLineHeader(dwarf: *Dwarf, dlw: *Writer) Writer.Error!void {
1570 try dwarf.genUnitLength(dlw);
1571 @memset(dlw.unusedCapacitySlice(), 0xaa);
1572}
1573
1574pub fn genDebugLinePadding(dlw: *Writer, size: u64) Writer.Error!void {
1575 switch (size) {
1576 0 => {},
1577 1 => try dlw.writeByte(DW.LNS.const_add_pc),
1578 else => {
1579 const extended_op_offset = dlw.end;
1580 try dlw.writeByte(DW.LNS.extended_op);
1581 const extended_op_size = dlw.end - extended_op_offset;
1582 var op_len_size: u5 = 1;
1583 while (true) switch (std.math.order(size - extended_op_size - op_len_size, @as(u64, 1) << 7 * op_len_size)) {
1584 .lt => break try dlw.writeUleb128(size - extended_op_size - op_len_size),
1585 .eq => {
1586 // no length will ever work, so undercount and futz with the leb encoding to make up the missing byte
1587 op_len_size += 1;
1588 std.leb.writeUnsignedExtended(try dlw.writableSlice(op_len_size), size - extended_op_size - op_len_size);
1589 break;
1590 },
1591 .gt => op_len_size += 1,
1592 };
1593 },
1594 }
1595}
1596
1597fn refAbbrevCodeIfExists(
1598 dwarf: *Dwarf,
1599 abbrev_code: AbbrevCode,
1600) ?@typeInfo(AbbrevCode).@"enum".tag_type {
1601 assert(abbrev_code != .null);
1602 return if (dwarf.debug_abbrev.set.contains(abbrev_code)) @backingInt(abbrev_code) else null;
1603}
1604
14311605fn refAbbrevCode(
14321606 dwarf: *Dwarf,
14331607 abbrev_code: AbbrevCode,
14341608) link.EmitError!@typeInfo(AbbrevCode).@"enum".tag_type {
1435 if (true) @panic("TODO");
1436 const Entry = {};
1437 const DebugAbbrev = {};
1438 assert(abbrev_code != .null);
1439 const entry: Entry.Index = @fromBackingInt(@intCast(@backingInt(abbrev_code)));
1440 if (dwarf.debug_abbrev.section.getUnit(DebugAbbrev.unit).getEntry(entry).len > 0) return @backingInt(abbrev_code);
1441 var debug_abbrev_aw: Writer.Allocating = .init(dwarf.gpa);
1442 defer debug_abbrev_aw.deinit();
1443 const daw = &debug_abbrev_aw.writer;
1609 if (dwarf.refAbbrevCodeIfExists(abbrev_code)) |backing_int| {
1610 @branchHint(.likely);
1611 return backing_int;
1612 }
1613 const elf = dwarf.lf.cast(.elf2).?;
1614 var nw: MappedFile.Node.Writer = undefined;
1615 dwarf.debug_abbrev.ni.unwrap().?.writer(&elf.mf, elf.base.comp.gpa, &nw);
1616 defer nw.deinit();
14441617 const abbrev = AbbrevCode.abbrevs.get(abbrev_code);
1618 const daw = &nw.interface;
1619 daw.end = dwarf.debug_abbrev.offset;
14451620 try daw.writeUleb128(@backingInt(abbrev_code));
14461621 try daw.writeUleb128(@backingInt(abbrev.tag));
14471622 try daw.writeByte(if (abbrev.children) DW.CHILDREN.yes else DW.CHILDREN.no);
14481623 for (abbrev.attrs) |*attr| inline for (attr) |info| try daw.writeUleb128(@backingInt(info));
14491624 for (0..2) |_| try daw.writeUleb128(0);
1450 try dwarf.debug_abbrev.section.replaceEntry(DebugAbbrev.unit, entry, dwarf, debug_abbrev_aw.written());
1451 return @backingInt(abbrev_code);
1625 dwarf.debug_abbrev.offset = daw.end;
1626 dwarf.debug_abbrev.set.insert(abbrev_code);
1627 return dwarf.refAbbrevCodeIfExists(abbrev_code).?;
1628}
1629
1630fn sectionOffset(
1631 dwarf: *Dwarf,
1632 nw: *MappedFile.Node.Writer,
1633 target_ni: MappedFile.Node.Index,
1634 addend: usize,
1635) link.EmitError!void {
1636 const offset = nw.interface.end;
1637 switch (dwarf.format) {
1638 .@"32" => try nw.interface.writeInt(u32, 0, dwarf.endian),
1639 .@"64" => try nw.interface.writeInt(u64, 0, dwarf.endian),
1640 }
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 );
1651}
1652
1653fn strp(dwarf: *Dwarf, s: *String, nw: *MappedFile.Node.Writer, str: []const u8) link.EmitError!void {
1654 const comp = dwarf.lf.comp;
1655 const mf = &dwarf.lf.cast(.elf2).?.mf;
1656 try dwarf.sectionOffset(nw, s.ni.unwrap().?, s.get(comp.gpa, mf, str) catch |err| switch (err) {
1657 error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{
1658 mf.io_err.?,
1659 }),
1660 else => |e| return e,
1661 });
14521662}
14531663
14541664fn DeclValEnum(comptime T: type) type {
......@@ -1473,7 +1683,7 @@ fn DeclValEnum(comptime T: type) type {
14731683 return @Enum(TagInt, .exhaustive, field_names[0..fields_len], &field_vals);
14741684}
14751685
1476const AbbrevCode = enum {
1686pub const AbbrevCode = enum {
14771687 null,
14781688 // padding codes must be one byte uleb128 values to function
14791689 pad_1,
......@@ -1524,6 +1734,7 @@ const AbbrevCode = enum {
15241734 // than the non-empty variant, and so should appear first
15251735 compile_unit,
15261736 module,
1737 module_dependency,
15271738 empty_file,
15281739 file,
15291740 access,
......@@ -1765,14 +1976,14 @@ const AbbrevCode = enum {
17651976 .decl_func = .{
17661977 .tag = .subprogram,
17671978 .children = true,
1768 .attrs = decl_abbrev_common_attrs ++ .{
1979 .attrs = decl_abbrev_common_attrs[4..] ++ .{
17691980 .{ .linkage_name, .strp },
1770 .{ .type, .ref_addr },
1771 .{ .low_pc, .addr },
1772 .{ .high_pc, .data4 },
1773 .{ .alignment, .udata },
1774 .{ .external, .flag },
1775 .{ .noreturn, .flag },
1981 //.{ .type, .ref_addr },
1982 //.{ .low_pc, .addr },
1983 //.{ .high_pc, .data4 },
1984 //.{ .alignment, .udata },
1985 //.{ .external, .flag },
1986 //.{ .noreturn, .flag },
17761987 },
17771988 },
17781989 .decl_nullary_func_generic = .{
......@@ -1989,14 +2200,15 @@ const AbbrevCode = enum {
19892200 .tag = .compile_unit,
19902201 .children = true,
19912202 .attrs = &.{
2203 .{ .producer, .strp },
19922204 .{ .language, .data1 },
1993 .{ .producer, .line_strp },
19942205 .{ .comp_dir, .line_strp },
19952206 .{ .name, .line_strp },
19962207 .{ .base_types, .ref_addr },
19972208 .{ .stmt_list, .sec_offset },
1998 .{ .rnglists_base, .sec_offset },
1999 .{ .ranges, .rnglistx },
2209 //.{ .rnglists_base, .sec_offset },
2210 //.{ .ranges, .rnglistx },
2211 .{ .use_UTF8, .flag_present },
20002212 },
20012213 },
20022214 .module = .{
......@@ -2004,7 +2216,14 @@ const AbbrevCode = enum {
20042216 .children = true,
20052217 .attrs = &.{
20062218 .{ .name, .strp },
2007 .{ .ranges, .rnglistx },
2219 //.{ .ranges, .rnglistx },
2220 },
2221 },
2222 .module_dependency = .{
2223 .tag = .imported_module,
2224 .attrs = &.{
2225 .{ .name, .string },
2226 .{ .import, .ref_addr },
20082227 },
20092228 },
20102229 .empty_file = .{
......@@ -2662,23 +2881,23 @@ const AbbrevCode = enum {
26622881 });
26632882};
26642883
2665fn uleb128Bytes(value: anytype) u32 {
2884pub fn uleb128Bytes(value: anytype) u32 {
26662885 var buf: [64]u8 = undefined;
26672886 var dw: Writer.Discarding = .init(&buf);
26682887 dw.writer.writeUleb128(value) catch unreachable;
26692888 return @intCast(dw.fullCount());
26702889}
26712890
2672fn sleb128Bytes(value: anytype) u32 {
2891pub fn sleb128Bytes(value: anytype) u32 {
26732892 var buf: [64]u8 = undefined;
26742893 var dw: Writer.Discarding = .init(&buf);
26752894 dw.writer.writeSleb128(value) catch unreachable;
26762895 return @intCast(dw.fullCount());
26772896}
26782897
2679const Allocator = std.mem.Allocator;
26802898const assert = std.debug.assert;
26812899const codegen = @import("../codegen.zig");
2900const Compilation = @import("../Compilation.zig");
26822901const dev = @import("../dev.zig");
26832902const DW = std.dwarf;
26842903const Dwarf = @This();
src/link/Elf2.zig+635-223
......@@ -42,11 +42,15 @@ shndx: struct {
4242 tdata: Section.Index,
4343 rela_dyn: Section.Index,
4444 rela_plt: Section.Index,
45 debug_abbrev: Section.Index,
4546 eh_frame_hdr: Section.Index,
4647 eh_frame: Section.Index,
4748 debug_frame: Section.Index,
4849 debug_info: Section.Index,
4950 debug_line: Section.Index,
51 debug_line_str: Section.Index,
52 debug_str: Section.Index,
53 debug_str_offsets: Section.Index,
5054 // These sections are created only as needed, and are initially `.UNDEF`.
5155 init_array: Section.Index,
5256 fini_array: Section.Index,
......@@ -199,14 +203,34 @@ changed_symtab_index: std.array_hash_map.Auto(String(.strtab), void),
199203textrel_count: u32,
200204
201205dwarf: Dwarf,
206dwarf_shared: std.enums.EnumArray(Dwarf.SharedSection, struct {
207 first_target_reloc: NodeReloc.Index,
208}),
202209dwarf_units: std.ArrayList(struct {
203 unit_frame_cie_first_target_reloc: NodeReloc.Index,
210 frame_cie_first_target_reloc: NodeReloc.Index,
211 debug_info_header_first_target_reloc: NodeReloc.Index,
212 debug_info_header_first_node_reloc: NodeReloc.Index,
213 debug_line_header_first_target_reloc: NodeReloc.Index,
214 debug_line_header_first_node_reloc: NodeReloc.Index,
215}),
216dwarf_values: std.ArrayList(struct {
217 debug_info_first_target_reloc: NodeReloc.Index,
218 debug_info_first_symbol_reloc: SymbolReloc.Index,
219 debug_info_first_node_reloc: NodeReloc.Index,
220}),
221dwarf_globals: std.ArrayList(struct {
222 debug_info_first_target_reloc: NodeReloc.Index,
223 debug_info_first_symbol_reloc: SymbolReloc.Index,
224 debug_info_first_node_reloc: NodeReloc.Index,
204225}),
205dwarf_values: std.ArrayList(struct {}),
206dwarf_globals: std.ArrayList(struct {}),
207226dwarf_funcs: std.ArrayList(struct {
208 func_frame_fde_first_symbol_reloc: SymbolReloc.Index,
209 func_frame_fde_first_node_reloc: NodeReloc.Index,
227 frame_fde_first_symbol_reloc: SymbolReloc.Index,
228 frame_fde_first_node_reloc: NodeReloc.Index,
229 debug_info_first_target_reloc: NodeReloc.Index,
230 debug_info_first_symbol_reloc: SymbolReloc.Index,
231 debug_info_first_node_reloc: NodeReloc.Index,
232 debug_line_first_symbol_reloc: SymbolReloc.Index,
233 debug_line_first_node_reloc: NodeReloc.Index,
210234}),
211235
212236overflowed_reloc_count: u32,
......@@ -272,11 +296,17 @@ const Node = union(enum) {
272296 /// May contain relocations.
273297 lazy_const_data: LazyMapRef.Index(.const_data),
274298
275 value_debug_info: link.ConstPool.Index,
276 global_debug_info: Dwarf.Global.Index,
277 frame_padding,
299 debug_shared: Dwarf.SharedSection,
300 unit_padding,
278301 unit_frame: Dwarf.Unit.Index,
279302 unit_frame_cie: Dwarf.Unit.Index,
303 unit_debug_info: Dwarf.Unit.Index,
304 unit_debug_info_header: Dwarf.Unit.Index,
305 unit_debug_line: Dwarf.Unit.Index,
306 unit_debug_line_header: Dwarf.Unit.Index,
307
308 value_debug_info: link.ConstPool.Index,
309 global_debug_info: Dwarf.Global.Index,
280310 func_frame_fde: Dwarf.Func.Index,
281311 func_debug_info: Dwarf.Func.Index,
282312 func_debug_line: Dwarf.Func.Index,
......@@ -1778,7 +1808,9 @@ const NodeReloc = struct {
17781808 .none => {
17791809 const first_target_reloc = switch (elf.getNode(reloc.target)) {
17801810 else => unreachable,
1781 .unit_frame_cie => |ui| &elf.dwarf_units.items[@backingInt(ui)].unit_frame_cie_first_target_reloc,
1811 .unit_frame_cie => |ui| &elf.dwarf_units.items[@backingInt(ui)].frame_cie_first_target_reloc,
1812 .unit_debug_info_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_target_reloc,
1813 .unit_debug_line_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_target_reloc,
17821814 };
17831815 first_target_reloc.* = reloc.next;
17841816 },
......@@ -3218,11 +3250,16 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {
32183250 .section_manual_size,
32193251 .input_section,
32203252 .copied_global,
3221 .value_debug_info,
3222 .global_debug_info,
3223 .frame_padding,
3253 .debug_shared,
3254 .unit_padding,
32243255 .unit_frame,
32253256 .unit_frame_cie,
3257 .unit_debug_info,
3258 .unit_debug_info_header,
3259 .unit_debug_line,
3260 .unit_debug_line_header,
3261 .value_debug_info,
3262 .global_debug_info,
32263263 .func_frame_fde,
32273264 .func_debug_info,
32283265 .func_debug_line,
......@@ -3661,11 +3698,15 @@ fn create(
36613698 .tdata = .UNDEF,
36623699 .rela_dyn = .UNDEF,
36633700 .rela_plt = .UNDEF,
3701 .debug_abbrev = .UNDEF,
36643702 .eh_frame_hdr = .UNDEF,
36653703 .eh_frame = .UNDEF,
36663704 .debug_frame = .UNDEF,
36673705 .debug_info = .UNDEF,
36683706 .debug_line = .UNDEF,
3707 .debug_line_str = .UNDEF,
3708 .debug_str = .UNDEF,
3709 .debug_str_offsets = .UNDEF,
36693710 .init_array = .UNDEF,
36703711 .fini_array = .UNDEF,
36713712 .preinit_array = .UNDEF,
......@@ -3720,6 +3761,9 @@ fn create(
37203761 .dwarf => |v| v,
37213762 .code_view => unreachable,
37223763 }),
3764 .dwarf_shared = .initFill(.{
3765 .first_target_reloc = .none,
3766 }),
37233767 .dwarf_units = .empty,
37243768 .dwarf_values = .empty,
37253769 .dwarf_globals = .empty,
......@@ -3774,7 +3818,7 @@ pub fn deinit(elf: *Elf) void {
37743818 elf.section_by_name.deinit(gpa);
37753819 elf.changed_symtab_index.deinit(gpa);
37763820
3777 elf.dwarf.deinit(gpa);
3821 elf.dwarf.deinit();
37783822 elf.dwarf_units.deinit(gpa);
37793823 elf.dwarf_values.deinit(gpa);
37803824 elf.dwarf_globals.deinit(gpa);
......@@ -3851,9 +3895,13 @@ fn initHeaders(
38513895 switch (comp.config.debug_format) {
38523896 .strip => {},
38533897 .dwarf => {
3898 shnum += 1; // .debug_abbrev
38543899 shnum += @intFromBool(have_debug_frame); // .debug_frame
38553900 shnum += 1; // .debug_info
38563901 shnum += 1; // .debug_line
3902 shnum += 1; // .debug_line_str
3903 shnum += 1; // .debug_str
3904 shnum += 1; // .debug_str_offsets
38573905 },
38583906 .code_view => unreachable,
38593907 }
......@@ -4942,6 +4990,7 @@ fn initHeaders(
49424990 switch (comp.config.debug_format) {
49434991 .strip => {},
49444992 .dwarf => {
4993 elf.shndx.debug_abbrev = try elf.addSection(elf.ni.elf, .{ .name = ".debug_abbrev" });
49454994 if (have_debug_frame) elf.shndx.debug_frame = try elf.addSection(elf.ni.elf, .{
49464995 .name = ".debug_frame",
49474996 .addralign = addr_align,
......@@ -4955,6 +5004,17 @@ fn initHeaders(
49555004 .name = ".debug_line",
49565005 .node_align = elf.mf.flags.block_size,
49575006 });
5007 elf.shndx.debug_line_str = try elf.addSection(elf.ni.elf, .{
5008 .name = ".debug_line_str",
5009 .flags = .{ .MERGE = true, .STRINGS = true },
5010 });
5011 elf.shndx.debug_str = try elf.addSection(elf.ni.elf, .{
5012 .name = ".debug_str",
5013 .flags = .{ .MERGE = true, .STRINGS = true },
5014 });
5015 elf.shndx.debug_str_offsets = try elf.addSection(elf.ni.elf, .{
5016 .name = ".debug_str_offsets",
5017 });
49585018 },
49595019 .code_view => unreachable,
49605020 }
......@@ -5045,11 +5105,6 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
50455105 .ehdr,
50465106 .shdr,
50475107 .segment,
5048 .value_debug_info,
5049 .global_debug_info,
5050 .frame_padding,
5051 .func_debug_info,
5052 .func_debug_line,
50535108 => unreachable,
50545109 .section, .section_manual_size => |shndx| shndx,
50555110 .input_section,
......@@ -5058,13 +5113,21 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
50585113 .uav,
50595114 .lazy_code,
50605115 .lazy_const_data,
5116 .debug_shared,
5117 .unit_padding,
50615118 .unit_frame,
5119 .unit_debug_info,
5120 .unit_debug_line,
50625121 => elf.getNode(ni.parent(&elf.mf).unwrap().?).section,
5063 .unit_frame_cie, .func_frame_fde => {
5064 const unit_frame_ni = ni.parent(&elf.mf).unwrap().?;
5065 assert(elf.getNode(unit_frame_ni) == .unit_frame);
5066 return elf.getNode(unit_frame_ni.parent(&elf.mf).unwrap().?).section;
5067 },
5122 .unit_frame_cie,
5123 .unit_debug_info_header,
5124 .unit_debug_line_header,
5125 .value_debug_info,
5126 .global_debug_info,
5127 .func_frame_fde,
5128 .func_debug_info,
5129 .func_debug_line,
5130 => elf.getNode(ni.parent(&elf.mf).unwrap().?.parent(&elf.mf).unwrap().?).section,
50685131 };
50695132}
50705133fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
......@@ -5078,11 +5141,6 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
50785141 .shdr,
50795142 .segment,
50805143 .copied_global,
5081 .value_debug_info,
5082 .global_debug_info,
5083 .frame_padding,
5084 .func_debug_info,
5085 .func_debug_line,
50865144 => unreachable,
50875145 .section, .section_manual_size => |shndx| shndx.vaddr(elf),
50885146 .input_section => |isi| isi.ptrConst(elf).vaddr,
......@@ -5091,7 +5149,20 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
50915149 .lazy_code,
50925150 .lazy_const_data,
50935151 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
5094 .unit_frame, .unit_frame_cie, .func_frame_fde => elf.computeNodeVAddr(ni),
5152 .debug_shared,
5153 .unit_padding,
5154 .unit_frame,
5155 .unit_frame_cie,
5156 .unit_debug_info,
5157 .unit_debug_info_header,
5158 .unit_debug_line,
5159 .unit_debug_line_header,
5160 .value_debug_info,
5161 .global_debug_info,
5162 .func_frame_fde,
5163 .func_debug_info,
5164 .func_debug_line,
5165 => elf.computeNodeVAddr(ni),
50955166 };
50965167}
50975168fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
......@@ -5110,16 +5181,17 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
51105181 .lazy_code,
51115182 .lazy_const_data,
51125183 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
5113 .value_debug_info,
5114 .global_debug_info,
5115 .frame_padding,
5116 => unreachable,
5117 .unit_frame => {
5184 .debug_shared, .unit_padding => unreachable,
5185 .unit_frame, .unit_debug_info, .unit_debug_line => {
51185186 const section_ni = parent_ni.parent(&elf.mf).unwrap().?;
51195187 const section_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);
51205188 break :parent_vaddr elf.getNode(section_ni).section.vaddr(elf) + section_offset;
51215189 },
51225190 .unit_frame_cie,
5191 .unit_debug_info_header,
5192 .unit_debug_line_header,
5193 .value_debug_info,
5194 .global_debug_info,
51235195 .func_frame_fde,
51245196 .func_debug_info,
51255197 .func_debug_line,
......@@ -5138,7 +5210,7 @@ fn getNodeElfOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 {
51385210/// Asserts that `ni` must be a node which supports relocations (see `Elf.Node`). Does not support
51395211/// the special-case sections '.plt', '.dynamic', and '.eh_frame_hdr'.
51405212fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
5141 const symbol_relocs: *SymbolReloc.Index, const node_relocs: ?*NodeReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) {
5213 const symbol_relocs: ?*SymbolReloc.Index, const node_relocs: ?*NodeReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) {
51425214 .archive,
51435215 .archive_header,
51445216 .archive_input_member,
......@@ -5148,13 +5220,12 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
51485220 .shdr,
51495221 .segment,
51505222 .copied_global,
5151 .value_debug_info,
5152 .global_debug_info,
5153 .frame_padding,
5223 .debug_shared,
5224 .unit_padding,
51545225 .unit_frame,
51555226 .unit_frame_cie,
5156 .func_debug_info,
5157 .func_debug_line,
5227 .unit_debug_info,
5228 .unit_debug_line,
51585229 => unreachable, // cannot contain relocs
51595230 .section,
51605231 .section_manual_size,
......@@ -5179,23 +5250,52 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
51795250 null,
51805251 &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_got_reloc,
51815252 },
5253 .unit_debug_info_header => |ui| .{
5254 null,
5255 &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_node_reloc,
5256 null,
5257 },
5258 .unit_debug_line_header => |ui| .{
5259 null,
5260 &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_node_reloc,
5261 null,
5262 },
5263 .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,
5267 },
5268 .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,
5272 },
51825273 .func_frame_fde => |fi| .{
5183 &elf.dwarf_funcs.items[@backingInt(fi)].func_frame_fde_first_symbol_reloc,
5184 &elf.dwarf_funcs.items[@backingInt(fi)].func_frame_fde_first_node_reloc,
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,
5277 },
5278 .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,
5282 },
5283 .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,
51855286 null,
51865287 },
51875288 };
51885289
5189 if (symbol_relocs.* != .none) {
5190 for (
5191 elf.symbol_relocs.items[@backingInt(symbol_relocs.*)..],
5192 @backingInt(symbol_relocs.*)..,
5193 ) |*reloc, index| {
5194 if (reloc.node != ni) break;
5195 reloc.delete(elf, @fromBackingInt(@intCast(index)));
5290 if (symbol_relocs) |ptr| {
5291 if (ptr.* != .none) {
5292 for (elf.symbol_relocs.items[@backingInt(ptr.*)..], @backingInt(ptr.*)..) |*reloc, index| {
5293 if (reloc.node != ni) break;
5294 reloc.delete(elf, @fromBackingInt(@intCast(index)));
5295 }
51965296 }
5297 ptr.* = @fromBackingInt(@intCast(elf.symbol_relocs.items.len));
51975298 }
5198 symbol_relocs.* = @fromBackingInt(@intCast(elf.symbol_relocs.items.len));
51995299
52005300 if (node_relocs) |ptr| {
52015301 if (ptr.* != .none) {
......@@ -5962,7 +6062,7 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load
59626062 return error.BadMagic;
59636063 }
59646064 }
5965 var strtab: std.Io.Writer.Allocating = .init(gpa);
6065 var strtab: Io.Writer.Allocating = .init(gpa);
59666066 defer strtab.deinit();
59676067 while (r.takeStruct(std.elf.ar_hdr, .native)) |header| {
59686068 if (!std.mem.eql(u8, &header.ar_fmag, std.elf.ARFMAG))
......@@ -6013,7 +6113,7 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load
60136113fn fmtMemberString(member: ?[]const u8) std.fmt.Alt(?[]const u8, memberStringEscape) {
60146114 return .{ .data = member };
60156115}
6016fn memberStringEscape(member: ?[]const u8, w: *std.Io.Writer) std.Io.Writer.Error!void {
6116fn memberStringEscape(member: ?[]const u8, w: *Io.Writer) Io.Writer.Error!void {
60176117 try w.print("({f})", .{std.zig.fmtString(member orelse return)});
60186118}
60196119fn loadObject(
......@@ -6897,7 +6997,6 @@ pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) link.Error!void {
68976997fn prelinkInner(elf: *Elf) Error!void {
68986998 const comp = elf.base.comp;
68996999 const gpa = comp.gpa;
6900
69017000 if (comp.zcu) |zcu| self_hosted_codegen: {
69027001 if (comp.config.use_llvm) break :self_hosted_codegen;
69037002
......@@ -6922,35 +7021,130 @@ fn prelinkInner(elf: *Elf) Error!void {
69227021 elf.input_pending_index += 1;
69237022
69247023 try elf.dwarf.initUnits(zcu);
7024 try elf.nodes.ensureUnusedCapacity(gpa, 4 + 4 + (4 + 4) * elf.dwarf.units.count());
69257025 try elf.dwarf_units.appendNTimes(gpa, .{
6926 .unit_frame_cie_first_target_reloc = .none,
7026 .frame_cie_first_target_reloc = .none,
7027 .debug_info_header_first_target_reloc = .none,
7028 .debug_info_header_first_node_reloc = .none,
7029 .debug_line_header_first_target_reloc = .none,
7030 .debug_line_header_first_node_reloc = .none,
69277031 }, elf.dwarf.units.count());
69287032
6929 try elf.nodes.ensureUnusedCapacity(gpa, 2);
6930 for (
6931 [2]Dwarf.Frame.Format{ .eh_frame, .debug_frame },
6932 [2]Section.Index{ elf.shndx.eh_frame, elf.shndx.debug_frame },
6933 ) |format, frame_shndx| {
6934 if (frame_shndx == .UNDEF) continue;
6935 const frame_ni = frame_shndx.get(elf).ni;
6936 _ = frame_ni.last(&elf.mf).unwrap() orelse continue;
6937 const frame_padding_ni = try frame_ni.addFloatingChild(&elf.mf, gpa, .{
6938 .alignment = switch (elf.identClass()) {
7033 elf.dwarf.debug_abbrev.ni =
7034 .wrap(try elf.shndx.debug_abbrev.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}));
7035 elf.nodes.appendAssumeCapacity(.{ .debug_shared = .debug_abbrev });
7036
7037 elf.dwarf.debug_line_str.ni =
7038 .wrap(try elf.shndx.debug_line_str.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}));
7039 elf.nodes.appendAssumeCapacity(.{ .debug_shared = .debug_line_str });
7040
7041 elf.dwarf.debug_str.ni =
7042 .wrap(try elf.shndx.debug_str.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}));
7043 elf.nodes.appendAssumeCapacity(.{ .debug_shared = .debug_str });
7044
7045 elf.dwarf.debug_str_offsets.ni =
7046 .wrap(try elf.shndx.debug_str_offsets.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}));
7047 elf.nodes.appendAssumeCapacity(.{ .debug_shared = .debug_str_offsets });
7048
7049 for ([4]Section.Index{
7050 elf.shndx.eh_frame,
7051 elf.shndx.debug_frame,
7052 elf.shndx.debug_info,
7053 elf.shndx.debug_line,
7054 }) |debug_shndx| {
7055 if (debug_shndx == .UNDEF) continue;
7056 const debug_ni = debug_shndx.get(elf).ni;
7057 _ = debug_ni.last(&elf.mf).unwrap() orelse continue;
7058 const frame_format = debug_shndx.debugFrameFormat(elf);
7059 const unit_padding_ni = try debug_ni.addFloatingChild(&elf.mf, gpa, .{
7060 .alignment = if (frame_format) |_| switch (elf.identClass()) {
69397061 .NONE, _ => unreachable,
69407062 .@"32" => .@"4",
69417063 .@"64" => .@"8",
6942 },
7064 } else .@"1",
69437065 .next_moved = true,
69447066 .enable_next_moved = true,
69457067 });
6946 elf.nodes.appendAssumeCapacity(.frame_padding);
6947 var cie_writer: MappedFile.Node.Writer = undefined;
6948 frame_padding_ni.writer(&elf.mf, gpa, &cie_writer);
6949 defer cie_writer.deinit();
6950 elf.dwarf.genDebugFrameCie(&cie_writer.interface, null, format) catch |err| switch (err) {
6951 error.WriteFailed => return cie_writer.err.?,
7068 elf.nodes.appendAssumeCapacity(.unit_padding);
7069 var debug_nw: MappedFile.Node.Writer = undefined;
7070 unit_padding_ni.writer(&elf.mf, gpa, &debug_nw);
7071 defer debug_nw.deinit();
7072 (if (frame_format) |format|
7073 elf.dwarf.genDebugFrameCie(&debug_nw.interface, null, format)
7074 else
7075 elf.dwarf.genUnitPadding(&debug_nw.interface)) catch |err| switch (err) {
7076 error.WriteFailed => return debug_nw.err.?,
69527077 };
69537078 }
7079
7080 for (0.., elf.dwarf.units.values()) |unit_index, *unit| {
7081 const ui: Dwarf.Unit.Index = @fromBackingInt(@intCast(unit_index));
7082 switch (elf.shndx.debug_info) {
7083 .UNDEF => {},
7084 else => |debug_info_shndx| {
7085 const debug_info_ni =
7086 try debug_info_shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{
7087 .alignment = elf.mf.flags.block_size,
7088 .next_moved = true,
7089 .enable_next_moved = true,
7090 });
7091 unit.debug_info_ni = .wrap(debug_info_ni);
7092 elf.nodes.appendAssumeCapacity(.{ .unit_debug_info = ui });
7093
7094 unit.debug_info_header_ni =
7095 .wrap(try debug_info_ni.addOnlyHeaderChild(&elf.mf, gpa, .{
7096 .next_moved = true,
7097 .enable_next_moved = true,
7098 }));
7099 elf.nodes.appendAssumeCapacity(.{ .unit_debug_info_header = ui });
7100 },
7101 }
7102 switch (elf.shndx.debug_line) {
7103 .UNDEF => {},
7104 else => |debug_line_shndx| {
7105 const debug_line_ni =
7106 try debug_line_shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{
7107 .alignment = elf.mf.flags.block_size,
7108 .next_moved = true,
7109 .enable_next_moved = true,
7110 });
7111 unit.debug_line_ni = .wrap(debug_line_ni);
7112 elf.nodes.appendAssumeCapacity(.{ .unit_debug_line = ui });
7113
7114 unit.debug_line_header_ni =
7115 .wrap(try debug_line_ni.addOnlyHeaderChild(&elf.mf, gpa, .{
7116 .next_moved = true,
7117 .enable_next_moved = true,
7118 }));
7119 elf.nodes.appendAssumeCapacity(.{ .unit_debug_line_header = ui });
7120 },
7121 }
7122 }
7123
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.?,
7134 else => |e| return e,
7135 };
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 }
7147 }
69547148 }
69557149}
69567150
......@@ -7750,7 +7944,10 @@ fn addNodeRelocAssumeCapacity(
77507944 assert(!shndx.flags(elf).ALLOC); // not yet needed so not implemented
77517945 const first_target_reloc = switch (elf.getNode(target)) {
77527946 else => unreachable,
7753 .unit_frame_cie => |ui| &elf.dwarf_units.items[@backingInt(ui)].unit_frame_cie_first_target_reloc,
7947 .debug_shared => |ss| &elf.dwarf_shared.getPtr(ss).first_target_reloc,
7948 .unit_frame_cie => |ui| &elf.dwarf_units.items[@backingInt(ui)].frame_cie_first_target_reloc,
7949 .unit_debug_info_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_target_reloc,
7950 .unit_debug_line_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_target_reloc,
77547951 };
77557952 const next = first_target_reloc.*;
77567953 const ri: NodeReloc.Index = @fromBackingInt(@intCast(elf.node_relocs.items.len));
......@@ -7843,11 +8040,16 @@ fn addGotRelocAssumeCapacity(
78438040 .shdr,
78448041 .segment,
78458042 .copied_global,
7846 .value_debug_info,
7847 .global_debug_info,
7848 .frame_padding,
8043 .debug_shared,
8044 .unit_padding,
78498045 .unit_frame,
78508046 .unit_frame_cie,
8047 .unit_debug_info,
8048 .unit_debug_info_header,
8049 .unit_debug_line,
8050 .unit_debug_line_header,
8051 .value_debug_info,
8052 .global_debug_info,
78518053 .func_frame_fde,
78528054 .func_debug_info,
78538055 .func_debug_line,
......@@ -8207,21 +8409,27 @@ fn updateFuncInner(
82078409 var nw: MappedFile.Node.Writer = undefined;
82088410 ni.writer(&elf.mf, gpa, &nw);
82098411 defer nw.deinit();
8210 var debug: Dwarf.WipNav.Debug = undefined;
8211 const debug_output: link.File.DebugInfoOutput = debug_output: {
8212 if (elf.ehdrMachine() != .X86_64) break :debug_output .none;
8412 var debug_output_buf: Dwarf.WipNav.Debug = undefined;
8413 const debug_output: link.File.DebugInfoOutput, const dwarf_func = debug_output: {
8414 if (elf.ehdrMachine() != .X86_64) break :debug_output .{ .none, undefined };
82138415 const dwarf = &elf.dwarf;
82148416 const mod = zcu.navFileScope(func.owner_nav).mod.?;
8215 if (mod.strip and mod.unwind_tables == .none) break :debug_output .none;
8417 if (mod.strip and mod.unwind_tables == .none) break :debug_output .{ .none, undefined };
82168418
82178419 try elf.nodes.ensureUnusedCapacity(gpa, 5);
82188420 const dwarf_func_index = try dwarf.getFunc(func.owner_nav);
82198421 try elf.dwarf_funcs.appendNTimes(gpa, .{
8220 .func_frame_fde_first_symbol_reloc = .none,
8221 .func_frame_fde_first_node_reloc = .none,
8422 .frame_fde_first_symbol_reloc = .none,
8423 .frame_fde_first_node_reloc = .none,
8424 .debug_info_first_target_reloc = .none,
8425 .debug_info_first_symbol_reloc = .none,
8426 .debug_info_first_node_reloc = .none,
8427 .debug_line_first_symbol_reloc = .none,
8428 .debug_line_first_node_reloc = .none,
82228429 }, @backingInt(dwarf_func_index) + 1 -| elf.dwarf_funcs.items.len);
82238430
8224 debug.wip_nav = .{
8431 const wip_nav = &debug_output_buf.wip_nav;
8432 wip_nav.* = .{
82258433 .dwarf = dwarf,
82268434 .unit = dwarf.getUnit(mod),
82278435 .func = dwarf_func_index,
......@@ -8235,16 +8443,17 @@ fn updateFuncInner(
82358443 .sync, .async => .eh_frame,
82368444 },
82378445 .fde_writer = undefined,
8238 .frame_func_length_offset = std.math.maxInt(usize),
8446 .frame_func_length = undefined,
82398447 };
8240 const unit = debug.wip_nav.unit.get(dwarf);
8448 const unit = wip_nav.unit.get(dwarf);
8449
82418450 const frame_align: Alignment = switch (elf.identClass()) {
82428451 .NONE, _ => unreachable,
82438452 .@"32" => .@"4",
82448453 .@"64" => .@"8",
82458454 };
82468455 const frame_ni = unit.frame_ni.unwrap() orelse frame_ni: {
8247 const frame_ni = try switch (debug.wip_nav.frame_format) {
8456 const frame_ni = try switch (wip_nav.frame_format) {
82488457 .debug_frame => elf.shndx.debug_frame,
82498458 .eh_frame => elf.shndx.eh_frame,
82508459 }.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{
......@@ -8253,7 +8462,7 @@ fn updateFuncInner(
82538462 .enable_next_moved = true,
82548463 });
82558464 unit.frame_ni = .wrap(frame_ni);
8256 elf.nodes.appendAssumeCapacity(.{ .unit_frame = debug.wip_nav.unit });
8465 elf.nodes.appendAssumeCapacity(.{ .unit_frame = wip_nav.unit });
82578466 break :frame_ni frame_ni;
82588467 };
82598468 _ = unit.cie_ni.unwrap() orelse {
......@@ -8263,17 +8472,16 @@ fn updateFuncInner(
82638472 .enable_next_moved = true,
82648473 });
82658474 unit.cie_ni = .wrap(cie_ni);
8266 elf.nodes.appendAssumeCapacity(.{ .unit_frame_cie = debug.wip_nav.unit });
8267 var cie_writer: MappedFile.Node.Writer = undefined;
8268 cie_ni.writer(&elf.mf, gpa, &cie_writer);
8269 defer cie_writer.deinit();
8270 dwarf.genDebugFrameCie(&cie_writer.interface, switch (elf.ehdrMachine()) {
8475 elf.nodes.appendAssumeCapacity(.{ .unit_frame_cie = wip_nav.unit });
8476 var cie_nw: MappedFile.Node.Writer = undefined;
8477 cie_ni.writer(&elf.mf, gpa, &cie_nw);
8478 defer cie_nw.deinit();
8479 dwarf.genDebugFrameCie(&cie_nw.interface, switch (elf.ehdrMachine()) {
82718480 else => unreachable,
82728481 .X86_64 => .x86_64,
8273 }, debug.wip_nav.frame_format) catch |err| switch (err) {
8274 error.WriteFailed => return cie_writer.err.?,
8482 }, wip_nav.frame_format) catch |err| switch (err) {
8483 error.WriteFailed => return cie_nw.err.?,
82758484 };
8276 @memset(cie_writer.interface.unusedCapacitySlice(), std.dwarf.CFA.nop);
82778485 };
82788486 const dwarf_func = dwarf_func_index.get(dwarf);
82798487 const fde_ni = if (dwarf_func.fde_ni.unwrap()) |fde_ni| fde_ni: {
......@@ -8290,15 +8498,17 @@ fn updateFuncInner(
82908498 dwarf_func.fde_ni = .wrap(fde_ni);
82918499 break :fde_ni fde_ni;
82928500 };
8293 fde_ni.writer(&elf.mf, gpa, &debug.wip_nav.fde_writer);
8294 if (mod.strip) break :debug_output .{ .eh_frame = &debug.wip_nav };
8501 fde_ni.writer(&elf.mf, gpa, &wip_nav.fde_writer);
8502
8503 if (mod.strip) break :debug_output .{ .{ .eh_frame = wip_nav }, dwarf_func };
82958504
8505 const debug = &debug_output_buf;
82968506 debug.pt = pt;
82978507 debug.any_children = false;
82988508 debug.blocks = .empty;
82998509 const debug_info_ni = dwarf_func.debug_info_ni.unwrap() orelse debug_info_ni: {
83008510 const debug_info_ni =
8301 try elf.shndx.debug_info.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{
8511 try unit.debug_info_ni.unwrap().?.addFloatingChild(&elf.mf, gpa, .{
83028512 .next_moved = true,
83038513 .enable_next_moved = true,
83048514 });
......@@ -8309,7 +8519,7 @@ fn updateFuncInner(
83098519 debug_info_ni.writer(&elf.mf, gpa, &debug.info_writer);
83108520 const debug_line_ni = dwarf_func.debug_line_ni.unwrap() orelse debug_line_ni: {
83118521 const debug_line_ni =
8312 try elf.shndx.debug_line.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{
8522 try unit.debug_line_ni.unwrap().?.addFloatingChild(&elf.mf, gpa, .{
83138523 .next_moved = true,
83148524 .enable_next_moved = true,
83158525 });
......@@ -8317,18 +8527,25 @@ fn updateFuncInner(
83178527 break :debug_line_ni debug_line_ni;
83188528 };
83198529 debug_line_ni.writer(&elf.mf, gpa, &debug.line_writer);
8320 break :debug_output .{ .dwarf2 = &debug };
8530
8531 break :debug_output .{ .{ .dwarf2 = debug }, dwarf_func };
83218532 };
83228533 defer switch (debug_output) {
83238534 .dwarf => unreachable,
8324 inline .eh_frame, .dwarf2 => |dwarf| dwarf.deinit(gpa),
8535 inline .eh_frame, .dwarf2 => |dwarf| dwarf.deinit(),
83258536 .none => {},
83268537 };
83278538 switch (debug_output) {
83288539 .dwarf => unreachable,
8329 inline .eh_frame, .dwarf2 => |dwarf| {
8330 elf.resetNodeRelocs(debug.wip_nav.func.?.get(&elf.dwarf).fde_ni.unwrap().?);
8331 try dwarf.genFuncHeaders();
8540 .eh_frame => |wip_nav| {
8541 elf.resetNodeRelocs(dwarf_func.fde_ni.unwrap().?);
8542 try wip_nav.genDebugFrameHeader();
8543 },
8544 .dwarf2 => |debug| {
8545 elf.resetNodeRelocs(dwarf_func.fde_ni.unwrap().?);
8546 try debug.wip_nav.genDebugFrameHeader();
8547 elf.resetNodeRelocs(dwarf_func.debug_info_ni.unwrap().?);
8548 try debug.startDebugInfo();
83328549 },
83338550 .none => {},
83348551 }
......@@ -8348,30 +8565,45 @@ fn updateFuncInner(
83488565 else => |e| return e,
83498566 };
83508567 const func_length = nw.interface.end;
8351 switch (debug_output) {
8568 switch (elf.symPtr(nmi.symbol(elf).index())) {
8569 inline else => |sym| elf.targetStore(&sym.size, @intCast(func_length)),
8570 }
8571 debug_output: switch (debug_output) {
83528572 .dwarf => unreachable,
8353 .eh_frame, .dwarf2 => {
8354 debug.wip_nav.finishDebugFrameFde(func_length);
8355 const frame_ni = switch (debug.wip_nav.frame_format) {
8573 .eh_frame => |wip_nav| {
8574 wip_nav.finishDebugFrameFde(func_length);
8575 const frame_ni = switch (wip_nav.frame_format) {
83568576 .debug_frame => elf.shndx.debug_frame,
83578577 .eh_frame => elf.shndx.eh_frame,
83588578 }.get(elf).ni;
8359 try frame_ni.trimStart(&elf.mf, elf.base.comp.gpa);
8360 switch (debug.wip_nav.frame_format) {
8579 try frame_ni.trimStart(&elf.mf, gpa);
8580 switch (wip_nav.frame_format) {
83618581 .debug_frame => {},
83628582 .eh_frame => {
83638583 const last_offset, const last_size =
83648584 frame_ni.last(&elf.mf).unwrap().?.location(&elf.mf).resolve(&elf.mf);
8365 const last_end = last_offset + last_size;
8366 try frame_ni.ensureMinimumSize(&elf.mf, elf.base.comp.gpa, last_end + 4);
8585 try frame_ni.ensureMinimumSize(&elf.mf, gpa, last_offset + last_size + 4);
83678586 },
83688587 }
83698588 },
8589 .dwarf2 => |debug| {
8590 try debug.finishFunc();
8591 for ([2]Section.Index{
8592 elf.shndx.debug_info,
8593 elf.shndx.debug_line,
8594 }) |debug_shndx| try debug_shndx.get(elf).ni.trimStart(&elf.mf, gpa);
8595 {
8596 const debug_info_ni =
8597 debug.wip_nav.unit.get(debug.wip_nav.dwarf).debug_info_ni.unwrap().?;
8598 const last_offset, const last_size =
8599 debug_info_ni.last(&elf.mf).unwrap().?.location(&elf.mf).resolve(&elf.mf);
8600 try debug_info_ni.ensureMinimumSize(&elf.mf, gpa, last_offset + last_size +
8601 comptime Dwarf.uleb128Bytes(@backingInt(Dwarf.AbbrevCode.null)) * 2);
8602 }
8603 continue :debug_output .{ .eh_frame = &debug.wip_nav };
8604 },
83708605 .none => {},
83718606 }
8372 switch (elf.symPtr(nmi.symbol(elf).index())) {
8373 inline else => |sym| elf.targetStore(&sym.size, @intCast(func_length)),
8374 }
83758607 }
83768608
83778609 // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs.
......@@ -8427,8 +8659,14 @@ fn flushInner(
84278659
84288660 while (try elf.idle(tid)) {}
84298661
8662 assert(elf.pending_uavs.items.len == 0);
8663 var lazy_it = elf.lazy.iterator();
8664 while (lazy_it.next()) |lazy| assert(lazy.value.pending_index == lazy.value.map.count());
8665
84308666 // We've done the final `idle` loop, so everything is at its final place in the file. We have a
84318667 // few more things to check and write now that addresses and offsets are finalized.
8668 elf.mf.nodes_lock.lock();
8669 defer elf.mf.nodes_lock.unlock();
84328670
84338671 if (elf.overflowed_reloc_count > 0) {
84348672 diags.addError("failed to apply {d} relocations: overflow", .{elf.overflowed_reloc_count});
......@@ -8476,12 +8714,13 @@ fn flushInner(
84768714}
84778715
84788716pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
8479 const comp = elf.base.comp;
8480 const diags = &comp.link_diags;
8481
8717 // This function is called non-deterministically, and so must not affect the layout of any nodes.
84828718 elf.mf.nodes_lock.lock();
84838719 defer elf.mf.nodes_lock.unlock();
84848720
8721 const comp = elf.base.comp;
8722 const diags = &comp.link_diags;
8723
84858724 assert(elf.pending_uavs.items.len == 0);
84868725 for (&elf.lazy.values) |*lazy| {
84878726 assert(lazy.pending_index == lazy.map.count());
......@@ -8654,6 +8893,25 @@ fn idleProgNode(
86548893 .uav => |umi| std.mem.print(&name, "{f}", .{
86558894 Value.fromInterned(umi.uavValue(elf)).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
86568895 }) catch &name,
8896 .debug_shared => |ss| switch (ss) {
8897 .debug_abbrev, .debug_str, .debug_str_offsets => "debug info",
8898 .debug_line_str => "line info",
8899 },
8900 .unit_frame,
8901 .unit_frame_cie,
8902 .unit_debug_info,
8903 .unit_debug_info_header,
8904 .unit_debug_line,
8905 .unit_debug_line_header,
8906 => |ui, tag| std.mem.print(&name, "{s} info for {s}", .{
8907 switch (tag) {
8908 else => unreachable,
8909 .unit_frame, .unit_frame_cie => "unwind",
8910 .unit_debug_info, .unit_debug_info_header => "debug",
8911 .unit_debug_line, .unit_debug_line_header => "line",
8912 },
8913 ui.mod(&elf.dwarf).fully_qualified_name,
8914 }) catch &name,
86578915 .value_debug_info => |cpi| std.mem.print(&name, "debug info for {f}", .{
86588916 Value.fromInterned(cpi.val(&elf.dwarf.const_pool))
86598917 .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
......@@ -8664,9 +8922,6 @@ fn idleProgNode(
86648922 ip.getNav(gi.nav(&elf.dwarf)).fqn.fmt(ip),
86658923 }) catch &name;
86668924 },
8667 .unit_frame, .unit_frame_cie => |ui| std.mem.print(&name, "unwind info for {s}", .{
8668 ui.mod(&elf.dwarf).fully_qualified_name,
8669 }) catch &name,
86708925 .func_frame_fde, .func_debug_info, .func_debug_line => |fi, tag| {
86718926 const ip = &elf.base.comp.zcu.?.intern_pool;
86728927 break :name std.mem.print(&name, "{s} info for {f}", .{
......@@ -8684,38 +8939,35 @@ fn idleProgNode(
86848939
86858940fn genPending(elf: *Elf, pt: Zcu.PerThread) Error!void {
86868941 const zcu = elf.base.comp.zcu.?;
8687 pending: while (true) {
8688 if (elf.pending_uavs.pop()) |umi| {
8689 var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;
8690 const prog_name = std.mem.print(&prog_name_buf, "{f}", .{
8691 Value.fromInterned(umi.uavValue(elf)).fmtValue(pt),
8692 }) catch &prog_name_buf;
8693 const prog_node = elf.const_prog_node.start(prog_name, 0);
8694 defer prog_node.end();
8695 try elf.genUav(pt, umi);
8696 continue :pending;
8697 }
8698 var lazy_it = elf.lazy.iterator();
8699 while (lazy_it.next()) |lazy| if (lazy.value.pending_index < lazy.value.map.count()) {
8700 const lmr: Node.LazyMapRef = .{ .kind = lazy.key, .index = lazy.value.pending_index };
8701 lazy.value.pending_index += 1;
8702 const lazy_ty: Type = .fromInterned(lmr.lazySymbol(elf).ty);
8703 var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;
8704 const prog_name: []const u8 = switch (lazy_ty.zigTypeTag(zcu)) {
8705 .@"enum" => std.mem.print(&prog_name_buf, "@tagName({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,
8706 .error_set => switch (lmr.kind) {
8707 .code => std.mem.print(&prog_name_buf, "@errorCast({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,
8708 .const_data => "@errorName",
8709 },
8710 else => unreachable,
8711 };
8712 const prog_node = elf.synth_prog_node.start(prog_name, 0);
8713 defer prog_node.end();
8714 try elf.genLazy(pt, lmr);
8715 continue :pending;
8942
8943 while (elf.pending_uavs.pop()) |umi| {
8944 var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;
8945 const prog_name = std.mem.print(&prog_name_buf, "{f}", .{
8946 Value.fromInterned(umi.uavValue(elf)).fmtValue(pt),
8947 }) catch &prog_name_buf;
8948 const prog_node = elf.const_prog_node.start(prog_name, 0);
8949 defer prog_node.end();
8950 try elf.genUav(pt, umi);
8951 }
8952
8953 var lazy_it = elf.lazy.iterator();
8954 while (lazy_it.next()) |lazy| while (lazy.value.pending_index < lazy.value.map.count()) {
8955 const lmr: Node.LazyMapRef = .{ .kind = lazy.key, .index = lazy.value.pending_index };
8956 lazy.value.pending_index += 1;
8957 const lazy_ty: Type = .fromInterned(lmr.lazySymbol(elf).ty);
8958 var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;
8959 const prog_name: []const u8 = switch (lazy_ty.zigTypeTag(zcu)) {
8960 .@"enum" => std.mem.print(&prog_name_buf, "@tagName({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,
8961 .error_set => switch (lmr.kind) {
8962 .code => std.mem.print(&prog_name_buf, "@errorCast({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,
8963 .const_data => "@errorName",
8964 },
8965 else => unreachable,
87168966 };
8717 break;
8718 }
8967 const prog_node = elf.synth_prog_node.start(prog_name, 0);
8968 defer prog_node.end();
8969 try elf.genLazy(pt, lmr);
8970 };
87198971}
87208972
87218973fn genUav(
......@@ -9071,25 +9323,103 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
90719323 name = elf.globalByName(name).?.next_in_node;
90729324 }
90739325 }
9074 elf.flushMovedNodeRelocs(ni, new_addr, mi.firstSymbolReloc(elf), .none, mi.firstGotReloc(elf));
9326 elf.flushMovedNodeRelocs(
9327 ni,
9328 new_addr,
9329 mi.firstSymbolReloc(elf),
9330 .none,
9331 mi.firstGotReloc(elf),
9332 );
90759333 },
9076 .value_debug_info,
9077 .global_debug_info,
9078 .frame_padding,
9079 .unit_frame,
9080 => {},
9334 .debug_shared => |ss| {
9335 var target_ri = elf.dwarf_shared.getPtr(ss).first_target_reloc;
9336 while (target_ri != .none) {
9337 const target_reloc = target_ri.get(elf);
9338 assert(target_reloc.target == ni);
9339 target_reloc.apply(elf);
9340 target_ri = target_reloc.next;
9341 }
9342 },
9343 .unit_padding, .unit_frame, .unit_debug_info, .unit_debug_line => {},
90819344 .unit_frame_cie => |ui| {
90829345 const dwarf_unit = &elf.dwarf_units.items[@backingInt(ui)];
9083 var target_ri = dwarf_unit.unit_frame_cie_first_target_reloc;
9346 var target_ri = dwarf_unit.frame_cie_first_target_reloc;
9347 while (target_ri != .none) {
9348 const target_reloc = target_ri.get(elf);
9349 assert(target_reloc.target == ni);
9350 target_reloc.apply(elf);
9351 target_ri = target_reloc.next;
9352 }
9353 },
9354 .unit_debug_info_header => |ui| {
9355 const dwarf_unit = &elf.dwarf_units.items[@backingInt(ui)];
9356 var target_ri = dwarf_unit.debug_info_header_first_target_reloc;
9357 while (target_ri != .none) {
9358 const target_reloc = target_ri.get(elf);
9359 assert(target_reloc.target == ni);
9360 target_reloc.apply(elf);
9361 target_ri = target_reloc.next;
9362 }
9363 elf.flushMovedNodeRelocs(
9364 ni,
9365 elf.computeNodeVAddr(ni),
9366 .none,
9367 dwarf_unit.debug_info_header_first_node_reloc,
9368 .none,
9369 );
9370 },
9371 .unit_debug_line_header => |ui| {
9372 const dwarf_unit = &elf.dwarf_units.items[@backingInt(ui)];
9373 var target_ri = dwarf_unit.debug_line_header_first_target_reloc;
9374 while (target_ri != .none) {
9375 const target_reloc = target_ri.get(elf);
9376 assert(target_reloc.target == ni);
9377 target_reloc.apply(elf);
9378 target_ri = target_reloc.next;
9379 }
9380 elf.flushMovedNodeRelocs(
9381 ni,
9382 elf.computeNodeVAddr(ni),
9383 .none,
9384 dwarf_unit.debug_line_header_first_node_reloc,
9385 .none,
9386 );
9387 },
9388 .value_debug_info => |vi| {
9389 const dwarf_value = &elf.dwarf_values.items[@backingInt(vi)];
9390 var target_ri = dwarf_value.debug_info_first_target_reloc;
9391 while (target_ri != .none) {
9392 const target_reloc = target_ri.get(elf);
9393 assert(target_reloc.target == ni);
9394 target_reloc.apply(elf);
9395 target_ri = target_reloc.next;
9396 }
9397 elf.flushMovedNodeRelocs(
9398 ni,
9399 elf.computeNodeVAddr(ni),
9400 dwarf_value.debug_info_first_symbol_reloc,
9401 dwarf_value.debug_info_first_node_reloc,
9402 .none,
9403 );
9404 },
9405 .global_debug_info => |vi| {
9406 const dwarf_global = &elf.dwarf_globals.items[@backingInt(vi)];
9407 var target_ri = dwarf_global.debug_info_first_target_reloc;
90849408 while (target_ri != .none) {
90859409 const target_reloc = target_ri.get(elf);
90869410 assert(target_reloc.target == ni);
90879411 target_reloc.apply(elf);
90889412 target_ri = target_reloc.next;
90899413 }
9414 elf.flushMovedNodeRelocs(
9415 ni,
9416 elf.computeNodeVAddr(ni),
9417 dwarf_global.debug_info_first_symbol_reloc,
9418 dwarf_global.debug_info_first_node_reloc,
9419 .none,
9420 );
90909421 },
90919422 .func_frame_fde => |fi| {
9092 const new_addr = elf.computeNodeVAddr(ni);
90939423 const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)];
90949424 const mod = elf.base.comp.zcu.?.navFileScope(fi.nav(&elf.dwarf)).mod.?;
90959425 switch (mod.unwind_tables) {
......@@ -9101,15 +9431,39 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
91019431 }
91029432 elf.flushMovedNodeRelocs(
91039433 ni,
9104 new_addr,
9105 dwarf_func.func_frame_fde_first_symbol_reloc,
9106 dwarf_func.func_frame_fde_first_node_reloc,
9434 elf.computeNodeVAddr(ni),
9435 dwarf_func.frame_fde_first_symbol_reloc,
9436 dwarf_func.frame_fde_first_node_reloc,
9437 .none,
9438 );
9439 },
9440 .func_debug_info => |fi| {
9441 const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)];
9442 var target_ri = dwarf_func.debug_info_first_target_reloc;
9443 while (target_ri != .none) {
9444 const target_reloc = target_ri.get(elf);
9445 assert(target_reloc.target == ni);
9446 target_reloc.apply(elf);
9447 target_ri = target_reloc.next;
9448 }
9449 elf.flushMovedNodeRelocs(
9450 ni,
9451 elf.computeNodeVAddr(ni),
9452 dwarf_func.debug_info_first_symbol_reloc,
9453 dwarf_func.debug_info_first_node_reloc,
9454 .none,
9455 );
9456 },
9457 .func_debug_line => |fi| {
9458 const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)];
9459 elf.flushMovedNodeRelocs(
9460 ni,
9461 elf.computeNodeVAddr(ni),
9462 dwarf_func.debug_line_first_symbol_reloc,
9463 dwarf_func.debug_line_first_node_reloc,
91079464 .none,
91089465 );
91099466 },
9110 .func_debug_info,
9111 .func_debug_line,
9112 => {},
91139467 }
91149468 try ni.childrenMoved(elf.base.comp.gpa, &elf.mf);
91159469}
......@@ -9346,11 +9700,16 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
93469700 .uav,
93479701 .lazy_code,
93489702 .lazy_const_data,
9349 .value_debug_info,
9350 .global_debug_info,
9351 .frame_padding,
9703 .debug_shared,
9704 .unit_padding,
93529705 .unit_frame,
93539706 .unit_frame_cie,
9707 .unit_debug_info,
9708 .unit_debug_info_header,
9709 .unit_debug_line,
9710 .unit_debug_line_header,
9711 .value_debug_info,
9712 .global_debug_info,
93549713 .func_frame_fde,
93559714 .func_debug_info,
93569715 .func_debug_line,
......@@ -9378,6 +9737,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
93789737 .uav,
93799738 .lazy_code,
93809739 .lazy_const_data,
9740 .debug_shared,
93819741 => unreachable,
93829742
93839743 .archive_header => {
......@@ -9406,66 +9766,111 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
94069766 error.NoSpaceLeft => archive.strtab_member_too_big = true,
94079767 }
94089768 },
9769 .unit_padding,
9770 .unit_frame_cie,
9771 .unit_debug_info_header,
9772 .unit_debug_line_header,
94099773 .value_debug_info,
94109774 .global_debug_info,
9411 => {},
9412 .frame_padding, .unit_frame_cie, .func_frame_fde => |_, tag| {
9775 .func_frame_fde,
9776 .func_debug_info,
9777 .func_debug_line,
9778 => |_, tag| {
94139779 const offset, const size = ni.location(&elf.mf).resolve(&elf.mf);
9414 const slice = slice: {
9415 const parent_ni = ni.parent(&elf.mf).unwrap().?;
9416 if (ni.next(&elf.mf).unwrap()) |next_ni| {
9417 const parent_slice = parent_ni.slicePadding(&elf.mf);
9418 const next_offset, _ = next_ni.location(&elf.mf).resolve(&elf.mf);
9419 break :slice parent_slice[@intCast(offset)..@intCast(next_offset)];
9420 } else switch (tag) {
9421 else => unreachable,
9422 .frame_padding => {
9423 const frame_slice = parent_ni.slicePadding(&elf.mf);
9424 switch (elf.getNode(parent_ni).section.debugFrameFormat(elf).?) {
9425 .eh_frame => {
9426 const end = frame_slice.len - 4;
9427 std.mem.writeInt(u32, frame_slice[end..][0..4], 0, elf.dwarf.endian);
9428 break :slice frame_slice[@intCast(offset)..end];
9429 },
9430 .debug_frame => break :slice frame_slice[@intCast(offset)..],
9431 }
9432 },
9433 .unit_frame_cie, .func_frame_fde => {
9434 const parent_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);
9435 const frame_ni = parent_ni.parent(&elf.mf).unwrap().?;
9436 const frame_slice = frame_ni.slicePadding(&elf.mf);
9437 const format = elf.getNode(frame_ni).section.debugFrameFormat(elf).?;
9438 const slice = frame_slice[@intCast(parent_offset + offset)..if (parent_ni.next(&elf.mf).unwrap()) |parent_next_ni| frame_end: {
9439 const parent_next_offset, _ = parent_next_ni.location(&elf.mf).resolve(&elf.mf);
9440 break :frame_end @intCast(parent_next_offset);
9441 } else frame_end: switch (format) {
9442 .eh_frame => {
9443 const frame_end = frame_slice.len - 4;
9444 std.mem.writeInt(u32, frame_slice[frame_end..][0..4], 0, elf.dwarf.endian);
9445 break :frame_end frame_end;
9446 },
9447 .debug_frame => frame_slice.len,
9448 }];
9449 var fw: std.Io.Writer = .fixed(slice[@intCast(size)..]);
9450 elf.dwarf.genDebugFrameCie(&fw, null, format) catch |err| switch (err) {
9451 error.WriteFailed => break :slice slice,
9452 };
9453 elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len);
9454 break :slice slice[0..@intCast(size)];
9455 },
9456 }
9780 const parent_ni = ni.parent(&elf.mf).unwrap().?;
9781 const slice = if (ni.next(&elf.mf).unwrap()) |next_ni| slice: {
9782 const parent_slice = parent_ni.slicePadding(&elf.mf);
9783 const next_offset, _ = next_ni.location(&elf.mf).resolve(&elf.mf);
9784 break :slice parent_slice[@intCast(offset)..@intCast(next_offset)];
9785 } else slice: switch (tag) {
9786 else => unreachable,
9787 .unit_padding => {
9788 const frame_slice = parent_ni.slicePadding(&elf.mf);
9789 switch (elf.getNode(parent_ni).section.debugFrameFormat(elf) orelse .debug_frame) {
9790 .eh_frame => {
9791 const end = frame_slice.len - 4;
9792 std.mem.writeInt(u32, frame_slice[end..][0..4], 0, elf.dwarf.endian);
9793 break :slice frame_slice[@intCast(offset)..end];
9794 },
9795 .debug_frame => break :slice frame_slice[@intCast(offset)..],
9796 }
9797 },
9798 .unit_frame_cie, .func_frame_fde => {
9799 const parent_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);
9800 const frame_ni = parent_ni.parent(&elf.mf).unwrap().?;
9801 const frame_slice = frame_ni.slicePadding(&elf.mf);
9802 const frame_format = elf.getNode(frame_ni).section.debugFrameFormat(elf);
9803 const slice = frame_slice[@intCast(parent_offset + offset)..if (parent_ni.next(&elf.mf).unwrap()) |parent_next_ni| frame_end: {
9804 const parent_next_offset, _ = parent_next_ni.location(&elf.mf).resolve(&elf.mf);
9805 break :frame_end @intCast(parent_next_offset);
9806 } else frame_end: switch (frame_format orelse .debug_frame) {
9807 .eh_frame => {
9808 const frame_end = frame_slice.len - 4;
9809 std.mem.writeInt(u32, frame_slice[frame_end..][0..4], 0, elf.dwarf.endian);
9810 break :frame_end frame_end;
9811 },
9812 .debug_frame => frame_slice.len,
9813 }];
9814 var fw: Io.Writer = .fixed(slice[@intCast(size)..]);
9815 (if (frame_format) |format|
9816 elf.dwarf.genDebugFrameCie(&fw, null, format)
9817 else
9818 elf.dwarf.genUnitPadding(&fw)) catch |err| switch (err) {
9819 error.WriteFailed => break :slice slice,
9820 };
9821 elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len);
9822 break :slice slice[0..@intCast(size)];
9823 },
9824 .unit_debug_info_header,
9825 .unit_debug_line_header,
9826 .value_debug_info,
9827 .global_debug_info,
9828 .func_debug_info,
9829 .func_debug_line,
9830 => {
9831 const parent_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);
9832 const debug_ni = parent_ni.parent(&elf.mf).unwrap().?;
9833 const debug_slice = debug_ni.slicePadding(&elf.mf);
9834 var fw: Io.Writer = .fixed(debug_slice[@intCast(parent_offset)..if (parent_ni.next(&elf.mf).unwrap()) |parent_next_ni| debug_end: {
9835 const parent_next_offset, _ = parent_next_ni.location(&elf.mf).resolve(&elf.mf);
9836 break :debug_end @intCast(parent_next_offset);
9837 } else debug_slice.len]);
9838 fw.end = @intCast(offset + size);
9839 for (0..2) |_| fw.writeUleb128(@backingInt(Dwarf.AbbrevCode.null)) catch
9840 unreachable; // ensured by `updateFunc`
9841 elf.dwarf.updateUnitLength(fw.buffer, fw.end);
9842 const unit_padding = fw.unusedCapacitySlice();
9843 elf.dwarf.genUnitPadding(&fw) catch |err| switch (err) {
9844 error.WriteFailed => {
9845 comptime assert(Dwarf.uleb128Bytes(@backingInt(Dwarf.AbbrevCode.null)) == 1);
9846 @memset(fw.buffer, @backingInt(Dwarf.AbbrevCode.null));
9847 },
9848 };
9849 elf.dwarf.updateUnitLength(unit_padding, unit_padding.len);
9850 return;
9851 },
94579852 };
9458 elf.dwarf.updateUnitLength(slice, slice.len);
94599853 switch (tag) {
94609854 else => unreachable,
9461 .frame_padding => {},
9462 .unit_frame_cie, .func_frame_fde => @memset(slice[@intCast(size)..], std.dwarf.CFA.nop),
9855 .unit_padding => elf.dwarf.updateUnitLength(slice, slice.len),
9856 .unit_frame_cie, .func_frame_fde => {
9857 elf.dwarf.updateUnitLength(slice, slice.len);
9858 @memset(slice[@intCast(size)..], std.dwarf.CFA.nop);
9859 },
9860 .unit_debug_info_header,
9861 .unit_debug_line_header,
9862 .value_debug_info,
9863 .global_debug_info,
9864 .func_debug_info,
9865 .func_debug_line,
9866 => {
9867 var fw: Io.Writer = .fixed(slice[@intCast(size)..]);
9868 elf.dwarf.genDebugInfoPadding(&fw, fw.unusedCapacityLen()) catch unreachable;
9869 },
94639870 }
94649871 },
9465 .unit_frame,
9466 .func_debug_info,
9467 .func_debug_line,
9468 => {},
9872 .unit_frame, .unit_debug_info, .unit_debug_line => if (ni.last(&elf.mf).unwrap()) |last_ni|
9873 try last_ni.nextMoved(elf.base.comp.gpa, &elf.mf),
94699874 }
94709875}
94719876
......@@ -9986,6 +10391,16 @@ pub fn printNode(
998610391 .tid = tid,
998710392 }),
998810393 }),
10394 .debug_shared => |ss| try w.print("({})", .{ss}),
10395 .unit_frame,
10396 .unit_frame_cie,
10397 .unit_debug_info,
10398 .unit_debug_info_header,
10399 .unit_debug_line,
10400 .unit_debug_line_header,
10401 => |ui| try w.print("({s})", .{
10402 ui.mod(&elf.dwarf).fully_qualified_name,
10403 }),
998910404 .value_debug_info => |cpi| try w.print("({f})", .{
999010405 Value.fromInterned(cpi.val(&elf.dwarf.const_pool))
999110406 .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
......@@ -9999,9 +10414,6 @@ pub fn printNode(
999910414 nav.fqn.fmt(ip),
1000010415 });
1000110416 },
10002 .unit_frame, .unit_frame_cie => |ui| try w.print("({s})", .{
10003 ui.mod(&elf.dwarf).fully_qualified_name,
10004 }),
1000510417 .func_frame_fde, .func_debug_info, .func_debug_line => |fi| {
1000610418 const zcu = elf.base.comp.zcu.?;
1000710419 const ip = &zcu.intern_pool;