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...@@ -487,7 +487,7 @@ pub fn writableSliceGreedyPreserve(w: *Writer, preserve: usize, minimum_len: usi
487 @branchHint(.likely);487 @branchHint(.likely);
488 return w.buffer[w.end..];488 return w.buffer[w.end..];
489 }489 }
490 try rebase(w, preserve, minimum_len);490 try w.vtable.rebase(w, preserve, minimum_len);
491 assert(w.buffer.len >= preserve + minimum_len);491 assert(w.buffer.len >= preserve + minimum_len);
492 return w.buffer[w.end..];492 return w.buffer[w.end..];
493}493}
...@@ -845,13 +845,10 @@ pub fn writeByte(w: *Writer, byte: u8) Error!void {...@@ -845,13 +845,10 @@ pub fn writeByte(w: *Writer, byte: u8) Error!void {
845///845///
846/// Asserts buffer capacity is at least `preserve`.846/// Asserts buffer capacity is at least `preserve`.
847pub fn writeBytePreserve(w: *Writer, preserve: usize, byte: u8) Error!void {847pub fn writeBytePreserve(w: *Writer, preserve: usize, byte: u8) Error!void {
848 if (w.buffer.len - w.end != 0) {848 if (w.buffer.len - w.end == 0) {
849 @branchHint(.likely);849 @branchHint(.unlikely);
850 w.buffer[w.end] = byte;850 try w.vtable.rebase(w, preserve -| 1, 1);
851 w.end += 1;
852 return;
853 }851 }
854 try w.vtable.rebase(w, preserve -| 1, 1);
855 w.buffer[w.end] = byte;852 w.buffer[w.end] = byte;
856 w.end += 1;853 w.end += 1;
857}854}
src/codegen/x86_64/Emit.zig+15-13
...@@ -36,7 +36,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -36,7 +36,7 @@ pub fn emitMir(emit: *Emit) Error!void {
36 if (lowered_inst.prefix == .directive) {36 if (lowered_inst.prefix == .directive) {
37 const start_offset: u32 = @intCast(emit.w.end);37 const start_offset: u32 = @intCast(emit.w.end);
38 switch (emit.debug_output) {38 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) {
40 .@".cfi_def_cfa" => try dwarf.genDebugFrame(start_offset, .{ .def_cfa = .{40 .@".cfi_def_cfa" => try dwarf.genDebugFrame(start_offset, .{ .def_cfa = .{
41 .reg = lowered_inst.ops[0].reg.dwarfNum(),41 .reg = lowered_inst.ops[0].reg.dwarfNum(),
42 .off = lowered_inst.ops[1].imm.signed,42 .off = lowered_inst.ops[1].imm.signed,
...@@ -475,15 +475,17 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -475,15 +475,17 @@ pub fn emitMir(emit: *Emit) Error!void {
475 .column = mir_inst.data.line_column.column,475 .column = mir_inst.data.line_column.column,
476 .is_stmt = false,476 .is_stmt = false,
477 }),477 }),
478 .pseudo_dbg_epilogue_begin_none => switch (emit.debug_output) {478 .pseudo_dbg_epilogue_begin_none => {
479 inline .dwarf, .dwarf2 => |dwarf| {479 switch (emit.debug_output) {
480 try dwarf.setEpilogueBegin();480 inline .dwarf, .dwarf2 => |dwarf| {
481 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{481 try dwarf.setEpilogueBegin();
482 emit.prev_di_loc.line, emit.prev_di_loc.column,482 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
483 });483 emit.prev_di_loc.line, emit.prev_di_loc.column,
484 try emit.dbgAdvancePcAndLine(emit.prev_di_loc);484 });
485 },485 },
486 .eh_frame, .none => {},486 .eh_frame, .none => {},
487 }
488 try emit.dbgAdvancePcAndLine(emit.prev_di_loc);
487 },489 },
488 .pseudo_dbg_enter_block_none => switch (emit.debug_output) {490 .pseudo_dbg_enter_block_none => switch (emit.debug_output) {
489 inline .dwarf, .dwarf2 => |dwarf| {491 inline .dwarf, .dwarf2 => |dwarf| {
...@@ -976,11 +978,11 @@ const Loc = struct {...@@ -976,11 +978,11 @@ const Loc = struct {
976};978};
977979
978fn dbgAdvancePcAndLine(emit: *Emit, loc: Loc) Error!void {980fn 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 });
982 switch (emit.debug_output) {981 switch (emit.debug_output) {
983 inline .dwarf, .dwarf2 => |dwarf| {982 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 });
984 if (loc.is_stmt != emit.prev_di_loc.is_stmt) try dwarf.negateStmt();986 if (loc.is_stmt != emit.prev_di_loc.is_stmt) try dwarf.negateStmt();
985 if (loc.column != emit.prev_di_loc.column) try dwarf.setColumn(loc.column);987 if (loc.column != emit.prev_di_loc.column) try dwarf.setColumn(loc.column);
986 try dwarf.advancePcAndLine(delta_line, delta_pc);988 try dwarf.advancePcAndLine(delta_line, delta_pc);
src/link/Dwarf2.zig+427-208
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1tag: link.File.Tag,1lf: *link.File,
2format: DW.Format,2format: DW.Format,
3endian: std.lang.Endian,3endian: std.lang.Endian,
4address_size: AddressSize,4address_size: AddressSize,
...@@ -12,15 +12,23 @@ values: std.ArrayList(struct {...@@ -12,15 +12,23 @@ values: std.ArrayList(struct {
12globals: std.array_hash_map.Auto(InternPool.Nav.Index, Global),12globals: std.array_hash_map.Auto(InternPool.Nav.Index, Global),
13funcs: std.array_hash_map.Auto(InternPool.Nav.Index, Func),13funcs: std.array_hash_map.Auto(InternPool.Nav.Index, Func),
1414
15debug_abbrev: DebugAbbrev,
15frame: Frame,16frame: Frame,
16debug_info: DebugInfo,17debug_info: DebugInfo,
17debug_line: DebugLine,18debug_line: DebugLine,
19debug_line_str: String,
20debug_str: String,
21debug_str_offsets: StringOffsets,
1822
19pub const AddressSize = enum(u8) { @"32" = 4, @"64" = 8, _ };23pub const AddressSize = enum(u8) { @"32" = 4, @"64" = 8, _ };
2024
21pub const Unit = struct {25pub const Unit = struct {
22 frame_ni: MappedFile.Node.Index.Optional,26 frame_ni: MappedFile.Node.Index.Optional,
23 cie_ni: MappedFile.Node.Index.Optional,27 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
25 pub const Index = enum(u32) {33 pub const Index = enum(u32) {
26 _,34 _,
...@@ -71,7 +79,6 @@ pub const Func = struct {...@@ -71,7 +79,6 @@ pub const Func = struct {
7179
72pub const Frame = struct {80pub const Frame = struct {
73 header: Header,81 header: Header,
74 section_index: SectionIndex,
7582
76 pub const Header = struct {83 pub const Header = struct {
77 code_alignment_factor: u32,84 code_alignment_factor: u32,
...@@ -83,13 +90,16 @@ pub const Frame = struct {...@@ -83,13 +90,16 @@ pub const Frame = struct {
83 pub const Format = std.debug.Dwarf.Unwind.Section;90 pub const Format = std.debug.Dwarf.Unwind.Section;
84};91};
8592
86pub const DebugInfo = struct {93pub const DebugAbbrev = struct {
87 section_index: SectionIndex,94 ni: MappedFile.Node.Index.Optional,
95 offset: usize,
96 set: std.enums.EnumSet(AbbrevCode),
88};97};
8998
99pub const DebugInfo = struct {};
100
90pub const DebugLine = struct {101pub const DebugLine = struct {
91 header: Header,102 header: Header,
92 section_index: SectionIndex,
93103
94 pub const Header = struct {104 pub const Header = struct {
95 minimum_instruction_length: u8,105 minimum_instruction_length: u8,
...@@ -101,7 +111,49 @@ pub const DebugLine = struct {...@@ -101,7 +111,49 @@ pub const DebugLine = struct {
101 };111 };
102};112};
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
106pub const Loc = union(enum) {158pub const Loc = union(enum) {
107 empty,159 empty,
...@@ -463,7 +515,7 @@ pub const WipNav = struct {...@@ -463,7 +515,7 @@ pub const WipNav = struct {
463 },515 },
464 frame_format: Frame.Format,516 frame_format: Frame.Format,
465 fde_writer: MappedFile.Node.Writer,517 fde_writer: MappedFile.Node.Writer,
466 frame_func_length_offset: usize,518 frame_func_length: struct { offset: usize, size: AddressSize },
467519
468 pub const Debug = struct {520 pub const Debug = struct {
469 wip_nav: WipNav,521 wip_nav: WipNav,
...@@ -477,22 +529,53 @@ pub const WipNav = struct {...@@ -477,22 +529,53 @@ pub const WipNav = struct {
477 info_writer: MappedFile.Node.Writer,529 info_writer: MappedFile.Node.Writer,
478 line_writer: MappedFile.Node.Writer,530 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;
481 debug.line_writer.deinit();534 debug.line_writer.deinit();
482 debug.info_writer.deinit();535 debug.info_writer.deinit();
483 debug.blocks.deinit(gpa);536 debug.blocks.deinit(gpa);
484 debug.wip_nav.deinit(gpa);537 debug.wip_nav.deinit();
485 debug.* = undefined;538 debug.* = undefined;
486 }539 }
487540
488 pub fn genFuncHeaders(debug: *Debug) link.Error!void {541 pub fn startDebugInfo(debug: *Debug) link.Error!void {
489 try debug.wip_nav.genFuncHeaders();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));
490 }555 }
491556
492 pub fn genDebugFrame(debug: *Debug, loc: u32, cfa: Cfa) link.Error!void {557 pub fn genDebugFrame(debug: *Debug, loc: u32, cfa: Cfa) link.Error!void {
493 return debug.wip_nav.genDebugFrame(loc, cfa);558 return debug.wip_nav.genDebugFrame(loc, cfa);
494 }559 }
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
496 pub const LocalVarTag = enum { arg, local_var };579 pub const LocalVarTag = enum { arg, local_var };
497 pub fn genLocalVarDebugInfo(580 pub fn genLocalVarDebugInfo(
498 debug: *Debug,581 debug: *Debug,
...@@ -675,7 +758,7 @@ pub const WipNav = struct {...@@ -675,7 +758,7 @@ pub const WipNav = struct {
675 fn enterBlockInner(debug: *Debug, code_off: u64) link.EmitError!void {758 fn enterBlockInner(debug: *Debug, code_off: u64) link.EmitError!void {
676 const dwarf = debug.wip_nav.dwarf;759 const dwarf = debug.wip_nav.dwarf;
677 const diw = &debug.info_writer.interface;760 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
680 block.abbrev_code = @intCast(diw.end);763 block.abbrev_code = @intCast(diw.end);
681 try debug.abbrevCode(.block);764 try debug.abbrevCode(.block);
...@@ -767,17 +850,18 @@ pub const WipNav = struct {...@@ -767,17 +850,18 @@ pub const WipNav = struct {
767 const dwarf = debug.wip_nav.dwarf;850 const dwarf = debug.wip_nav.dwarf;
768 const inlined_func_bytes = comptime uleb128Bytes(@backingInt(AbbrevCode.inlined_func));851 const inlined_func_bytes = comptime uleb128Bytes(@backingInt(AbbrevCode.inlined_func));
769 const block = debug.blocks.pop().?;852 const block = debug.blocks.pop().?;
853 const diw = &debug.info_writer.interface;
770 if (debug.any_children)854 if (debug.any_children)
771 try debug.info_writer.interface.writeUleb128(@backingInt(AbbrevCode.null))855 try diw.writeUleb128(@backingInt(AbbrevCode.null))
772 else856 else
773 std.leb.writeUnsignedFixed(857 std.leb.writeUnsignedFixed(
774 inlined_func_bytes,858 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],
776 @intCast(try dwarf.refAbbrevCode(.empty_inlined_func)),860 @intCast(try dwarf.refAbbrevCode(.empty_inlined_func)),
777 );861 );
778 std.mem.writeInt(862 std.mem.writeInt(
779 u32,863 u32,
780 debug.info_writer.interface.buffered()[block.high_pc..][0..4],864 diw.buffered()[block.high_pc..][0..4],
781 @intCast(code_off - block.low_pc_off),865 @intCast(code_off - block.low_pc_off),
782 dwarf.endian,866 dwarf.endian,
783 );867 );
...@@ -806,7 +890,7 @@ pub const WipNav = struct {...@@ -806,7 +890,7 @@ pub const WipNav = struct {
806890
807 const dlw = &debug.line_writer.interface;891 const dlw = &debug.line_writer.interface;
808 if (zcu.comp.config.incremental) {892 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);
810 errdefer _ = if (!new_func_gop.found_existing) dwarf.funcs.pop();894 errdefer _ = if (!new_func_gop.found_existing) dwarf.funcs.pop();
811 if (!new_func_gop.found_existing) new_func_gop.value_ptr.* = .{895 if (!new_func_gop.found_existing) new_func_gop.value_ptr.* = .{
812 .frame_node = .none,896 .frame_node = .none,
...@@ -822,8 +906,8 @@ pub const WipNav = struct {...@@ -822,8 +906,8 @@ pub const WipNav = struct {
822 try dlw.writeByte(DW.LNS.extended_op);906 try dlw.writeByte(DW.LNS.extended_op);
823 try dlw.writeUleb128(1 + section_offset_size);907 try dlw.writeUleb128(1 + section_offset_size);
824 try dlw.writeByte(DW.LNE.ZIG_set_decl);908 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, .{909 try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(zcu.gpa, .{
826 .source_off = @intCast(dlw.end),910 .source_off = @bitCast(@as(u64, dlw.end)),
827 .target_sec = .debug_info,911 .target_sec = .debug_info,
828 .target_unit = new_unit,912 .target_unit = new_unit,
829 .target_entry = new_func_gop.value_ptr.toOptional(),913 .target_entry = new_func_gop.value_ptr.toOptional(),
...@@ -836,8 +920,8 @@ pub const WipNav = struct {...@@ -836,8 +920,8 @@ pub const WipNav = struct {
836 const old_file = zcu.navFileScopeIndex(old_func_info.owner_nav);920 const old_file = zcu.navFileScopeIndex(old_func_info.owner_nav);
837 if (old_file != new_file) {921 if (old_file != new_file) {
838 const mod_info = dwarf.getModInfo(wip_nav.unit);922 const mod_info = dwarf.getModInfo(wip_nav.unit);
839 try mod_info.dirs.put(dwarf.gpa, new_unit, {});923 try mod_info.dirs.put(zcu.gpa, new_unit, {});
840 const file_gop = try mod_info.files.getOrPut(dwarf.gpa, new_file);924 const file_gop = try mod_info.files.getOrPut(zcu.gpa, new_file);
841925
842 try dlw.writeByte(DW.LNS.set_file);926 try dlw.writeByte(DW.LNS.set_file);
843 try dlw.writeUleb128(file_gop.index);927 try dlw.writeUleb128(file_gop.index);
...@@ -854,57 +938,38 @@ pub const WipNav = struct {...@@ -854,57 +938,38 @@ pub const WipNav = struct {
854 }938 }
855939
856 fn abbrevCode(debug: *Debug, abbrev_code: AbbrevCode) link.EmitError!void {940 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 );
858 }944 }
859945
860 fn infoExternalReloc(debug: *Debug, reloc: struct {946 fn infoExternalReloc(debug: *Debug, reloc: struct {
861 source_off: u32 = 0,947 source_off: u32 = 0,
862 target_si: link.File.SymbolId,948 target_si: link.File.SymbolId,
863 target_off: u64 = 0,949 target_off: u64 = 0,
864 }) Allocator.Error!void {950 }) std.mem.Allocator.Error!void {
865 if (true) @panic("TODO");951 if (true) @panic("TODO");
866 try debug.wip_nav.externalReloc(&debug.wip_nav.dwarf.debug_frame.section, reloc);952 try debug.wip_nav.externalReloc(&debug.wip_nav.dwarf.debug_frame.section, reloc);
867 }953 }
868954
869 fn infoSectionOffset(955 fn infoSectionOffset(
870 debug: *Debug,956 debug: *Debug,
871 target: MappedFile.Node.Index,957 target_ni: MappedFile.Node.Index,
872 addend: i64,958 addend: i64,
873 ) link.EmitError!void {959 ) link.EmitError!void {
874 const dwarf = debug.wip_nav.dwarf;960 try debug.wip_nav.dwarf.sectionOffset(&debug.info_writer, target_ni, addend);
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 );
891 }961 }
892962
893 fn strp(debug: *Debug, str: []const u8) link.EmitError!void {963 fn strp(debug: *Debug, str: []const u8) link.EmitError!void {
894 if (true) @panic("TODO");
895 const dwarf = debug.wip_nav.dwarf;964 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);
897 }966 }
898967
899 fn strpFmt(968 fn strpFmt(debug: *Debug, comptime fmt: []const u8, args: anytype) link.EmitError!void {
900 debug: *Debug,969 const gpa = debug.pt.zcu.gpa;
901 comptime fmt: []const u8,
902 args: anytype,
903 ) link.EmitError!void {
904 const gpa = &debug.wip_nav.dwarf.gpa;
905 const str = try std.fmt.allocPrint(gpa, fmt, args);970 const str = try std.fmt.allocPrint(gpa, fmt, args);
906 defer gpa.free(str);971 defer gpa.free(str);
907 return debug.strp(str);972 try debug.strp(str);
908 }973 }
909974
910 fn infoExprLoc(debug: *Debug, loc: Loc) link.EmitError!void {975 fn infoExprLoc(debug: *Debug, loc: Loc) link.EmitError!void {
...@@ -923,10 +988,7 @@ pub const WipNav = struct {...@@ -923,10 +988,7 @@ pub const WipNav = struct {
923 fn addrSym(ctx: @This(), si: link.File.SymbolId) link.EmitError!void {988 fn addrSym(ctx: @This(), si: link.File.SymbolId) link.EmitError!void {
924 try ctx.debug.infoAddrSym(si, 0);989 try ctx.debug.infoAddrSym(si, 0);
925 }990 }
926 fn infoEntry(991 fn infoEntry(ctx: @This(), node: MappedFile.Node.Index) link.EmitError!void {
927 ctx: @This(),
928 node: MappedFile.Node.Index,
929 ) link.EmitError!void {
930 try ctx.debug.infoSectionOffset(node, 0);992 try ctx.debug.infoSectionOffset(node, 0);
931 }993 }
932 } = .{ .debug = debug };994 } = .{ .debug = debug };
...@@ -941,7 +1003,7 @@ pub const WipNav = struct {...@@ -941,7 +1003,7 @@ pub const WipNav = struct {
941 ) link.EmitError!void {1003 ) link.EmitError!void {
942 const diw = &debug.info_writer.interface;1004 const diw = &debug.info_writer.interface;
943 try debug.infoExternalReloc(.{1005 try debug.infoExternalReloc(.{
944 .source_off = @intCast(diw.end),1006 .source_off = @bitCast(@as(u64, diw.end)),
945 .target_si = si,1007 .target_si = si,
946 .target_off = sym_off,1008 .target_off = sym_off,
947 });1009 });
...@@ -957,7 +1019,6 @@ pub const WipNav = struct {...@@ -957,7 +1019,6 @@ pub const WipNav = struct {
957 }1019 }
9581020
959 fn refValue(debug: *Debug, value: Value) link.EmitError!void {1021 fn refValue(debug: *Debug, value: Value) link.EmitError!void {
960 if (true) @panic("TODO");
961 try debug.infoSectionOffset(.debug_info, try debug.getValueNode(value), 0);1022 try debug.infoSectionOffset(.debug_info, try debug.getValueNode(value), 0);
962 }1023 }
9631024
...@@ -978,7 +1039,7 @@ pub const WipNav = struct {...@@ -978,7 +1039,7 @@ pub const WipNav = struct {
978 if (size == 0) return;1039 if (size == 0) return;
979 const old_end = diw.end;1040 const old_end = diw.end;
980 try codegen.generateSymbol(1041 try codegen.generateSymbol(
981 debug.wip_nav.dwarf.linkFile(),1042 debug.wip_nav.dwarf.lf,
982 debug.pt,1043 debug.pt,
983 val,1044 val,
984 diw,1045 diw,
...@@ -996,37 +1057,29 @@ pub const WipNav = struct {...@@ -996,37 +1057,29 @@ pub const WipNav = struct {
996 }1057 }
997 };1058 };
9981059
999 pub fn deinit(wip_nav: *WipNav, gpa: Allocator) void {1060 pub fn deinit(wip_nav: *WipNav) void {
1000 _ = gpa;
1001 wip_nav.fde_writer.deinit();1061 wip_nav.fde_writer.deinit();
1002 wip_nav.* = undefined;1062 wip_nav.* = undefined;
1003 }1063 }
10041064
1005 pub fn genFuncHeaders(wip_nav: *WipNav) link.Error!void {1065 pub fn genDebugFrameHeader(wip_nav: *WipNav) link.Error!void {
1006 wip_nav.genDebugFrameHeader() catch |err| switch (err) {1066 wip_nav.genDebugFrameHeaderInner() catch |err| switch (err) {
1007 error.WriteFailed => return wip_nav.reportWriteError(&wip_nav.fde_writer),1067 error.WriteFailed => return wip_nav.reportWriteError(&wip_nav.fde_writer),
1008 else => |e| return e,1068 else => |e| return e,
1009 };1069 };
1010 }1070 }
1011 fn genDebugFrameHeader(wip_nav: *WipNav) link.EmitError!void {1071 fn genDebugFrameHeaderInner(wip_nav: *WipNav) link.EmitError!void {
1012 assert(wip_nav.func != null);1072 assert(wip_nav.func != null);
1013 const dwarf = wip_nav.dwarf;1073 const dwarf = wip_nav.dwarf;
1014 const dfw = &wip_nav.fde_writer.interface;1074 const dfw = &wip_nav.fde_writer.interface;
1015 switch (dwarf.format) {1075 try dwarf.genUnitLength(dfw);
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);
1023 switch (wip_nav.frame_format) {1076 switch (wip_nav.frame_format) {
1024 .eh_frame => {1077 .eh_frame => {
1025 try dfw.writeInt(u32, undefined, dwarf.endian);1078 try dfw.writeInt(u32, undefined, dwarf.endian);
1026 {1079 {
1027 const offset = dfw.end;1080 const offset = dfw.end;
1028 try dfw.writeInt(u32, 0, dwarf.endian);1081 try dfw.writeInt(u32, 0, dwarf.endian);
1029 const elf = dwarf.linkFile().cast(.elf2).?;1082 const elf = dwarf.lf.cast(.elf2).?;
1030 try elf.addReloc(1083 try elf.addReloc(
1031 @bitCast(wip_nav.fde_writer.ni),1084 @bitCast(wip_nav.fde_writer.ni),
1032 offset,1085 offset,
...@@ -1035,14 +1088,14 @@ pub const WipNav = struct {...@@ -1035,14 +1088,14 @@ pub const WipNav = struct {
1035 .rel32(elf),1088 .rel32(elf),
1036 );1089 );
1037 }1090 }
1038 wip_nav.frame_func_length_offset = dfw.end;1091 wip_nav.frame_func_length = .{ .offset = dfw.end, .size = .@"32" };
1039 try dfw.writeInt(u32, undefined, dwarf.endian);1092 try dfw.writeInt(u32, undefined, dwarf.endian);
1040 try dfw.writeUleb128(0);1093 try dfw.writeUleb128(0);
1041 },1094 },
1042 .debug_frame => {1095 .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);
1044 try wip_nav.frameAddrSym(wip_nav.func_si, 0);1097 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 };
1046 try dfw.splatByteAll(undefined, @backingInt(dwarf.address_size));1099 try dfw.splatByteAll(undefined, @backingInt(dwarf.address_size));
1047 },1100 },
1048 }1101 }
...@@ -1063,30 +1116,23 @@ pub const WipNav = struct {...@@ -1063,30 +1116,23 @@ pub const WipNav = struct {
10631116
1064 pub fn finishDebugFrameFde(wip_nav: *WipNav, func_length: u64) void {1117 pub fn finishDebugFrameFde(wip_nav: *WipNav, func_length: u64) void {
1065 const dwarf = wip_nav.dwarf;1118 const dwarf = wip_nav.dwarf;
1066 const fde = wip_nav.fde_writer.interface.buffer;1119 const dfw = &wip_nav.fde_writer.interface;
1067 switch (wip_nav.frame_format) {1120 switch (wip_nav.frame_func_length.size) {
1068 .eh_frame => std.mem.writeInt(1121 _ => unreachable,
1122 .@"32" => std.mem.writeInt(
1069 u32,1123 u32,
1070 fde[wip_nav.frame_func_length_offset..][0..4],1124 dfw.buffered()[wip_nav.frame_func_length.offset..][0..4],
1071 @intCast(func_length),1125 @intCast(func_length),
1072 dwarf.endian,1126 dwarf.endian,
1073 ),1127 ),
1074 .debug_frame => switch (dwarf.address_size) {1128 .@"64" => std.mem.writeInt(
1075 _ => unreachable,1129 u64,
1076 .@"32" => std.mem.writeInt(1130 dfw.buffered()[wip_nav.frame_func_length.offset..][0..8],
1077 u32,1131 func_length,
1078 fde[wip_nav.frame_func_length_offset..][0..4],1132 dwarf.endian,
1079 @intCast(func_length),1133 ),
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 },
1089 }1134 }
1135 @memset(dfw.unusedCapacitySlice(), DW.CFA.nop);
1090 }1136 }
10911137
1092 const ExprLocCounter = struct {1138 const ExprLocCounter = struct {
...@@ -1119,26 +1165,10 @@ pub const WipNav = struct {...@@ -1119,26 +1165,10 @@ pub const WipNav = struct {
11191165
1120 fn frameSectionOffset(1166 fn frameSectionOffset(
1121 wip_nav: *WipNav,1167 wip_nav: *WipNav,
1122 target: MappedFile.Node.Index,1168 target_ni: MappedFile.Node.Index,
1123 addend: i64,1169 addend: usize,
1124 ) link.EmitError!void {1170 ) link.EmitError!void {
1125 const dwarf = wip_nav.dwarf;1171 try wip_nav.dwarf.sectionOffset(&wip_nav.fde_writer, target_ni, addend);
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 );
1142 }1172 }
11431173
1144 fn frameExprLoc(wip_nav: *WipNav, loc: Loc) link.EmitError!void {1174 fn frameExprLoc(wip_nav: *WipNav, loc: Loc) link.EmitError!void {
...@@ -1174,7 +1204,7 @@ pub const WipNav = struct {...@@ -1174,7 +1204,7 @@ pub const WipNav = struct {
1174 const dfw = &wip_nav.fde_writer.interface;1204 const dfw = &wip_nav.fde_writer.interface;
1175 const offset = dfw.end;1205 const offset = dfw.end;
1176 try dfw.splatByteAll(0, @backingInt(dwarf.address_size));1206 try dfw.splatByteAll(0, @backingInt(dwarf.address_size));
1177 const elf = dwarf.linkFile().cast(.elf2).?;1207 const elf = dwarf.lf.cast(.elf2).?;
1178 try elf.addReloc(1208 try elf.addReloc(
1179 @bitCast(wip_nav.fde_writer.ni),1209 @bitCast(wip_nav.fde_writer.ni),
1180 offset,1210 offset,
...@@ -1190,7 +1220,7 @@ pub const WipNav = struct {...@@ -1190,7 +1220,7 @@ pub const WipNav = struct {
1190 fn reportWriteError(wip_nav: *WipNav, mfnw: *const MappedFile.Node.Writer) link.Error {1220 fn reportWriteError(wip_nav: *WipNav, mfnw: *const MappedFile.Node.Writer) link.Error {
1191 switch (mfnw.err.?) {1221 switch (mfnw.err.?) {
1192 else => |e| return e,1222 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(
1194 "failed to write output file: {t}",1224 "failed to write output file: {t}",
1195 .{mfnw.mf.io_err.?},1225 .{mfnw.mf.io_err.?},
1196 ),1226 ),
...@@ -1199,10 +1229,9 @@ pub const WipNav = struct {...@@ -1199,10 +1229,9 @@ pub const WipNav = struct {
1199};1229};
12001230
1201pub fn init(lf: *link.File, format: DW.Format) Dwarf {1231pub fn init(lf: *link.File, format: DW.Format) Dwarf {
1202 const comp = lf.comp;1232 const target = &lf.comp.root_mod.resolved_target.result;
1203 const target = &comp.root_mod.resolved_target.result;
1204 return .{1233 return .{
1205 .tag = lf.tag,1234 .lf = lf,
1206 .format = format,1235 .format = format,
1207 .address_size = switch (target.ptrBitWidth()) {1236 .address_size = switch (target.ptrBitWidth()) {
1208 0...32 => .@"32",1237 0...32 => .@"32",
...@@ -1216,9 +1245,32 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {...@@ -1216,9 +1245,32 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {
1216 .globals = .empty,1245 .globals = .empty,
1217 .funcs = .empty,1246 .funcs = .empty,
12181247
1219 .debug_info = .{1248 .debug_abbrev = .{
1220 .section_index = .none,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 },
1221 },1272 },
1273 .debug_info = .{},
1222 .debug_line = .{1274 .debug_line = .{
1223 .header = switch (target.cpu.arch) {1275 .header = switch (target.cpu.arch) {
1224 .x86_64, .aarch64 => .{1276 .x86_64, .aarch64 => .{
...@@ -1238,55 +1290,46 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {...@@ -1238,55 +1290,46 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {
1238 .opcode_base = DW.LNS.set_isa + 1,1290 .opcode_base = DW.LNS.set_isa + 1,
1239 },1291 },
1240 },1292 },
1241 .section_index = .none,
1242 },1293 },
1243 .frame = .{1294 .debug_line_str = .{
1244 .header = if (target.cpu.arch == .x86_64 and target.ofmt == .elf) header: {1295 .ni = .none,
1245 dev.check(.x86_64_backend);1296 .offset = 0,
1246 const Register = @import("../codegen/x86_64/bits.zig").Register;1297 .map = .empty,
1247 break :header comptime .{1298 },
1248 .code_alignment_factor = 1,1299 .debug_str = .{
1249 .data_alignment_factor = -8,1300 .ni = .none,
1250 .return_address_register = Register.rip.dwarfNum(),1301 .offset = 0,
1251 .initial_instructions = &.{1302 .map = .empty,
1252 .{ .def_cfa = .{ .reg = Register.rsp.dwarfNum(), .off = 8 } },1303 },
1253 .{ .offset = .{ .reg = Register.rip.dwarfNum(), .off = -8 } },1304 .debug_str_offsets = .{
1254 },1305 .ni = .none,
1255 };1306 .offset = 0,
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,
1263 },1307 },
1264 };1308 };
1265}1309}
12661310
1267pub fn deinit(dwarf: *Dwarf, gpa: Allocator) void {1311pub fn deinit(dwarf: *Dwarf) void {
1312 const gpa = dwarf.lf.comp.gpa;
1268 dwarf.const_pool.deinit(gpa);1313 dwarf.const_pool.deinit(gpa);
1269 dwarf.units.deinit(gpa);1314 dwarf.units.deinit(gpa);
1270 dwarf.values.deinit(gpa);1315 dwarf.values.deinit(gpa);
1271 dwarf.globals.deinit(gpa);1316 dwarf.globals.deinit(gpa);
1272 dwarf.funcs.deinit(gpa);1317 dwarf.funcs.deinit(gpa);
1318 dwarf.debug_str.map.deinit(gpa);
1273 dwarf.* = undefined;1319 dwarf.* = undefined;
1274}1320}
12751321
1276fn linkFile(dwarf: *Dwarf) *link.File {1322pub fn initUnits(dwarf: *Dwarf, zcu: *Zcu) std.mem.Allocator.Error!void {
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 {
1284 try dwarf.units.ensureTotalCapacity(zcu.gpa, zcu.module_roots.count());1323 try dwarf.units.ensureTotalCapacity(zcu.gpa, zcu.module_roots.count());
1285 for (zcu.module_roots.keys(), zcu.module_roots.values()) |mod, root| switch (root) {1324 for (zcu.module_roots.keys(), zcu.module_roots.values()) |mod, root| switch (root) {
1286 .none => {},1325 .none => {},
1287 else => dwarf.units.putAssumeCapacityNoClobber(mod, .{1326 else => dwarf.units.putAssumeCapacityNoClobber(mod, .{
1288 .frame_ni = .none,1327 .frame_ni = .none,
1289 .cie_ni = .none,1328 .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,
1290 }),1333 }),
1291 };1334 };
1292}1335}
...@@ -1308,8 +1351,8 @@ pub fn getUnit(dwarf: *Dwarf, mod: *Module) Unit.Index {...@@ -1308,8 +1351,8 @@ pub fn getUnit(dwarf: *Dwarf, mod: *Module) Unit.Index {
1308 return @fromBackingInt(@intCast(dwarf.units.getIndex(mod).?));1351 return @fromBackingInt(@intCast(dwarf.units.getIndex(mod).?));
1309}1352}
13101353
1311pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) Allocator.Error!Func.Index {1354pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) std.mem.Allocator.Error!Func.Index {
1312 const func_gop = try dwarf.funcs.getOrPut(dwarf.linkFile().comp.gpa, owner_nav);1355 const func_gop = try dwarf.funcs.getOrPut(dwarf.lf.comp.gpa, owner_nav);
1313 if (!func_gop.found_existing) func_gop.value_ptr.* = .{1356 if (!func_gop.found_existing) func_gop.value_ptr.* = .{
1314 .fde_ni = .none,1357 .fde_ni = .none,
1315 .debug_info_ni = .none,1358 .debug_info_ni = .none,
...@@ -1318,6 +1361,21 @@ pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) Allocator.Error!F...@@ -1318,6 +1361,21 @@ pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) Allocator.Error!F
1318 return @fromBackingInt(@intCast(func_gop.index));1361 return @fromBackingInt(@intCast(func_gop.index));
1319}1362}
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}
1321pub fn updateUnitLength(dwarf: *Dwarf, header: []u8, unit_length: u64) void {1379pub fn updateUnitLength(dwarf: *Dwarf, header: []u8, unit_length: u64) void {
1322 switch (dwarf.format) {1380 switch (dwarf.format) {
1323 .@"32" => std.mem.writeInt(u32, header[0..4], @intCast(unit_length - 4), dwarf.endian),1381 .@"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 {...@@ -1325,6 +1383,11 @@ pub fn updateUnitLength(dwarf: *Dwarf, header: []u8, unit_length: u64) void {
1325 }1383 }
1326}1384}
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
1328pub const EhFrameHdr = extern struct {1391pub const EhFrameHdr = extern struct {
1329 version: u8,1392 version: u8,
1330 eh_frame_ptr_enc: std.dwarf.EH.PE,1393 eh_frame_ptr_enc: std.dwarf.EH.PE,
...@@ -1345,7 +1408,7 @@ pub fn genEhFrameHdr(...@@ -1345,7 +1408,7 @@ pub fn genEhFrameHdr(
1345 .table_enc = .omit,1408 .table_enc = .omit,
1346 .eh_frame_ptr = undefined,1409 .eh_frame_ptr = undefined,
1347 };1410 };
1348 const elf = dwarf.linkFile().cast(.elf2).?;1411 const elf = dwarf.lf.cast(.elf2).?;
1349 try elf.addReloc(1412 try elf.addReloc(
1350 eh_frame_hdr_ai,1413 eh_frame_hdr_ai,
1351 @offsetOf(EhFrameHdr, "eh_frame_ptr"),1414 @offsetOf(EhFrameHdr, "eh_frame_ptr"),
...@@ -1357,26 +1420,20 @@ pub fn genEhFrameHdr(...@@ -1357,26 +1420,20 @@ pub fn genEhFrameHdr(
13571420
1358pub fn genDebugFrameCie(1421pub fn genDebugFrameCie(
1359 dwarf: *Dwarf,1422 dwarf: *Dwarf,
1360 w: *Writer,1423 dfw: *Writer,
1361 /// `null` means to generate an architecture-agnostic padding cie1424 /// `null` means to generate an architecture-agnostic padding cie
1362 arch: ?std.Target.Cpu.Arch,1425 arch: ?std.Target.Cpu.Arch,
1363 format: Frame.Format,1426 format: Frame.Format,
1364) Writer.Error!void {1427) Writer.Error!void {
1365 switch (dwarf.format) {1428 try dwarf.genUnitLength(dfw);
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 }
1372 switch (format) {1429 switch (format) {
1373 .eh_frame => try w.writeInt(u32, 0, dwarf.endian),1430 .eh_frame => try dfw.writeInt(u32, 0, dwarf.endian),
1374 .debug_frame => switch (dwarf.format) {1431 .debug_frame => switch (dwarf.format) {
1375 .@"32" => try w.writeInt(u32, std.math.maxInt(u32), dwarf.endian),1432 .@"32" => try dfw.writeInt(u32, std.math.maxInt(u32), dwarf.endian),
1376 .@"64" => try w.writeInt(u64, std.math.maxInt(u64), dwarf.endian),1433 .@"64" => try dfw.writeInt(u64, std.math.maxInt(u64), dwarf.endian),
1377 },1434 },
1378 }1435 }
1379 try w.writeByte(if (arch) |_| switch (format) {1436 try dfw.writeByte(if (arch) |_| switch (format) {
1380 .eh_frame => 1,1437 .eh_frame => 1,
1381 .debug_frame => 4,1438 .debug_frame => 4,
1382 } else 0);1439 } else 0);
...@@ -1386,40 +1443,38 @@ pub fn genDebugFrameCie(...@@ -1386,40 +1443,38 @@ pub fn genDebugFrameCie(
1386 dev.check(.x86_64_backend);1443 dev.check(.x86_64_backend);
1387 const Register = @import("../codegen/x86_64/bits.zig").Register;1444 const Register = @import("../codegen/x86_64/bits.zig").Register;
1388 switch (format) {1445 switch (format) {
1389 .eh_frame => try w.writeAll("zR\x00"),1446 .eh_frame => try dfw.writeAll("zR\x00"),
1390 .debug_frame => {1447 .debug_frame => {
1391 try w.writeAll("\x00");1448 try dfw.writeAll("\x00");
1392 try w.writeByte(@backingInt(dwarf.address_size));1449 try dfw.writeByte(@backingInt(dwarf.address_size));
1393 try w.writeByte(0);1450 try dfw.writeByte(0);
1394 },1451 },
1395 }1452 }
1396 try w.writeUleb128(dwarf.frame.header.code_alignment_factor);1453 try dfw.writeUleb128(dwarf.frame.header.code_alignment_factor);
1397 try w.writeSleb128(dwarf.frame.header.data_alignment_factor);1454 try dfw.writeSleb128(dwarf.frame.header.data_alignment_factor);
1398 switch (format) {1455 switch (format) {
1399 .eh_frame => try w.writeByte(@intCast(dwarf.frame.header.return_address_register)),1456 .eh_frame => try dfw.writeByte(@intCast(dwarf.frame.header.return_address_register)),
1400 .debug_frame => try w.writeUleb128(dwarf.frame.header.return_address_register),1457 .debug_frame => try dfw.writeUleb128(dwarf.frame.header.return_address_register),
1401 }1458 }
1402 switch (format) {1459 switch (format) {
1403 .eh_frame => {1460 .eh_frame => {
1404 try w.writeUleb128(1);1461 try dfw.writeUleb128(1);
1405 try w.writeByte(@bitCast(@as(DW.EH.PE, .{ .type = .sdata4, .rel = .pcrel })));1462 try dfw.writeByte(@bitCast(@as(DW.EH.PE, .{ .type = .sdata4, .rel = .pcrel })));
1406 },1463 },
1407 .debug_frame => {},1464 .debug_frame => {},
1408 }1465 }
1409 try w.writeByte(DW.CFA.def_cfa_sf);1466 try dfw.writeByte(DW.CFA.def_cfa_sf);
1410 try w.writeUleb128(Register.rsp.dwarfNum());1467 try dfw.writeUleb128(Register.rsp.dwarfNum());
1411 try w.writeSleb128(-1);1468 try dfw.writeSleb128(-1);
1412 try w.writeByte(@as(u8, DW.CFA.offset) + Register.rip.dwarfNum());1469 try dfw.writeByte(@as(u8, DW.CFA.offset) + Register.rip.dwarfNum());
1413 try w.writeUleb128(1);1470 try dfw.writeUleb128(1);
1414 },1471 },
1415 }1472 }
1473 @memset(dfw.unusedCapacitySlice(), DW.CFA.nop);
1416}1474}
14171475
1418pub fn updateEhFrameFde(dwarf: *Dwarf, fde: []u8, fde_offset: u64) void {1476pub fn updateEhFrameFde(dwarf: *Dwarf, fde: []u8, fde_offset: u64) void {
1419 const cie_pointer_offset: usize = switch (dwarf.format) {1477 const cie_pointer_offset = dwarf.unitLengthSize();
1420 .@"32" => 4,
1421 .@"64" => 12,
1422 };
1423 std.mem.writeInt(1478 std.mem.writeInt(
1424 u32,1479 u32,
1425 fde[cie_pointer_offset..][0..4],1480 fde[cie_pointer_offset..][0..4],
...@@ -1428,27 +1483,182 @@ pub fn updateEhFrameFde(dwarf: *Dwarf, fde: []u8, fde_offset: u64) void {...@@ -1428,27 +1483,182 @@ pub fn updateEhFrameFde(dwarf: *Dwarf, fde: []u8, fde_offset: u64) void {
1428 );1483 );
1429}1484}
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
1431fn refAbbrevCode(1605fn refAbbrevCode(
1432 dwarf: *Dwarf,1606 dwarf: *Dwarf,
1433 abbrev_code: AbbrevCode,1607 abbrev_code: AbbrevCode,
1434) link.EmitError!@typeInfo(AbbrevCode).@"enum".tag_type {1608) link.EmitError!@typeInfo(AbbrevCode).@"enum".tag_type {
1435 if (true) @panic("TODO");1609 if (dwarf.refAbbrevCodeIfExists(abbrev_code)) |backing_int| {
1436 const Entry = {};1610 @branchHint(.likely);
1437 const DebugAbbrev = {};1611 return backing_int;
1438 assert(abbrev_code != .null);1612 }
1439 const entry: Entry.Index = @fromBackingInt(@intCast(@backingInt(abbrev_code)));1613 const elf = dwarf.lf.cast(.elf2).?;
1440 if (dwarf.debug_abbrev.section.getUnit(DebugAbbrev.unit).getEntry(entry).len > 0) return @backingInt(abbrev_code);1614 var nw: MappedFile.Node.Writer = undefined;
1441 var debug_abbrev_aw: Writer.Allocating = .init(dwarf.gpa);1615 dwarf.debug_abbrev.ni.unwrap().?.writer(&elf.mf, elf.base.comp.gpa, &nw);
1442 defer debug_abbrev_aw.deinit();1616 defer nw.deinit();
1443 const daw = &debug_abbrev_aw.writer;
1444 const abbrev = AbbrevCode.abbrevs.get(abbrev_code);1617 const abbrev = AbbrevCode.abbrevs.get(abbrev_code);
1618 const daw = &nw.interface;
1619 daw.end = dwarf.debug_abbrev.offset;
1445 try daw.writeUleb128(@backingInt(abbrev_code));1620 try daw.writeUleb128(@backingInt(abbrev_code));
1446 try daw.writeUleb128(@backingInt(abbrev.tag));1621 try daw.writeUleb128(@backingInt(abbrev.tag));
1447 try daw.writeByte(if (abbrev.children) DW.CHILDREN.yes else DW.CHILDREN.no);1622 try daw.writeByte(if (abbrev.children) DW.CHILDREN.yes else DW.CHILDREN.no);
1448 for (abbrev.attrs) |*attr| inline for (attr) |info| try daw.writeUleb128(@backingInt(info));1623 for (abbrev.attrs) |*attr| inline for (attr) |info| try daw.writeUleb128(@backingInt(info));
1449 for (0..2) |_| try daw.writeUleb128(0);1624 for (0..2) |_| try daw.writeUleb128(0);
1450 try dwarf.debug_abbrev.section.replaceEntry(DebugAbbrev.unit, entry, dwarf, debug_abbrev_aw.written());1625 dwarf.debug_abbrev.offset = daw.end;
1451 return @backingInt(abbrev_code);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 });
1452}1662}
14531663
1454fn DeclValEnum(comptime T: type) type {1664fn DeclValEnum(comptime T: type) type {
...@@ -1473,7 +1683,7 @@ fn DeclValEnum(comptime T: type) type {...@@ -1473,7 +1683,7 @@ fn DeclValEnum(comptime T: type) type {
1473 return @Enum(TagInt, .exhaustive, field_names[0..fields_len], &field_vals);1683 return @Enum(TagInt, .exhaustive, field_names[0..fields_len], &field_vals);
1474}1684}
14751685
1476const AbbrevCode = enum {1686pub const AbbrevCode = enum {
1477 null,1687 null,
1478 // padding codes must be one byte uleb128 values to function1688 // padding codes must be one byte uleb128 values to function
1479 pad_1,1689 pad_1,
...@@ -1524,6 +1734,7 @@ const AbbrevCode = enum {...@@ -1524,6 +1734,7 @@ const AbbrevCode = enum {
1524 // than the non-empty variant, and so should appear first1734 // than the non-empty variant, and so should appear first
1525 compile_unit,1735 compile_unit,
1526 module,1736 module,
1737 module_dependency,
1527 empty_file,1738 empty_file,
1528 file,1739 file,
1529 access,1740 access,
...@@ -1765,14 +1976,14 @@ const AbbrevCode = enum {...@@ -1765,14 +1976,14 @@ const AbbrevCode = enum {
1765 .decl_func = .{1976 .decl_func = .{
1766 .tag = .subprogram,1977 .tag = .subprogram,
1767 .children = true,1978 .children = true,
1768 .attrs = decl_abbrev_common_attrs ++ .{1979 .attrs = decl_abbrev_common_attrs[4..] ++ .{
1769 .{ .linkage_name, .strp },1980 .{ .linkage_name, .strp },
1770 .{ .type, .ref_addr },1981 //.{ .type, .ref_addr },
1771 .{ .low_pc, .addr },1982 //.{ .low_pc, .addr },
1772 .{ .high_pc, .data4 },1983 //.{ .high_pc, .data4 },
1773 .{ .alignment, .udata },1984 //.{ .alignment, .udata },
1774 .{ .external, .flag },1985 //.{ .external, .flag },
1775 .{ .noreturn, .flag },1986 //.{ .noreturn, .flag },
1776 },1987 },
1777 },1988 },
1778 .decl_nullary_func_generic = .{1989 .decl_nullary_func_generic = .{
...@@ -1989,14 +2200,15 @@ const AbbrevCode = enum {...@@ -1989,14 +2200,15 @@ const AbbrevCode = enum {
1989 .tag = .compile_unit,2200 .tag = .compile_unit,
1990 .children = true,2201 .children = true,
1991 .attrs = &.{2202 .attrs = &.{
2203 .{ .producer, .strp },
1992 .{ .language, .data1 },2204 .{ .language, .data1 },
1993 .{ .producer, .line_strp },
1994 .{ .comp_dir, .line_strp },2205 .{ .comp_dir, .line_strp },
1995 .{ .name, .line_strp },2206 .{ .name, .line_strp },
1996 .{ .base_types, .ref_addr },2207 .{ .base_types, .ref_addr },
1997 .{ .stmt_list, .sec_offset },2208 .{ .stmt_list, .sec_offset },
1998 .{ .rnglists_base, .sec_offset },2209 //.{ .rnglists_base, .sec_offset },
1999 .{ .ranges, .rnglistx },2210 //.{ .ranges, .rnglistx },
2211 .{ .use_UTF8, .flag_present },
2000 },2212 },
2001 },2213 },
2002 .module = .{2214 .module = .{
...@@ -2004,7 +2216,14 @@ const AbbrevCode = enum {...@@ -2004,7 +2216,14 @@ const AbbrevCode = enum {
2004 .children = true,2216 .children = true,
2005 .attrs = &.{2217 .attrs = &.{
2006 .{ .name, .strp },2218 .{ .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 },
2008 },2227 },
2009 },2228 },
2010 .empty_file = .{2229 .empty_file = .{
...@@ -2662,23 +2881,23 @@ const AbbrevCode = enum {...@@ -2662,23 +2881,23 @@ const AbbrevCode = enum {
2662 });2881 });
2663};2882};
26642883
2665fn uleb128Bytes(value: anytype) u32 {2884pub fn uleb128Bytes(value: anytype) u32 {
2666 var buf: [64]u8 = undefined;2885 var buf: [64]u8 = undefined;
2667 var dw: Writer.Discarding = .init(&buf);2886 var dw: Writer.Discarding = .init(&buf);
2668 dw.writer.writeUleb128(value) catch unreachable;2887 dw.writer.writeUleb128(value) catch unreachable;
2669 return @intCast(dw.fullCount());2888 return @intCast(dw.fullCount());
2670}2889}
26712890
2672fn sleb128Bytes(value: anytype) u32 {2891pub fn sleb128Bytes(value: anytype) u32 {
2673 var buf: [64]u8 = undefined;2892 var buf: [64]u8 = undefined;
2674 var dw: Writer.Discarding = .init(&buf);2893 var dw: Writer.Discarding = .init(&buf);
2675 dw.writer.writeSleb128(value) catch unreachable;2894 dw.writer.writeSleb128(value) catch unreachable;
2676 return @intCast(dw.fullCount());2895 return @intCast(dw.fullCount());
2677}2896}
26782897
2679const Allocator = std.mem.Allocator;
2680const assert = std.debug.assert;2898const assert = std.debug.assert;
2681const codegen = @import("../codegen.zig");2899const codegen = @import("../codegen.zig");
2900const Compilation = @import("../Compilation.zig");
2682const dev = @import("../dev.zig");2901const dev = @import("../dev.zig");
2683const DW = std.dwarf;2902const DW = std.dwarf;
2684const Dwarf = @This();2903const Dwarf = @This();
src/link/Elf2.zig+635-223
...@@ -42,11 +42,15 @@ shndx: struct {...@@ -42,11 +42,15 @@ shndx: struct {
42 tdata: Section.Index,42 tdata: Section.Index,
43 rela_dyn: Section.Index,43 rela_dyn: Section.Index,
44 rela_plt: Section.Index,44 rela_plt: Section.Index,
45 debug_abbrev: Section.Index,
45 eh_frame_hdr: Section.Index,46 eh_frame_hdr: Section.Index,
46 eh_frame: Section.Index,47 eh_frame: Section.Index,
47 debug_frame: Section.Index,48 debug_frame: Section.Index,
48 debug_info: Section.Index,49 debug_info: Section.Index,
49 debug_line: Section.Index,50 debug_line: Section.Index,
51 debug_line_str: Section.Index,
52 debug_str: Section.Index,
53 debug_str_offsets: Section.Index,
50 // These sections are created only as needed, and are initially `.UNDEF`.54 // These sections are created only as needed, and are initially `.UNDEF`.
51 init_array: Section.Index,55 init_array: Section.Index,
52 fini_array: Section.Index,56 fini_array: Section.Index,
...@@ -199,14 +203,34 @@ changed_symtab_index: std.array_hash_map.Auto(String(.strtab), void),...@@ -199,14 +203,34 @@ changed_symtab_index: std.array_hash_map.Auto(String(.strtab), void),
199textrel_count: u32,203textrel_count: u32,
200204
201dwarf: Dwarf,205dwarf: Dwarf,
206dwarf_shared: std.enums.EnumArray(Dwarf.SharedSection, struct {
207 first_target_reloc: NodeReloc.Index,
208}),
202dwarf_units: std.ArrayList(struct {209dwarf_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,
204}),225}),
205dwarf_values: std.ArrayList(struct {}),
206dwarf_globals: std.ArrayList(struct {}),
207dwarf_funcs: std.ArrayList(struct {226dwarf_funcs: std.ArrayList(struct {
208 func_frame_fde_first_symbol_reloc: SymbolReloc.Index,227 frame_fde_first_symbol_reloc: SymbolReloc.Index,
209 func_frame_fde_first_node_reloc: NodeReloc.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,
210}),234}),
211235
212overflowed_reloc_count: u32,236overflowed_reloc_count: u32,
...@@ -272,11 +296,17 @@ const Node = union(enum) {...@@ -272,11 +296,17 @@ const Node = union(enum) {
272 /// May contain relocations.296 /// May contain relocations.
273 lazy_const_data: LazyMapRef.Index(.const_data),297 lazy_const_data: LazyMapRef.Index(.const_data),
274298
275 value_debug_info: link.ConstPool.Index,299 debug_shared: Dwarf.SharedSection,
276 global_debug_info: Dwarf.Global.Index,300 unit_padding,
277 frame_padding,
278 unit_frame: Dwarf.Unit.Index,301 unit_frame: Dwarf.Unit.Index,
279 unit_frame_cie: Dwarf.Unit.Index,302 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,
280 func_frame_fde: Dwarf.Func.Index,310 func_frame_fde: Dwarf.Func.Index,
281 func_debug_info: Dwarf.Func.Index,311 func_debug_info: Dwarf.Func.Index,
282 func_debug_line: Dwarf.Func.Index,312 func_debug_line: Dwarf.Func.Index,
...@@ -1778,7 +1808,9 @@ const NodeReloc = struct {...@@ -1778,7 +1808,9 @@ const NodeReloc = struct {
1778 .none => {1808 .none => {
1779 const first_target_reloc = switch (elf.getNode(reloc.target)) {1809 const first_target_reloc = switch (elf.getNode(reloc.target)) {
1780 else => unreachable,1810 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,
1782 };1814 };
1783 first_target_reloc.* = reloc.next;1815 first_target_reloc.* = reloc.next;
1784 },1816 },
...@@ -3218,11 +3250,16 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {...@@ -3218,11 +3250,16 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {
3218 .section_manual_size,3250 .section_manual_size,
3219 .input_section,3251 .input_section,
3220 .copied_global,3252 .copied_global,
3221 .value_debug_info,3253 .debug_shared,
3222 .global_debug_info,3254 .unit_padding,
3223 .frame_padding,
3224 .unit_frame,3255 .unit_frame,
3225 .unit_frame_cie,3256 .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,
3226 .func_frame_fde,3263 .func_frame_fde,
3227 .func_debug_info,3264 .func_debug_info,
3228 .func_debug_line,3265 .func_debug_line,
...@@ -3661,11 +3698,15 @@ fn create(...@@ -3661,11 +3698,15 @@ fn create(
3661 .tdata = .UNDEF,3698 .tdata = .UNDEF,
3662 .rela_dyn = .UNDEF,3699 .rela_dyn = .UNDEF,
3663 .rela_plt = .UNDEF,3700 .rela_plt = .UNDEF,
3701 .debug_abbrev = .UNDEF,
3664 .eh_frame_hdr = .UNDEF,3702 .eh_frame_hdr = .UNDEF,
3665 .eh_frame = .UNDEF,3703 .eh_frame = .UNDEF,
3666 .debug_frame = .UNDEF,3704 .debug_frame = .UNDEF,
3667 .debug_info = .UNDEF,3705 .debug_info = .UNDEF,
3668 .debug_line = .UNDEF,3706 .debug_line = .UNDEF,
3707 .debug_line_str = .UNDEF,
3708 .debug_str = .UNDEF,
3709 .debug_str_offsets = .UNDEF,
3669 .init_array = .UNDEF,3710 .init_array = .UNDEF,
3670 .fini_array = .UNDEF,3711 .fini_array = .UNDEF,
3671 .preinit_array = .UNDEF,3712 .preinit_array = .UNDEF,
...@@ -3720,6 +3761,9 @@ fn create(...@@ -3720,6 +3761,9 @@ fn create(
3720 .dwarf => |v| v,3761 .dwarf => |v| v,
3721 .code_view => unreachable,3762 .code_view => unreachable,
3722 }),3763 }),
3764 .dwarf_shared = .initFill(.{
3765 .first_target_reloc = .none,
3766 }),
3723 .dwarf_units = .empty,3767 .dwarf_units = .empty,
3724 .dwarf_values = .empty,3768 .dwarf_values = .empty,
3725 .dwarf_globals = .empty,3769 .dwarf_globals = .empty,
...@@ -3774,7 +3818,7 @@ pub fn deinit(elf: *Elf) void {...@@ -3774,7 +3818,7 @@ pub fn deinit(elf: *Elf) void {
3774 elf.section_by_name.deinit(gpa);3818 elf.section_by_name.deinit(gpa);
3775 elf.changed_symtab_index.deinit(gpa);3819 elf.changed_symtab_index.deinit(gpa);
37763820
3777 elf.dwarf.deinit(gpa);3821 elf.dwarf.deinit();
3778 elf.dwarf_units.deinit(gpa);3822 elf.dwarf_units.deinit(gpa);
3779 elf.dwarf_values.deinit(gpa);3823 elf.dwarf_values.deinit(gpa);
3780 elf.dwarf_globals.deinit(gpa);3824 elf.dwarf_globals.deinit(gpa);
...@@ -3851,9 +3895,13 @@ fn initHeaders(...@@ -3851,9 +3895,13 @@ fn initHeaders(
3851 switch (comp.config.debug_format) {3895 switch (comp.config.debug_format) {
3852 .strip => {},3896 .strip => {},
3853 .dwarf => {3897 .dwarf => {
3898 shnum += 1; // .debug_abbrev
3854 shnum += @intFromBool(have_debug_frame); // .debug_frame3899 shnum += @intFromBool(have_debug_frame); // .debug_frame
3855 shnum += 1; // .debug_info3900 shnum += 1; // .debug_info
3856 shnum += 1; // .debug_line3901 shnum += 1; // .debug_line
3902 shnum += 1; // .debug_line_str
3903 shnum += 1; // .debug_str
3904 shnum += 1; // .debug_str_offsets
3857 },3905 },
3858 .code_view => unreachable,3906 .code_view => unreachable,
3859 }3907 }
...@@ -4942,6 +4990,7 @@ fn initHeaders(...@@ -4942,6 +4990,7 @@ fn initHeaders(
4942 switch (comp.config.debug_format) {4990 switch (comp.config.debug_format) {
4943 .strip => {},4991 .strip => {},
4944 .dwarf => {4992 .dwarf => {
4993 elf.shndx.debug_abbrev = try elf.addSection(elf.ni.elf, .{ .name = ".debug_abbrev" });
4945 if (have_debug_frame) elf.shndx.debug_frame = try elf.addSection(elf.ni.elf, .{4994 if (have_debug_frame) elf.shndx.debug_frame = try elf.addSection(elf.ni.elf, .{
4946 .name = ".debug_frame",4995 .name = ".debug_frame",
4947 .addralign = addr_align,4996 .addralign = addr_align,
...@@ -4955,6 +5004,17 @@ fn initHeaders(...@@ -4955,6 +5004,17 @@ fn initHeaders(
4955 .name = ".debug_line",5004 .name = ".debug_line",
4956 .node_align = elf.mf.flags.block_size,5005 .node_align = elf.mf.flags.block_size,
4957 });5006 });
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 });
4958 },5018 },
4959 .code_view => unreachable,5019 .code_view => unreachable,
4960 }5020 }
...@@ -5045,11 +5105,6 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {...@@ -5045,11 +5105,6 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
5045 .ehdr,5105 .ehdr,
5046 .shdr,5106 .shdr,
5047 .segment,5107 .segment,
5048 .value_debug_info,
5049 .global_debug_info,
5050 .frame_padding,
5051 .func_debug_info,
5052 .func_debug_line,
5053 => unreachable,5108 => unreachable,
5054 .section, .section_manual_size => |shndx| shndx,5109 .section, .section_manual_size => |shndx| shndx,
5055 .input_section,5110 .input_section,
...@@ -5058,13 +5113,21 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {...@@ -5058,13 +5113,21 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
5058 .uav,5113 .uav,
5059 .lazy_code,5114 .lazy_code,
5060 .lazy_const_data,5115 .lazy_const_data,
5116 .debug_shared,
5117 .unit_padding,
5061 .unit_frame,5118 .unit_frame,
5119 .unit_debug_info,
5120 .unit_debug_line,
5062 => elf.getNode(ni.parent(&elf.mf).unwrap().?).section,5121 => elf.getNode(ni.parent(&elf.mf).unwrap().?).section,
5063 .unit_frame_cie, .func_frame_fde => {5122 .unit_frame_cie,
5064 const unit_frame_ni = ni.parent(&elf.mf).unwrap().?;5123 .unit_debug_info_header,
5065 assert(elf.getNode(unit_frame_ni) == .unit_frame);5124 .unit_debug_line_header,
5066 return elf.getNode(unit_frame_ni.parent(&elf.mf).unwrap().?).section;5125 .value_debug_info,
5067 },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,
5068 };5131 };
5069}5132}
5070fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {5133fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
...@@ -5078,11 +5141,6 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {...@@ -5078,11 +5141,6 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
5078 .shdr,5141 .shdr,
5079 .segment,5142 .segment,
5080 .copied_global,5143 .copied_global,
5081 .value_debug_info,
5082 .global_debug_info,
5083 .frame_padding,
5084 .func_debug_info,
5085 .func_debug_line,
5086 => unreachable,5144 => unreachable,
5087 .section, .section_manual_size => |shndx| shndx.vaddr(elf),5145 .section, .section_manual_size => |shndx| shndx.vaddr(elf),
5088 .input_section => |isi| isi.ptrConst(elf).vaddr,5146 .input_section => |isi| isi.ptrConst(elf).vaddr,
...@@ -5091,7 +5149,20 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {...@@ -5091,7 +5149,20 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
5091 .lazy_code,5149 .lazy_code,
5092 .lazy_const_data,5150 .lazy_const_data,
5093 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),5151 => |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),
5095 };5166 };
5096}5167}
5097fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {5168fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
...@@ -5110,16 +5181,17 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {...@@ -5110,16 +5181,17 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
5110 .lazy_code,5181 .lazy_code,
5111 .lazy_const_data,5182 .lazy_const_data,
5112 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),5183 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
5113 .value_debug_info,5184 .debug_shared, .unit_padding => unreachable,
5114 .global_debug_info,5185 .unit_frame, .unit_debug_info, .unit_debug_line => {
5115 .frame_padding,
5116 => unreachable,
5117 .unit_frame => {
5118 const section_ni = parent_ni.parent(&elf.mf).unwrap().?;5186 const section_ni = parent_ni.parent(&elf.mf).unwrap().?;
5119 const section_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);5187 const section_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);
5120 break :parent_vaddr elf.getNode(section_ni).section.vaddr(elf) + section_offset;5188 break :parent_vaddr elf.getNode(section_ni).section.vaddr(elf) + section_offset;
5121 },5189 },
5122 .unit_frame_cie,5190 .unit_frame_cie,
5191 .unit_debug_info_header,
5192 .unit_debug_line_header,
5193 .value_debug_info,
5194 .global_debug_info,
5123 .func_frame_fde,5195 .func_frame_fde,
5124 .func_debug_info,5196 .func_debug_info,
5125 .func_debug_line,5197 .func_debug_line,
...@@ -5138,7 +5210,7 @@ fn getNodeElfOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 {...@@ -5138,7 +5210,7 @@ fn getNodeElfOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 {
5138/// Asserts that `ni` must be a node which supports relocations (see `Elf.Node`). Does not support5210/// Asserts that `ni` must be a node which supports relocations (see `Elf.Node`). Does not support
5139/// the special-case sections '.plt', '.dynamic', and '.eh_frame_hdr'.5211/// the special-case sections '.plt', '.dynamic', and '.eh_frame_hdr'.
5140fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {5212fn 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)) {
5142 .archive,5214 .archive,
5143 .archive_header,5215 .archive_header,
5144 .archive_input_member,5216 .archive_input_member,
...@@ -5148,13 +5220,12 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {...@@ -5148,13 +5220,12 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
5148 .shdr,5220 .shdr,
5149 .segment,5221 .segment,
5150 .copied_global,5222 .copied_global,
5151 .value_debug_info,5223 .debug_shared,
5152 .global_debug_info,5224 .unit_padding,
5153 .frame_padding,
5154 .unit_frame,5225 .unit_frame,
5155 .unit_frame_cie,5226 .unit_frame_cie,
5156 .func_debug_info,5227 .unit_debug_info,
5157 .func_debug_line,5228 .unit_debug_line,
5158 => unreachable, // cannot contain relocs5229 => unreachable, // cannot contain relocs
5159 .section,5230 .section,
5160 .section_manual_size,5231 .section_manual_size,
...@@ -5179,23 +5250,52 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {...@@ -5179,23 +5250,52 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
5179 null,5250 null,
5180 &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_got_reloc,5251 &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_got_reloc,
5181 },5252 },
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 },
5182 .func_frame_fde => |fi| .{5273 .func_frame_fde => |fi| .{
5183 &elf.dwarf_funcs.items[@backingInt(fi)].func_frame_fde_first_symbol_reloc,5274 &elf.dwarf_funcs.items[@backingInt(fi)].frame_fde_first_symbol_reloc,
5184 &elf.dwarf_funcs.items[@backingInt(fi)].func_frame_fde_first_node_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,
5185 null,5286 null,
5186 },5287 },
5187 };5288 };
51885289
5189 if (symbol_relocs.* != .none) {5290 if (symbol_relocs) |ptr| {
5190 for (5291 if (ptr.* != .none) {
5191 elf.symbol_relocs.items[@backingInt(symbol_relocs.*)..],5292 for (elf.symbol_relocs.items[@backingInt(ptr.*)..], @backingInt(ptr.*)..) |*reloc, index| {
5192 @backingInt(symbol_relocs.*)..,5293 if (reloc.node != ni) break;
5193 ) |*reloc, index| {5294 reloc.delete(elf, @fromBackingInt(@intCast(index)));
5194 if (reloc.node != ni) break;5295 }
5195 reloc.delete(elf, @fromBackingInt(@intCast(index)));
5196 }5296 }
5297 ptr.* = @fromBackingInt(@intCast(elf.symbol_relocs.items.len));
5197 }5298 }
5198 symbol_relocs.* = @fromBackingInt(@intCast(elf.symbol_relocs.items.len));
51995299
5200 if (node_relocs) |ptr| {5300 if (node_relocs) |ptr| {
5201 if (ptr.* != .none) {5301 if (ptr.* != .none) {
...@@ -5962,7 +6062,7 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load...@@ -5962,7 +6062,7 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load
5962 return error.BadMagic;6062 return error.BadMagic;
5963 }6063 }
5964 }6064 }
5965 var strtab: std.Io.Writer.Allocating = .init(gpa);6065 var strtab: Io.Writer.Allocating = .init(gpa);
5966 defer strtab.deinit();6066 defer strtab.deinit();
5967 while (r.takeStruct(std.elf.ar_hdr, .native)) |header| {6067 while (r.takeStruct(std.elf.ar_hdr, .native)) |header| {
5968 if (!std.mem.eql(u8, &header.ar_fmag, std.elf.ARFMAG))6068 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...@@ -6013,7 +6113,7 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load
6013fn fmtMemberString(member: ?[]const u8) std.fmt.Alt(?[]const u8, memberStringEscape) {6113fn fmtMemberString(member: ?[]const u8) std.fmt.Alt(?[]const u8, memberStringEscape) {
6014 return .{ .data = member };6114 return .{ .data = member };
6015}6115}
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 {
6017 try w.print("({f})", .{std.zig.fmtString(member orelse return)});6117 try w.print("({f})", .{std.zig.fmtString(member orelse return)});
6018}6118}
6019fn loadObject(6119fn loadObject(
...@@ -6897,7 +6997,6 @@ pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) link.Error!void {...@@ -6897,7 +6997,6 @@ pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) link.Error!void {
6897fn prelinkInner(elf: *Elf) Error!void {6997fn prelinkInner(elf: *Elf) Error!void {
6898 const comp = elf.base.comp;6998 const comp = elf.base.comp;
6899 const gpa = comp.gpa;6999 const gpa = comp.gpa;
6900
6901 if (comp.zcu) |zcu| self_hosted_codegen: {7000 if (comp.zcu) |zcu| self_hosted_codegen: {
6902 if (comp.config.use_llvm) break :self_hosted_codegen;7001 if (comp.config.use_llvm) break :self_hosted_codegen;
69037002
...@@ -6922,35 +7021,130 @@ fn prelinkInner(elf: *Elf) Error!void {...@@ -6922,35 +7021,130 @@ fn prelinkInner(elf: *Elf) Error!void {
6922 elf.input_pending_index += 1;7021 elf.input_pending_index += 1;
69237022
6924 try elf.dwarf.initUnits(zcu);7023 try elf.dwarf.initUnits(zcu);
7024 try elf.nodes.ensureUnusedCapacity(gpa, 4 + 4 + (4 + 4) * elf.dwarf.units.count());
6925 try elf.dwarf_units.appendNTimes(gpa, .{7025 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,
6927 }, elf.dwarf.units.count());7031 }, elf.dwarf.units.count());
69287032
6929 try elf.nodes.ensureUnusedCapacity(gpa, 2);7033 elf.dwarf.debug_abbrev.ni =
6930 for (7034 .wrap(try elf.shndx.debug_abbrev.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}));
6931 [2]Dwarf.Frame.Format{ .eh_frame, .debug_frame },7035 elf.nodes.appendAssumeCapacity(.{ .debug_shared = .debug_abbrev });
6932 [2]Section.Index{ elf.shndx.eh_frame, elf.shndx.debug_frame },7036
6933 ) |format, frame_shndx| {7037 elf.dwarf.debug_line_str.ni =
6934 if (frame_shndx == .UNDEF) continue;7038 .wrap(try elf.shndx.debug_line_str.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}));
6935 const frame_ni = frame_shndx.get(elf).ni;7039 elf.nodes.appendAssumeCapacity(.{ .debug_shared = .debug_line_str });
6936 _ = frame_ni.last(&elf.mf).unwrap() orelse continue;7040
6937 const frame_padding_ni = try frame_ni.addFloatingChild(&elf.mf, gpa, .{7041 elf.dwarf.debug_str.ni =
6938 .alignment = switch (elf.identClass()) {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()) {
6939 .NONE, _ => unreachable,7061 .NONE, _ => unreachable,
6940 .@"32" => .@"4",7062 .@"32" => .@"4",
6941 .@"64" => .@"8",7063 .@"64" => .@"8",
6942 },7064 } else .@"1",
6943 .next_moved = true,7065 .next_moved = true,
6944 .enable_next_moved = true,7066 .enable_next_moved = true,
6945 });7067 });
6946 elf.nodes.appendAssumeCapacity(.frame_padding);7068 elf.nodes.appendAssumeCapacity(.unit_padding);
6947 var cie_writer: MappedFile.Node.Writer = undefined;7069 var debug_nw: MappedFile.Node.Writer = undefined;
6948 frame_padding_ni.writer(&elf.mf, gpa, &cie_writer);7070 unit_padding_ni.writer(&elf.mf, gpa, &debug_nw);
6949 defer cie_writer.deinit();7071 defer debug_nw.deinit();
6950 elf.dwarf.genDebugFrameCie(&cie_writer.interface, null, format) catch |err| switch (err) {7072 (if (frame_format) |format|
6951 error.WriteFailed => return cie_writer.err.?,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.?,
6952 };7077 };
6953 }7078 }
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 }
6954 }7148 }
6955}7149}
69567150
...@@ -7750,7 +7944,10 @@ fn addNodeRelocAssumeCapacity(...@@ -7750,7 +7944,10 @@ fn addNodeRelocAssumeCapacity(
7750 assert(!shndx.flags(elf).ALLOC); // not yet needed so not implemented7944 assert(!shndx.flags(elf).ALLOC); // not yet needed so not implemented
7751 const first_target_reloc = switch (elf.getNode(target)) {7945 const first_target_reloc = switch (elf.getNode(target)) {
7752 else => unreachable,7946 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,
7754 };7951 };
7755 const next = first_target_reloc.*;7952 const next = first_target_reloc.*;
7756 const ri: NodeReloc.Index = @fromBackingInt(@intCast(elf.node_relocs.items.len));7953 const ri: NodeReloc.Index = @fromBackingInt(@intCast(elf.node_relocs.items.len));
...@@ -7843,11 +8040,16 @@ fn addGotRelocAssumeCapacity(...@@ -7843,11 +8040,16 @@ fn addGotRelocAssumeCapacity(
7843 .shdr,8040 .shdr,
7844 .segment,8041 .segment,
7845 .copied_global,8042 .copied_global,
7846 .value_debug_info,8043 .debug_shared,
7847 .global_debug_info,8044 .unit_padding,
7848 .frame_padding,
7849 .unit_frame,8045 .unit_frame,
7850 .unit_frame_cie,8046 .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,
7851 .func_frame_fde,8053 .func_frame_fde,
7852 .func_debug_info,8054 .func_debug_info,
7853 .func_debug_line,8055 .func_debug_line,
...@@ -8207,21 +8409,27 @@ fn updateFuncInner(...@@ -8207,21 +8409,27 @@ fn updateFuncInner(
8207 var nw: MappedFile.Node.Writer = undefined;8409 var nw: MappedFile.Node.Writer = undefined;
8208 ni.writer(&elf.mf, gpa, &nw);8410 ni.writer(&elf.mf, gpa, &nw);
8209 defer nw.deinit();8411 defer nw.deinit();
8210 var debug: Dwarf.WipNav.Debug = undefined;8412 var debug_output_buf: Dwarf.WipNav.Debug = undefined;
8211 const debug_output: link.File.DebugInfoOutput = debug_output: {8413 const debug_output: link.File.DebugInfoOutput, const dwarf_func = debug_output: {
8212 if (elf.ehdrMachine() != .X86_64) break :debug_output .none;8414 if (elf.ehdrMachine() != .X86_64) break :debug_output .{ .none, undefined };
8213 const dwarf = &elf.dwarf;8415 const dwarf = &elf.dwarf;
8214 const mod = zcu.navFileScope(func.owner_nav).mod.?;8416 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
8217 try elf.nodes.ensureUnusedCapacity(gpa, 5);8419 try elf.nodes.ensureUnusedCapacity(gpa, 5);
8218 const dwarf_func_index = try dwarf.getFunc(func.owner_nav);8420 const dwarf_func_index = try dwarf.getFunc(func.owner_nav);
8219 try elf.dwarf_funcs.appendNTimes(gpa, .{8421 try elf.dwarf_funcs.appendNTimes(gpa, .{
8220 .func_frame_fde_first_symbol_reloc = .none,8422 .frame_fde_first_symbol_reloc = .none,
8221 .func_frame_fde_first_node_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,
8222 }, @backingInt(dwarf_func_index) + 1 -| elf.dwarf_funcs.items.len);8429 }, @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.* = .{
8225 .dwarf = dwarf,8433 .dwarf = dwarf,
8226 .unit = dwarf.getUnit(mod),8434 .unit = dwarf.getUnit(mod),
8227 .func = dwarf_func_index,8435 .func = dwarf_func_index,
...@@ -8235,16 +8443,17 @@ fn updateFuncInner(...@@ -8235,16 +8443,17 @@ fn updateFuncInner(
8235 .sync, .async => .eh_frame,8443 .sync, .async => .eh_frame,
8236 },8444 },
8237 .fde_writer = undefined,8445 .fde_writer = undefined,
8238 .frame_func_length_offset = std.math.maxInt(usize),8446 .frame_func_length = undefined,
8239 };8447 };
8240 const unit = debug.wip_nav.unit.get(dwarf);8448 const unit = wip_nav.unit.get(dwarf);
8449
8241 const frame_align: Alignment = switch (elf.identClass()) {8450 const frame_align: Alignment = switch (elf.identClass()) {
8242 .NONE, _ => unreachable,8451 .NONE, _ => unreachable,
8243 .@"32" => .@"4",8452 .@"32" => .@"4",
8244 .@"64" => .@"8",8453 .@"64" => .@"8",
8245 };8454 };
8246 const frame_ni = unit.frame_ni.unwrap() orelse frame_ni: {8455 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) {
8248 .debug_frame => elf.shndx.debug_frame,8457 .debug_frame => elf.shndx.debug_frame,
8249 .eh_frame => elf.shndx.eh_frame,8458 .eh_frame => elf.shndx.eh_frame,
8250 }.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{8459 }.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{
...@@ -8253,7 +8462,7 @@ fn updateFuncInner(...@@ -8253,7 +8462,7 @@ fn updateFuncInner(
8253 .enable_next_moved = true,8462 .enable_next_moved = true,
8254 });8463 });
8255 unit.frame_ni = .wrap(frame_ni);8464 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 });
8257 break :frame_ni frame_ni;8466 break :frame_ni frame_ni;
8258 };8467 };
8259 _ = unit.cie_ni.unwrap() orelse {8468 _ = unit.cie_ni.unwrap() orelse {
...@@ -8263,17 +8472,16 @@ fn updateFuncInner(...@@ -8263,17 +8472,16 @@ fn updateFuncInner(
8263 .enable_next_moved = true,8472 .enable_next_moved = true,
8264 });8473 });
8265 unit.cie_ni = .wrap(cie_ni);8474 unit.cie_ni = .wrap(cie_ni);
8266 elf.nodes.appendAssumeCapacity(.{ .unit_frame_cie = debug.wip_nav.unit });8475 elf.nodes.appendAssumeCapacity(.{ .unit_frame_cie = wip_nav.unit });
8267 var cie_writer: MappedFile.Node.Writer = undefined;8476 var cie_nw: MappedFile.Node.Writer = undefined;
8268 cie_ni.writer(&elf.mf, gpa, &cie_writer);8477 cie_ni.writer(&elf.mf, gpa, &cie_nw);
8269 defer cie_writer.deinit();8478 defer cie_nw.deinit();
8270 dwarf.genDebugFrameCie(&cie_writer.interface, switch (elf.ehdrMachine()) {8479 dwarf.genDebugFrameCie(&cie_nw.interface, switch (elf.ehdrMachine()) {
8271 else => unreachable,8480 else => unreachable,
8272 .X86_64 => .x86_64,8481 .X86_64 => .x86_64,
8273 }, debug.wip_nav.frame_format) catch |err| switch (err) {8482 }, wip_nav.frame_format) catch |err| switch (err) {
8274 error.WriteFailed => return cie_writer.err.?,8483 error.WriteFailed => return cie_nw.err.?,
8275 };8484 };
8276 @memset(cie_writer.interface.unusedCapacitySlice(), std.dwarf.CFA.nop);
8277 };8485 };
8278 const dwarf_func = dwarf_func_index.get(dwarf);8486 const dwarf_func = dwarf_func_index.get(dwarf);
8279 const fde_ni = if (dwarf_func.fde_ni.unwrap()) |fde_ni| fde_ni: {8487 const fde_ni = if (dwarf_func.fde_ni.unwrap()) |fde_ni| fde_ni: {
...@@ -8290,15 +8498,17 @@ fn updateFuncInner(...@@ -8290,15 +8498,17 @@ fn updateFuncInner(
8290 dwarf_func.fde_ni = .wrap(fde_ni);8498 dwarf_func.fde_ni = .wrap(fde_ni);
8291 break :fde_ni fde_ni;8499 break :fde_ni fde_ni;
8292 };8500 };
8293 fde_ni.writer(&elf.mf, gpa, &debug.wip_nav.fde_writer);8501 fde_ni.writer(&elf.mf, gpa, &wip_nav.fde_writer);
8294 if (mod.strip) break :debug_output .{ .eh_frame = &debug.wip_nav };8502
8503 if (mod.strip) break :debug_output .{ .{ .eh_frame = wip_nav }, dwarf_func };
82958504
8505 const debug = &debug_output_buf;
8296 debug.pt = pt;8506 debug.pt = pt;
8297 debug.any_children = false;8507 debug.any_children = false;
8298 debug.blocks = .empty;8508 debug.blocks = .empty;
8299 const debug_info_ni = dwarf_func.debug_info_ni.unwrap() orelse debug_info_ni: {8509 const debug_info_ni = dwarf_func.debug_info_ni.unwrap() orelse debug_info_ni: {
8300 const debug_info_ni =8510 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, .{
8302 .next_moved = true,8512 .next_moved = true,
8303 .enable_next_moved = true,8513 .enable_next_moved = true,
8304 });8514 });
...@@ -8309,7 +8519,7 @@ fn updateFuncInner(...@@ -8309,7 +8519,7 @@ fn updateFuncInner(
8309 debug_info_ni.writer(&elf.mf, gpa, &debug.info_writer);8519 debug_info_ni.writer(&elf.mf, gpa, &debug.info_writer);
8310 const debug_line_ni = dwarf_func.debug_line_ni.unwrap() orelse debug_line_ni: {8520 const debug_line_ni = dwarf_func.debug_line_ni.unwrap() orelse debug_line_ni: {
8311 const debug_line_ni =8521 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, .{
8313 .next_moved = true,8523 .next_moved = true,
8314 .enable_next_moved = true,8524 .enable_next_moved = true,
8315 });8525 });
...@@ -8317,18 +8527,25 @@ fn updateFuncInner(...@@ -8317,18 +8527,25 @@ fn updateFuncInner(
8317 break :debug_line_ni debug_line_ni;8527 break :debug_line_ni debug_line_ni;
8318 };8528 };
8319 debug_line_ni.writer(&elf.mf, gpa, &debug.line_writer);8529 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 };
8321 };8532 };
8322 defer switch (debug_output) {8533 defer switch (debug_output) {
8323 .dwarf => unreachable,8534 .dwarf => unreachable,
8324 inline .eh_frame, .dwarf2 => |dwarf| dwarf.deinit(gpa),8535 inline .eh_frame, .dwarf2 => |dwarf| dwarf.deinit(),
8325 .none => {},8536 .none => {},
8326 };8537 };
8327 switch (debug_output) {8538 switch (debug_output) {
8328 .dwarf => unreachable,8539 .dwarf => unreachable,
8329 inline .eh_frame, .dwarf2 => |dwarf| {8540 .eh_frame => |wip_nav| {
8330 elf.resetNodeRelocs(debug.wip_nav.func.?.get(&elf.dwarf).fde_ni.unwrap().?);8541 elf.resetNodeRelocs(dwarf_func.fde_ni.unwrap().?);
8331 try dwarf.genFuncHeaders();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();
8332 },8549 },
8333 .none => {},8550 .none => {},
8334 }8551 }
...@@ -8348,30 +8565,45 @@ fn updateFuncInner(...@@ -8348,30 +8565,45 @@ fn updateFuncInner(
8348 else => |e| return e,8565 else => |e| return e,
8349 };8566 };
8350 const func_length = nw.interface.end;8567 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) {
8352 .dwarf => unreachable,8572 .dwarf => unreachable,
8353 .eh_frame, .dwarf2 => {8573 .eh_frame => |wip_nav| {
8354 debug.wip_nav.finishDebugFrameFde(func_length);8574 wip_nav.finishDebugFrameFde(func_length);
8355 const frame_ni = switch (debug.wip_nav.frame_format) {8575 const frame_ni = switch (wip_nav.frame_format) {
8356 .debug_frame => elf.shndx.debug_frame,8576 .debug_frame => elf.shndx.debug_frame,
8357 .eh_frame => elf.shndx.eh_frame,8577 .eh_frame => elf.shndx.eh_frame,
8358 }.get(elf).ni;8578 }.get(elf).ni;
8359 try frame_ni.trimStart(&elf.mf, elf.base.comp.gpa);8579 try frame_ni.trimStart(&elf.mf, gpa);
8360 switch (debug.wip_nav.frame_format) {8580 switch (wip_nav.frame_format) {
8361 .debug_frame => {},8581 .debug_frame => {},
8362 .eh_frame => {8582 .eh_frame => {
8363 const last_offset, const last_size =8583 const last_offset, const last_size =
8364 frame_ni.last(&elf.mf).unwrap().?.location(&elf.mf).resolve(&elf.mf);8584 frame_ni.last(&elf.mf).unwrap().?.location(&elf.mf).resolve(&elf.mf);
8365 const last_end = last_offset + last_size;8585 try frame_ni.ensureMinimumSize(&elf.mf, gpa, last_offset + last_size + 4);
8366 try frame_ni.ensureMinimumSize(&elf.mf, elf.base.comp.gpa, last_end + 4);
8367 },8586 },
8368 }8587 }
8369 },8588 },
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 },
8370 .none => {},8605 .none => {},
8371 }8606 }
8372 switch (elf.symPtr(nmi.symbol(elf).index())) {
8373 inline else => |sym| elf.targetStore(&sym.size, @intCast(func_length)),
8374 }
8375 }8607 }
83768608
8377 // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs.8609 // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs.
...@@ -8427,8 +8659,14 @@ fn flushInner(...@@ -8427,8 +8659,14 @@ fn flushInner(
84278659
8428 while (try elf.idle(tid)) {}8660 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
8430 // We've done the final `idle` loop, so everything is at its final place in the file. We have a8666 // We've done the final `idle` loop, so everything is at its final place in the file. We have a
8431 // few more things to check and write now that addresses and offsets are finalized.8667 // 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
8433 if (elf.overflowed_reloc_count > 0) {8671 if (elf.overflowed_reloc_count > 0) {
8434 diags.addError("failed to apply {d} relocations: overflow", .{elf.overflowed_reloc_count});8672 diags.addError("failed to apply {d} relocations: overflow", .{elf.overflowed_reloc_count});
...@@ -8476,12 +8714,13 @@ fn flushInner(...@@ -8476,12 +8714,13 @@ fn flushInner(
8476}8714}
84778715
8478pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {8716pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
8479 const comp = elf.base.comp;8717 // This function is called non-deterministically, and so must not affect the layout of any nodes.
8480 const diags = &comp.link_diags;
8481
8482 elf.mf.nodes_lock.lock();8718 elf.mf.nodes_lock.lock();
8483 defer elf.mf.nodes_lock.unlock();8719 defer elf.mf.nodes_lock.unlock();
84848720
8721 const comp = elf.base.comp;
8722 const diags = &comp.link_diags;
8723
8485 assert(elf.pending_uavs.items.len == 0);8724 assert(elf.pending_uavs.items.len == 0);
8486 for (&elf.lazy.values) |*lazy| {8725 for (&elf.lazy.values) |*lazy| {
8487 assert(lazy.pending_index == lazy.map.count());8726 assert(lazy.pending_index == lazy.map.count());
...@@ -8654,6 +8893,25 @@ fn idleProgNode(...@@ -8654,6 +8893,25 @@ fn idleProgNode(
8654 .uav => |umi| std.mem.print(&name, "{f}", .{8893 .uav => |umi| std.mem.print(&name, "{f}", .{
8655 Value.fromInterned(umi.uavValue(elf)).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),8894 Value.fromInterned(umi.uavValue(elf)).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
8656 }) catch &name,8895 }) 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,
8657 .value_debug_info => |cpi| std.mem.print(&name, "debug info for {f}", .{8915 .value_debug_info => |cpi| std.mem.print(&name, "debug info for {f}", .{
8658 Value.fromInterned(cpi.val(&elf.dwarf.const_pool))8916 Value.fromInterned(cpi.val(&elf.dwarf.const_pool))
8659 .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),8917 .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
...@@ -8664,9 +8922,6 @@ fn idleProgNode(...@@ -8664,9 +8922,6 @@ fn idleProgNode(
8664 ip.getNav(gi.nav(&elf.dwarf)).fqn.fmt(ip),8922 ip.getNav(gi.nav(&elf.dwarf)).fqn.fmt(ip),
8665 }) catch &name;8923 }) catch &name;
8666 },8924 },
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,
8670 .func_frame_fde, .func_debug_info, .func_debug_line => |fi, tag| {8925 .func_frame_fde, .func_debug_info, .func_debug_line => |fi, tag| {
8671 const ip = &elf.base.comp.zcu.?.intern_pool;8926 const ip = &elf.base.comp.zcu.?.intern_pool;
8672 break :name std.mem.print(&name, "{s} info for {f}", .{8927 break :name std.mem.print(&name, "{s} info for {f}", .{
...@@ -8684,38 +8939,35 @@ fn idleProgNode(...@@ -8684,38 +8939,35 @@ fn idleProgNode(
86848939
8685fn genPending(elf: *Elf, pt: Zcu.PerThread) Error!void {8940fn genPending(elf: *Elf, pt: Zcu.PerThread) Error!void {
8686 const zcu = elf.base.comp.zcu.?;8941 const zcu = elf.base.comp.zcu.?;
8687 pending: while (true) {8942
8688 if (elf.pending_uavs.pop()) |umi| {8943 while (elf.pending_uavs.pop()) |umi| {
8689 var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;8944 var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;
8690 const prog_name = std.mem.print(&prog_name_buf, "{f}", .{8945 const prog_name = std.mem.print(&prog_name_buf, "{f}", .{
8691 Value.fromInterned(umi.uavValue(elf)).fmtValue(pt),8946 Value.fromInterned(umi.uavValue(elf)).fmtValue(pt),
8692 }) catch &prog_name_buf;8947 }) catch &prog_name_buf;
8693 const prog_node = elf.const_prog_node.start(prog_name, 0);8948 const prog_node = elf.const_prog_node.start(prog_name, 0);
8694 defer prog_node.end();8949 defer prog_node.end();
8695 try elf.genUav(pt, umi);8950 try elf.genUav(pt, umi);
8696 continue :pending;8951 }
8697 }8952
8698 var lazy_it = elf.lazy.iterator();8953 var lazy_it = elf.lazy.iterator();
8699 while (lazy_it.next()) |lazy| if (lazy.value.pending_index < lazy.value.map.count()) {8954 while (lazy_it.next()) |lazy| while (lazy.value.pending_index < lazy.value.map.count()) {
8700 const lmr: Node.LazyMapRef = .{ .kind = lazy.key, .index = lazy.value.pending_index };8955 const lmr: Node.LazyMapRef = .{ .kind = lazy.key, .index = lazy.value.pending_index };
8701 lazy.value.pending_index += 1;8956 lazy.value.pending_index += 1;
8702 const lazy_ty: Type = .fromInterned(lmr.lazySymbol(elf).ty);8957 const lazy_ty: Type = .fromInterned(lmr.lazySymbol(elf).ty);
8703 var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;8958 var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;
8704 const prog_name: []const u8 = switch (lazy_ty.zigTypeTag(zcu)) {8959 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,8960 .@"enum" => std.mem.print(&prog_name_buf, "@tagName({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,
8706 .error_set => switch (lmr.kind) {8961 .error_set => switch (lmr.kind) {
8707 .code => std.mem.print(&prog_name_buf, "@errorCast({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,8962 .code => std.mem.print(&prog_name_buf, "@errorCast({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,
8708 .const_data => "@errorName",8963 .const_data => "@errorName",
8709 },8964 },
8710 else => unreachable,8965 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;
8716 };8966 };
8717 break;8967 const prog_node = elf.synth_prog_node.start(prog_name, 0);
8718 }8968 defer prog_node.end();
8969 try elf.genLazy(pt, lmr);
8970 };
8719}8971}
87208972
8721fn genUav(8973fn genUav(
...@@ -9071,25 +9323,103 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -9071,25 +9323,103 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
9071 name = elf.globalByName(name).?.next_in_node;9323 name = elf.globalByName(name).?.next_in_node;
9072 }9324 }
9073 }9325 }
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 );
9075 },9333 },
9076 .value_debug_info,9334 .debug_shared => |ss| {
9077 .global_debug_info,9335 var target_ri = elf.dwarf_shared.getPtr(ss).first_target_reloc;
9078 .frame_padding,9336 while (target_ri != .none) {
9079 .unit_frame,9337 const target_reloc = target_ri.get(elf);
9080 => {},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 => {},
9081 .unit_frame_cie => |ui| {9344 .unit_frame_cie => |ui| {
9082 const dwarf_unit = &elf.dwarf_units.items[@backingInt(ui)];9345 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;
9084 while (target_ri != .none) {9408 while (target_ri != .none) {
9085 const target_reloc = target_ri.get(elf);9409 const target_reloc = target_ri.get(elf);
9086 assert(target_reloc.target == ni);9410 assert(target_reloc.target == ni);
9087 target_reloc.apply(elf);9411 target_reloc.apply(elf);
9088 target_ri = target_reloc.next;9412 target_ri = target_reloc.next;
9089 }9413 }
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 );
9090 },9421 },
9091 .func_frame_fde => |fi| {9422 .func_frame_fde => |fi| {
9092 const new_addr = elf.computeNodeVAddr(ni);
9093 const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)];9423 const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)];
9094 const mod = elf.base.comp.zcu.?.navFileScope(fi.nav(&elf.dwarf)).mod.?;9424 const mod = elf.base.comp.zcu.?.navFileScope(fi.nav(&elf.dwarf)).mod.?;
9095 switch (mod.unwind_tables) {9425 switch (mod.unwind_tables) {
...@@ -9101,15 +9431,39 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -9101,15 +9431,39 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
9101 }9431 }
9102 elf.flushMovedNodeRelocs(9432 elf.flushMovedNodeRelocs(
9103 ni,9433 ni,
9104 new_addr,9434 elf.computeNodeVAddr(ni),
9105 dwarf_func.func_frame_fde_first_symbol_reloc,9435 dwarf_func.frame_fde_first_symbol_reloc,
9106 dwarf_func.func_frame_fde_first_node_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,
9107 .none,9464 .none,
9108 );9465 );
9109 },9466 },
9110 .func_debug_info,
9111 .func_debug_line,
9112 => {},
9113 }9467 }
9114 try ni.childrenMoved(elf.base.comp.gpa, &elf.mf);9468 try ni.childrenMoved(elf.base.comp.gpa, &elf.mf);
9115}9469}
...@@ -9346,11 +9700,16 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo...@@ -9346,11 +9700,16 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
9346 .uav,9700 .uav,
9347 .lazy_code,9701 .lazy_code,
9348 .lazy_const_data,9702 .lazy_const_data,
9349 .value_debug_info,9703 .debug_shared,
9350 .global_debug_info,9704 .unit_padding,
9351 .frame_padding,
9352 .unit_frame,9705 .unit_frame,
9353 .unit_frame_cie,9706 .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,
9354 .func_frame_fde,9713 .func_frame_fde,
9355 .func_debug_info,9714 .func_debug_info,
9356 .func_debug_line,9715 .func_debug_line,
...@@ -9378,6 +9737,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!...@@ -9378,6 +9737,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
9378 .uav,9737 .uav,
9379 .lazy_code,9738 .lazy_code,
9380 .lazy_const_data,9739 .lazy_const_data,
9740 .debug_shared,
9381 => unreachable,9741 => unreachable,
93829742
9383 .archive_header => {9743 .archive_header => {
...@@ -9406,66 +9766,111 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!...@@ -9406,66 +9766,111 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
9406 error.NoSpaceLeft => archive.strtab_member_too_big = true,9766 error.NoSpaceLeft => archive.strtab_member_too_big = true,
9407 }9767 }
9408 },9768 },
9769 .unit_padding,
9770 .unit_frame_cie,
9771 .unit_debug_info_header,
9772 .unit_debug_line_header,
9409 .value_debug_info,9773 .value_debug_info,
9410 .global_debug_info,9774 .global_debug_info,
9411 => {},9775 .func_frame_fde,
9412 .frame_padding, .unit_frame_cie, .func_frame_fde => |_, tag| {9776 .func_debug_info,
9777 .func_debug_line,
9778 => |_, tag| {
9413 const offset, const size = ni.location(&elf.mf).resolve(&elf.mf);9779 const offset, const size = ni.location(&elf.mf).resolve(&elf.mf);
9414 const slice = slice: {9780 const parent_ni = ni.parent(&elf.mf).unwrap().?;
9415 const parent_ni = ni.parent(&elf.mf).unwrap().?;9781 const slice = if (ni.next(&elf.mf).unwrap()) |next_ni| slice: {
9416 if (ni.next(&elf.mf).unwrap()) |next_ni| {9782 const parent_slice = parent_ni.slicePadding(&elf.mf);
9417 const parent_slice = parent_ni.slicePadding(&elf.mf);9783 const next_offset, _ = next_ni.location(&elf.mf).resolve(&elf.mf);
9418 const next_offset, _ = next_ni.location(&elf.mf).resolve(&elf.mf);9784 break :slice parent_slice[@intCast(offset)..@intCast(next_offset)];
9419 break :slice parent_slice[@intCast(offset)..@intCast(next_offset)];9785 } else slice: switch (tag) {
9420 } else switch (tag) {9786 else => unreachable,
9421 else => unreachable,9787 .unit_padding => {
9422 .frame_padding => {9788 const frame_slice = parent_ni.slicePadding(&elf.mf);
9423 const frame_slice = parent_ni.slicePadding(&elf.mf);9789 switch (elf.getNode(parent_ni).section.debugFrameFormat(elf) orelse .debug_frame) {
9424 switch (elf.getNode(parent_ni).section.debugFrameFormat(elf).?) {9790 .eh_frame => {
9425 .eh_frame => {9791 const end = frame_slice.len - 4;
9426 const end = frame_slice.len - 4;9792 std.mem.writeInt(u32, frame_slice[end..][0..4], 0, elf.dwarf.endian);
9427 std.mem.writeInt(u32, frame_slice[end..][0..4], 0, elf.dwarf.endian);9793 break :slice frame_slice[@intCast(offset)..end];
9428 break :slice frame_slice[@intCast(offset)..end];9794 },
9429 },9795 .debug_frame => break :slice frame_slice[@intCast(offset)..],
9430 .debug_frame => break :slice frame_slice[@intCast(offset)..],9796 }
9431 }9797 },
9432 },9798 .unit_frame_cie, .func_frame_fde => {
9433 .unit_frame_cie, .func_frame_fde => {9799 const parent_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);
9434 const parent_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);9800 const frame_ni = parent_ni.parent(&elf.mf).unwrap().?;
9435 const frame_ni = parent_ni.parent(&elf.mf).unwrap().?;9801 const frame_slice = frame_ni.slicePadding(&elf.mf);
9436 const frame_slice = frame_ni.slicePadding(&elf.mf);9802 const frame_format = elf.getNode(frame_ni).section.debugFrameFormat(elf);
9437 const 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: {
9438 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);
9439 const parent_next_offset, _ = parent_next_ni.location(&elf.mf).resolve(&elf.mf);9805 break :frame_end @intCast(parent_next_offset);
9440 break :frame_end @intCast(parent_next_offset);9806 } else frame_end: switch (frame_format orelse .debug_frame) {
9441 } else frame_end: switch (format) {9807 .eh_frame => {
9442 .eh_frame => {9808 const frame_end = frame_slice.len - 4;
9443 const frame_end = frame_slice.len - 4;9809 std.mem.writeInt(u32, frame_slice[frame_end..][0..4], 0, elf.dwarf.endian);
9444 std.mem.writeInt(u32, frame_slice[frame_end..][0..4], 0, elf.dwarf.endian);9810 break :frame_end frame_end;
9445 break :frame_end frame_end;9811 },
9446 },9812 .debug_frame => frame_slice.len,
9447 .debug_frame => frame_slice.len,9813 }];
9448 }];9814 var fw: Io.Writer = .fixed(slice[@intCast(size)..]);
9449 var fw: std.Io.Writer = .fixed(slice[@intCast(size)..]);9815 (if (frame_format) |format|
9450 elf.dwarf.genDebugFrameCie(&fw, null, format) catch |err| switch (err) {9816 elf.dwarf.genDebugFrameCie(&fw, null, format)
9451 error.WriteFailed => break :slice slice,9817 else
9452 };9818 elf.dwarf.genUnitPadding(&fw)) catch |err| switch (err) {
9453 elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len);9819 error.WriteFailed => break :slice slice,
9454 break :slice slice[0..@intCast(size)];9820 };
9455 },9821 elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len);
9456 }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 },
9457 };9852 };
9458 elf.dwarf.updateUnitLength(slice, slice.len);
9459 switch (tag) {9853 switch (tag) {
9460 else => unreachable,9854 else => unreachable,
9461 .frame_padding => {},9855 .unit_padding => elf.dwarf.updateUnitLength(slice, slice.len),
9462 .unit_frame_cie, .func_frame_fde => @memset(slice[@intCast(size)..], std.dwarf.CFA.nop),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 },
9463 }9870 }
9464 },9871 },
9465 .unit_frame,9872 .unit_frame, .unit_debug_info, .unit_debug_line => if (ni.last(&elf.mf).unwrap()) |last_ni|
9466 .func_debug_info,9873 try last_ni.nextMoved(elf.base.comp.gpa, &elf.mf),
9467 .func_debug_line,
9468 => {},
9469 }9874 }
9470}9875}
94719876
...@@ -9986,6 +10391,16 @@ pub fn printNode(...@@ -9986,6 +10391,16 @@ pub fn printNode(
9986 .tid = tid,10391 .tid = tid,
9987 }),10392 }),
9988 }),10393 }),
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 }),
9989 .value_debug_info => |cpi| try w.print("({f})", .{10404 .value_debug_info => |cpi| try w.print("({f})", .{
9990 Value.fromInterned(cpi.val(&elf.dwarf.const_pool))10405 Value.fromInterned(cpi.val(&elf.dwarf.const_pool))
9991 .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),10406 .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
...@@ -9999,9 +10414,6 @@ pub fn printNode(...@@ -9999,9 +10414,6 @@ pub fn printNode(
9999 nav.fqn.fmt(ip),10414 nav.fqn.fmt(ip),
10000 });10415 });
10001 },10416 },
10002 .unit_frame, .unit_frame_cie => |ui| try w.print("({s})", .{
10003 ui.mod(&elf.dwarf).fully_qualified_name,
10004 }),
10005 .func_frame_fde, .func_debug_info, .func_debug_line => |fi| {10417 .func_frame_fde, .func_debug_info, .func_debug_line => |fi| {
10006 const zcu = elf.base.comp.zcu.?;10418 const zcu = elf.base.comp.zcu.?;
10007 const ip = &zcu.intern_pool;10419 const ip = &zcu.intern_pool;