| ... | @@ -162,7 +162,10 @@ strtab: std.ArrayListUnmanaged(u8) = .{}, | ... | @@ -162,7 +162,10 @@ strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 162 | strtab_dir: std.HashMapUnmanaged(u32, void, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, | 162 | strtab_dir: std.HashMapUnmanaged(u32, void, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, |
| 163 | | 163 | |
| 164 | got_entries_map: std.AutoArrayHashMapUnmanaged(Atom.Relocation.Target, *Atom) = .{}, | 164 | got_entries_map: std.AutoArrayHashMapUnmanaged(Atom.Relocation.Target, *Atom) = .{}, |
| | 165 | got_entries_map_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| | 166 | |
| 165 | stubs_map: std.AutoArrayHashMapUnmanaged(u32, *Atom) = .{}, | 167 | stubs_map: std.AutoArrayHashMapUnmanaged(u32, *Atom) = .{}, |
| | 168 | stubs_map_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 166 | | 169 | |
| 167 | error_flags: File.ErrorFlags = File.ErrorFlags{}, | 170 | error_flags: File.ErrorFlags = File.ErrorFlags{}, |
| 168 | | 171 | |
| ... | @@ -175,6 +178,7 @@ has_stabs: bool = false, | ... | @@ -175,6 +178,7 @@ has_stabs: bool = false, |
| 175 | /// TODO once we add opening a prelinked output binary from file, this will become | 178 | /// TODO once we add opening a prelinked output binary from file, this will become |
| 176 | /// obsolete as we will carry on where we left off. | 179 | /// obsolete as we will carry on where we left off. |
| 177 | cold_start: bool = false, | 180 | cold_start: bool = false, |
| | 181 | invalidate_relocs: bool = false, |
| 178 | | 182 | |
| 179 | section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{}, | 183 | section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{}, |
| 180 | | 184 | |
| ... | @@ -610,9 +614,24 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -610,9 +614,24 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 610 | sym.n_desc = 0; | 614 | sym.n_desc = 0; |
| 611 | }, | 615 | }, |
| 612 | } | 616 | } |
| | 617 | if (self.got_entries_map.getIndex(.{ .global = entry.key })) |i| { |
| | 618 | self.got_entries_map_free_list.append( |
| | 619 | self.base.allocator, |
| | 620 | @intCast(u32, i), |
| | 621 | ) catch {}; |
| | 622 | self.got_entries_map.keys()[i] = .{ .local = 0 }; |
| | 623 | } |
| | 624 | if (self.stubs_map.getIndex(entry.key)) |i| { |
| | 625 | self.stubs_map_free_list.append(self.base.allocator, @intCast(u32, i)) catch {}; |
| | 626 | self.stubs_map.keys()[i] = 0; |
| | 627 | } |
| 613 | } | 628 | } |
| 614 | } | 629 | } |
| 615 | } | 630 | } |
| | 631 | // Invalidate all relocs |
| | 632 | // TODO we only need to invalidate the backlinks to the relinked atoms from |
| | 633 | // the relocatable object files. |
| | 634 | self.invalidate_relocs = true; |
| 616 | | 635 | |
| 617 | // Positional arguments to the linker such as object files and static archives. | 636 | // Positional arguments to the linker such as object files and static archives. |
| 618 | var positionals = std.ArrayList([]const u8).init(arena); | 637 | var positionals = std.ArrayList([]const u8).init(arena); |
| ... | @@ -889,6 +908,19 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -889,6 +908,19 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 889 | } | 908 | } |
| 890 | } | 909 | } |
| 891 | | 910 | |
| | 911 | log.debug("GOT entries:", .{}); |
| | 912 | for (self.got_entries_map.keys()) |key| { |
| | 913 | switch (key) { |
| | 914 | .local => |sym_index| log.debug(" {} => {d}", .{ key, sym_index }), |
| | 915 | .global => |n_strx| log.debug(" {} => {s}", .{ key, self.getString(n_strx) }), |
| | 916 | } |
| | 917 | } |
| | 918 | |
| | 919 | log.debug("stubs:", .{}); |
| | 920 | for (self.stubs_map.keys()) |key| { |
| | 921 | log.debug(" {} => {s}", .{ key, self.getString(key) }); |
| | 922 | } |
| | 923 | |
| 892 | try self.writeAtoms(); | 924 | try self.writeAtoms(); |
| 893 | | 925 | |
| 894 | if (self.bss_section_index) |idx| { | 926 | if (self.bss_section_index) |idx| { |
| ... | @@ -1838,7 +1870,7 @@ fn writeAtoms(self: *MachO) !void { | ... | @@ -1838,7 +1870,7 @@ fn writeAtoms(self: *MachO) !void { |
| 1838 | } | 1870 | } |
| 1839 | | 1871 | |
| 1840 | while (true) { | 1872 | while (true) { |
| 1841 | if (atom.dirty) { | 1873 | if (atom.dirty or self.invalidate_relocs) { |
| 1842 | const atom_sym = self.locals.items[atom.local_sym_index]; | 1874 | const atom_sym = self.locals.items[atom.local_sym_index]; |
| 1843 | const padding_size: u64 = if (atom.next) |next| blk: { | 1875 | const padding_size: u64 = if (atom.next) |next| blk: { |
| 1844 | const next_sym = self.locals.items[next.local_sym_index]; | 1876 | const next_sym = self.locals.items[next.local_sym_index]; |
| ... | @@ -2907,7 +2939,9 @@ pub fn deinit(self: *MachO) void { | ... | @@ -2907,7 +2939,9 @@ pub fn deinit(self: *MachO) void { |
| 2907 | | 2939 | |
| 2908 | self.section_ordinals.deinit(self.base.allocator); | 2940 | self.section_ordinals.deinit(self.base.allocator); |
| 2909 | self.got_entries_map.deinit(self.base.allocator); | 2941 | self.got_entries_map.deinit(self.base.allocator); |
| | 2942 | self.got_entries_map_free_list.deinit(self.base.allocator); |
| 2910 | self.stubs_map.deinit(self.base.allocator); | 2943 | self.stubs_map.deinit(self.base.allocator); |
| | 2944 | self.stubs_map_free_list.deinit(self.base.allocator); |
| 2911 | self.strtab_dir.deinit(self.base.allocator); | 2945 | self.strtab_dir.deinit(self.base.allocator); |
| 2912 | self.strtab.deinit(self.base.allocator); | 2946 | self.strtab.deinit(self.base.allocator); |
| 2913 | self.undefs.deinit(self.base.allocator); | 2947 | self.undefs.deinit(self.base.allocator); |
| ... | @@ -3091,8 +3125,22 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { | ... | @@ -3091,8 +3125,22 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { |
| 3091 | | 3125 | |
| 3092 | // TODO try popping from free list first before allocating a new GOT atom. | 3126 | // TODO try popping from free list first before allocating a new GOT atom. |
| 3093 | const target = Atom.Relocation.Target{ .local = decl.link.macho.local_sym_index }; | 3127 | const target = Atom.Relocation.Target{ .local = decl.link.macho.local_sym_index }; |
| 3094 | const got_atom = try self.createGotAtom(target); | 3128 | const value_ptr = blk: { |
| 3095 | try self.got_entries_map.put(self.base.allocator, target, got_atom); | 3129 | if (self.got_entries_map_free_list.popOrNull()) |i| { |
| | 3130 | log.debug("reusing GOT entry index {d} for {s}", .{ i, decl.name }); |
| | 3131 | self.got_entries_map.keys()[i] = target; |
| | 3132 | const value_ptr = self.got_entries_map.getPtr(target).?; |
| | 3133 | break :blk value_ptr; |
| | 3134 | } else { |
| | 3135 | const res = try self.got_entries_map.getOrPut(self.base.allocator, target); |
| | 3136 | log.debug("creating new GOT entry at index {d} for {s}", .{ |
| | 3137 | self.got_entries_map.getIndex(target).?, |
| | 3138 | decl.name, |
| | 3139 | }); |
| | 3140 | break :blk res.value_ptr; |
| | 3141 | } |
| | 3142 | }; |
| | 3143 | value_ptr.* = try self.createGotAtom(target); |
| 3096 | } | 3144 | } |
| 3097 | | 3145 | |
| 3098 | pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { | 3146 | pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { |
| ... | @@ -3516,7 +3564,9 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { | ... | @@ -3516,7 +3564,9 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { |
| 3516 | if (decl.link.macho.local_sym_index != 0) { | 3564 | if (decl.link.macho.local_sym_index != 0) { |
| 3517 | self.locals_free_list.append(self.base.allocator, decl.link.macho.local_sym_index) catch {}; | 3565 | self.locals_free_list.append(self.base.allocator, decl.link.macho.local_sym_index) catch {}; |
| 3518 | | 3566 | |
| 3519 | // TODO free GOT atom here. | 3567 | // Try freeing GOT atom |
| | 3568 | const got_index = self.got_entries_map.getIndex(.{ .local = decl.link.macho.local_sym_index }).?; |
| | 3569 | self.got_entries_map_free_list.append(self.base.allocator, @intCast(u32, got_index)) catch {}; |
| 3520 | | 3570 | |
| 3521 | self.locals.items[decl.link.macho.local_sym_index].n_type = 0; | 3571 | self.locals.items[decl.link.macho.local_sym_index].n_type = 0; |
| 3522 | decl.link.macho.local_sym_index = 0; | 3572 | decl.link.macho.local_sym_index = 0; |
| ... | @@ -4907,7 +4957,7 @@ fn writeSymbolTable(self: *MachO) !void { | ... | @@ -4907,7 +4957,7 @@ fn writeSymbolTable(self: *MachO) !void { |
| 4907 | | 4957 | |
| 4908 | stubs.reserved1 = 0; | 4958 | stubs.reserved1 = 0; |
| 4909 | for (self.stubs_map.keys()) |key| { | 4959 | for (self.stubs_map.keys()) |key| { |
| 4910 | const resolv = self.symbol_resolver.get(key).?; | 4960 | const resolv = self.symbol_resolver.get(key) orelse continue; |
| 4911 | switch (resolv.where) { | 4961 | switch (resolv.where) { |
| 4912 | .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), | 4962 | .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), |
| 4913 | .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + resolv.where_index), | 4963 | .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + resolv.where_index), |
| ... | @@ -4919,7 +4969,7 @@ fn writeSymbolTable(self: *MachO) !void { | ... | @@ -4919,7 +4969,7 @@ fn writeSymbolTable(self: *MachO) !void { |
| 4919 | switch (key) { | 4969 | switch (key) { |
| 4920 | .local => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), | 4970 | .local => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), |
| 4921 | .global => |n_strx| { | 4971 | .global => |n_strx| { |
| 4922 | const resolv = self.symbol_resolver.get(n_strx).?; | 4972 | const resolv = self.symbol_resolver.get(n_strx) orelse continue; |
| 4923 | switch (resolv.where) { | 4973 | switch (resolv.where) { |
| 4924 | .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), | 4974 | .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), |
| 4925 | .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + resolv.where_index), | 4975 | .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + resolv.where_index), |
| ... | @@ -4930,7 +4980,7 @@ fn writeSymbolTable(self: *MachO) !void { | ... | @@ -4930,7 +4980,7 @@ fn writeSymbolTable(self: *MachO) !void { |
| 4930 | | 4980 | |
| 4931 | la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries; | 4981 | la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries; |
| 4932 | for (self.stubs_map.keys()) |key| { | 4982 | for (self.stubs_map.keys()) |key| { |
| 4933 | const resolv = self.symbol_resolver.get(key).?; | 4983 | const resolv = self.symbol_resolver.get(key) orelse continue; |
| 4934 | switch (resolv.where) { | 4984 | switch (resolv.where) { |
| 4935 | .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), | 4985 | .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), |
| 4936 | .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + resolv.where_index), | 4986 | .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + resolv.where_index), |
| ... | @@ -5346,7 +5396,7 @@ fn snapshotState(self: *MachO) !void { | ... | @@ -5346,7 +5396,7 @@ fn snapshotState(self: *MachO) !void { |
| 5346 | }; | 5396 | }; |
| 5347 | | 5397 | |
| 5348 | if (is_via_got) { | 5398 | if (is_via_got) { |
| 5349 | const got_atom = self.got_entries_map.get(rel.target).?; | 5399 | const got_atom = self.got_entries_map.get(rel.target) orelse break :blk 0; |
| 5350 | break :blk self.locals.items[got_atom.local_sym_index].n_value; | 5400 | break :blk self.locals.items[got_atom.local_sym_index].n_value; |
| 5351 | } | 5401 | } |
| 5352 | | 5402 | |