authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-03 13:37:48+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-12 10:20:57+02:00
logda57d6df320cb6bd9ce09bef192f201d59a50b28
tree96deedef1ca153086d9326433c1f398937121d0d
parent493822ac3bab344821aad180aae27b629eb920c1

macho: simplify symbol management and resolution

instead of globally storing unresolved and tentative defs, store indices to actual symbols in the functions that are responsible for symbol resolution.

3 files changed, 137 insertions(+), 149 deletions(-)

src/codegen.zig+1-1
...@@ -2714,7 +2714,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2714,7 +2714,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2714 // Add relocation to the decl.2714 // Add relocation to the decl.
2715 try macho_file.active_decl.?.link.macho.relocs.append(self.bin_file.allocator, .{2715 try macho_file.active_decl.?.link.macho.relocs.append(self.bin_file.allocator, .{
2716 .offset = offset,2716 .offset = offset,
2717 .where = .import,2717 .where = .undef,
2718 .where_index = where_index,2718 .where_index = where_index,
2719 .payload = .{ .branch = .{2719 .payload = .{ .branch = .{
2720 .arch = arch,2720 .arch = arch,
src/link/MachO.zig+126-137
...@@ -134,9 +134,7 @@ objc_data_section_index: ?u16 = null,...@@ -134,9 +134,7 @@ objc_data_section_index: ?u16 = null,
134134
135locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},135locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
136globals: std.ArrayListUnmanaged(macho.nlist_64) = .{},136globals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
137imports: std.ArrayListUnmanaged(macho.nlist_64) = .{},
138undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{},137undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{},
139tentatives: std.ArrayListUnmanaged(macho.nlist_64) = .{},
140symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{},138symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{},
141139
142locals_free_list: std.ArrayListUnmanaged(u32) = .{},140locals_free_list: std.ArrayListUnmanaged(u32) = .{},
...@@ -252,9 +250,7 @@ const SymbolWithLoc = struct {...@@ -252,9 +250,7 @@ const SymbolWithLoc = struct {
252 // Table where the symbol can be found.250 // Table where the symbol can be found.
253 where: enum {251 where: enum {
254 global,252 global,
255 import,
256 undef,253 undef,
257 tentative,
258 },254 },
259 where_index: u32,255 where_index: u32,
260 local_sym_index: u32 = 0,256 local_sym_index: u32 = 0,
...@@ -264,22 +260,11 @@ const SymbolWithLoc = struct {...@@ -264,22 +260,11 @@ const SymbolWithLoc = struct {
264pub const GotIndirectionKey = struct {260pub const GotIndirectionKey = struct {
265 where: enum {261 where: enum {
266 local,262 local,
267 import,263 undef,
268 },264 },
269 where_index: u32,265 where_index: u32,
270};266};
271267
272pub 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/// When allocating, the ideal_capacity is calculated by268/// When allocating, the ideal_capacity is calculated by
284/// actual_capacity + (actual_capacity / ideal_factor)269/// actual_capacity + (actual_capacity / ideal_factor)
285const ideal_factor = 2;270const ideal_factor = 2;
...@@ -960,7 +945,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {...@@ -960,7 +945,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
960 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;945 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
961 const got_index = @intCast(u32, self.got_entries.items.len);946 const got_index = @intCast(u32, self.got_entries.items.len);
962 const got_entry = GotIndirectionKey{947 const got_entry = GotIndirectionKey{
963 .where = .import,948 .where = .undef,
964 .where_index = resolv.where_index,949 .where_index = resolv.where_index,
965 };950 };
966 try self.got_entries.append(self.base.allocator, got_entry);951 try self.got_entries.append(self.base.allocator, got_entry);
...@@ -1991,7 +1976,7 @@ fn writeStubHelperCommon(self: *MachO) !void {...@@ -1991,7 +1976,7 @@ fn writeStubHelperCommon(self: *MachO) !void {
1991 }) orelse unreachable;1976 }) orelse unreachable;
1992 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;1977 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
1993 const got_index = self.got_entries_map.get(.{1978 const got_index = self.got_entries_map.get(.{
1994 .where = .import,1979 .where = .undef,
1995 .where_index = resolv.where_index,1980 .where_index = resolv.where_index,
1996 }) orelse unreachable;1981 }) orelse unreachable;
1997 const addr = got.addr + got_index * @sizeOf(u64);1982 const addr = got.addr + got_index * @sizeOf(u64);
...@@ -2042,7 +2027,7 @@ fn writeStubHelperCommon(self: *MachO) !void {...@@ -2042,7 +2027,7 @@ fn writeStubHelperCommon(self: *MachO) !void {
2042 }) orelse unreachable;2027 }) orelse unreachable;
2043 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;2028 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
2044 const got_index = self.got_entries_map.get(.{2029 const got_index = self.got_entries_map.get(.{
2045 .where = .import,2030 .where = .undef,
2046 .where_index = resolv.where_index,2031 .where_index = resolv.where_index,
2047 }) orelse unreachable;2032 }) orelse unreachable;
2048 const this_addr = stub_helper.addr + 3 * @sizeOf(u32);2033 const this_addr = stub_helper.addr + 3 * @sizeOf(u32);
...@@ -2106,7 +2091,12 @@ fn writeStubHelperCommon(self: *MachO) !void {...@@ -2106,7 +2091,12 @@ fn writeStubHelperCommon(self: *MachO) !void {
2106 }2091 }
2107}2092}
21082093
2109fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {2094fn resolveSymbolsInObject(
2095 self: *MachO,
2096 object_id: u16,
2097 tentatives: *std.ArrayList(u32),
2098 unresolved: *std.ArrayList(u32),
2099) !void {
2110 const object = &self.objects.items[object_id];2100 const object = &self.objects.items[object_id];
21112101
2112 log.debug("resolving symbols in '{s}'", .{object.name});2102 log.debug("resolving symbols in '{s}'", .{object.name});
...@@ -2174,7 +2164,6 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {...@@ -2174,7 +2164,6 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
2174 };2164 };
21752165
2176 switch (resolv.where) {2166 switch (resolv.where) {
2177 .import => unreachable,
2178 .global => {2167 .global => {
2179 const global = &self.globals.items[resolv.where_index];2168 const global = &self.globals.items[resolv.where_index];
21802169
...@@ -2186,8 +2175,16 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {...@@ -2186,8 +2175,16 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
2186 log.err(" next definition in '{s}'", .{object.name});2175 log.err(" next definition in '{s}'", .{object.name});
2187 return error.MultipleSymbolDefinitions;2176 return error.MultipleSymbolDefinitions;
2188 }2177 }
2189
2190 if (symbolIsWeakDef(sym) or symbolIsPext(sym)) continue; // Current symbol is weak, so skip it.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 }
21912188
2192 // Otherwise, update the resolver and the global symbol.2189 // Otherwise, update the resolver and the global symbol.
2193 global.n_type = sym.n_type;2190 global.n_type = sym.n_type;
...@@ -2205,16 +2202,14 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {...@@ -2205,16 +2202,14 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
2205 .n_desc = 0,2202 .n_desc = 0,
2206 .n_value = 0,2203 .n_value = 0,
2207 };2204 };
2208 },2205
2209 .tentative => {2206 var i: usize = 0;
2210 const tentative = &self.tentatives.items[resolv.where_index];2207 while (i < unresolved.items.len) : (i += 1) {
2211 tentative.* = .{2208 if (unresolved.items[i] == resolv.where_index) {
2212 .n_strx = 0,2209 _ = unresolved.swapRemove(i);
2213 .n_type = macho.N_UNDF,2210 break;
2214 .n_sect = 0,2211 }
2215 .n_desc = 0,2212 }
2216 .n_value = 0,
2217 };
2218 },2213 },
2219 }2214 }
22202215
...@@ -2235,8 +2230,8 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {...@@ -2235,8 +2230,8 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
2235 } else if (symbolIsTentative(sym)) {2230 } else if (symbolIsTentative(sym)) {
2236 // Symbol is a tentative definition.2231 // Symbol is a tentative definition.
2237 const resolv = self.symbol_resolver.getPtr(n_strx) orelse {2232 const resolv = self.symbol_resolver.getPtr(n_strx) orelse {
2238 const tent_sym_index = @intCast(u32, self.tentatives.items.len);2233 const global_sym_index = @intCast(u32, self.globals.items.len);
2239 try self.tentatives.append(self.base.allocator, .{2234 try self.globals.append(self.base.allocator, .{
2240 .n_strx = try self.makeString(sym_name),2235 .n_strx = try self.makeString(sym_name),
2241 .n_type = sym.n_type,2236 .n_type = sym.n_type,
2242 .n_sect = 0,2237 .n_sect = 0,
...@@ -2244,29 +2239,38 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {...@@ -2244,29 +2239,38 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
2244 .n_value = sym.n_value,2239 .n_value = sym.n_value,
2245 });2240 });
2246 try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{2241 try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
2247 .where = .tentative,2242 .where = .global,
2248 .where_index = tent_sym_index,2243 .where_index = global_sym_index,
2249 .file = object_id,2244 .file = object_id,
2250 });2245 });
2246 try tentatives.append(global_sym_index);
2251 continue;2247 continue;
2252 };2248 };
22532249
2254 switch (resolv.where) {2250 switch (resolv.where) {
2255 .import => unreachable,2251 .global => {
2256 .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 .undef => {2260 .undef => {
2258 const undef = &self.undefs.items[resolv.where_index];2261 const undef = &self.undefs.items[resolv.where_index];
2259 const tent_sym_index = @intCast(u32, self.tentatives.items.len);2262 const global_sym_index = @intCast(u32, self.globals.items.len);
2260 try self.tentatives.append(self.base.allocator, .{2263 try self.globals.append(self.base.allocator, .{
2261 .n_strx = undef.n_strx,2264 .n_strx = undef.n_strx,
2262 .n_type = sym.n_type,2265 .n_type = sym.n_type,
2263 .n_sect = 0,2266 .n_sect = 0,
2264 .n_desc = sym.n_desc,2267 .n_desc = sym.n_desc,
2265 .n_value = sym.n_value,2268 .n_value = sym.n_value,
2266 });2269 });
2270 try tentatives.append(global_sym_index);
2267 resolv.* = .{2271 resolv.* = .{
2268 .where = .tentative,2272 .where = .global,
2269 .where_index = tent_sym_index,2273 .where_index = global_sym_index,
2270 .file = object_id,2274 .file = object_id,
2271 };2275 };
2272 undef.* = .{2276 undef.* = .{
...@@ -2276,14 +2280,13 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {...@@ -2276,14 +2280,13 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
2276 .n_desc = 0,2280 .n_desc = 0,
2277 .n_value = 0,2281 .n_value = 0,
2278 };2282 };
2279 },2283 var i: usize = 0;
2280 .tentative => {2284 while (i < unresolved.items.len) : (i += 1) {
2281 const tentative = &self.tentatives.items[resolv.where_index];2285 if (unresolved.items[i] == resolv.where_index) {
2282 if (tentative.n_value >= sym.n_value) continue;2286 _ = unresolved.swapRemove(i);
22832287 break;
2284 tentative.n_desc = sym.n_desc;2288 }
2285 tentative.n_value = sym.n_value;2289 }
2286 resolv.file = object_id;
2287 },2290 },
2288 }2291 }
2289 } else {2292 } else {
...@@ -2303,24 +2306,27 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {...@@ -2303,24 +2306,27 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
2303 .where_index = undef_sym_index,2306 .where_index = undef_sym_index,
2304 .file = object_id,2307 .file = object_id,
2305 });2308 });
2309 try unresolved.append(undef_sym_index);
2306 }2310 }
2307 }2311 }
2308}2312}
23092313
2310fn resolveSymbols(self: *MachO) !void {2314fn 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 // First pass, resolve symbols in provided objects.2321 // First pass, resolve symbols in provided objects.
2312 for (self.objects.items) |_, object_id| {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 }
23152325
2316 // Second pass, resolve symbols in static libraries.2326 // Second pass, resolve symbols in static libraries.
2317 var next_sym: usize = 0;2327 var next_sym: usize = 0;
2318 loop: while (true) : (next_sym += 1) {2328 loop: while (next_sym < unresolved.items.len) {
2319 if (next_sym == self.undefs.items.len) break;2329 const sym = self.undefs.items[unresolved.items[next_sym]];
2320
2321 const sym = self.undefs.items[next_sym];
2322 if (symbolIsNull(sym)) continue;
2323
2324 const sym_name = self.getString(sym.n_strx);2330 const sym_name = self.getString(sym.n_strx);
23252331
2326 for (self.archives.items) |archive| {2332 for (self.archives.items) |archive| {
...@@ -2334,17 +2340,18 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2334,17 +2340,18 @@ fn resolveSymbols(self: *MachO) !void {
2334 const object_id = @intCast(u16, self.objects.items.len);2340 const object_id = @intCast(u16, self.objects.items.len);
2335 const object = try self.objects.addOne(self.base.allocator);2341 const object = try self.objects.addOne(self.base.allocator);
2336 object.* = try archive.parseObject(self.base.allocator, self.base.options.target, offsets.items[0]);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);
23382344
2339 continue :loop;2345 continue :loop;
2340 }2346 }
2347
2348 next_sym += 1;
2341 }2349 }
23422350
2343 // Convert any tentative definition into a regular symbol and allocate2351 // Convert any tentative definition into a regular symbol and allocate
2344 // text blocks for each tentative defintion.2352 // text blocks for each tentative defintion.
2345 for (self.tentatives.items) |sym| {2353 while (tentatives.popOrNull()) |index| {
2346 if (symbolIsNull(sym)) continue;2354 const sym = &self.globals.items[index];
2347
2348 const match: MatchingSection = blk: {2355 const match: MatchingSection = blk: {
2349 if (self.common_section_index == null) {2356 if (self.common_section_index == null) {
2350 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;2357 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
...@@ -2366,24 +2373,17 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2366,24 +2373,17 @@ fn resolveSymbols(self: *MachO) !void {
2366 mem.set(u8, code, 0);2373 mem.set(u8, code, 0);
2367 const alignment = (sym.n_desc >> 8) & 0x0f;2374 const alignment = (sym.n_desc >> 8) & 0x0f;
23682375
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 const local_sym_index = @intCast(u32, self.locals.items.len);2382 const local_sym_index = @intCast(u32, self.locals.items.len);
2371 var nlist = macho.nlist_64{2383 try self.locals.append(self.base.allocator, local_sym);
2372 .n_strx = sym.n_strx,2384
2373 .n_type = macho.N_SECT,2385 const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable;
2374 .n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1),2386 resolv.local_sym_index = local_sym_index;
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 };
23872387
2388 const block = try self.base.allocator.create(TextBlock);2388 const block = try self.base.allocator.create(TextBlock);
2389 block.* = TextBlock.empty;2389 block.* = TextBlock.empty;
...@@ -2430,13 +2430,15 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2430,13 +2430,15 @@ fn resolveSymbols(self: *MachO) !void {
2430 .where = .undef,2430 .where = .undef,
2431 .where_index = undef_sym_index,2431 .where_index = undef_sym_index,
2432 });2432 });
2433 try unresolved.append(undef_sym_index);
2433 }2434 }
24342435
2435 loop: for (self.undefs.items) |sym| {2436 next_sym = 0;
2436 if (symbolIsNull(sym)) continue;2437 loop: while (next_sym < unresolved.items.len) {
24372438 const sym = self.undefs.items[unresolved.items[next_sym]];
2438 const sym_name = self.getString(sym.n_strx);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 if (!dylib.symbols.contains(sym_name)) continue;2442 if (!dylib.symbols.contains(sym_name)) continue;
24412443
2442 const dylib_id = @intCast(u16, id);2444 const dylib_id = @intCast(u16, id);
...@@ -2447,28 +2449,15 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2447,28 +2449,15 @@ fn resolveSymbols(self: *MachO) !void {
2447 const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable;2449 const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable;
2448 const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable;2450 const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable;
2449 const undef = &self.undefs.items[resolv.where_index];2451 const undef = &self.undefs.items[resolv.where_index];
2450 const import_sym_index = @intCast(u32, self.imports.items.len);2452 undef.n_type |= macho.N_EXT;
2451 try self.imports.append(self.base.allocator, .{2453 undef.n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER;
2452 .n_strx = undef.n_strx,2454
2453 .n_type = macho.N_UNDF | macho.N_EXT,2455 _ = unresolved.swapRemove(next_sym);
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 };
24692456
2470 continue :loop;2457 continue :loop;
2471 }2458 }
2459
2460 next_sym += 1;
2472 }2461 }
24732462
2474 // Fourth pass, handle synthetic symbols and flag any undefined references.2463 // Fourth pass, handle synthetic symbols and flag any undefined references.
...@@ -2497,6 +2486,14 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2497,6 +2486,14 @@ fn resolveSymbols(self: *MachO) !void {
2497 nlist.n_desc = macho.N_WEAK_DEF;2486 nlist.n_desc = macho.N_WEAK_DEF;
2498 try self.globals.append(self.base.allocator, nlist);2487 try self.globals.append(self.base.allocator, nlist);
24992488
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 undef.* = .{2497 undef.* = .{
2501 .n_strx = 0,2498 .n_strx = 0,
2502 .n_type = macho.N_UNDF,2499 .n_type = macho.N_UNDF,
...@@ -2529,19 +2526,17 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2529,19 +2526,17 @@ fn resolveSymbols(self: *MachO) !void {
2529 }2526 }
2530 }2527 }
25312528
2532 var has_undefined = false;2529 for (unresolved.items) |index| {
2533 for (self.undefs.items) |sym| {2530 const sym = self.undefs.items[index];
2534 if (symbolIsNull(sym)) continue;
2535
2536 const sym_name = self.getString(sym.n_strx);2531 const sym_name = self.getString(sym.n_strx);
2537 const resolv = self.symbol_resolver.get(sym.n_strx) orelse unreachable;2532 const resolv = self.symbol_resolver.get(sym.n_strx) orelse unreachable;
25382533
2539 log.err("undefined reference to symbol '{s}'", .{sym_name});2534 log.err("undefined reference to symbol '{s}'", .{sym_name});
2540 log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name});2535 log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name});
2541 has_undefined = true;
2542 }2536 }
25432537
2544 if (has_undefined) return error.UndefinedSymbolReference;2538 if (unresolved.items.len > 0)
2539 return error.UndefinedSymbolReference;
2545}2540}
25462541
2547fn parseTextBlocks(self: *MachO) !void {2542fn parseTextBlocks(self: *MachO) !void {
...@@ -3006,7 +3001,7 @@ fn writeGotEntries(self: *MachO) !void {...@@ -3006,7 +3001,7 @@ fn writeGotEntries(self: *MachO) !void {
3006 for (self.got_entries.items) |key| {3001 for (self.got_entries.items) |key| {
3007 const address: u64 = switch (key.where) {3002 const address: u64 = switch (key.where) {
3008 .local => self.locals.items[key.where_index].n_value,3003 .local => self.locals.items[key.where_index].n_value,
3009 .import => 0,3004 .undef => 0,
3010 };3005 };
3011 try writer.writeIntLittle(u64, address);3006 try writer.writeIntLittle(u64, address);
3012 }3007 }
...@@ -3075,7 +3070,7 @@ fn writeRebaseInfoTableZld(self: *MachO) !void {...@@ -3075,7 +3070,7 @@ fn writeRebaseInfoTableZld(self: *MachO) !void {
3075 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);3070 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
30763071
3077 for (self.got_entries.items) |entry, i| {3072 for (self.got_entries.items) |entry, i| {
3078 if (entry.where == .import) continue;3073 if (entry.where == .undef) continue;
30793074
3080 try pointers.append(.{3075 try pointers.append(.{
3081 .offset = base_offset + i * @sizeOf(u64),3076 .offset = base_offset + i * @sizeOf(u64),
...@@ -3132,7 +3127,7 @@ fn writeBindInfoTableZld(self: *MachO) !void {...@@ -3132,7 +3127,7 @@ fn writeBindInfoTableZld(self: *MachO) !void {
3132 for (self.got_entries.items) |entry, i| {3127 for (self.got_entries.items) |entry, i| {
3133 if (entry.where == .local) continue;3128 if (entry.where == .local) continue;
31343129
3135 const sym = self.imports.items[entry.where_index];3130 const sym = self.undefs.items[entry.where_index];
3136 try pointers.append(.{3131 try pointers.append(.{
3137 .offset = base_offset + i * @sizeOf(u64),3132 .offset = base_offset + i * @sizeOf(u64),
3138 .segment_id = segment_id,3133 .segment_id = segment_id,
...@@ -3157,7 +3152,7 @@ fn writeBindInfoTableZld(self: *MachO) !void {...@@ -3157,7 +3152,7 @@ fn writeBindInfoTableZld(self: *MachO) !void {
3157 const base_offset = sym.n_value - seg.inner.vmaddr;3152 const base_offset = sym.n_value - seg.inner.vmaddr;
31583153
3159 for (block.bindings.items) |binding| {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 try pointers.append(.{3156 try pointers.append(.{
3162 .offset = binding.offset + base_offset,3157 .offset = binding.offset + base_offset,
3163 .segment_id = match.seg,3158 .segment_id = match.seg,
...@@ -3204,7 +3199,7 @@ fn writeLazyBindInfoTableZld(self: *MachO) !void {...@@ -3204,7 +3199,7 @@ fn writeLazyBindInfoTableZld(self: *MachO) !void {
3204 try pointers.ensureUnusedCapacity(self.stubs.items.len);3199 try pointers.ensureUnusedCapacity(self.stubs.items.len);
32053200
3206 for (self.stubs.items) |import_id, i| {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 pointers.appendAssumeCapacity(.{3203 pointers.appendAssumeCapacity(.{
3209 .offset = base_offset + i * @sizeOf(u64),3204 .offset = base_offset + i * @sizeOf(u64),
3210 .segment_id = segment_id,3205 .segment_id = segment_id,
...@@ -3338,7 +3333,7 @@ fn writeSymbolTable(self: *MachO) !void {...@@ -3338,7 +3333,7 @@ fn writeSymbolTable(self: *MachO) !void {
33383333
3339 const nlocals = locals.items.len;3334 const nlocals = locals.items.len;
3340 const nexports = self.globals.items.len;3335 const nexports = self.globals.items.len;
3341 const nundefs = self.imports.items.len;3336 const nundefs = self.undefs.items.len;
33423337
3343 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);3338 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);
3344 const locals_size = nlocals * @sizeOf(macho.nlist_64);3339 const locals_size = nlocals * @sizeOf(macho.nlist_64);
...@@ -3353,7 +3348,7 @@ fn writeSymbolTable(self: *MachO) !void {...@@ -3353,7 +3348,7 @@ fn writeSymbolTable(self: *MachO) !void {
3353 const undefs_off = exports_off + exports_size;3348 const undefs_off = exports_off + exports_size;
3354 const undefs_size = nundefs * @sizeOf(macho.nlist_64);3349 const undefs_size = nundefs * @sizeOf(macho.nlist_64);
3355 log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });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);
33573352
3358 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);3353 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);
3359 seg.inner.filesize += locals_size + exports_size + undefs_size;3354 seg.inner.filesize += locals_size + exports_size + undefs_size;
...@@ -3401,7 +3396,7 @@ fn writeSymbolTable(self: *MachO) !void {...@@ -3401,7 +3396,7 @@ fn writeSymbolTable(self: *MachO) !void {
3401 got.reserved1 = nstubs;3396 got.reserved1 = nstubs;
3402 for (self.got_entries.items) |entry| {3397 for (self.got_entries.items) |entry| {
3403 switch (entry.where) {3398 switch (entry.where) {
3404 .import => {3399 .undef => {
3405 try writer.writeIntLittle(u32, dysymtab.iundefsym + entry.where_index);3400 try writer.writeIntLittle(u32, dysymtab.iundefsym + entry.where_index);
3406 },3401 },
3407 .local => {3402 .local => {
...@@ -3437,8 +3432,6 @@ pub fn deinit(self: *MachO) void {...@@ -3437,8 +3432,6 @@ pub fn deinit(self: *MachO) void {
3437 self.strtab_dir.deinit(self.base.allocator);3432 self.strtab_dir.deinit(self.base.allocator);
3438 self.strtab.deinit(self.base.allocator);3433 self.strtab.deinit(self.base.allocator);
3439 self.undefs.deinit(self.base.allocator);3434 self.undefs.deinit(self.base.allocator);
3440 self.tentatives.deinit(self.base.allocator);
3441 self.imports.deinit(self.base.allocator);
3442 self.globals.deinit(self.base.allocator);3435 self.globals.deinit(self.base.allocator);
3443 self.globals_free_list.deinit(self.base.allocator);3436 self.globals_free_list.deinit(self.base.allocator);
3444 self.locals.deinit(self.base.allocator);3437 self.locals.deinit(self.base.allocator);
...@@ -4517,9 +4510,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -4517,9 +4510,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {
4517 if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{4510 if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
4518 .strtab = &self.strtab,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 const n_strx = try self.makeString("dyld_stub_binder");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 .n_strx = n_strx,4516 .n_strx = n_strx,
4524 .n_type = macho.N_UNDF | macho.N_EXT,4517 .n_type = macho.N_UNDF | macho.N_EXT,
4525 .n_sect = 0,4518 .n_sect = 0,
...@@ -4527,11 +4520,11 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -4527,11 +4520,11 @@ pub fn populateMissingMetadata(self: *MachO) !void {
4527 .n_value = 0,4520 .n_value = 0,
4528 });4521 });
4529 try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{4522 try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
4530 .where = .import,4523 .where = .undef,
4531 .where_index = import_sym_index,4524 .where_index = import_sym_index,
4532 });4525 });
4533 const got_key = GotIndirectionKey{4526 const got_key = GotIndirectionKey{
4534 .where = .import,4527 .where = .undef,
4535 .where_index = import_sym_index,4528 .where_index = import_sym_index,
4536 };4529 };
4537 const got_index = @intCast(u32, self.got_entries.items.len);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,9 +4656,9 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
4663 }4656 }
46644657
4665 log.debug("adding new extern function '{s}' with dylib ordinal 1", .{sym_name});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 const n_strx = try self.makeString(sym_name);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 .n_strx = n_strx,4662 .n_strx = n_strx,
4670 .n_type = macho.N_UNDF | macho.N_EXT,4663 .n_type = macho.N_UNDF | macho.N_EXT,
4671 .n_sect = 0,4664 .n_sect = 0,
...@@ -4673,7 +4666,7 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {...@@ -4673,7 +4666,7 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
4673 .n_value = 0,4666 .n_value = 0,
4674 });4667 });
4675 try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{4668 try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
4676 .where = .import,4669 .where = .undef,
4677 .where_index = import_sym_index,4670 .where_index = import_sym_index,
4678 });4671 });
46794672
...@@ -4856,7 +4849,7 @@ fn writeGotEntry(self: *MachO, index: usize) !void {...@@ -4856,7 +4849,7 @@ fn writeGotEntry(self: *MachO, index: usize) !void {
4856 const got_entry = self.got_entries.items[index];4849 const got_entry = self.got_entries.items[index];
4857 const sym = switch (got_entry.where) {4850 const sym = switch (got_entry.where) {
4858 .local => self.locals.items[got_entry.where_index],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 log.debug("writing offset table entry [ 0x{x} => 0x{x} ({s}) ]", .{4854 log.debug("writing offset table entry [ 0x{x} => 0x{x} ({s}) ]", .{
4862 off,4855 off,
...@@ -5140,7 +5133,7 @@ fn relocateSymbolTable(self: *MachO) !void {...@@ -5140,7 +5133,7 @@ fn relocateSymbolTable(self: *MachO) !void {
5140 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;5133 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
5141 const nlocals = self.locals.items.len;5134 const nlocals = self.locals.items.len;
5142 const nglobals = self.globals.items.len;5135 const nglobals = self.globals.items.len;
5143 const nundefs = self.imports.items.len;5136 const nundefs = self.undefs.items.len;
5144 const nsyms = nlocals + nglobals + nundefs;5137 const nsyms = nlocals + nglobals + nundefs;
51455138
5146 if (symtab.nsyms < nsyms) {5139 if (symtab.nsyms < nsyms) {
...@@ -5185,7 +5178,7 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {...@@ -5185,7 +5178,7 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {
5185 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;5178 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
5186 const nlocals = self.locals.items.len;5179 const nlocals = self.locals.items.len;
5187 const nglobals = self.globals.items.len;5180 const nglobals = self.globals.items.len;
5188 const nundefs = self.imports.items.len;5181 const nundefs = self.undefs.items.len;
51895182
5190 const locals_off = symtab.symoff;5183 const locals_off = symtab.symoff;
5191 const locals_size = nlocals * @sizeOf(macho.nlist_64);5184 const locals_size = nlocals * @sizeOf(macho.nlist_64);
...@@ -5198,7 +5191,7 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {...@@ -5198,7 +5191,7 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {
5198 const undefs_off = globals_off + globals_size;5191 const undefs_off = globals_off + globals_size;
5199 const undefs_size = nundefs * @sizeOf(macho.nlist_64);5192 const undefs_size = nundefs * @sizeOf(macho.nlist_64);
5200 log.debug("writing extern symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });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);
52025195
5203 // Update dynamic symbol table.5196 // Update dynamic symbol table.
5204 const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;5197 const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
...@@ -5253,7 +5246,7 @@ fn writeIndirectSymbolTable(self: *MachO) !void {...@@ -5253,7 +5246,7 @@ fn writeIndirectSymbolTable(self: *MachO) !void {
5253 got.reserved1 = nstubs;5246 got.reserved1 = nstubs;
5254 for (self.got_entries.items) |entry| {5247 for (self.got_entries.items) |entry| {
5255 switch (entry.where) {5248 switch (entry.where) {
5256 .import => {5249 .undef => {
5257 try writer.writeIntLittle(u32, dysymtab.iundefsym + entry.where_index);5250 try writer.writeIntLittle(u32, dysymtab.iundefsym + entry.where_index);
5258 },5251 },
5259 .local => {5252 .local => {
...@@ -5478,7 +5471,7 @@ fn writeRebaseInfoTable(self: *MachO) !void {...@@ -5478,7 +5471,7 @@ fn writeRebaseInfoTable(self: *MachO) !void {
5478 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);5471 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
54795472
5480 for (self.got_entries.items) |entry, i| {5473 for (self.got_entries.items) |entry, i| {
5481 if (entry.where == .import) continue;5474 if (entry.where == .undef) continue;
54825475
5483 try pointers.append(.{5476 try pointers.append(.{
5484 .offset = base_offset + i * @sizeOf(u64),5477 .offset = base_offset + i * @sizeOf(u64),
...@@ -5547,7 +5540,7 @@ fn writeBindInfoTable(self: *MachO) !void {...@@ -5547,7 +5540,7 @@ fn writeBindInfoTable(self: *MachO) !void {
5547 for (self.got_entries.items) |entry, i| {5540 for (self.got_entries.items) |entry, i| {
5548 if (entry.where == .local) continue;5541 if (entry.where == .local) continue;
55495542
5550 const sym = self.imports.items[entry.where_index];5543 const sym = self.undefs.items[entry.where_index];
5551 try pointers.append(.{5544 try pointers.append(.{
5552 .offset = base_offset + i * @sizeOf(u64),5545 .offset = base_offset + i * @sizeOf(u64),
5553 .segment_id = segment_id,5546 .segment_id = segment_id,
...@@ -5572,7 +5565,7 @@ fn writeBindInfoTable(self: *MachO) !void {...@@ -5572,7 +5565,7 @@ fn writeBindInfoTable(self: *MachO) !void {
5572 const base_offset = sym.n_value - seg.inner.vmaddr;5565 const base_offset = sym.n_value - seg.inner.vmaddr;
55735566
5574 for (block.bindings.items) |binding| {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 try pointers.append(.{5569 try pointers.append(.{
5577 .offset = binding.offset + base_offset,5570 .offset = binding.offset + base_offset,
5578 .segment_id = match.seg,5571 .segment_id = match.seg,
...@@ -5631,7 +5624,7 @@ fn writeLazyBindInfoTable(self: *MachO) !void {...@@ -5631,7 +5624,7 @@ fn writeLazyBindInfoTable(self: *MachO) !void {
5631 try pointers.ensureUnusedCapacity(self.stubs.items.len);5624 try pointers.ensureUnusedCapacity(self.stubs.items.len);
56325625
5633 for (self.stubs.items) |import_id, i| {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 pointers.appendAssumeCapacity(.{5628 pointers.appendAssumeCapacity(.{
5636 .offset = base_offset + i * @sizeOf(u64),5629 .offset = base_offset + i * @sizeOf(u64),
5637 .segment_id = segment_id,5630 .segment_id = segment_id,
...@@ -5967,10 +5960,6 @@ pub fn symbolIsTentative(sym: macho.nlist_64) bool {...@@ -5967,10 +5960,6 @@ pub fn symbolIsTentative(sym: macho.nlist_64) bool {
5967 return sym.n_value != 0;5960 return sym.n_value != 0;
5968}5961}
59695962
5970pub 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
5974pub fn symbolIsTemp(sym: macho.nlist_64, sym_name: []const u8) bool {5963pub fn symbolIsTemp(sym: macho.nlist_64, sym_name: []const u8) bool {
5975 if (!symbolIsSect(sym)) return false;5964 if (!symbolIsSect(sym)) return false;
5976 if (symbolIsExt(sym)) return false;5965 if (symbolIsExt(sym)) return false;
src/link/MachO/TextBlock.zig+10-11
...@@ -165,7 +165,7 @@ pub const Relocation = struct {...@@ -165,7 +165,7 @@ pub const Relocation = struct {
165165
166 where: enum {166 where: enum {
167 local,167 local,
168 import,168 undef,
169 },169 },
170170
171 where_index: u32,171 where_index: u32,
...@@ -665,11 +665,10 @@ fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Reloc...@@ -665,11 +665,10 @@ fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Reloc
665 parsed_rel.where = .local;665 parsed_rel.where = .local;
666 parsed_rel.where_index = resolv.local_sym_index;666 parsed_rel.where_index = resolv.local_sym_index;
667 },667 },
668 .import => {668 .undef => {
669 parsed_rel.where = .import;669 parsed_rel.where = .undef;
670 parsed_rel.where_index = resolv.where_index;670 parsed_rel.where_index = resolv.where_index;
671 },671 },
672 else => unreachable,
673 }672 }
674 }673 }
675 }674 }
...@@ -825,7 +824,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R...@@ -825,7 +824,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
825 const key = MachO.GotIndirectionKey{824 const key = MachO.GotIndirectionKey{
826 .where = switch (parsed_rel.where) {825 .where = switch (parsed_rel.where) {
827 .local => .local,826 .local => .local,
828 .import => .import,827 .undef => .undef,
829 },828 },
830 .where_index = parsed_rel.where_index,829 .where_index = parsed_rel.where_index,
831 };830 };
...@@ -836,7 +835,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R...@@ -836,7 +835,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
836 try context.macho_file.got_entries_map.putNoClobber(context.allocator, key, got_index);835 try context.macho_file.got_entries_map.putNoClobber(context.allocator, key, got_index);
837 } else if (parsed_rel.payload == .unsigned) {836 } else if (parsed_rel.payload == .unsigned) {
838 switch (parsed_rel.where) {837 switch (parsed_rel.where) {
839 .import => {838 .undef => {
840 try self.bindings.append(context.allocator, .{839 try self.bindings.append(context.allocator, .{
841 .local_sym_index = parsed_rel.where_index,840 .local_sym_index = parsed_rel.where_index,
842 .offset = parsed_rel.offset,841 .offset = parsed_rel.offset,
...@@ -886,7 +885,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R...@@ -886,7 +885,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
886 },885 },
887 }886 }
888 } else if (parsed_rel.payload == .branch) blk: {887 } else if (parsed_rel.payload == .branch) blk: {
889 if (parsed_rel.where != .import) break :blk;888 if (parsed_rel.where != .undef) break :blk;
890 if (context.macho_file.stubs_map.contains(parsed_rel.where_index)) break :blk;889 if (context.macho_file.stubs_map.contains(parsed_rel.where_index)) break :blk;
891890
892 const stubs_index = @intCast(u32, context.macho_file.stubs.items.len);891 const stubs_index = @intCast(u32, context.macho_file.stubs.items.len);
...@@ -1030,7 +1029,7 @@ fn parseSigned(self: TextBlock, rel: macho.relocation_info, out: *Relocation, co...@@ -1030,7 +1029,7 @@ fn parseSigned(self: TextBlock, rel: macho.relocation_info, out: *Relocation, co
1030 const source_sym = context.macho_file.locals.items[self.local_sym_index];1029 const source_sym = context.macho_file.locals.items[self.local_sym_index];
1031 const target_sym = switch (out.where) {1030 const target_sym = switch (out.where) {
1032 .local => context.macho_file.locals.items[out.where_index],1031 .local => context.macho_file.locals.items[out.where_index],
1033 .import => context.macho_file.imports.items[out.where_index],1032 .undef => context.macho_file.undefs.items[out.where_index],
1034 };1033 };
1035 addend = @intCast(i64, source_sym.n_value + out.offset + 4) + addend - @intCast(i64, target_sym.n_value);1034 addend = @intCast(i64, source_sym.n_value + out.offset + 4) + addend - @intCast(i64, target_sym.n_value);
1036 }1035 }
...@@ -1088,13 +1087,13 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {...@@ -1088,13 +1087,13 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {
1088 const got_index = macho_file.got_entries_map.get(.{1087 const got_index = macho_file.got_entries_map.get(.{
1089 .where = switch (rel.where) {1088 .where = switch (rel.where) {
1090 .local => .local,1089 .local => .local,
1091 .import => .import,1090 .undef => .undef,
1092 },1091 },
1093 .where_index = rel.where_index,1092 .where_index = rel.where_index,
1094 }) orelse {1093 }) orelse {
1095 const sym = switch (rel.where) {1094 const sym = switch (rel.where) {
1096 .local => macho_file.locals.items[rel.where_index],1095 .local => macho_file.locals.items[rel.where_index],
1097 .import => macho_file.imports.items[rel.where_index],1096 .undef => macho_file.undefs.items[rel.where_index],
1098 };1097 };
1099 log.err("expected GOT entry for symbol '{s}'", .{macho_file.getString(sym.n_strx)});1098 log.err("expected GOT entry for symbol '{s}'", .{macho_file.getString(sym.n_strx)});
1100 log.err(" this is an internal linker error", .{});1099 log.err(" this is an internal linker error", .{});
...@@ -1137,7 +1136,7 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {...@@ -1137,7 +1136,7 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {
11371136
1138 break :blk sym.n_value;1137 break :blk sym.n_value;
1139 },1138 },
1140 .import => {1139 .undef => {
1141 const stubs_index = macho_file.stubs_map.get(rel.where_index) orelse {1140 const stubs_index = macho_file.stubs_map.get(rel.where_index) orelse {
1142 // TODO verify in TextBlock that the symbol is indeed dynamically bound.1141 // TODO verify in TextBlock that the symbol is indeed dynamically bound.
1143 break :blk 0; // Dynamically bound by dyld.1142 break :blk 0; // Dynamically bound by dyld.