| ... | ... | @@ -134,9 +134,7 @@ objc_data_section_index: ?u16 = null, |
| 134 | 134 | |
| 135 | 135 | locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 136 | 136 | globals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 137 | | imports: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 138 | 137 | undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 139 | | tentatives: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 140 | 138 | symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{}, |
| 141 | 139 | |
| 142 | 140 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| ... | ... | @@ -252,9 +250,7 @@ const SymbolWithLoc = struct { |
| 252 | 250 | // Table where the symbol can be found. |
| 253 | 251 | where: enum { |
| 254 | 252 | global, |
| 255 | | import, |
| 256 | 253 | undef, |
| 257 | | tentative, |
| 258 | 254 | }, |
| 259 | 255 | where_index: u32, |
| 260 | 256 | local_sym_index: u32 = 0, |
| ... | ... | @@ -264,22 +260,11 @@ const SymbolWithLoc = struct { |
| 264 | 260 | pub const GotIndirectionKey = struct { |
| 265 | 261 | where: enum { |
| 266 | 262 | local, |
| 267 | | import, |
| 263 | undef, |
| 268 | 264 | }, |
| 269 | 265 | where_index: u32, |
| 270 | 266 | }; |
| 271 | 267 | |
| 272 | | pub const PIEFixup = struct { |
| 273 | | /// Target VM address of this relocation. |
| 274 | | target_addr: u64, |
| 275 | | |
| 276 | | /// Offset within the byte stream. |
| 277 | | offset: usize, |
| 278 | | |
| 279 | | /// Size of the relocation. |
| 280 | | size: usize, |
| 281 | | }; |
| 282 | | |
| 283 | 268 | /// When allocating, the ideal_capacity is calculated by |
| 284 | 269 | /// actual_capacity + (actual_capacity / ideal_factor) |
| 285 | 270 | const ideal_factor = 2; |
| ... | ... | @@ -960,7 +945,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void { |
| 960 | 945 | const resolv = self.symbol_resolver.get(n_strx) orelse unreachable; |
| 961 | 946 | const got_index = @intCast(u32, self.got_entries.items.len); |
| 962 | 947 | const got_entry = GotIndirectionKey{ |
| 963 | | .where = .import, |
| 948 | .where = .undef, |
| 964 | 949 | .where_index = resolv.where_index, |
| 965 | 950 | }; |
| 966 | 951 | try self.got_entries.append(self.base.allocator, got_entry); |
| ... | ... | @@ -1991,7 +1976,7 @@ fn writeStubHelperCommon(self: *MachO) !void { |
| 1991 | 1976 | }) orelse unreachable; |
| 1992 | 1977 | const resolv = self.symbol_resolver.get(n_strx) orelse unreachable; |
| 1993 | 1978 | const got_index = self.got_entries_map.get(.{ |
| 1994 | | .where = .import, |
| 1979 | .where = .undef, |
| 1995 | 1980 | .where_index = resolv.where_index, |
| 1996 | 1981 | }) orelse unreachable; |
| 1997 | 1982 | const addr = got.addr + got_index * @sizeOf(u64); |
| ... | ... | @@ -2042,7 +2027,7 @@ fn writeStubHelperCommon(self: *MachO) !void { |
| 2042 | 2027 | }) orelse unreachable; |
| 2043 | 2028 | const resolv = self.symbol_resolver.get(n_strx) orelse unreachable; |
| 2044 | 2029 | const got_index = self.got_entries_map.get(.{ |
| 2045 | | .where = .import, |
| 2030 | .where = .undef, |
| 2046 | 2031 | .where_index = resolv.where_index, |
| 2047 | 2032 | }) orelse unreachable; |
| 2048 | 2033 | const this_addr = stub_helper.addr + 3 * @sizeOf(u32); |
| ... | ... | @@ -2106,7 +2091,12 @@ fn writeStubHelperCommon(self: *MachO) !void { |
| 2106 | 2091 | } |
| 2107 | 2092 | } |
| 2108 | 2093 | |
| 2109 | | fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2094 | fn resolveSymbolsInObject( |
| 2095 | self: *MachO, |
| 2096 | object_id: u16, |
| 2097 | tentatives: *std.ArrayList(u32), |
| 2098 | unresolved: *std.ArrayList(u32), |
| 2099 | ) !void { |
| 2110 | 2100 | const object = &self.objects.items[object_id]; |
| 2111 | 2101 | |
| 2112 | 2102 | log.debug("resolving symbols in '{s}'", .{object.name}); |
| ... | ... | @@ -2174,7 +2164,6 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2174 | 2164 | }; |
| 2175 | 2165 | |
| 2176 | 2166 | switch (resolv.where) { |
| 2177 | | .import => unreachable, |
| 2178 | 2167 | .global => { |
| 2179 | 2168 | const global = &self.globals.items[resolv.where_index]; |
| 2180 | 2169 | |
| ... | ... | @@ -2186,8 +2175,16 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2186 | 2175 | log.err(" next definition in '{s}'", .{object.name}); |
| 2187 | 2176 | return error.MultipleSymbolDefinitions; |
| 2188 | 2177 | } |
| 2189 | | |
| 2190 | 2178 | if (symbolIsWeakDef(sym) or symbolIsPext(sym)) continue; // Current symbol is weak, so skip it. |
| 2179 | if (symbolIsTentative(global.*)) { |
| 2180 | var i: usize = 0; |
| 2181 | while (i < tentatives.items.len) : (i += 1) { |
| 2182 | if (tentatives.items[i] == resolv.where_index) { |
| 2183 | _ = tentatives.swapRemove(i); |
| 2184 | break; |
| 2185 | } |
| 2186 | } |
| 2187 | } |
| 2191 | 2188 | |
| 2192 | 2189 | // Otherwise, update the resolver and the global symbol. |
| 2193 | 2190 | global.n_type = sym.n_type; |
| ... | ... | @@ -2205,16 +2202,14 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2205 | 2202 | .n_desc = 0, |
| 2206 | 2203 | .n_value = 0, |
| 2207 | 2204 | }; |
| 2208 | | }, |
| 2209 | | .tentative => { |
| 2210 | | const tentative = &self.tentatives.items[resolv.where_index]; |
| 2211 | | tentative.* = .{ |
| 2212 | | .n_strx = 0, |
| 2213 | | .n_type = macho.N_UNDF, |
| 2214 | | .n_sect = 0, |
| 2215 | | .n_desc = 0, |
| 2216 | | .n_value = 0, |
| 2217 | | }; |
| 2205 | |
| 2206 | var i: usize = 0; |
| 2207 | while (i < unresolved.items.len) : (i += 1) { |
| 2208 | if (unresolved.items[i] == resolv.where_index) { |
| 2209 | _ = unresolved.swapRemove(i); |
| 2210 | break; |
| 2211 | } |
| 2212 | } |
| 2218 | 2213 | }, |
| 2219 | 2214 | } |
| 2220 | 2215 | |
| ... | ... | @@ -2235,8 +2230,8 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2235 | 2230 | } else if (symbolIsTentative(sym)) { |
| 2236 | 2231 | // Symbol is a tentative definition. |
| 2237 | 2232 | const resolv = self.symbol_resolver.getPtr(n_strx) orelse { |
| 2238 | | const tent_sym_index = @intCast(u32, self.tentatives.items.len); |
| 2239 | | try self.tentatives.append(self.base.allocator, .{ |
| 2233 | const global_sym_index = @intCast(u32, self.globals.items.len); |
| 2234 | try self.globals.append(self.base.allocator, .{ |
| 2240 | 2235 | .n_strx = try self.makeString(sym_name), |
| 2241 | 2236 | .n_type = sym.n_type, |
| 2242 | 2237 | .n_sect = 0, |
| ... | ... | @@ -2244,29 +2239,38 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2244 | 2239 | .n_value = sym.n_value, |
| 2245 | 2240 | }); |
| 2246 | 2241 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ |
| 2247 | | .where = .tentative, |
| 2248 | | .where_index = tent_sym_index, |
| 2242 | .where = .global, |
| 2243 | .where_index = global_sym_index, |
| 2249 | 2244 | .file = object_id, |
| 2250 | 2245 | }); |
| 2246 | try tentatives.append(global_sym_index); |
| 2251 | 2247 | continue; |
| 2252 | 2248 | }; |
| 2253 | 2249 | |
| 2254 | 2250 | switch (resolv.where) { |
| 2255 | | .import => unreachable, |
| 2256 | | .global => {}, |
| 2251 | .global => { |
| 2252 | const global = &self.globals.items[resolv.where_index]; |
| 2253 | if (!symbolIsTentative(global.*)) continue; |
| 2254 | if (global.n_value >= sym.n_value) continue; |
| 2255 | |
| 2256 | global.n_desc = sym.n_desc; |
| 2257 | global.n_value = sym.n_value; |
| 2258 | resolv.file = object_id; |
| 2259 | }, |
| 2257 | 2260 | .undef => { |
| 2258 | 2261 | const undef = &self.undefs.items[resolv.where_index]; |
| 2259 | | const tent_sym_index = @intCast(u32, self.tentatives.items.len); |
| 2260 | | try self.tentatives.append(self.base.allocator, .{ |
| 2262 | const global_sym_index = @intCast(u32, self.globals.items.len); |
| 2263 | try self.globals.append(self.base.allocator, .{ |
| 2261 | 2264 | .n_strx = undef.n_strx, |
| 2262 | 2265 | .n_type = sym.n_type, |
| 2263 | 2266 | .n_sect = 0, |
| 2264 | 2267 | .n_desc = sym.n_desc, |
| 2265 | 2268 | .n_value = sym.n_value, |
| 2266 | 2269 | }); |
| 2270 | try tentatives.append(global_sym_index); |
| 2267 | 2271 | resolv.* = .{ |
| 2268 | | .where = .tentative, |
| 2269 | | .where_index = tent_sym_index, |
| 2272 | .where = .global, |
| 2273 | .where_index = global_sym_index, |
| 2270 | 2274 | .file = object_id, |
| 2271 | 2275 | }; |
| 2272 | 2276 | undef.* = .{ |
| ... | ... | @@ -2276,14 +2280,13 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2276 | 2280 | .n_desc = 0, |
| 2277 | 2281 | .n_value = 0, |
| 2278 | 2282 | }; |
| 2279 | | }, |
| 2280 | | .tentative => { |
| 2281 | | const tentative = &self.tentatives.items[resolv.where_index]; |
| 2282 | | if (tentative.n_value >= sym.n_value) continue; |
| 2283 | | |
| 2284 | | tentative.n_desc = sym.n_desc; |
| 2285 | | tentative.n_value = sym.n_value; |
| 2286 | | resolv.file = object_id; |
| 2283 | var i: usize = 0; |
| 2284 | while (i < unresolved.items.len) : (i += 1) { |
| 2285 | if (unresolved.items[i] == resolv.where_index) { |
| 2286 | _ = unresolved.swapRemove(i); |
| 2287 | break; |
| 2288 | } |
| 2289 | } |
| 2287 | 2290 | }, |
| 2288 | 2291 | } |
| 2289 | 2292 | } else { |
| ... | ... | @@ -2303,24 +2306,27 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2303 | 2306 | .where_index = undef_sym_index, |
| 2304 | 2307 | .file = object_id, |
| 2305 | 2308 | }); |
| 2309 | try unresolved.append(undef_sym_index); |
| 2306 | 2310 | } |
| 2307 | 2311 | } |
| 2308 | 2312 | } |
| 2309 | 2313 | |
| 2310 | 2314 | fn resolveSymbols(self: *MachO) !void { |
| 2315 | var tentatives = std.ArrayList(u32).init(self.base.allocator); |
| 2316 | defer tentatives.deinit(); |
| 2317 | |
| 2318 | var unresolved = std.ArrayList(u32).init(self.base.allocator); |
| 2319 | defer unresolved.deinit(); |
| 2320 | |
| 2311 | 2321 | // First pass, resolve symbols in provided objects. |
| 2312 | 2322 | for (self.objects.items) |_, object_id| { |
| 2313 | | try self.resolveSymbolsInObject(@intCast(u16, object_id)); |
| 2323 | try self.resolveSymbolsInObject(@intCast(u16, object_id), &tentatives, &unresolved); |
| 2314 | 2324 | } |
| 2315 | 2325 | |
| 2316 | 2326 | // Second pass, resolve symbols in static libraries. |
| 2317 | 2327 | var next_sym: usize = 0; |
| 2318 | | loop: while (true) : (next_sym += 1) { |
| 2319 | | if (next_sym == self.undefs.items.len) break; |
| 2320 | | |
| 2321 | | const sym = self.undefs.items[next_sym]; |
| 2322 | | if (symbolIsNull(sym)) continue; |
| 2323 | | |
| 2328 | loop: while (next_sym < unresolved.items.len) { |
| 2329 | const sym = self.undefs.items[unresolved.items[next_sym]]; |
| 2324 | 2330 | const sym_name = self.getString(sym.n_strx); |
| 2325 | 2331 | |
| 2326 | 2332 | for (self.archives.items) |archive| { |
| ... | ... | @@ -2334,17 +2340,18 @@ fn resolveSymbols(self: *MachO) !void { |
| 2334 | 2340 | const object_id = @intCast(u16, self.objects.items.len); |
| 2335 | 2341 | const object = try self.objects.addOne(self.base.allocator); |
| 2336 | 2342 | object.* = try archive.parseObject(self.base.allocator, self.base.options.target, offsets.items[0]); |
| 2337 | | try self.resolveSymbolsInObject(object_id); |
| 2343 | try self.resolveSymbolsInObject(object_id, &tentatives, &unresolved); |
| 2338 | 2344 | |
| 2339 | 2345 | continue :loop; |
| 2340 | 2346 | } |
| 2347 | |
| 2348 | next_sym += 1; |
| 2341 | 2349 | } |
| 2342 | 2350 | |
| 2343 | 2351 | // Convert any tentative definition into a regular symbol and allocate |
| 2344 | 2352 | // text blocks for each tentative defintion. |
| 2345 | | for (self.tentatives.items) |sym| { |
| 2346 | | if (symbolIsNull(sym)) continue; |
| 2347 | | |
| 2353 | while (tentatives.popOrNull()) |index| { |
| 2354 | const sym = &self.globals.items[index]; |
| 2348 | 2355 | const match: MatchingSection = blk: { |
| 2349 | 2356 | if (self.common_section_index == null) { |
| 2350 | 2357 | const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| ... | ... | @@ -2366,24 +2373,17 @@ fn resolveSymbols(self: *MachO) !void { |
| 2366 | 2373 | mem.set(u8, code, 0); |
| 2367 | 2374 | const alignment = (sym.n_desc >> 8) & 0x0f; |
| 2368 | 2375 | |
| 2369 | | const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable; |
| 2376 | sym.n_value = 0; |
| 2377 | sym.n_desc = 0; |
| 2378 | sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| 2379 | var local_sym = sym.*; |
| 2380 | local_sym.n_type = macho.N_SECT; |
| 2381 | |
| 2370 | 2382 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 2371 | | var nlist = macho.nlist_64{ |
| 2372 | | .n_strx = sym.n_strx, |
| 2373 | | .n_type = macho.N_SECT, |
| 2374 | | .n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1), |
| 2375 | | .n_desc = 0, |
| 2376 | | .n_value = 0, |
| 2377 | | }; |
| 2378 | | try self.locals.append(self.base.allocator, nlist); |
| 2379 | | const global_sym_index = @intCast(u32, self.globals.items.len); |
| 2380 | | nlist.n_type |= macho.N_EXT; |
| 2381 | | try self.globals.append(self.base.allocator, nlist); |
| 2382 | | resolv.* = .{ |
| 2383 | | .where = .global, |
| 2384 | | .where_index = global_sym_index, |
| 2385 | | .local_sym_index = local_sym_index, |
| 2386 | | }; |
| 2383 | try self.locals.append(self.base.allocator, local_sym); |
| 2384 | |
| 2385 | const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable; |
| 2386 | resolv.local_sym_index = local_sym_index; |
| 2387 | 2387 | |
| 2388 | 2388 | const block = try self.base.allocator.create(TextBlock); |
| 2389 | 2389 | block.* = TextBlock.empty; |
| ... | ... | @@ -2430,13 +2430,15 @@ fn resolveSymbols(self: *MachO) !void { |
| 2430 | 2430 | .where = .undef, |
| 2431 | 2431 | .where_index = undef_sym_index, |
| 2432 | 2432 | }); |
| 2433 | try unresolved.append(undef_sym_index); |
| 2433 | 2434 | } |
| 2434 | 2435 | |
| 2435 | | loop: for (self.undefs.items) |sym| { |
| 2436 | | if (symbolIsNull(sym)) continue; |
| 2437 | | |
| 2436 | next_sym = 0; |
| 2437 | loop: while (next_sym < unresolved.items.len) { |
| 2438 | const sym = self.undefs.items[unresolved.items[next_sym]]; |
| 2438 | 2439 | const sym_name = self.getString(sym.n_strx); |
| 2439 | | for (self.dylibs.items) |*dylib, id| { |
| 2440 | |
| 2441 | for (self.dylibs.items) |dylib, id| { |
| 2440 | 2442 | if (!dylib.symbols.contains(sym_name)) continue; |
| 2441 | 2443 | |
| 2442 | 2444 | const dylib_id = @intCast(u16, id); |
| ... | ... | @@ -2447,28 +2449,15 @@ fn resolveSymbols(self: *MachO) !void { |
| 2447 | 2449 | const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable; |
| 2448 | 2450 | const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable; |
| 2449 | 2451 | const undef = &self.undefs.items[resolv.where_index]; |
| 2450 | | const import_sym_index = @intCast(u32, self.imports.items.len); |
| 2451 | | try self.imports.append(self.base.allocator, .{ |
| 2452 | | .n_strx = undef.n_strx, |
| 2453 | | .n_type = macho.N_UNDF | macho.N_EXT, |
| 2454 | | .n_sect = 0, |
| 2455 | | .n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER, |
| 2456 | | .n_value = 0, |
| 2457 | | }); |
| 2458 | | resolv.* = .{ |
| 2459 | | .where = .import, |
| 2460 | | .where_index = import_sym_index, |
| 2461 | | }; |
| 2462 | | undef.* = .{ |
| 2463 | | .n_strx = 0, |
| 2464 | | .n_type = macho.N_UNDF, |
| 2465 | | .n_sect = 0, |
| 2466 | | .n_desc = 0, |
| 2467 | | .n_value = 0, |
| 2468 | | }; |
| 2452 | undef.n_type |= macho.N_EXT; |
| 2453 | undef.n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER; |
| 2454 | |
| 2455 | _ = unresolved.swapRemove(next_sym); |
| 2469 | 2456 | |
| 2470 | 2457 | continue :loop; |
| 2471 | 2458 | } |
| 2459 | |
| 2460 | next_sym += 1; |
| 2472 | 2461 | } |
| 2473 | 2462 | |
| 2474 | 2463 | // Fourth pass, handle synthetic symbols and flag any undefined references. |
| ... | ... | @@ -2497,6 +2486,14 @@ fn resolveSymbols(self: *MachO) !void { |
| 2497 | 2486 | nlist.n_desc = macho.N_WEAK_DEF; |
| 2498 | 2487 | try self.globals.append(self.base.allocator, nlist); |
| 2499 | 2488 | |
| 2489 | var i: usize = 0; |
| 2490 | while (i < unresolved.items.len) : (i += 1) { |
| 2491 | if (unresolved.items[i] == resolv.where_index) { |
| 2492 | _ = unresolved.swapRemove(i); |
| 2493 | break; |
| 2494 | } |
| 2495 | } |
| 2496 | |
| 2500 | 2497 | undef.* = .{ |
| 2501 | 2498 | .n_strx = 0, |
| 2502 | 2499 | .n_type = macho.N_UNDF, |
| ... | ... | @@ -2529,19 +2526,17 @@ fn resolveSymbols(self: *MachO) !void { |
| 2529 | 2526 | } |
| 2530 | 2527 | } |
| 2531 | 2528 | |
| 2532 | | var has_undefined = false; |
| 2533 | | for (self.undefs.items) |sym| { |
| 2534 | | if (symbolIsNull(sym)) continue; |
| 2535 | | |
| 2529 | for (unresolved.items) |index| { |
| 2530 | const sym = self.undefs.items[index]; |
| 2536 | 2531 | const sym_name = self.getString(sym.n_strx); |
| 2537 | 2532 | const resolv = self.symbol_resolver.get(sym.n_strx) orelse unreachable; |
| 2538 | 2533 | |
| 2539 | 2534 | log.err("undefined reference to symbol '{s}'", .{sym_name}); |
| 2540 | 2535 | log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name}); |
| 2541 | | has_undefined = true; |
| 2542 | 2536 | } |
| 2543 | 2537 | |
| 2544 | | if (has_undefined) return error.UndefinedSymbolReference; |
| 2538 | if (unresolved.items.len > 0) |
| 2539 | return error.UndefinedSymbolReference; |
| 2545 | 2540 | } |
| 2546 | 2541 | |
| 2547 | 2542 | fn parseTextBlocks(self: *MachO) !void { |
| ... | ... | @@ -3006,7 +3001,7 @@ fn writeGotEntries(self: *MachO) !void { |
| 3006 | 3001 | for (self.got_entries.items) |key| { |
| 3007 | 3002 | const address: u64 = switch (key.where) { |
| 3008 | 3003 | .local => self.locals.items[key.where_index].n_value, |
| 3009 | | .import => 0, |
| 3004 | .undef => 0, |
| 3010 | 3005 | }; |
| 3011 | 3006 | try writer.writeIntLittle(u64, address); |
| 3012 | 3007 | } |
| ... | ... | @@ -3075,7 +3070,7 @@ fn writeRebaseInfoTableZld(self: *MachO) !void { |
| 3075 | 3070 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); |
| 3076 | 3071 | |
| 3077 | 3072 | for (self.got_entries.items) |entry, i| { |
| 3078 | | if (entry.where == .import) continue; |
| 3073 | if (entry.where == .undef) continue; |
| 3079 | 3074 | |
| 3080 | 3075 | try pointers.append(.{ |
| 3081 | 3076 | .offset = base_offset + i * @sizeOf(u64), |
| ... | ... | @@ -3132,7 +3127,7 @@ fn writeBindInfoTableZld(self: *MachO) !void { |
| 3132 | 3127 | for (self.got_entries.items) |entry, i| { |
| 3133 | 3128 | if (entry.where == .local) continue; |
| 3134 | 3129 | |
| 3135 | | const sym = self.imports.items[entry.where_index]; |
| 3130 | const sym = self.undefs.items[entry.where_index]; |
| 3136 | 3131 | try pointers.append(.{ |
| 3137 | 3132 | .offset = base_offset + i * @sizeOf(u64), |
| 3138 | 3133 | .segment_id = segment_id, |
| ... | ... | @@ -3157,7 +3152,7 @@ fn writeBindInfoTableZld(self: *MachO) !void { |
| 3157 | 3152 | const base_offset = sym.n_value - seg.inner.vmaddr; |
| 3158 | 3153 | |
| 3159 | 3154 | for (block.bindings.items) |binding| { |
| 3160 | | const bind_sym = self.imports.items[binding.local_sym_index]; |
| 3155 | const bind_sym = self.undefs.items[binding.local_sym_index]; |
| 3161 | 3156 | try pointers.append(.{ |
| 3162 | 3157 | .offset = binding.offset + base_offset, |
| 3163 | 3158 | .segment_id = match.seg, |
| ... | ... | @@ -3204,7 +3199,7 @@ fn writeLazyBindInfoTableZld(self: *MachO) !void { |
| 3204 | 3199 | try pointers.ensureUnusedCapacity(self.stubs.items.len); |
| 3205 | 3200 | |
| 3206 | 3201 | for (self.stubs.items) |import_id, i| { |
| 3207 | | const sym = self.imports.items[import_id]; |
| 3202 | const sym = self.undefs.items[import_id]; |
| 3208 | 3203 | pointers.appendAssumeCapacity(.{ |
| 3209 | 3204 | .offset = base_offset + i * @sizeOf(u64), |
| 3210 | 3205 | .segment_id = segment_id, |
| ... | ... | @@ -3338,7 +3333,7 @@ fn writeSymbolTable(self: *MachO) !void { |
| 3338 | 3333 | |
| 3339 | 3334 | const nlocals = locals.items.len; |
| 3340 | 3335 | const nexports = self.globals.items.len; |
| 3341 | | const nundefs = self.imports.items.len; |
| 3336 | const nundefs = self.undefs.items.len; |
| 3342 | 3337 | |
| 3343 | 3338 | const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64); |
| 3344 | 3339 | const locals_size = nlocals * @sizeOf(macho.nlist_64); |
| ... | ... | @@ -3353,7 +3348,7 @@ fn writeSymbolTable(self: *MachO) !void { |
| 3353 | 3348 | const undefs_off = exports_off + exports_size; |
| 3354 | 3349 | const undefs_size = nundefs * @sizeOf(macho.nlist_64); |
| 3355 | 3350 | log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off }); |
| 3356 | | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.imports.items), undefs_off); |
| 3351 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.undefs.items), undefs_off); |
| 3357 | 3352 | |
| 3358 | 3353 | symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs); |
| 3359 | 3354 | seg.inner.filesize += locals_size + exports_size + undefs_size; |
| ... | ... | @@ -3401,7 +3396,7 @@ fn writeSymbolTable(self: *MachO) !void { |
| 3401 | 3396 | got.reserved1 = nstubs; |
| 3402 | 3397 | for (self.got_entries.items) |entry| { |
| 3403 | 3398 | switch (entry.where) { |
| 3404 | | .import => { |
| 3399 | .undef => { |
| 3405 | 3400 | try writer.writeIntLittle(u32, dysymtab.iundefsym + entry.where_index); |
| 3406 | 3401 | }, |
| 3407 | 3402 | .local => { |
| ... | ... | @@ -3437,8 +3432,6 @@ pub fn deinit(self: *MachO) void { |
| 3437 | 3432 | self.strtab_dir.deinit(self.base.allocator); |
| 3438 | 3433 | self.strtab.deinit(self.base.allocator); |
| 3439 | 3434 | self.undefs.deinit(self.base.allocator); |
| 3440 | | self.tentatives.deinit(self.base.allocator); |
| 3441 | | self.imports.deinit(self.base.allocator); |
| 3442 | 3435 | self.globals.deinit(self.base.allocator); |
| 3443 | 3436 | self.globals_free_list.deinit(self.base.allocator); |
| 3444 | 3437 | self.locals.deinit(self.base.allocator); |
| ... | ... | @@ -4517,9 +4510,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 4517 | 4510 | if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{ |
| 4518 | 4511 | .strtab = &self.strtab, |
| 4519 | 4512 | })) { |
| 4520 | | const import_sym_index = @intCast(u32, self.imports.items.len); |
| 4513 | const import_sym_index = @intCast(u32, self.undefs.items.len); |
| 4521 | 4514 | const n_strx = try self.makeString("dyld_stub_binder"); |
| 4522 | | try self.imports.append(self.base.allocator, .{ |
| 4515 | try self.undefs.append(self.base.allocator, .{ |
| 4523 | 4516 | .n_strx = n_strx, |
| 4524 | 4517 | .n_type = macho.N_UNDF | macho.N_EXT, |
| 4525 | 4518 | .n_sect = 0, |
| ... | ... | @@ -4527,11 +4520,11 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 4527 | 4520 | .n_value = 0, |
| 4528 | 4521 | }); |
| 4529 | 4522 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ |
| 4530 | | .where = .import, |
| 4523 | .where = .undef, |
| 4531 | 4524 | .where_index = import_sym_index, |
| 4532 | 4525 | }); |
| 4533 | 4526 | const got_key = GotIndirectionKey{ |
| 4534 | | .where = .import, |
| 4527 | .where = .undef, |
| 4535 | 4528 | .where_index = import_sym_index, |
| 4536 | 4529 | }; |
| 4537 | 4530 | const got_index = @intCast(u32, self.got_entries.items.len); |
| ... | ... | @@ -4663,9 +4656,9 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 { |
| 4663 | 4656 | } |
| 4664 | 4657 | |
| 4665 | 4658 | log.debug("adding new extern function '{s}' with dylib ordinal 1", .{sym_name}); |
| 4666 | | const import_sym_index = @intCast(u32, self.imports.items.len); |
| 4659 | const import_sym_index = @intCast(u32, self.undefs.items.len); |
| 4667 | 4660 | const n_strx = try self.makeString(sym_name); |
| 4668 | | try self.imports.append(self.base.allocator, .{ |
| 4661 | try self.undefs.append(self.base.allocator, .{ |
| 4669 | 4662 | .n_strx = n_strx, |
| 4670 | 4663 | .n_type = macho.N_UNDF | macho.N_EXT, |
| 4671 | 4664 | .n_sect = 0, |
| ... | ... | @@ -4673,7 +4666,7 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 { |
| 4673 | 4666 | .n_value = 0, |
| 4674 | 4667 | }); |
| 4675 | 4668 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ |
| 4676 | | .where = .import, |
| 4669 | .where = .undef, |
| 4677 | 4670 | .where_index = import_sym_index, |
| 4678 | 4671 | }); |
| 4679 | 4672 | |
| ... | ... | @@ -4856,7 +4849,7 @@ fn writeGotEntry(self: *MachO, index: usize) !void { |
| 4856 | 4849 | const got_entry = self.got_entries.items[index]; |
| 4857 | 4850 | const sym = switch (got_entry.where) { |
| 4858 | 4851 | .local => self.locals.items[got_entry.where_index], |
| 4859 | | .import => self.imports.items[got_entry.where_index], |
| 4852 | .undef => self.undefs.items[got_entry.where_index], |
| 4860 | 4853 | }; |
| 4861 | 4854 | log.debug("writing offset table entry [ 0x{x} => 0x{x} ({s}) ]", .{ |
| 4862 | 4855 | off, |
| ... | ... | @@ -5140,7 +5133,7 @@ fn relocateSymbolTable(self: *MachO) !void { |
| 5140 | 5133 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| 5141 | 5134 | const nlocals = self.locals.items.len; |
| 5142 | 5135 | const nglobals = self.globals.items.len; |
| 5143 | | const nundefs = self.imports.items.len; |
| 5136 | const nundefs = self.undefs.items.len; |
| 5144 | 5137 | const nsyms = nlocals + nglobals + nundefs; |
| 5145 | 5138 | |
| 5146 | 5139 | if (symtab.nsyms < nsyms) { |
| ... | ... | @@ -5185,7 +5178,7 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void { |
| 5185 | 5178 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| 5186 | 5179 | const nlocals = self.locals.items.len; |
| 5187 | 5180 | const nglobals = self.globals.items.len; |
| 5188 | | const nundefs = self.imports.items.len; |
| 5181 | const nundefs = self.undefs.items.len; |
| 5189 | 5182 | |
| 5190 | 5183 | const locals_off = symtab.symoff; |
| 5191 | 5184 | const locals_size = nlocals * @sizeOf(macho.nlist_64); |
| ... | ... | @@ -5198,7 +5191,7 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void { |
| 5198 | 5191 | const undefs_off = globals_off + globals_size; |
| 5199 | 5192 | const undefs_size = nundefs * @sizeOf(macho.nlist_64); |
| 5200 | 5193 | log.debug("writing extern symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off }); |
| 5201 | | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.imports.items), undefs_off); |
| 5194 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.undefs.items), undefs_off); |
| 5202 | 5195 | |
| 5203 | 5196 | // Update dynamic symbol table. |
| 5204 | 5197 | const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab; |
| ... | ... | @@ -5253,7 +5246,7 @@ fn writeIndirectSymbolTable(self: *MachO) !void { |
| 5253 | 5246 | got.reserved1 = nstubs; |
| 5254 | 5247 | for (self.got_entries.items) |entry| { |
| 5255 | 5248 | switch (entry.where) { |
| 5256 | | .import => { |
| 5249 | .undef => { |
| 5257 | 5250 | try writer.writeIntLittle(u32, dysymtab.iundefsym + entry.where_index); |
| 5258 | 5251 | }, |
| 5259 | 5252 | .local => { |
| ... | ... | @@ -5478,7 +5471,7 @@ fn writeRebaseInfoTable(self: *MachO) !void { |
| 5478 | 5471 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); |
| 5479 | 5472 | |
| 5480 | 5473 | for (self.got_entries.items) |entry, i| { |
| 5481 | | if (entry.where == .import) continue; |
| 5474 | if (entry.where == .undef) continue; |
| 5482 | 5475 | |
| 5483 | 5476 | try pointers.append(.{ |
| 5484 | 5477 | .offset = base_offset + i * @sizeOf(u64), |
| ... | ... | @@ -5547,7 +5540,7 @@ fn writeBindInfoTable(self: *MachO) !void { |
| 5547 | 5540 | for (self.got_entries.items) |entry, i| { |
| 5548 | 5541 | if (entry.where == .local) continue; |
| 5549 | 5542 | |
| 5550 | | const sym = self.imports.items[entry.where_index]; |
| 5543 | const sym = self.undefs.items[entry.where_index]; |
| 5551 | 5544 | try pointers.append(.{ |
| 5552 | 5545 | .offset = base_offset + i * @sizeOf(u64), |
| 5553 | 5546 | .segment_id = segment_id, |
| ... | ... | @@ -5572,7 +5565,7 @@ fn writeBindInfoTable(self: *MachO) !void { |
| 5572 | 5565 | const base_offset = sym.n_value - seg.inner.vmaddr; |
| 5573 | 5566 | |
| 5574 | 5567 | for (block.bindings.items) |binding| { |
| 5575 | | const bind_sym = self.imports.items[binding.local_sym_index]; |
| 5568 | const bind_sym = self.undefs.items[binding.local_sym_index]; |
| 5576 | 5569 | try pointers.append(.{ |
| 5577 | 5570 | .offset = binding.offset + base_offset, |
| 5578 | 5571 | .segment_id = match.seg, |
| ... | ... | @@ -5631,7 +5624,7 @@ fn writeLazyBindInfoTable(self: *MachO) !void { |
| 5631 | 5624 | try pointers.ensureUnusedCapacity(self.stubs.items.len); |
| 5632 | 5625 | |
| 5633 | 5626 | for (self.stubs.items) |import_id, i| { |
| 5634 | | const sym = self.imports.items[import_id]; |
| 5627 | const sym = self.undefs.items[import_id]; |
| 5635 | 5628 | pointers.appendAssumeCapacity(.{ |
| 5636 | 5629 | .offset = base_offset + i * @sizeOf(u64), |
| 5637 | 5630 | .segment_id = segment_id, |
| ... | ... | @@ -5967,10 +5960,6 @@ pub fn symbolIsTentative(sym: macho.nlist_64) bool { |
| 5967 | 5960 | return sym.n_value != 0; |
| 5968 | 5961 | } |
| 5969 | 5962 | |
| 5970 | | pub fn symbolIsNull(sym: macho.nlist_64) bool { |
| 5971 | | return sym.n_value == 0 and sym.n_desc == 0 and sym.n_type == 0 and sym.n_strx == 0 and sym.n_sect == 0; |
| 5972 | | } |
| 5973 | | |
| 5974 | 5963 | pub fn symbolIsTemp(sym: macho.nlist_64, sym_name: []const u8) bool { |
| 5975 | 5964 | if (!symbolIsSect(sym)) return false; |
| 5976 | 5965 | if (symbolIsExt(sym)) return false; |