authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-04 10:22:21+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-07 22:42:57+02:00
log66bad3eaaf82b21363c2212eeb1eaa4c171f2625
treeba2f96279590b7df0e13df408af8d931c2da13f6
parent1e2a2d6fad8d83329de1b65338d741c1c6cd2e7d

coff: mark relocations dirty when target atoms change


2 files changed, 30 insertions(+), 28 deletions(-)

src/arch/x86_64/Emit.zig-2
......@@ -1029,7 +1029,6 @@ fn mirLeaPic(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
10291029 .addend = 0,
10301030 .pcrel = true,
10311031 .length = 2,
1032 .prev_vaddr = atom.getSymbol(coff_file).value,
10331032 });
10341033 } else {
10351034 return emit.fail("TODO implement lea reg, [rip + reloc] for linking backends different than MachO", .{});
......@@ -1165,7 +1164,6 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
11651164 .addend = 0,
11661165 .pcrel = true,
11671166 .length = 2,
1168 .prev_vaddr = atom.getSymbol(coff_file).value,
11691167 });
11701168 } else {
11711169 return emit.fail("TODO implement call_extern for linking backends different than MachO", .{});
src/link/Coff.zig+30-26
......@@ -114,11 +114,6 @@ relocs: RelocTable = .{},
114114/// this will be a table indexed by index into the list of Atoms.
115115base_relocs: BaseRelocationTable = .{},
116116
117/// A table of bindings indexed by the owning them `Atom`.
118/// Note that once we refactor `Atom`'s lifetime and ownership rules,
119/// this will be a table indexed by index into the list of Atoms.
120bindings: BindingTable = .{},
121
122117pub const Reloc = struct {
123118 @"type": enum {
124119 got,
......@@ -130,12 +125,11 @@ pub const Reloc = struct {
130125 addend: u32,
131126 pcrel: bool,
132127 length: u2,
133 prev_vaddr: u32,
128 dirty: bool = true,
134129};
135130
136131const RelocTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Reloc));
137132const BaseRelocationTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(u32));
138const BindingTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(SymbolWithLoc));
139133const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom));
140134
141135const default_file_alignment: u16 = 0x200;
......@@ -192,6 +186,16 @@ pub const SymbolWithLoc = struct {
192186
193187 // null means it's a synthetic global or Zig source.
194188 file: ?u32 = null,
189
190 pub fn eql(this: SymbolWithLoc, other: SymbolWithLoc) bool {
191 if (this.file == null and other.file == null) {
192 return this.sym_index == other.sym_index;
193 }
194 if (this.file != null and other.file != null) {
195 return this.sym_index == other.sym_index and this.file.? == other.file.?;
196 }
197 return false;
198 }
195199};
196200
197201/// When allocating, the ideal_capacity is calculated by
......@@ -314,14 +318,6 @@ pub fn deinit(self: *Coff) void {
314318 }
315319 self.base_relocs.deinit(gpa);
316320 }
317
318 {
319 var it = self.bindings.valueIterator();
320 while (it.next()) |bindings| {
321 bindings.deinit(gpa);
322 }
323 self.bindings.deinit(gpa);
324 }
325321}
326322
327323fn populateMissingMetadata(self: *Coff) !void {
......@@ -720,7 +716,6 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom {
720716 .addend = 0,
721717 .pcrel = false,
722718 .length = 3,
723 .prev_vaddr = sym.value,
724719 });
725720
726721 const target_sym = self.getSymbol(target);
......@@ -753,10 +748,6 @@ fn createImportAtom(self: *Coff, target: SymbolWithLoc) !*Atom {
753748
754749 log.debug("allocated import atom at 0x{x}", .{sym.value});
755750
756 const target_sym = self.getSymbol(target);
757 assert(target_sym.section_number == .UNDEFINED);
758 try atom.addBinding(self, target);
759
760751 return atom;
761752}
762753
......@@ -798,6 +789,17 @@ fn writePtrWidthAtom(self: *Coff, atom: *Atom) !void {
798789 }
799790}
800791
792fn markRelocsDirty(self: *Coff, target: SymbolWithLoc) void {
793 // TODO: reverse-lookup might come in handy here
794 var it = self.relocs.valueIterator();
795 while (it.next()) |relocs| {
796 for (relocs.items) |*reloc| {
797 if (!reloc.target.eql(target)) continue;
798 reloc.dirty = true;
799 }
800 }
801}
802
801803fn resolveRelocs(self: *Coff, atom: *Atom) !void {
802804 const relocs = self.relocs.get(atom) orelse return;
803805 const source_sym = atom.getSymbol(self);
......@@ -807,6 +809,8 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void {
807809 log.debug("relocating '{s}'", .{atom.getName(self)});
808810
809811 for (relocs.items) |*reloc| {
812 if (!reloc.dirty) continue;
813
810814 const target_vaddr = switch (reloc.@"type") {
811815 .got => blk: {
812816 const got_atom = self.getGotAtomForSymbol(reloc.target) orelse continue;
......@@ -821,7 +825,6 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void {
821825 },
822826 };
823827 const target_vaddr_with_addend = target_vaddr + reloc.addend;
824 if (target_vaddr_with_addend == reloc.prev_vaddr) continue;
825828
826829 log.debug(" ({x}: [() => 0x{x} ({s})) ({s})", .{
827830 source_sym.value + reloc.offset,
......@@ -830,6 +833,8 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void {
830833 @tagName(reloc.@"type"),
831834 });
832835
836 reloc.dirty = false;
837
833838 if (reloc.pcrel) {
834839 const source_vaddr = source_sym.value + reloc.offset;
835840 const disp = target_vaddr_with_addend - source_vaddr - 4;
......@@ -854,8 +859,6 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void {
854859 else => unreachable,
855860 },
856861 }
857
858 reloc.prev_vaddr = target_vaddr_with_addend;
859862 }
860863}
861864
......@@ -1131,7 +1134,9 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,
11311134 if (vaddr != sym.value) {
11321135 sym.value = vaddr;
11331136 log.debug(" (updating GOT entry)", .{});
1134 const got_atom = self.getGotAtomForSymbol(.{ .sym_index = atom.sym_index, .file = null }).?;
1137 const got_target = SymbolWithLoc{ .sym_index = atom.sym_index, .file = null };
1138 const got_atom = self.getGotAtomForSymbol(got_target).?;
1139 self.markRelocsDirty(got_target);
11351140 try self.writePtrWidthAtom(got_atom);
11361141 }
11371142 } else if (code_len < atom.size) {
......@@ -1156,6 +1161,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,
11561161 try self.writePtrWidthAtom(got_atom);
11571162 }
11581163
1164 self.markRelocsDirty(atom.getSymbolWithLoc());
11591165 try self.writeAtom(atom, code);
11601166}
11611167
......@@ -1457,7 +1463,6 @@ pub fn getDeclVAddr(
14571463
14581464 const atom = self.atom_by_index_table.get(reloc_info.parent_atom_index).?;
14591465 const target = SymbolWithLoc{ .sym_index = decl.link.coff.sym_index, .file = null };
1460 const target_sym = self.getSymbol(target);
14611466 try atom.addRelocation(self, .{
14621467 .@"type" = .direct,
14631468 .target = target,
......@@ -1465,7 +1470,6 @@ pub fn getDeclVAddr(
14651470 .addend = reloc_info.addend,
14661471 .pcrel = false,
14671472 .length = 3,
1468 .prev_vaddr = target_sym.value,
14691473 });
14701474 try atom.addBaseRelocation(self, @intCast(u32, reloc_info.offset));
14711475