| ... | ... | @@ -114,11 +114,6 @@ relocs: RelocTable = .{}, |
| 114 | 114 | /// this will be a table indexed by index into the list of Atoms. |
| 115 | 115 | base_relocs: BaseRelocationTable = .{}, |
| 116 | 116 | |
| 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. |
| 120 | | bindings: BindingTable = .{}, |
| 121 | | |
| 122 | 117 | pub const Reloc = struct { |
| 123 | 118 | @"type": enum { |
| 124 | 119 | got, |
| ... | ... | @@ -130,12 +125,11 @@ pub const Reloc = struct { |
| 130 | 125 | addend: u32, |
| 131 | 126 | pcrel: bool, |
| 132 | 127 | length: u2, |
| 133 | | prev_vaddr: u32, |
| 128 | dirty: bool = true, |
| 134 | 129 | }; |
| 135 | 130 | |
| 136 | 131 | const RelocTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Reloc)); |
| 137 | 132 | const BaseRelocationTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(u32)); |
| 138 | | const BindingTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(SymbolWithLoc)); |
| 139 | 133 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom)); |
| 140 | 134 | |
| 141 | 135 | const default_file_alignment: u16 = 0x200; |
| ... | ... | @@ -192,6 +186,16 @@ pub const SymbolWithLoc = struct { |
| 192 | 186 | |
| 193 | 187 | // null means it's a synthetic global or Zig source. |
| 194 | 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 | }; |
| 196 | 200 | |
| 197 | 201 | /// When allocating, the ideal_capacity is calculated by |
| ... | ... | @@ -314,14 +318,6 @@ pub fn deinit(self: *Coff) void { |
| 314 | 318 | } |
| 315 | 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 | } |
| 326 | 322 | |
| 327 | 323 | fn populateMissingMetadata(self: *Coff) !void { |
| ... | ... | @@ -720,7 +716,6 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom { |
| 720 | 716 | .addend = 0, |
| 721 | 717 | .pcrel = false, |
| 722 | 718 | .length = 3, |
| 723 | | .prev_vaddr = sym.value, |
| 724 | 719 | }); |
| 725 | 720 | |
| 726 | 721 | const target_sym = self.getSymbol(target); |
| ... | ... | @@ -753,10 +748,6 @@ fn createImportAtom(self: *Coff, target: SymbolWithLoc) !*Atom { |
| 753 | 748 | |
| 754 | 749 | log.debug("allocated import atom at 0x{x}", .{sym.value}); |
| 755 | 750 | |
| 756 | | const target_sym = self.getSymbol(target); |
| 757 | | assert(target_sym.section_number == .UNDEFINED); |
| 758 | | try atom.addBinding(self, target); |
| 759 | | |
| 760 | 751 | return atom; |
| 761 | 752 | } |
| 762 | 753 | |
| ... | ... | @@ -798,6 +789,17 @@ fn writePtrWidthAtom(self: *Coff, atom: *Atom) !void { |
| 798 | 789 | } |
| 799 | 790 | } |
| 800 | 791 | |
| 792 | fn 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 | |
| 801 | 803 | fn resolveRelocs(self: *Coff, atom: *Atom) !void { |
| 802 | 804 | const relocs = self.relocs.get(atom) orelse return; |
| 803 | 805 | const source_sym = atom.getSymbol(self); |
| ... | ... | @@ -807,6 +809,8 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void { |
| 807 | 809 | log.debug("relocating '{s}'", .{atom.getName(self)}); |
| 808 | 810 | |
| 809 | 811 | for (relocs.items) |*reloc| { |
| 812 | if (!reloc.dirty) continue; |
| 813 | |
| 810 | 814 | const target_vaddr = switch (reloc.@"type") { |
| 811 | 815 | .got => blk: { |
| 812 | 816 | const got_atom = self.getGotAtomForSymbol(reloc.target) orelse continue; |
| ... | ... | @@ -821,7 +825,6 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void { |
| 821 | 825 | }, |
| 822 | 826 | }; |
| 823 | 827 | const target_vaddr_with_addend = target_vaddr + reloc.addend; |
| 824 | | if (target_vaddr_with_addend == reloc.prev_vaddr) continue; |
| 825 | 828 | |
| 826 | 829 | log.debug(" ({x}: [() => 0x{x} ({s})) ({s})", .{ |
| 827 | 830 | source_sym.value + reloc.offset, |
| ... | ... | @@ -830,6 +833,8 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void { |
| 830 | 833 | @tagName(reloc.@"type"), |
| 831 | 834 | }); |
| 832 | 835 | |
| 836 | reloc.dirty = false; |
| 837 | |
| 833 | 838 | if (reloc.pcrel) { |
| 834 | 839 | const source_vaddr = source_sym.value + reloc.offset; |
| 835 | 840 | const disp = target_vaddr_with_addend - source_vaddr - 4; |
| ... | ... | @@ -854,8 +859,6 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void { |
| 854 | 859 | else => unreachable, |
| 855 | 860 | }, |
| 856 | 861 | } |
| 857 | | |
| 858 | | reloc.prev_vaddr = target_vaddr_with_addend; |
| 859 | 862 | } |
| 860 | 863 | } |
| 861 | 864 | |
| ... | ... | @@ -1131,7 +1134,9 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, |
| 1131 | 1134 | if (vaddr != sym.value) { |
| 1132 | 1135 | sym.value = vaddr; |
| 1133 | 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 | 1140 | try self.writePtrWidthAtom(got_atom); |
| 1136 | 1141 | } |
| 1137 | 1142 | } else if (code_len < atom.size) { |
| ... | ... | @@ -1156,6 +1161,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, |
| 1156 | 1161 | try self.writePtrWidthAtom(got_atom); |
| 1157 | 1162 | } |
| 1158 | 1163 | |
| 1164 | self.markRelocsDirty(atom.getSymbolWithLoc()); |
| 1159 | 1165 | try self.writeAtom(atom, code); |
| 1160 | 1166 | } |
| 1161 | 1167 | |
| ... | ... | @@ -1457,7 +1463,6 @@ pub fn getDeclVAddr( |
| 1457 | 1463 | |
| 1458 | 1464 | const atom = self.atom_by_index_table.get(reloc_info.parent_atom_index).?; |
| 1459 | 1465 | const target = SymbolWithLoc{ .sym_index = decl.link.coff.sym_index, .file = null }; |
| 1460 | | const target_sym = self.getSymbol(target); |
| 1461 | 1466 | try atom.addRelocation(self, .{ |
| 1462 | 1467 | .@"type" = .direct, |
| 1463 | 1468 | .target = target, |
| ... | ... | @@ -1465,7 +1470,6 @@ pub fn getDeclVAddr( |
| 1465 | 1470 | .addend = reloc_info.addend, |
| 1466 | 1471 | .pcrel = false, |
| 1467 | 1472 | .length = 3, |
| 1468 | | .prev_vaddr = target_sym.value, |
| 1469 | 1473 | }); |
| 1470 | 1474 | try atom.addBaseRelocation(self, @intCast(u32, reloc_info.offset)); |
| 1471 | 1475 | |