| ... | @@ -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. |
| 115 | base_relocs: BaseRelocationTable = .{}, | 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 | pub const Reloc = struct { | 117 | pub 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 | }; |
| 135 | | 130 | |
| 136 | const RelocTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Reloc)); | 131 | const RelocTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Reloc)); |
| 137 | const BaseRelocationTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(u32)); | 132 | const BaseRelocationTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(u32)); |
| 138 | const BindingTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(SymbolWithLoc)); | | |
| 139 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom)); | 133 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom)); |
| 140 | | 134 | |
| 141 | const default_file_alignment: u16 = 0x200; | 135 | const default_file_alignment: u16 = 0x200; |
| ... | @@ -192,6 +186,16 @@ pub const SymbolWithLoc = struct { | ... | @@ -192,6 +186,16 @@ pub const SymbolWithLoc = struct { |
| 192 | | 186 | |
| 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 | }; |
| 196 | | 200 | |
| 197 | /// When allocating, the ideal_capacity is calculated by | 201 | /// 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 | } |
| 326 | | 322 | |
| 327 | fn populateMissingMetadata(self: *Coff) !void { | 323 | fn 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 | }); |
| 725 | | 720 | |
| 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 { |
| 753 | | 748 | |
| 754 | log.debug("allocated import atom at 0x{x}", .{sym.value}); | 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 | return atom; | 751 | return atom; |
| 761 | } | 752 | } |
| 762 | | 753 | |
| ... | @@ -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 | } |
| 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 | fn resolveRelocs(self: *Coff, atom: *Atom) !void { | 803 | fn 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)}); |
| 808 | | 810 | |
| 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; | | |
| 825 | | 828 | |
| 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 | }); |
| 832 | | 835 | |
| | 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 | } |
| 861 | | 864 | |
| ... | @@ -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 | } |
| 1158 | | 1163 | |
| | 1164 | self.markRelocsDirty(atom.getSymbolWithLoc()); |
| 1159 | try self.writeAtom(atom, code); | 1165 | try self.writeAtom(atom, code); |
| 1160 | } | 1166 | } |
| 1161 | | 1167 | |
| ... | @@ -1457,7 +1463,6 @@ pub fn getDeclVAddr( | ... | @@ -1457,7 +1463,6 @@ pub fn getDeclVAddr( |
| 1457 | | 1463 | |
| 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)); |
| 1471 | | 1475 | |