| ... | ... | @@ -127,7 +127,7 @@ globals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 127 | 127 | imports: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 128 | 128 | undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 129 | 129 | tentatives: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 130 | | symbol_resolver: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{}, |
| 130 | symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{}, |
| 131 | 131 | |
| 132 | 132 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 133 | 133 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| ... | ... | @@ -135,6 +135,7 @@ globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 135 | 135 | stub_helper_stubs_start_off: ?u64 = null, |
| 136 | 136 | |
| 137 | 137 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 138 | strtab_dir: std.HashMapUnmanaged(u32, u32, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, |
| 138 | 139 | |
| 139 | 140 | got_entries: std.ArrayListUnmanaged(GotIndirectionKey) = .{}, |
| 140 | 141 | got_entries_map: std.AutoHashMapUnmanaged(GotIndirectionKey, u32) = .{}, |
| ... | ... | @@ -199,6 +200,33 @@ blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{}, |
| 199 | 200 | /// backends. |
| 200 | 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 | 230 | const SymbolWithLoc = struct { |
| 203 | 231 | // Table where the symbol can be found. |
| 204 | 232 | where: enum { |
| ... | ... | @@ -882,7 +910,10 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void { |
| 882 | 910 | |
| 883 | 911 | { |
| 884 | 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 | 917 | const got_index = @intCast(u32, self.got_entries.items.len); |
| 887 | 918 | const got_entry = GotIndirectionKey{ |
| 888 | 919 | .where = .import, |
| ... | ... | @@ -1722,14 +1753,17 @@ fn allocateTextBlocks(self: *MachO) !void { |
| 1722 | 1753 | } |
| 1723 | 1754 | |
| 1724 | 1755 | // Update globals |
| 1725 | | for (self.symbol_resolver.values()) |resolv| { |
| 1726 | | if (resolv.where != .global) continue; |
| 1727 | | |
| 1728 | | assert(resolv.local_sym_index != 0); |
| 1729 | | const local_sym = self.locals.items[resolv.local_sym_index]; |
| 1730 | | const sym = &self.globals.items[resolv.where_index]; |
| 1731 | | sym.n_value = local_sym.n_value; |
| 1732 | | sym.n_sect = local_sym.n_sect; |
| 1756 | { |
| 1757 | var sym_it = self.symbol_resolver.valueIterator(); |
| 1758 | while (sym_it.next()) |resolv| { |
| 1759 | if (resolv.where != .global) continue; |
| 1760 | |
| 1761 | assert(resolv.local_sym_index != 0); |
| 1762 | const local_sym = self.locals.items[resolv.local_sym_index]; |
| 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 | 1855 | code[9] = 0xff; |
| 1822 | 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 | 1862 | const got_index = self.got_entries_map.get(.{ |
| 1826 | 1863 | .where = .import, |
| 1827 | 1864 | .where_index = resolv.where_index, |
| ... | ... | @@ -1869,7 +1906,10 @@ fn writeStubHelperCommon(self: *MachO) !void { |
| 1869 | 1906 | code[10] = 0xbf; |
| 1870 | 1907 | code[11] = 0xa9; |
| 1871 | 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 | 1913 | const got_index = self.got_entries_map.get(.{ |
| 1874 | 1914 | .where = .import, |
| 1875 | 1915 | .where_index = resolv.where_index, |
| ... | ... | @@ -1965,19 +2005,9 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 1965 | 2005 | return error.UnhandledSymbolType; |
| 1966 | 2006 | } |
| 1967 | 2007 | |
| 2008 | const n_strx = try self.makeString(sym_name); |
| 1968 | 2009 | if (symbolIsSect(sym)) { |
| 1969 | 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 | 2011 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 1982 | 2012 | try self.locals.append(self.base.allocator, .{ |
| 1983 | 2013 | .n_strx = n_strx, |
| ... | ... | @@ -1993,7 +2023,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 1993 | 2023 | if (!symbolIsExt(sym)) continue; |
| 1994 | 2024 | |
| 1995 | 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 | 2027 | const global_sym_index = @intCast(u32, self.globals.items.len); |
| 1998 | 2028 | try self.globals.append(self.base.allocator, .{ |
| 1999 | 2029 | .n_strx = n_strx, |
| ... | ... | @@ -2002,7 +2032,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2002 | 2032 | .n_desc = sym.n_desc, |
| 2003 | 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 | 2036 | .where = .global, |
| 2007 | 2037 | .where_index = global_sym_index, |
| 2008 | 2038 | .local_sym_index = local_sym_index, |
| ... | ... | @@ -2072,7 +2102,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2072 | 2102 | }; |
| 2073 | 2103 | } else if (symbolIsTentative(sym)) { |
| 2074 | 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 | 2106 | const tent_sym_index = @intCast(u32, self.tentatives.items.len); |
| 2077 | 2107 | try self.tentatives.append(self.base.allocator, .{ |
| 2078 | 2108 | .n_strx = try self.makeString(sym_name), |
| ... | ... | @@ -2081,7 +2111,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2081 | 2111 | .n_desc = sym.n_desc, |
| 2082 | 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 | 2115 | .where = .tentative, |
| 2086 | 2116 | .where_index = tent_sym_index, |
| 2087 | 2117 | .file = object_id, |
| ... | ... | @@ -2126,7 +2156,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2126 | 2156 | } |
| 2127 | 2157 | } else { |
| 2128 | 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 | 2161 | const undef_sym_index = @intCast(u32, self.undefs.items.len); |
| 2132 | 2162 | try self.undefs.append(self.base.allocator, .{ |
| ... | ... | @@ -2136,7 +2166,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2136 | 2166 | .n_desc = 0, |
| 2137 | 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 | 2170 | .where = .undef, |
| 2141 | 2171 | .where_index = undef_sym_index, |
| 2142 | 2172 | .file = object_id, |
| ... | ... | @@ -2214,7 +2244,7 @@ fn resolveSymbols(self: *MachO) !void { |
| 2214 | 2244 | mem.set(u8, code, 0); |
| 2215 | 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 | 2248 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 2219 | 2249 | var nlist = macho.nlist_64{ |
| 2220 | 2250 | .n_strx = sym.n_strx, |
| ... | ... | @@ -2263,15 +2293,16 @@ fn resolveSymbols(self: *MachO) !void { |
| 2263 | 2293 | // Third pass, resolve symbols in dynamic libraries. |
| 2264 | 2294 | { |
| 2265 | 2295 | // Put dyld_stub_binder as an undefined special symbol. |
| 2296 | const n_strx = try self.makeString("dyld_stub_binder"); |
| 2266 | 2297 | const undef_sym_index = @intCast(u32, self.undefs.items.len); |
| 2267 | 2298 | try self.undefs.append(self.base.allocator, .{ |
| 2268 | | .n_strx = try self.makeString("dyld_stub_binder"), |
| 2299 | .n_strx = n_strx, |
| 2269 | 2300 | .n_type = macho.N_UNDF, |
| 2270 | 2301 | .n_sect = 0, |
| 2271 | 2302 | .n_desc = 0, |
| 2272 | 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 | 2306 | .where = .undef, |
| 2276 | 2307 | .where_index = undef_sym_index, |
| 2277 | 2308 | }); |
| ... | ... | @@ -2304,7 +2335,7 @@ fn resolveSymbols(self: *MachO) !void { |
| 2304 | 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 | 2339 | const undef = &self.undefs.items[resolv.where_index]; |
| 2309 | 2340 | const import_sym_index = @intCast(u32, self.imports.items.len); |
| 2310 | 2341 | try self.imports.append(self.base.allocator, .{ |
| ... | ... | @@ -2331,7 +2362,10 @@ fn resolveSymbols(self: *MachO) !void { |
| 2331 | 2362 | } |
| 2332 | 2363 | |
| 2333 | 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 | 2369 | if (resolv.where != .undef) break :blk; |
| 2336 | 2370 | |
| 2337 | 2371 | const undef = &self.undefs.items[resolv.where_index]; |
| ... | ... | @@ -2390,7 +2424,7 @@ fn resolveSymbols(self: *MachO) !void { |
| 2390 | 2424 | if (symbolIsNull(sym)) continue; |
| 2391 | 2425 | |
| 2392 | 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 | 2429 | log.err("undefined reference to symbol '{s}'", .{sym_name}); |
| 2396 | 2430 | log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name.?}); |
| ... | ... | @@ -2830,10 +2864,13 @@ fn setEntryPoint(self: *MachO) !void { |
| 2830 | 2864 | // TODO we should respect the -entry flag passed in by the user to set a custom |
| 2831 | 2865 | // entrypoint. For now, assume default of `_main`. |
| 2832 | 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 | 2870 | log.err("'_main' export not found", .{}); |
| 2835 | 2871 | return error.MissingMainEntrypoint; |
| 2836 | 2872 | }; |
| 2873 | const resolv = self.symbol_resolver.get(n_strx) orelse unreachable; |
| 2837 | 2874 | assert(resolv.where == .global); |
| 2838 | 2875 | const sym = self.globals.items[resolv.where_index]; |
| 2839 | 2876 | const ec = &self.load_commands.items[self.main_cmd_index.?].Main; |
| ... | ... | @@ -3235,6 +3272,7 @@ pub fn deinit(self: *MachO) void { |
| 3235 | 3272 | self.got_entries_free_list.deinit(self.base.allocator); |
| 3236 | 3273 | self.stubs.deinit(self.base.allocator); |
| 3237 | 3274 | self.stubs_map.deinit(self.base.allocator); |
| 3275 | self.strtab_dir.deinit(self.base.allocator); |
| 3238 | 3276 | self.strtab.deinit(self.base.allocator); |
| 3239 | 3277 | self.undefs.deinit(self.base.allocator); |
| 3240 | 3278 | self.tentatives.deinit(self.base.allocator); |
| ... | ... | @@ -3243,10 +3281,6 @@ pub fn deinit(self: *MachO) void { |
| 3243 | 3281 | self.globals_free_list.deinit(self.base.allocator); |
| 3244 | 3282 | self.locals.deinit(self.base.allocator); |
| 3245 | 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 | 3284 | self.symbol_resolver.deinit(self.base.allocator); |
| 3251 | 3285 | |
| 3252 | 3286 | for (self.objects.items) |object| { |
| ... | ... | @@ -3715,9 +3749,7 @@ pub fn updateDeclExports( |
| 3715 | 3749 | .n_desc = n_desc, |
| 3716 | 3750 | .n_value = decl_sym.n_value, |
| 3717 | 3751 | }; |
| 3718 | | const resolv_name = try self.base.allocator.dupe(u8, exp_name); |
| 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); |
| 3752 | const resolv = try self.symbol_resolver.getOrPut(self.base.allocator, name_str_index); |
| 3721 | 3753 | resolv.value_ptr.* = .{ |
| 3722 | 3754 | .where = .global, |
| 3723 | 3755 | .where_index = i, |
| ... | ... | @@ -4233,17 +4265,19 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 4233 | 4265 | }); |
| 4234 | 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 | 4271 | const import_sym_index = @intCast(u32, self.imports.items.len); |
| 4272 | const n_strx = try self.makeString("dyld_stub_binder"); |
| 4238 | 4273 | try self.imports.append(self.base.allocator, .{ |
| 4239 | | .n_strx = try self.makeString("dyld_stub_binder"), |
| 4274 | .n_strx = n_strx, |
| 4240 | 4275 | .n_type = macho.N_UNDF | macho.N_EXT, |
| 4241 | 4276 | .n_sect = 0, |
| 4242 | 4277 | .n_desc = packDylibOrdinal(1), |
| 4243 | 4278 | .n_value = 0, |
| 4244 | 4279 | }); |
| 4245 | | const name = try self.base.allocator.dupe(u8, "dyld_stub_binder"); |
| 4246 | | try self.symbol_resolver.putNoClobber(self.base.allocator, name, .{ |
| 4280 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ |
| 4247 | 4281 | .where = .import, |
| 4248 | 4282 | .where_index = import_sym_index, |
| 4249 | 4283 | }); |
| ... | ... | @@ -4370,24 +4404,26 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, |
| 4370 | 4404 | |
| 4371 | 4405 | pub fn addExternFn(self: *MachO, name: []const u8) !u32 { |
| 4372 | 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) { |
| 4376 | | const resolv = self.symbol_resolver.get(sym_name) orelse unreachable; |
| 4377 | | self.base.allocator.free(sym_name); |
| 4409 | if (self.strtab_dir.getAdapted(@as([]const u8, sym_name), StringSliceAdapter{ |
| 4410 | .strtab = &self.strtab, |
| 4411 | })) |n_strx| { |
| 4412 | const resolv = self.symbol_resolver.get(n_strx) orelse unreachable; |
| 4378 | 4413 | return resolv.where_index; |
| 4379 | 4414 | } |
| 4380 | 4415 | |
| 4381 | 4416 | log.debug("adding new extern function '{s}' with dylib ordinal 1", .{sym_name}); |
| 4382 | 4417 | const import_sym_index = @intCast(u32, self.imports.items.len); |
| 4418 | const n_strx = try self.makeString(sym_name); |
| 4383 | 4419 | try self.imports.append(self.base.allocator, .{ |
| 4384 | | .n_strx = try self.makeString(sym_name), |
| 4420 | .n_strx = n_strx, |
| 4385 | 4421 | .n_type = macho.N_UNDF | macho.N_EXT, |
| 4386 | 4422 | .n_sect = 0, |
| 4387 | 4423 | .n_desc = packDylibOrdinal(1), |
| 4388 | 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 | 4427 | .where = .import, |
| 4392 | 4428 | .where_index = import_sym_index, |
| 4393 | 4429 | }); |
| ... | ... | @@ -5609,6 +5645,11 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 5609 | 5645 | } |
| 5610 | 5646 | |
| 5611 | 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 | 5653 | try self.strtab.ensureUnusedCapacity(self.base.allocator, string.len + 1); |
| 5613 | 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 | 5658 | self.strtab.appendSliceAssumeCapacity(string); |
| 5618 | 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 | 5665 | return new_off; |
| 5621 | 5666 | } |
| 5622 | 5667 | |