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 {...@@ -1029,7 +1029,6 @@ fn mirLeaPic(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
1029 .addend = 0,1029 .addend = 0,
1030 .pcrel = true,1030 .pcrel = true,
1031 .length = 2,1031 .length = 2,
1032 .prev_vaddr = atom.getSymbol(coff_file).value,
1033 });1032 });
1034 } else {1033 } else {
1035 return emit.fail("TODO implement lea reg, [rip + reloc] for linking backends different than MachO", .{});1034 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 {...@@ -1165,7 +1164,6 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
1165 .addend = 0,1164 .addend = 0,
1166 .pcrel = true,1165 .pcrel = true,
1167 .length = 2,1166 .length = 2,
1168 .prev_vaddr = atom.getSymbol(coff_file).value,
1169 });1167 });
1170 } else {1168 } else {
1171 return emit.fail("TODO implement call_extern for linking backends different than MachO", .{});1169 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 = .{},...@@ -114,11 +114,6 @@ relocs: RelocTable = .{},
114/// this will be a table indexed by index into the list of Atoms.114/// this will be a table indexed by index into the list of Atoms.
115base_relocs: BaseRelocationTable = .{},115base_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
122pub const Reloc = struct {117pub const Reloc = struct {
123 @"type": enum {118 @"type": enum {
124 got,119 got,
...@@ -130,12 +125,11 @@ pub const Reloc = struct {...@@ -130,12 +125,11 @@ pub const Reloc = struct {
130 addend: u32,125 addend: u32,
131 pcrel: bool,126 pcrel: bool,
132 length: u2,127 length: u2,
133 prev_vaddr: u32,128 dirty: bool = true,
134};129};
135130
136const RelocTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Reloc));131const RelocTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Reloc));
137const BaseRelocationTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(u32));132const BaseRelocationTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(u32));
138const BindingTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(SymbolWithLoc));
139const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom));133const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom));
140134
141const default_file_alignment: u16 = 0x200;135const default_file_alignment: u16 = 0x200;
...@@ -192,6 +186,16 @@ pub const SymbolWithLoc = struct {...@@ -192,6 +186,16 @@ pub const SymbolWithLoc = struct {
192186
193 // null means it's a synthetic global or Zig source.187 // null means it's a synthetic global or Zig source.
194 file: ?u32 = null,188 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 }
195};199};
196200
197/// When allocating, the ideal_capacity is calculated by201/// When allocating, the ideal_capacity is calculated by
...@@ -314,14 +318,6 @@ pub fn deinit(self: *Coff) void {...@@ -314,14 +318,6 @@ pub fn deinit(self: *Coff) void {
314 }318 }
315 self.base_relocs.deinit(gpa);319 self.base_relocs.deinit(gpa);
316 }320 }
317
318 {
319 var it = self.bindings.valueIterator();
320 while (it.next()) |bindings| {
321 bindings.deinit(gpa);
322 }
323 self.bindings.deinit(gpa);
324 }
325}321}
326322
327fn populateMissingMetadata(self: *Coff) !void {323fn populateMissingMetadata(self: *Coff) !void {
...@@ -720,7 +716,6 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom {...@@ -720,7 +716,6 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom {
720 .addend = 0,716 .addend = 0,
721 .pcrel = false,717 .pcrel = false,
722 .length = 3,718 .length = 3,
723 .prev_vaddr = sym.value,
724 });719 });
725720
726 const target_sym = self.getSymbol(target);721 const target_sym = self.getSymbol(target);
...@@ -753,10 +748,6 @@ fn createImportAtom(self: *Coff, target: SymbolWithLoc) !*Atom {...@@ -753,10 +748,6 @@ fn createImportAtom(self: *Coff, target: SymbolWithLoc) !*Atom {
753748
754 log.debug("allocated import atom at 0x{x}", .{sym.value});749 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
760 return atom;751 return atom;
761}752}
762753
...@@ -798,6 +789,17 @@ fn writePtrWidthAtom(self: *Coff, atom: *Atom) !void {...@@ -798,6 +789,17 @@ fn writePtrWidthAtom(self: *Coff, atom: *Atom) !void {
798 }789 }
799}790}
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
801fn resolveRelocs(self: *Coff, atom: *Atom) !void {803fn resolveRelocs(self: *Coff, atom: *Atom) !void {
802 const relocs = self.relocs.get(atom) orelse return;804 const relocs = self.relocs.get(atom) orelse return;
803 const source_sym = atom.getSymbol(self);805 const source_sym = atom.getSymbol(self);
...@@ -807,6 +809,8 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void {...@@ -807,6 +809,8 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void {
807 log.debug("relocating '{s}'", .{atom.getName(self)});809 log.debug("relocating '{s}'", .{atom.getName(self)});
808810
809 for (relocs.items) |*reloc| {811 for (relocs.items) |*reloc| {
812 if (!reloc.dirty) continue;
813
810 const target_vaddr = switch (reloc.@"type") {814 const target_vaddr = switch (reloc.@"type") {
811 .got => blk: {815 .got => blk: {
812 const got_atom = self.getGotAtomForSymbol(reloc.target) orelse continue;816 const got_atom = self.getGotAtomForSymbol(reloc.target) orelse continue;
...@@ -821,7 +825,6 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void {...@@ -821,7 +825,6 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void {
821 },825 },
822 };826 };
823 const target_vaddr_with_addend = target_vaddr + reloc.addend;827 const target_vaddr_with_addend = target_vaddr + reloc.addend;
824 if (target_vaddr_with_addend == reloc.prev_vaddr) continue;
825828
826 log.debug(" ({x}: [() => 0x{x} ({s})) ({s})", .{829 log.debug(" ({x}: [() => 0x{x} ({s})) ({s})", .{
827 source_sym.value + reloc.offset,830 source_sym.value + reloc.offset,
...@@ -830,6 +833,8 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void {...@@ -830,6 +833,8 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void {
830 @tagName(reloc.@"type"),833 @tagName(reloc.@"type"),
831 });834 });
832835
836 reloc.dirty = false;
837
833 if (reloc.pcrel) {838 if (reloc.pcrel) {
834 const source_vaddr = source_sym.value + reloc.offset;839 const source_vaddr = source_sym.value + reloc.offset;
835 const disp = target_vaddr_with_addend - source_vaddr - 4;840 const disp = target_vaddr_with_addend - source_vaddr - 4;
...@@ -854,8 +859,6 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void {...@@ -854,8 +859,6 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void {
854 else => unreachable,859 else => unreachable,
855 },860 },
856 }861 }
857
858 reloc.prev_vaddr = target_vaddr_with_addend;
859 }862 }
860}863}
861864
...@@ -1131,7 +1134,9 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,...@@ -1131,7 +1134,9 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,
1131 if (vaddr != sym.value) {1134 if (vaddr != sym.value) {
1132 sym.value = vaddr;1135 sym.value = vaddr;
1133 log.debug(" (updating GOT entry)", .{});1136 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);
1135 try self.writePtrWidthAtom(got_atom);1140 try self.writePtrWidthAtom(got_atom);
1136 }1141 }
1137 } else if (code_len < atom.size) {1142 } else if (code_len < atom.size) {
...@@ -1156,6 +1161,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,...@@ -1156,6 +1161,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,
1156 try self.writePtrWidthAtom(got_atom);1161 try self.writePtrWidthAtom(got_atom);
1157 }1162 }
11581163
1164 self.markRelocsDirty(atom.getSymbolWithLoc());
1159 try self.writeAtom(atom, code);1165 try self.writeAtom(atom, code);
1160}1166}
11611167
...@@ -1457,7 +1463,6 @@ pub fn getDeclVAddr(...@@ -1457,7 +1463,6 @@ pub fn getDeclVAddr(
14571463
1458 const atom = self.atom_by_index_table.get(reloc_info.parent_atom_index).?;1464 const atom = self.atom_by_index_table.get(reloc_info.parent_atom_index).?;
1459 const target = SymbolWithLoc{ .sym_index = decl.link.coff.sym_index, .file = null };1465 const target = SymbolWithLoc{ .sym_index = decl.link.coff.sym_index, .file = null };
1460 const target_sym = self.getSymbol(target);
1461 try atom.addRelocation(self, .{1466 try atom.addRelocation(self, .{
1462 .@"type" = .direct,1467 .@"type" = .direct,
1463 .target = target,1468 .target = target,
...@@ -1465,7 +1470,6 @@ pub fn getDeclVAddr(...@@ -1465,7 +1470,6 @@ pub fn getDeclVAddr(
1465 .addend = reloc_info.addend,1470 .addend = reloc_info.addend,
1466 .pcrel = false,1471 .pcrel = false,
1467 .length = 3,1472 .length = 3,
1468 .prev_vaddr = target_sym.value,
1469 });1473 });
1470 try atom.addBaseRelocation(self, @intCast(u32, reloc_info.offset));1474 try atom.addBaseRelocation(self, @intCast(u32, reloc_info.offset));
14711475