| ... | @@ -127,7 +127,7 @@ globals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | ... | @@ -127,7 +127,7 @@ globals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 127 | imports: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 127 | imports: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 128 | undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 128 | undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 129 | tentatives: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 129 | tentatives: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 130 | symbol_resolver: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{}, | 130 | symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{}, |
| 131 | | 131 | |
| 132 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, | 132 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 133 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, | 133 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| ... | @@ -135,6 +135,7 @@ globals_free_list: std.ArrayListUnmanaged(u32) = .{}, | ... | @@ -135,6 +135,7 @@ globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 135 | stub_helper_stubs_start_off: ?u64 = null, | 135 | stub_helper_stubs_start_off: ?u64 = null, |
| 136 | | 136 | |
| 137 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 137 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| | 138 | strtab_dir: std.HashMapUnmanaged(u32, u32, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, |
| 138 | | 139 | |
| 139 | got_entries: std.ArrayListUnmanaged(GotIndirectionKey) = .{}, | 140 | got_entries: std.ArrayListUnmanaged(GotIndirectionKey) = .{}, |
| 140 | got_entries_map: std.AutoHashMapUnmanaged(GotIndirectionKey, u32) = .{}, | 141 | got_entries_map: std.AutoHashMapUnmanaged(GotIndirectionKey, u32) = .{}, |
| ... | @@ -199,6 +200,33 @@ blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{}, | ... | @@ -199,6 +200,33 @@ blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{}, |
| 199 | /// backends. | 200 | /// backends. |
| 200 | pie_fixups: std.ArrayListUnmanaged(PIEFixup) = .{}, | 201 | pie_fixups: std.ArrayListUnmanaged(PIEFixup) = .{}, |
| 201 | | 202 | |
| | 203 | const StringIndexContext = struct { |
| | 204 | strtab: *std.ArrayListUnmanaged(u8), |
| | 205 | |
| | 206 | pub fn eql(self: StringIndexContext, a: u32, b: u32) bool { |
| | 207 | return a == b; |
| | 208 | } |
| | 209 | |
| | 210 | pub fn hash(self: StringIndexContext, x: u32) u64 { |
| | 211 | const x_slice = mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr) + x); |
| | 212 | return std.hash_map.hashString(x_slice); |
| | 213 | } |
| | 214 | }; |
| | 215 | |
| | 216 | pub const StringSliceAdapter = struct { |
| | 217 | strtab: *std.ArrayListUnmanaged(u8), |
| | 218 | |
| | 219 | pub fn eql(self: StringSliceAdapter, a_slice: []const u8, b: u32) bool { |
| | 220 | const b_slice = mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr) + b); |
| | 221 | return mem.eql(u8, a_slice, b_slice); |
| | 222 | } |
| | 223 | |
| | 224 | pub fn hash(self: StringSliceAdapter, adapted_key: []const u8) u64 { |
| | 225 | _ = self; |
| | 226 | return std.hash_map.hashString(adapted_key); |
| | 227 | } |
| | 228 | }; |
| | 229 | |
| 202 | const SymbolWithLoc = struct { | 230 | const SymbolWithLoc = struct { |
| 203 | // Table where the symbol can be found. | 231 | // Table where the symbol can be found. |
| 204 | where: enum { | 232 | where: enum { |
| ... | @@ -882,7 +910,10 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void { | ... | @@ -882,7 +910,10 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void { |
| 882 | | 910 | |
| 883 | { | 911 | { |
| 884 | // Add dyld_stub_binder as the final GOT entry. | 912 | // Add dyld_stub_binder as the final GOT entry. |
| 885 | const resolv = self.symbol_resolver.get("dyld_stub_binder") orelse unreachable; | 913 | const n_strx = self.strtab_dir.getAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{ |
| | 914 | .strtab = &self.strtab, |
| | 915 | }) orelse unreachable; |
| | 916 | const resolv = self.symbol_resolver.get(n_strx) orelse unreachable; |
| 886 | const got_index = @intCast(u32, self.got_entries.items.len); | 917 | const got_index = @intCast(u32, self.got_entries.items.len); |
| 887 | const got_entry = GotIndirectionKey{ | 918 | const got_entry = GotIndirectionKey{ |
| 888 | .where = .import, | 919 | .where = .import, |
| ... | @@ -1722,14 +1753,17 @@ fn allocateTextBlocks(self: *MachO) !void { | ... | @@ -1722,14 +1753,17 @@ fn allocateTextBlocks(self: *MachO) !void { |
| 1722 | } | 1753 | } |
| 1723 | | 1754 | |
| 1724 | // Update globals | 1755 | // Update globals |
| 1725 | for (self.symbol_resolver.values()) |resolv| { | 1756 | { |
| 1726 | if (resolv.where != .global) continue; | 1757 | var sym_it = self.symbol_resolver.valueIterator(); |
| 1727 | | 1758 | while (sym_it.next()) |resolv| { |
| 1728 | assert(resolv.local_sym_index != 0); | 1759 | if (resolv.where != .global) continue; |
| 1729 | const local_sym = self.locals.items[resolv.local_sym_index]; | 1760 | |
| 1730 | const sym = &self.globals.items[resolv.where_index]; | 1761 | assert(resolv.local_sym_index != 0); |
| 1731 | sym.n_value = local_sym.n_value; | 1762 | const local_sym = self.locals.items[resolv.local_sym_index]; |
| 1732 | sym.n_sect = local_sym.n_sect; | 1763 | const sym = &self.globals.items[resolv.where_index]; |
| | 1764 | sym.n_value = local_sym.n_value; |
| | 1765 | sym.n_sect = local_sym.n_sect; |
| | 1766 | } |
| 1733 | } | 1767 | } |
| 1734 | } | 1768 | } |
| 1735 | | 1769 | |
| ... | @@ -1821,7 +1855,10 @@ fn writeStubHelperCommon(self: *MachO) !void { | ... | @@ -1821,7 +1855,10 @@ fn writeStubHelperCommon(self: *MachO) !void { |
| 1821 | code[9] = 0xff; | 1855 | code[9] = 0xff; |
| 1822 | code[10] = 0x25; | 1856 | code[10] = 0x25; |
| 1823 | { | 1857 | { |
| 1824 | const resolv = self.symbol_resolver.get("dyld_stub_binder") orelse unreachable; | 1858 | const n_strx = self.strtab_dir.getAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{ |
| | 1859 | .strtab = &self.strtab, |
| | 1860 | }) orelse unreachable; |
| | 1861 | const resolv = self.symbol_resolver.get(n_strx) orelse unreachable; |
| 1825 | const got_index = self.got_entries_map.get(.{ | 1862 | const got_index = self.got_entries_map.get(.{ |
| 1826 | .where = .import, | 1863 | .where = .import, |
| 1827 | .where_index = resolv.where_index, | 1864 | .where_index = resolv.where_index, |
| ... | @@ -1869,7 +1906,10 @@ fn writeStubHelperCommon(self: *MachO) !void { | ... | @@ -1869,7 +1906,10 @@ fn writeStubHelperCommon(self: *MachO) !void { |
| 1869 | code[10] = 0xbf; | 1906 | code[10] = 0xbf; |
| 1870 | code[11] = 0xa9; | 1907 | code[11] = 0xa9; |
| 1871 | binder_blk_outer: { | 1908 | binder_blk_outer: { |
| 1872 | const resolv = self.symbol_resolver.get("dyld_stub_binder") orelse unreachable; | 1909 | const n_strx = self.strtab_dir.getAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{ |
| | 1910 | .strtab = &self.strtab, |
| | 1911 | }) orelse unreachable; |
| | 1912 | const resolv = self.symbol_resolver.get(n_strx) orelse unreachable; |
| 1873 | const got_index = self.got_entries_map.get(.{ | 1913 | const got_index = self.got_entries_map.get(.{ |
| 1874 | .where = .import, | 1914 | .where = .import, |
| 1875 | .where_index = resolv.where_index, | 1915 | .where_index = resolv.where_index, |
| ... | @@ -1965,19 +2005,9 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { | ... | @@ -1965,19 +2005,9 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 1965 | return error.UnhandledSymbolType; | 2005 | return error.UnhandledSymbolType; |
| 1966 | } | 2006 | } |
| 1967 | | 2007 | |
| | 2008 | const n_strx = try self.makeString(sym_name); |
| 1968 | if (symbolIsSect(sym)) { | 2009 | if (symbolIsSect(sym)) { |
| 1969 | // Defined symbol regardless of scope lands in the locals symbol table. | 2010 | // Defined symbol regardless of scope lands in the locals symbol table. |
| 1970 | const n_strx = blk: { | | |
| 1971 | if (self.symbol_resolver.get(sym_name)) |resolv| { | | |
| 1972 | switch (resolv.where) { | | |
| 1973 | .global => break :blk self.globals.items[resolv.where_index].n_strx, | | |
| 1974 | .tentative => break :blk self.tentatives.items[resolv.where_index].n_strx, | | |
| 1975 | .undef => break :blk self.undefs.items[resolv.where_index].n_strx, | | |
| 1976 | .import => unreachable, | | |
| 1977 | } | | |
| 1978 | } | | |
| 1979 | break :blk try self.makeString(sym_name); | | |
| 1980 | }; | | |
| 1981 | const local_sym_index = @intCast(u32, self.locals.items.len); | 2011 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 1982 | try self.locals.append(self.base.allocator, .{ | 2012 | try self.locals.append(self.base.allocator, .{ |
| 1983 | .n_strx = n_strx, | 2013 | .n_strx = n_strx, |
| ... | @@ -1993,7 +2023,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { | ... | @@ -1993,7 +2023,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 1993 | if (!symbolIsExt(sym)) continue; | 2023 | if (!symbolIsExt(sym)) continue; |
| 1994 | | 2024 | |
| 1995 | const local = self.locals.items[local_sym_index]; | 2025 | const local = self.locals.items[local_sym_index]; |
| 1996 | const resolv = self.symbol_resolver.getPtr(sym_name) orelse { | 2026 | const resolv = self.symbol_resolver.getPtr(n_strx) orelse { |
| 1997 | const global_sym_index = @intCast(u32, self.globals.items.len); | 2027 | const global_sym_index = @intCast(u32, self.globals.items.len); |
| 1998 | try self.globals.append(self.base.allocator, .{ | 2028 | try self.globals.append(self.base.allocator, .{ |
| 1999 | .n_strx = n_strx, | 2029 | .n_strx = n_strx, |
| ... | @@ -2002,7 +2032,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { | ... | @@ -2002,7 +2032,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2002 | .n_desc = sym.n_desc, | 2032 | .n_desc = sym.n_desc, |
| 2003 | .n_value = sym.n_value, | 2033 | .n_value = sym.n_value, |
| 2004 | }); | 2034 | }); |
| 2005 | try self.symbol_resolver.putNoClobber(self.base.allocator, try self.base.allocator.dupe(u8, sym_name), .{ | 2035 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ |
| 2006 | .where = .global, | 2036 | .where = .global, |
| 2007 | .where_index = global_sym_index, | 2037 | .where_index = global_sym_index, |
| 2008 | .local_sym_index = local_sym_index, | 2038 | .local_sym_index = local_sym_index, |
| ... | @@ -2072,7 +2102,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { | ... | @@ -2072,7 +2102,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2072 | }; | 2102 | }; |
| 2073 | } else if (symbolIsTentative(sym)) { | 2103 | } else if (symbolIsTentative(sym)) { |
| 2074 | // Symbol is a tentative definition. | 2104 | // Symbol is a tentative definition. |
| 2075 | const resolv = self.symbol_resolver.getPtr(sym_name) orelse { | 2105 | const resolv = self.symbol_resolver.getPtr(n_strx) orelse { |
| 2076 | const tent_sym_index = @intCast(u32, self.tentatives.items.len); | 2106 | const tent_sym_index = @intCast(u32, self.tentatives.items.len); |
| 2077 | try self.tentatives.append(self.base.allocator, .{ | 2107 | try self.tentatives.append(self.base.allocator, .{ |
| 2078 | .n_strx = try self.makeString(sym_name), | 2108 | .n_strx = try self.makeString(sym_name), |
| ... | @@ -2081,7 +2111,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { | ... | @@ -2081,7 +2111,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2081 | .n_desc = sym.n_desc, | 2111 | .n_desc = sym.n_desc, |
| 2082 | .n_value = sym.n_value, | 2112 | .n_value = sym.n_value, |
| 2083 | }); | 2113 | }); |
| 2084 | try self.symbol_resolver.putNoClobber(self.base.allocator, try self.base.allocator.dupe(u8, sym_name), .{ | 2114 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ |
| 2085 | .where = .tentative, | 2115 | .where = .tentative, |
| 2086 | .where_index = tent_sym_index, | 2116 | .where_index = tent_sym_index, |
| 2087 | .file = object_id, | 2117 | .file = object_id, |
| ... | @@ -2126,7 +2156,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { | ... | @@ -2126,7 +2156,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2126 | } | 2156 | } |
| 2127 | } else { | 2157 | } else { |
| 2128 | // Symbol is undefined. | 2158 | // Symbol is undefined. |
| 2129 | if (self.symbol_resolver.contains(sym_name)) continue; | 2159 | if (self.symbol_resolver.contains(n_strx)) continue; |
| 2130 | | 2160 | |
| 2131 | const undef_sym_index = @intCast(u32, self.undefs.items.len); | 2161 | const undef_sym_index = @intCast(u32, self.undefs.items.len); |
| 2132 | try self.undefs.append(self.base.allocator, .{ | 2162 | try self.undefs.append(self.base.allocator, .{ |
| ... | @@ -2136,7 +2166,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { | ... | @@ -2136,7 +2166,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2136 | .n_desc = 0, | 2166 | .n_desc = 0, |
| 2137 | .n_value = 0, | 2167 | .n_value = 0, |
| 2138 | }); | 2168 | }); |
| 2139 | try self.symbol_resolver.putNoClobber(self.base.allocator, try self.base.allocator.dupe(u8, sym_name), .{ | 2169 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ |
| 2140 | .where = .undef, | 2170 | .where = .undef, |
| 2141 | .where_index = undef_sym_index, | 2171 | .where_index = undef_sym_index, |
| 2142 | .file = object_id, | 2172 | .file = object_id, |
| ... | @@ -2214,7 +2244,7 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2214,7 +2244,7 @@ fn resolveSymbols(self: *MachO) !void { |
| 2214 | mem.set(u8, code, 0); | 2244 | mem.set(u8, code, 0); |
| 2215 | const alignment = (sym.n_desc >> 8) & 0x0f; | 2245 | const alignment = (sym.n_desc >> 8) & 0x0f; |
| 2216 | | 2246 | |
| 2217 | const resolv = self.symbol_resolver.getPtr(sym_name) orelse unreachable; | 2247 | const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable; |
| 2218 | const local_sym_index = @intCast(u32, self.locals.items.len); | 2248 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 2219 | var nlist = macho.nlist_64{ | 2249 | var nlist = macho.nlist_64{ |
| 2220 | .n_strx = sym.n_strx, | 2250 | .n_strx = sym.n_strx, |
| ... | @@ -2263,15 +2293,16 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2263,15 +2293,16 @@ fn resolveSymbols(self: *MachO) !void { |
| 2263 | // Third pass, resolve symbols in dynamic libraries. | 2293 | // Third pass, resolve symbols in dynamic libraries. |
| 2264 | { | 2294 | { |
| 2265 | // Put dyld_stub_binder as an undefined special symbol. | 2295 | // Put dyld_stub_binder as an undefined special symbol. |
| | 2296 | const n_strx = try self.makeString("dyld_stub_binder"); |
| 2266 | const undef_sym_index = @intCast(u32, self.undefs.items.len); | 2297 | const undef_sym_index = @intCast(u32, self.undefs.items.len); |
| 2267 | try self.undefs.append(self.base.allocator, .{ | 2298 | try self.undefs.append(self.base.allocator, .{ |
| 2268 | .n_strx = try self.makeString("dyld_stub_binder"), | 2299 | .n_strx = n_strx, |
| 2269 | .n_type = macho.N_UNDF, | 2300 | .n_type = macho.N_UNDF, |
| 2270 | .n_sect = 0, | 2301 | .n_sect = 0, |
| 2271 | .n_desc = 0, | 2302 | .n_desc = 0, |
| 2272 | .n_value = 0, | 2303 | .n_value = 0, |
| 2273 | }); | 2304 | }); |
| 2274 | try self.symbol_resolver.putNoClobber(self.base.allocator, try self.base.allocator.dupe(u8, "dyld_stub_binder"), .{ | 2305 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ |
| 2275 | .where = .undef, | 2306 | .where = .undef, |
| 2276 | .where_index = undef_sym_index, | 2307 | .where_index = undef_sym_index, |
| 2277 | }); | 2308 | }); |
| ... | @@ -2304,7 +2335,7 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2304,7 +2335,7 @@ fn resolveSymbols(self: *MachO) !void { |
| 2304 | try referenced.putNoClobber(dylib, {}); | 2335 | try referenced.putNoClobber(dylib, {}); |
| 2305 | } | 2336 | } |
| 2306 | | 2337 | |
| 2307 | const resolv = self.symbol_resolver.getPtr(sym_name) orelse unreachable; | 2338 | const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable; |
| 2308 | const undef = &self.undefs.items[resolv.where_index]; | 2339 | const undef = &self.undefs.items[resolv.where_index]; |
| 2309 | const import_sym_index = @intCast(u32, self.imports.items.len); | 2340 | const import_sym_index = @intCast(u32, self.imports.items.len); |
| 2310 | try self.imports.append(self.base.allocator, .{ | 2341 | try self.imports.append(self.base.allocator, .{ |
| ... | @@ -2331,7 +2362,10 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2331,7 +2362,10 @@ fn resolveSymbols(self: *MachO) !void { |
| 2331 | } | 2362 | } |
| 2332 | | 2363 | |
| 2333 | // Fourth pass, handle synthetic symbols and flag any undefined references. | 2364 | // Fourth pass, handle synthetic symbols and flag any undefined references. |
| 2334 | if (self.symbol_resolver.getPtr("___dso_handle")) |resolv| blk: { | 2365 | if (self.strtab_dir.getAdapted(@as([]const u8, "___dso_handle"), StringSliceAdapter{ |
| | 2366 | .strtab = &self.strtab, |
| | 2367 | })) |n_strx| blk: { |
| | 2368 | const resolv = self.symbol_resolver.getPtr(n_strx) orelse break :blk; |
| 2335 | if (resolv.where != .undef) break :blk; | 2369 | if (resolv.where != .undef) break :blk; |
| 2336 | | 2370 | |
| 2337 | const undef = &self.undefs.items[resolv.where_index]; | 2371 | const undef = &self.undefs.items[resolv.where_index]; |
| ... | @@ -2390,7 +2424,7 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2390,7 +2424,7 @@ fn resolveSymbols(self: *MachO) !void { |
| 2390 | if (symbolIsNull(sym)) continue; | 2424 | if (symbolIsNull(sym)) continue; |
| 2391 | | 2425 | |
| 2392 | const sym_name = self.getString(sym.n_strx); | 2426 | const sym_name = self.getString(sym.n_strx); |
| 2393 | const resolv = self.symbol_resolver.get(sym_name) orelse unreachable; | 2427 | const resolv = self.symbol_resolver.get(sym.n_strx) orelse unreachable; |
| 2394 | | 2428 | |
| 2395 | log.err("undefined reference to symbol '{s}'", .{sym_name}); | 2429 | log.err("undefined reference to symbol '{s}'", .{sym_name}); |
| 2396 | log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name.?}); | 2430 | log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name.?}); |
| ... | @@ -2830,10 +2864,13 @@ fn setEntryPoint(self: *MachO) !void { | ... | @@ -2830,10 +2864,13 @@ fn setEntryPoint(self: *MachO) !void { |
| 2830 | // TODO we should respect the -entry flag passed in by the user to set a custom | 2864 | // TODO we should respect the -entry flag passed in by the user to set a custom |
| 2831 | // entrypoint. For now, assume default of `_main`. | 2865 | // entrypoint. For now, assume default of `_main`. |
| 2832 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 2866 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2833 | const resolv = self.symbol_resolver.get("_main") orelse { | 2867 | const n_strx = self.strtab_dir.getAdapted(@as([]const u8, "_main"), StringSliceAdapter{ |
| | 2868 | .strtab = &self.strtab, |
| | 2869 | }) orelse { |
| 2834 | log.err("'_main' export not found", .{}); | 2870 | log.err("'_main' export not found", .{}); |
| 2835 | return error.MissingMainEntrypoint; | 2871 | return error.MissingMainEntrypoint; |
| 2836 | }; | 2872 | }; |
| | 2873 | const resolv = self.symbol_resolver.get(n_strx) orelse unreachable; |
| 2837 | assert(resolv.where == .global); | 2874 | assert(resolv.where == .global); |
| 2838 | const sym = self.globals.items[resolv.where_index]; | 2875 | const sym = self.globals.items[resolv.where_index]; |
| 2839 | const ec = &self.load_commands.items[self.main_cmd_index.?].Main; | 2876 | const ec = &self.load_commands.items[self.main_cmd_index.?].Main; |
| ... | @@ -3235,6 +3272,7 @@ pub fn deinit(self: *MachO) void { | ... | @@ -3235,6 +3272,7 @@ pub fn deinit(self: *MachO) void { |
| 3235 | self.got_entries_free_list.deinit(self.base.allocator); | 3272 | self.got_entries_free_list.deinit(self.base.allocator); |
| 3236 | self.stubs.deinit(self.base.allocator); | 3273 | self.stubs.deinit(self.base.allocator); |
| 3237 | self.stubs_map.deinit(self.base.allocator); | 3274 | self.stubs_map.deinit(self.base.allocator); |
| | 3275 | self.strtab_dir.deinit(self.base.allocator); |
| 3238 | self.strtab.deinit(self.base.allocator); | 3276 | self.strtab.deinit(self.base.allocator); |
| 3239 | self.undefs.deinit(self.base.allocator); | 3277 | self.undefs.deinit(self.base.allocator); |
| 3240 | self.tentatives.deinit(self.base.allocator); | 3278 | self.tentatives.deinit(self.base.allocator); |
| ... | @@ -3243,10 +3281,6 @@ pub fn deinit(self: *MachO) void { | ... | @@ -3243,10 +3281,6 @@ pub fn deinit(self: *MachO) void { |
| 3243 | self.globals_free_list.deinit(self.base.allocator); | 3281 | self.globals_free_list.deinit(self.base.allocator); |
| 3244 | self.locals.deinit(self.base.allocator); | 3282 | self.locals.deinit(self.base.allocator); |
| 3245 | self.locals_free_list.deinit(self.base.allocator); | 3283 | self.locals_free_list.deinit(self.base.allocator); |
| 3246 | | | |
| 3247 | for (self.symbol_resolver.keys()) |key| { | | |
| 3248 | self.base.allocator.free(key); | | |
| 3249 | } | | |
| 3250 | self.symbol_resolver.deinit(self.base.allocator); | 3284 | self.symbol_resolver.deinit(self.base.allocator); |
| 3251 | | 3285 | |
| 3252 | for (self.objects.items) |object| { | 3286 | for (self.objects.items) |object| { |
| ... | @@ -3715,9 +3749,7 @@ pub fn updateDeclExports( | ... | @@ -3715,9 +3749,7 @@ pub fn updateDeclExports( |
| 3715 | .n_desc = n_desc, | 3749 | .n_desc = n_desc, |
| 3716 | .n_value = decl_sym.n_value, | 3750 | .n_value = decl_sym.n_value, |
| 3717 | }; | 3751 | }; |
| 3718 | const resolv_name = try self.base.allocator.dupe(u8, exp_name); | 3752 | const resolv = try self.symbol_resolver.getOrPut(self.base.allocator, name_str_index); |
| 3719 | const resolv = try self.symbol_resolver.getOrPut(self.base.allocator, resolv_name); | | |
| 3720 | defer if (resolv.found_existing) self.base.allocator.free(resolv_name); | | |
| 3721 | resolv.value_ptr.* = .{ | 3753 | resolv.value_ptr.* = .{ |
| 3722 | .where = .global, | 3754 | .where = .global, |
| 3723 | .where_index = i, | 3755 | .where_index = i, |
| ... | @@ -4233,17 +4265,19 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -4233,17 +4265,19 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 4233 | }); | 4265 | }); |
| 4234 | self.load_commands_dirty = true; | 4266 | self.load_commands_dirty = true; |
| 4235 | } | 4267 | } |
| 4236 | if (!self.symbol_resolver.contains("dyld_stub_binder")) { | 4268 | if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{ |
| | 4269 | .strtab = &self.strtab, |
| | 4270 | })) { |
| 4237 | const import_sym_index = @intCast(u32, self.imports.items.len); | 4271 | const import_sym_index = @intCast(u32, self.imports.items.len); |
| | 4272 | const n_strx = try self.makeString("dyld_stub_binder"); |
| 4238 | try self.imports.append(self.base.allocator, .{ | 4273 | try self.imports.append(self.base.allocator, .{ |
| 4239 | .n_strx = try self.makeString("dyld_stub_binder"), | 4274 | .n_strx = n_strx, |
| 4240 | .n_type = macho.N_UNDF | macho.N_EXT, | 4275 | .n_type = macho.N_UNDF | macho.N_EXT, |
| 4241 | .n_sect = 0, | 4276 | .n_sect = 0, |
| 4242 | .n_desc = packDylibOrdinal(1), | 4277 | .n_desc = packDylibOrdinal(1), |
| 4243 | .n_value = 0, | 4278 | .n_value = 0, |
| 4244 | }); | 4279 | }); |
| 4245 | const name = try self.base.allocator.dupe(u8, "dyld_stub_binder"); | 4280 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ |
| 4246 | try self.symbol_resolver.putNoClobber(self.base.allocator, name, .{ | | |
| 4247 | .where = .import, | 4281 | .where = .import, |
| 4248 | .where_index = import_sym_index, | 4282 | .where_index = import_sym_index, |
| 4249 | }); | 4283 | }); |
| ... | @@ -4370,24 +4404,26 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, | ... | @@ -4370,24 +4404,26 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, |
| 4370 | | 4404 | |
| 4371 | pub fn addExternFn(self: *MachO, name: []const u8) !u32 { | 4405 | pub fn addExternFn(self: *MachO, name: []const u8) !u32 { |
| 4372 | const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name}); | 4406 | const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name}); |
| 4373 | const already_defined = self.symbol_resolver.contains(sym_name); | 4407 | defer self.base.allocator.free(sym_name); |
| 4374 | | 4408 | |
| 4375 | if (already_defined) { | 4409 | if (self.strtab_dir.getAdapted(@as([]const u8, sym_name), StringSliceAdapter{ |
| 4376 | const resolv = self.symbol_resolver.get(sym_name) orelse unreachable; | 4410 | .strtab = &self.strtab, |
| 4377 | self.base.allocator.free(sym_name); | 4411 | })) |n_strx| { |
| | 4412 | const resolv = self.symbol_resolver.get(n_strx) orelse unreachable; |
| 4378 | return resolv.where_index; | 4413 | return resolv.where_index; |
| 4379 | } | 4414 | } |
| 4380 | | 4415 | |
| 4381 | log.debug("adding new extern function '{s}' with dylib ordinal 1", .{sym_name}); | 4416 | log.debug("adding new extern function '{s}' with dylib ordinal 1", .{sym_name}); |
| 4382 | const import_sym_index = @intCast(u32, self.imports.items.len); | 4417 | const import_sym_index = @intCast(u32, self.imports.items.len); |
| | 4418 | const n_strx = try self.makeString(sym_name); |
| 4383 | try self.imports.append(self.base.allocator, .{ | 4419 | try self.imports.append(self.base.allocator, .{ |
| 4384 | .n_strx = try self.makeString(sym_name), | 4420 | .n_strx = n_strx, |
| 4385 | .n_type = macho.N_UNDF | macho.N_EXT, | 4421 | .n_type = macho.N_UNDF | macho.N_EXT, |
| 4386 | .n_sect = 0, | 4422 | .n_sect = 0, |
| 4387 | .n_desc = packDylibOrdinal(1), | 4423 | .n_desc = packDylibOrdinal(1), |
| 4388 | .n_value = 0, | 4424 | .n_value = 0, |
| 4389 | }); | 4425 | }); |
| 4390 | try self.symbol_resolver.putNoClobber(self.base.allocator, sym_name, .{ | 4426 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ |
| 4391 | .where = .import, | 4427 | .where = .import, |
| 4392 | .where_index = import_sym_index, | 4428 | .where_index = import_sym_index, |
| 4393 | }); | 4429 | }); |
| ... | @@ -5609,6 +5645,11 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { | ... | @@ -5609,6 +5645,11 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 5609 | } | 5645 | } |
| 5610 | | 5646 | |
| 5611 | pub fn makeString(self: *MachO, string: []const u8) !u32 { | 5647 | pub fn makeString(self: *MachO, string: []const u8) !u32 { |
| | 5648 | if (self.strtab_dir.getAdapted(@as([]const u8, string), StringSliceAdapter{ .strtab = &self.strtab })) |off| { |
| | 5649 | log.debug("reusing string '{s}' at offset 0x{x}", .{ string, off }); |
| | 5650 | return off; |
| | 5651 | } |
| | 5652 | |
| 5612 | try self.strtab.ensureUnusedCapacity(self.base.allocator, string.len + 1); | 5653 | try self.strtab.ensureUnusedCapacity(self.base.allocator, string.len + 1); |
| 5613 | const new_off = @intCast(u32, self.strtab.items.len); | 5654 | const new_off = @intCast(u32, self.strtab.items.len); |
| 5614 | | 5655 | |
| ... | @@ -5617,6 +5658,10 @@ pub fn makeString(self: *MachO, string: []const u8) !u32 { | ... | @@ -5617,6 +5658,10 @@ pub fn makeString(self: *MachO, string: []const u8) !u32 { |
| 5617 | self.strtab.appendSliceAssumeCapacity(string); | 5658 | self.strtab.appendSliceAssumeCapacity(string); |
| 5618 | self.strtab.appendAssumeCapacity(0); | 5659 | self.strtab.appendAssumeCapacity(0); |
| 5619 | | 5660 | |
| | 5661 | try self.strtab_dir.putContext(self.base.allocator, new_off, new_off, StringIndexContext{ |
| | 5662 | .strtab = &self.strtab, |
| | 5663 | }); |
| | 5664 | |
| 5620 | return new_off; | 5665 | return new_off; |
| 5621 | } | 5666 | } |
| 5622 | | 5667 | |