authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-10-17 16:39:05+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-10-19 18:30:34+01:00
log77340b28c806e30c3d5759abe6883fc35eaed60c
tree91185aef36b2e9f36f409f073a855dc8cd6e7c9b
parent51cd726f86e0036e9cc19339a70655a149f9d79f
signature Commit is signed but in an unrecognized format.

Elf2: stop constantly re-applying DWARF relocations


1 files changed, 39 insertions(+), 2 deletions(-)

src/link/Elf2.zig+39-2
...@@ -1073,10 +1073,14 @@ const dwarf_relocs = struct {...@@ -1073,10 +1073,14 @@ const dwarf_relocs = struct {
1073 const Addr = struct {1073 const Addr = struct {
1074 first_target_reloc: NodeReloc.Index,1074 first_target_reloc: NodeReloc.Index,
1075 symbol_relocs: std.ArrayList(SymbolReloc.Index),1075 symbol_relocs: std.ArrayList(SymbolReloc.Index),
1076 /// Index into `symbol_relocs`.
1077 pending_reloc_index: usize,
1076 };1078 };
1077 const StrOffsets = struct {1079 const StrOffsets = struct {
1078 first_target_reloc: NodeReloc.Index,1080 first_target_reloc: NodeReloc.Index,
1079 node_relocs: std.ArrayList(NodeReloc.Index),1081 node_relocs: std.ArrayList(NodeReloc.Index),
1082 /// Index into `node_relocs`.
1083 pending_reloc_index: usize,
1080 };1084 };
1081 const Unit = struct {1085 const Unit = struct {
1082 frame_cie_first_target_reloc: NodeReloc.Index,1086 frame_cie_first_target_reloc: NodeReloc.Index,
...@@ -5000,10 +5004,12 @@ fn create(...@@ -5000,10 +5004,12 @@ fn create(
5000 .dwarf_addr = .{5004 .dwarf_addr = .{
5001 .first_target_reloc = .none,5005 .first_target_reloc = .none,
5002 .symbol_relocs = .empty,5006 .symbol_relocs = .empty,
5007 .pending_reloc_index = 0,
5003 },5008 },
5004 .dwarf_str_offsets = .{5009 .dwarf_str_offsets = .{
5005 .first_target_reloc = .none,5010 .first_target_reloc = .none,
5006 .node_relocs = .empty,5011 .node_relocs = .empty,
5012 .pending_reloc_index = 0,
5007 },5013 },
5008 .dwarf_units = &.{},5014 .dwarf_units = &.{},
5009 .dwarf_consts = .empty,5015 .dwarf_consts = .empty,
...@@ -11010,6 +11016,9 @@ pub fn idle(elf: *Elf) link.Error!bool {...@@ -11010,6 +11016,9 @@ pub fn idle(elf: *Elf) link.Error!bool {
11010 if (elf.bss_moved) {11016 if (elf.bss_moved) {
11011 elf.bss_moved = false;11017 elf.bss_moved = false;
1101211018
11019 const idle_prog_node = elf.mf.update_prog_node.start(".bss", 0);
11020 defer idle_prog_node.end();
11021
11013 const data_phndx = elf.getNode(elf.ni.data).segment;11022 const data_phndx = elf.getNode(elf.ni.data).segment;
11014 const data_offset: u64, const data_vaddr: u64, const data_filesz: u64 = switch (elf.phdrSlice()) {11023 const data_offset: u64, const data_vaddr: u64, const data_filesz: u64 = switch (elf.phdrSlice()) {
11015 inline else => |phdr| .{11024 inline else => |phdr| .{
...@@ -11040,6 +11049,32 @@ pub fn idle(elf: *Elf) link.Error!bool {...@@ -11040,6 +11049,32 @@ pub fn idle(elf: *Elf) link.Error!bool {
1104011049
11041 break :task;11050 break :task;
11042 }11051 }
11052 if (elf.dwarf_addr.pending_reloc_index < elf.dwarf_addr.symbol_relocs.items.len) {
11053 const idle_prog_node = elf.mf.update_prog_node.start(@tagName(Node.debug_addr), 0);
11054 defer idle_prog_node.end();
11055 const debug_addr_ni = elf.dwarf.debug_addr.ni.unwrap().?;
11056 const debug_addr_vaddr = elf.getNodeVAddr(debug_addr_ni);
11057 for (elf.dwarf_addr.symbol_relocs.items[elf.dwarf_addr.pending_reloc_index..]) |symbol_ri| {
11058 const symbol_reloc = symbol_ri.get(elf);
11059 assert(symbol_reloc.node.unwrap().? == debug_addr_ni);
11060 symbol_reloc.flushMovedNode(elf, debug_addr_vaddr);
11061 }
11062 elf.dwarf_addr.pending_reloc_index = elf.dwarf_addr.symbol_relocs.items.len;
11063 break :task;
11064 }
11065 if (elf.dwarf_str_offsets.pending_reloc_index < elf.dwarf_str_offsets.node_relocs.items.len) {
11066 const idle_prog_node = elf.mf.update_prog_node.start(@tagName(Node.debug_str_offsets), 0);
11067 defer idle_prog_node.end();
11068 const debug_str_offsets_ni = elf.dwarf.debug_str_offsets.ni.unwrap().?;
11069 const debug_str_offsets_vaddr = elf.getNodeVAddr(debug_str_offsets_ni);
11070 for (elf.dwarf_str_offsets.node_relocs.items[elf.dwarf_str_offsets.pending_reloc_index..]) |node_ri| {
11071 const node_reloc = node_ri.get(elf);
11072 assert(node_reloc.node.unwrap().? == debug_str_offsets_ni);
11073 node_reloc.flushMovedNode(elf, debug_str_offsets_vaddr);
11074 }
11075 elf.dwarf_str_offsets.pending_reloc_index = elf.dwarf_str_offsets.node_relocs.items.len;
11076 break :task;
11077 }
11043 }11078 }
11044 if (elf.inputs.items.len - elf.input_pending_index > 0) return true;11079 if (elf.inputs.items.len - elf.input_pending_index > 0) return true;
11045 if (elf.input_sections.items.len - elf.input_section_pending_index > 0) return true;11080 if (elf.input_sections.items.len - elf.input_section_pending_index > 0) return true;
...@@ -11047,6 +11082,8 @@ pub fn idle(elf: *Elf) link.Error!bool {...@@ -11047,6 +11082,8 @@ pub fn idle(elf: *Elf) link.Error!bool {
11047 if (elf.changed_symtab_index.count() > 0) return true;11082 if (elf.changed_symtab_index.count() > 0) return true;
11048 if (elf.mf.updates.items.len > 0) return true;11083 if (elf.mf.updates.items.len > 0) return true;
11049 if (elf.bss_moved) return true;11084 if (elf.bss_moved) return true;
11085 if (elf.dwarf_addr.pending_reloc_index < elf.dwarf_addr.symbol_relocs.items.len) return true;
11086 if (elf.dwarf_str_offsets.pending_reloc_index < elf.dwarf_str_offsets.node_relocs.items.len) return true;
11050 return false;11087 return false;
11051}11088}
1105211089
...@@ -11177,7 +11214,6 @@ fn genPending(elf: *Elf, pt: Zcu.PerThread) link.Error!void {...@@ -11177,7 +11214,6 @@ fn genPending(elf: *Elf, pt: Zcu.PerThread) link.Error!void {
11177fn genPendingDebug(elf: *Elf, gpa: std.mem.Allocator) link.Error!void {11214fn genPendingDebug(elf: *Elf, gpa: std.mem.Allocator) link.Error!void {
11178 while (elf.dwarf.debug_addr.map.count() - elf.dwarf.debug_addr.pending_index > 0) {11215 while (elf.dwarf.debug_addr.map.count() - elf.dwarf.debug_addr.pending_index > 0) {
11179 const debug_addr_ni = elf.dwarf.debug_addr.ni.unwrap().?;11216 const debug_addr_ni = elf.dwarf.debug_addr.ni.unwrap().?;
11180 try debug_addr_ni.moved(gpa, &elf.mf);
11181 var da_nw: link.MappedFile.Node.Writer = undefined;11217 var da_nw: link.MappedFile.Node.Writer = undefined;
11182 debug_addr_ni.writer(gpa, &elf.mf, &da_nw);11218 debug_addr_ni.writer(gpa, &elf.mf, &da_nw);
11183 defer da_nw.deinit();11219 defer da_nw.deinit();
...@@ -11190,7 +11226,6 @@ fn genPendingDebug(elf: *Elf, gpa: std.mem.Allocator) link.Error!void {...@@ -11190,7 +11226,6 @@ fn genPendingDebug(elf: *Elf, gpa: std.mem.Allocator) link.Error!void {
11190 }11226 }
11191 while (elf.dwarf.debug_str_offsets.map.count() - elf.dwarf.debug_str_offsets.pending_index > 0) {11227 while (elf.dwarf.debug_str_offsets.map.count() - elf.dwarf.debug_str_offsets.pending_index > 0) {
11192 const debug_str_offsets_ni = elf.dwarf.debug_str_offsets.ni.unwrap().?;11228 const debug_str_offsets_ni = elf.dwarf.debug_str_offsets.ni.unwrap().?;
11193 try debug_str_offsets_ni.moved(gpa, &elf.mf);
11194 var dso_nw: link.MappedFile.Node.Writer = undefined;11229 var dso_nw: link.MappedFile.Node.Writer = undefined;
11195 debug_str_offsets_ni.writer(gpa, &elf.mf, &dso_nw);11230 debug_str_offsets_ni.writer(gpa, &elf.mf, &dso_nw);
11196 defer dso_nw.deinit();11231 defer dso_nw.deinit();
...@@ -11659,6 +11694,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -11659,6 +11694,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
11659 assert(symbol_reloc.node.unwrap().? == ni);11694 assert(symbol_reloc.node.unwrap().? == ni);
11660 symbol_reloc.flushMovedNode(elf, node_vaddr);11695 symbol_reloc.flushMovedNode(elf, node_vaddr);
11661 }11696 }
11697 elf.dwarf_addr.pending_reloc_index = elf.dwarf_addr.symbol_relocs.items.len;
11662 },11698 },
11663 .debug_str_offsets => {11699 .debug_str_offsets => {
11664 const target_section_offset = elf.computeNodeSectionOffset(ni);11700 const target_section_offset = elf.computeNodeSectionOffset(ni);
...@@ -11675,6 +11711,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -11675,6 +11711,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
11675 assert(node_reloc.node.unwrap().? == ni);11711 assert(node_reloc.node.unwrap().? == ni);
11676 node_reloc.flushMovedNode(elf, node_vaddr);11712 node_reloc.flushMovedNode(elf, node_vaddr);
11677 }11713 }
11714 elf.dwarf_str_offsets.pending_reloc_index = elf.dwarf_str_offsets.node_relocs.items.len;
11678 },11715 },
11679 .unit_frame_cie => |ui| {11716 .unit_frame_cie => |ui| {
11680 const target_section_offset = elf.computeNodeSectionOffset(ni);11717 const target_section_offset = elf.computeNodeSectionOffset(ni);