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 {
27142714 // Add relocation to the decl.
27152715 try macho_file.active_decl.?.link.macho.relocs.append(self.bin_file.allocator, .{
27162716 .offset = offset,
2717 .where = .import,
2717 .where = .undef,
27182718 .where_index = where_index,
27192719 .payload = .{ .branch = .{
27202720 .arch = arch,
src/link/MachO.zig+126-137
......@@ -134,9 +134,7 @@ objc_data_section_index: ?u16 = null,
134134
135135locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
136136globals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
137imports: std.ArrayListUnmanaged(macho.nlist_64) = .{},
138137undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{},
139tentatives: std.ArrayListUnmanaged(macho.nlist_64) = .{},
140138symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{},
141139
142140locals_free_list: std.ArrayListUnmanaged(u32) = .{},
......@@ -252,9 +250,7 @@ const SymbolWithLoc = struct {
252250 // Table where the symbol can be found.
253251 where: enum {
254252 global,
255 import,
256253 undef,
257 tentative,
258254 },
259255 where_index: u32,
260256 local_sym_index: u32 = 0,
......@@ -264,22 +260,11 @@ const SymbolWithLoc = struct {
264260pub const GotIndirectionKey = struct {
265261 where: enum {
266262 local,
267 import,
263 undef,
268264 },
269265 where_index: u32,
270266};
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
283268/// When allocating, the ideal_capacity is calculated by
284269/// actual_capacity + (actual_capacity / ideal_factor)
285270const ideal_factor = 2;
......@@ -960,7 +945,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
960945 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
961946 const got_index = @intCast(u32, self.got_entries.items.len);
962947 const got_entry = GotIndirectionKey{
963 .where = .import,
948 .where = .undef,
964949 .where_index = resolv.where_index,
965950 };
966951 try self.got_entries.append(self.base.allocator, got_entry);
......@@ -1991,7 +1976,7 @@ fn writeStubHelperCommon(self: *MachO) !void {
19911976 }) orelse unreachable;
19921977 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
19931978 const got_index = self.got_entries_map.get(.{
1994 .where = .import,
1979 .where = .undef,
19951980 .where_index = resolv.where_index,
19961981 }) orelse unreachable;
19971982 const addr = got.addr + got_index * @sizeOf(u64);
......@@ -2042,7 +2027,7 @@ fn writeStubHelperCommon(self: *MachO) !void {
20422027 }) orelse unreachable;
20432028 const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
20442029 const got_index = self.got_entries_map.get(.{
2045 .where = .import,
2030 .where = .undef,
20462031 .where_index = resolv.where_index,
20472032 }) orelse unreachable;
20482033 const this_addr = stub_helper.addr + 3 * @sizeOf(u32);
......@@ -2106,7 +2091,12 @@ fn writeStubHelperCommon(self: *MachO) !void {
21062091 }
21072092}
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 {
21102100 const object = &self.objects.items[object_id];
21112101
21122102 log.debug("resolving symbols in '{s}'", .{object.name});
......@@ -2174,7 +2164,6 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
21742164 };
21752165
21762166 switch (resolv.where) {
2177 .import => unreachable,
21782167 .global => {
21792168 const global = &self.globals.items[resolv.where_index];
21802169
......@@ -2186,8 +2175,16 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
21862175 log.err(" next definition in '{s}'", .{object.name});
21872176 return error.MultipleSymbolDefinitions;
21882177 }
2189
21902178 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
21922189 // Otherwise, update the resolver and the global symbol.
21932190 global.n_type = sym.n_type;
......@@ -2205,16 +2202,14 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
22052202 .n_desc = 0,
22062203 .n_value = 0,
22072204 };
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 }
22182213 },
22192214 }
22202215
......@@ -2235,8 +2230,8 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
22352230 } else if (symbolIsTentative(sym)) {
22362231 // Symbol is a tentative definition.
22372232 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, .{
22402235 .n_strx = try self.makeString(sym_name),
22412236 .n_type = sym.n_type,
22422237 .n_sect = 0,
......@@ -2244,29 +2239,38 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
22442239 .n_value = sym.n_value,
22452240 });
22462241 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,
22492244 .file = object_id,
22502245 });
2246 try tentatives.append(global_sym_index);
22512247 continue;
22522248 };
22532249
22542250 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 },
22572260 .undef => {
22582261 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, .{
22612264 .n_strx = undef.n_strx,
22622265 .n_type = sym.n_type,
22632266 .n_sect = 0,
22642267 .n_desc = sym.n_desc,
22652268 .n_value = sym.n_value,
22662269 });
2270 try tentatives.append(global_sym_index);
22672271 resolv.* = .{
2268 .where = .tentative,
2269 .where_index = tent_sym_index,
2272 .where = .global,
2273 .where_index = global_sym_index,
22702274 .file = object_id,
22712275 };
22722276 undef.* = .{
......@@ -2276,14 +2280,13 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
22762280 .n_desc = 0,
22772281 .n_value = 0,
22782282 };
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 }
22872290 },
22882291 }
22892292 } else {
......@@ -2303,24 +2306,27 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
23032306 .where_index = undef_sym_index,
23042307 .file = object_id,
23052308 });
2309 try unresolved.append(undef_sym_index);
23062310 }
23072311 }
23082312}
23092313
23102314fn 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
23112321 // First pass, resolve symbols in provided objects.
23122322 for (self.objects.items) |_, object_id| {
2313 try self.resolveSymbolsInObject(@intCast(u16, object_id));
2323 try self.resolveSymbolsInObject(@intCast(u16, object_id), &tentatives, &unresolved);
23142324 }
23152325
23162326 // Second pass, resolve symbols in static libraries.
23172327 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]];
23242330 const sym_name = self.getString(sym.n_strx);
23252331
23262332 for (self.archives.items) |archive| {
......@@ -2334,17 +2340,18 @@ fn resolveSymbols(self: *MachO) !void {
23342340 const object_id = @intCast(u16, self.objects.items.len);
23352341 const object = try self.objects.addOne(self.base.allocator);
23362342 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
23392345 continue :loop;
23402346 }
2347
2348 next_sym += 1;
23412349 }
23422350
23432351 // Convert any tentative definition into a regular symbol and allocate
23442352 // 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];
23482355 const match: MatchingSection = blk: {
23492356 if (self.common_section_index == null) {
23502357 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
......@@ -2366,24 +2373,17 @@ fn resolveSymbols(self: *MachO) !void {
23662373 mem.set(u8, code, 0);
23672374 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
23702382 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;
23872387
23882388 const block = try self.base.allocator.create(TextBlock);
23892389 block.* = TextBlock.empty;
......@@ -2430,13 +2430,15 @@ fn resolveSymbols(self: *MachO) !void {
24302430 .where = .undef,
24312431 .where_index = undef_sym_index,
24322432 });
2433 try unresolved.append(undef_sym_index);
24332434 }
24342435
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]];
24382439 const sym_name = self.getString(sym.n_strx);
2439 for (self.dylibs.items) |*dylib, id| {
2440
2441 for (self.dylibs.items) |dylib, id| {
24402442 if (!dylib.symbols.contains(sym_name)) continue;
24412443
24422444 const dylib_id = @intCast(u16, id);
......@@ -2447,28 +2449,15 @@ fn resolveSymbols(self: *MachO) !void {
24472449 const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable;
24482450 const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable;
24492451 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);
24692456
24702457 continue :loop;
24712458 }
2459
2460 next_sym += 1;
24722461 }
24732462
24742463 // Fourth pass, handle synthetic symbols and flag any undefined references.
......@@ -2497,6 +2486,14 @@ fn resolveSymbols(self: *MachO) !void {
24972486 nlist.n_desc = macho.N_WEAK_DEF;
24982487 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
25002497 undef.* = .{
25012498 .n_strx = 0,
25022499 .n_type = macho.N_UNDF,
......@@ -2529,19 +2526,17 @@ fn resolveSymbols(self: *MachO) !void {
25292526 }
25302527 }
25312528
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];
25362531 const sym_name = self.getString(sym.n_strx);
25372532 const resolv = self.symbol_resolver.get(sym.n_strx) orelse unreachable;
25382533
25392534 log.err("undefined reference to symbol '{s}'", .{sym_name});
25402535 log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name});
2541 has_undefined = true;
25422536 }
25432537
2544 if (has_undefined) return error.UndefinedSymbolReference;
2538 if (unresolved.items.len > 0)
2539 return error.UndefinedSymbolReference;
25452540}
25462541
25472542fn parseTextBlocks(self: *MachO) !void {
......@@ -3006,7 +3001,7 @@ fn writeGotEntries(self: *MachO) !void {
30063001 for (self.got_entries.items) |key| {
30073002 const address: u64 = switch (key.where) {
30083003 .local => self.locals.items[key.where_index].n_value,
3009 .import => 0,
3004 .undef => 0,
30103005 };
30113006 try writer.writeIntLittle(u64, address);
30123007 }
......@@ -3075,7 +3070,7 @@ fn writeRebaseInfoTableZld(self: *MachO) !void {
30753070 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
30763071
30773072 for (self.got_entries.items) |entry, i| {
3078 if (entry.where == .import) continue;
3073 if (entry.where == .undef) continue;
30793074
30803075 try pointers.append(.{
30813076 .offset = base_offset + i * @sizeOf(u64),
......@@ -3132,7 +3127,7 @@ fn writeBindInfoTableZld(self: *MachO) !void {
31323127 for (self.got_entries.items) |entry, i| {
31333128 if (entry.where == .local) continue;
31343129
3135 const sym = self.imports.items[entry.where_index];
3130 const sym = self.undefs.items[entry.where_index];
31363131 try pointers.append(.{
31373132 .offset = base_offset + i * @sizeOf(u64),
31383133 .segment_id = segment_id,
......@@ -3157,7 +3152,7 @@ fn writeBindInfoTableZld(self: *MachO) !void {
31573152 const base_offset = sym.n_value - seg.inner.vmaddr;
31583153
31593154 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];
31613156 try pointers.append(.{
31623157 .offset = binding.offset + base_offset,
31633158 .segment_id = match.seg,
......@@ -3204,7 +3199,7 @@ fn writeLazyBindInfoTableZld(self: *MachO) !void {
32043199 try pointers.ensureUnusedCapacity(self.stubs.items.len);
32053200
32063201 for (self.stubs.items) |import_id, i| {
3207 const sym = self.imports.items[import_id];
3202 const sym = self.undefs.items[import_id];
32083203 pointers.appendAssumeCapacity(.{
32093204 .offset = base_offset + i * @sizeOf(u64),
32103205 .segment_id = segment_id,
......@@ -3338,7 +3333,7 @@ fn writeSymbolTable(self: *MachO) !void {
33383333
33393334 const nlocals = locals.items.len;
33403335 const nexports = self.globals.items.len;
3341 const nundefs = self.imports.items.len;
3336 const nundefs = self.undefs.items.len;
33423337
33433338 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);
33443339 const locals_size = nlocals * @sizeOf(macho.nlist_64);
......@@ -3353,7 +3348,7 @@ fn writeSymbolTable(self: *MachO) !void {
33533348 const undefs_off = exports_off + exports_size;
33543349 const undefs_size = nundefs * @sizeOf(macho.nlist_64);
33553350 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
33583353 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);
33593354 seg.inner.filesize += locals_size + exports_size + undefs_size;
......@@ -3401,7 +3396,7 @@ fn writeSymbolTable(self: *MachO) !void {
34013396 got.reserved1 = nstubs;
34023397 for (self.got_entries.items) |entry| {
34033398 switch (entry.where) {
3404 .import => {
3399 .undef => {
34053400 try writer.writeIntLittle(u32, dysymtab.iundefsym + entry.where_index);
34063401 },
34073402 .local => {
......@@ -3437,8 +3432,6 @@ pub fn deinit(self: *MachO) void {
34373432 self.strtab_dir.deinit(self.base.allocator);
34383433 self.strtab.deinit(self.base.allocator);
34393434 self.undefs.deinit(self.base.allocator);
3440 self.tentatives.deinit(self.base.allocator);
3441 self.imports.deinit(self.base.allocator);
34423435 self.globals.deinit(self.base.allocator);
34433436 self.globals_free_list.deinit(self.base.allocator);
34443437 self.locals.deinit(self.base.allocator);
......@@ -4517,9 +4510,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {
45174510 if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
45184511 .strtab = &self.strtab,
45194512 })) {
4520 const import_sym_index = @intCast(u32, self.imports.items.len);
4513 const import_sym_index = @intCast(u32, self.undefs.items.len);
45214514 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, .{
45234516 .n_strx = n_strx,
45244517 .n_type = macho.N_UNDF | macho.N_EXT,
45254518 .n_sect = 0,
......@@ -4527,11 +4520,11 @@ pub fn populateMissingMetadata(self: *MachO) !void {
45274520 .n_value = 0,
45284521 });
45294522 try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
4530 .where = .import,
4523 .where = .undef,
45314524 .where_index = import_sym_index,
45324525 });
45334526 const got_key = GotIndirectionKey{
4534 .where = .import,
4527 .where = .undef,
45354528 .where_index = import_sym_index,
45364529 };
45374530 const got_index = @intCast(u32, self.got_entries.items.len);
......@@ -4663,9 +4656,9 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
46634656 }
46644657
46654658 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);
46674660 const n_strx = try self.makeString(sym_name);
4668 try self.imports.append(self.base.allocator, .{
4661 try self.undefs.append(self.base.allocator, .{
46694662 .n_strx = n_strx,
46704663 .n_type = macho.N_UNDF | macho.N_EXT,
46714664 .n_sect = 0,
......@@ -4673,7 +4666,7 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
46734666 .n_value = 0,
46744667 });
46754668 try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
4676 .where = .import,
4669 .where = .undef,
46774670 .where_index = import_sym_index,
46784671 });
46794672
......@@ -4856,7 +4849,7 @@ fn writeGotEntry(self: *MachO, index: usize) !void {
48564849 const got_entry = self.got_entries.items[index];
48574850 const sym = switch (got_entry.where) {
48584851 .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],
48604853 };
48614854 log.debug("writing offset table entry [ 0x{x} => 0x{x} ({s}) ]", .{
48624855 off,
......@@ -5140,7 +5133,7 @@ fn relocateSymbolTable(self: *MachO) !void {
51405133 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
51415134 const nlocals = self.locals.items.len;
51425135 const nglobals = self.globals.items.len;
5143 const nundefs = self.imports.items.len;
5136 const nundefs = self.undefs.items.len;
51445137 const nsyms = nlocals + nglobals + nundefs;
51455138
51465139 if (symtab.nsyms < nsyms) {
......@@ -5185,7 +5178,7 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {
51855178 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
51865179 const nlocals = self.locals.items.len;
51875180 const nglobals = self.globals.items.len;
5188 const nundefs = self.imports.items.len;
5181 const nundefs = self.undefs.items.len;
51895182
51905183 const locals_off = symtab.symoff;
51915184 const locals_size = nlocals * @sizeOf(macho.nlist_64);
......@@ -5198,7 +5191,7 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {
51985191 const undefs_off = globals_off + globals_size;
51995192 const undefs_size = nundefs * @sizeOf(macho.nlist_64);
52005193 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
52035196 // Update dynamic symbol table.
52045197 const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
......@@ -5253,7 +5246,7 @@ fn writeIndirectSymbolTable(self: *MachO) !void {
52535246 got.reserved1 = nstubs;
52545247 for (self.got_entries.items) |entry| {
52555248 switch (entry.where) {
5256 .import => {
5249 .undef => {
52575250 try writer.writeIntLittle(u32, dysymtab.iundefsym + entry.where_index);
52585251 },
52595252 .local => {
......@@ -5478,7 +5471,7 @@ fn writeRebaseInfoTable(self: *MachO) !void {
54785471 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
54795472
54805473 for (self.got_entries.items) |entry, i| {
5481 if (entry.where == .import) continue;
5474 if (entry.where == .undef) continue;
54825475
54835476 try pointers.append(.{
54845477 .offset = base_offset + i * @sizeOf(u64),
......@@ -5547,7 +5540,7 @@ fn writeBindInfoTable(self: *MachO) !void {
55475540 for (self.got_entries.items) |entry, i| {
55485541 if (entry.where == .local) continue;
55495542
5550 const sym = self.imports.items[entry.where_index];
5543 const sym = self.undefs.items[entry.where_index];
55515544 try pointers.append(.{
55525545 .offset = base_offset + i * @sizeOf(u64),
55535546 .segment_id = segment_id,
......@@ -5572,7 +5565,7 @@ fn writeBindInfoTable(self: *MachO) !void {
55725565 const base_offset = sym.n_value - seg.inner.vmaddr;
55735566
55745567 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];
55765569 try pointers.append(.{
55775570 .offset = binding.offset + base_offset,
55785571 .segment_id = match.seg,
......@@ -5631,7 +5624,7 @@ fn writeLazyBindInfoTable(self: *MachO) !void {
56315624 try pointers.ensureUnusedCapacity(self.stubs.items.len);
56325625
56335626 for (self.stubs.items) |import_id, i| {
5634 const sym = self.imports.items[import_id];
5627 const sym = self.undefs.items[import_id];
56355628 pointers.appendAssumeCapacity(.{
56365629 .offset = base_offset + i * @sizeOf(u64),
56375630 .segment_id = segment_id,
......@@ -5967,10 +5960,6 @@ pub fn symbolIsTentative(sym: macho.nlist_64) bool {
59675960 return sym.n_value != 0;
59685961}
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
59745963pub fn symbolIsTemp(sym: macho.nlist_64, sym_name: []const u8) bool {
59755964 if (!symbolIsSect(sym)) return false;
59765965 if (symbolIsExt(sym)) return false;
src/link/MachO/TextBlock.zig+10-11
......@@ -165,7 +165,7 @@ pub const Relocation = struct {
165165
166166 where: enum {
167167 local,
168 import,
168 undef,
169169 },
170170
171171 where_index: u32,
......@@ -665,11 +665,10 @@ fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Reloc
665665 parsed_rel.where = .local;
666666 parsed_rel.where_index = resolv.local_sym_index;
667667 },
668 .import => {
669 parsed_rel.where = .import;
668 .undef => {
669 parsed_rel.where = .undef;
670670 parsed_rel.where_index = resolv.where_index;
671671 },
672 else => unreachable,
673672 }
674673 }
675674 }
......@@ -825,7 +824,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
825824 const key = MachO.GotIndirectionKey{
826825 .where = switch (parsed_rel.where) {
827826 .local => .local,
828 .import => .import,
827 .undef => .undef,
829828 },
830829 .where_index = parsed_rel.where_index,
831830 };
......@@ -836,7 +835,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
836835 try context.macho_file.got_entries_map.putNoClobber(context.allocator, key, got_index);
837836 } else if (parsed_rel.payload == .unsigned) {
838837 switch (parsed_rel.where) {
839 .import => {
838 .undef => {
840839 try self.bindings.append(context.allocator, .{
841840 .local_sym_index = parsed_rel.where_index,
842841 .offset = parsed_rel.offset,
......@@ -886,7 +885,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
886885 },
887886 }
888887 } else if (parsed_rel.payload == .branch) blk: {
889 if (parsed_rel.where != .import) break :blk;
888 if (parsed_rel.where != .undef) break :blk;
890889 if (context.macho_file.stubs_map.contains(parsed_rel.where_index)) break :blk;
891890
892891 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
10301029 const source_sym = context.macho_file.locals.items[self.local_sym_index];
10311030 const target_sym = switch (out.where) {
10321031 .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],
10341033 };
10351034 addend = @intCast(i64, source_sym.n_value + out.offset + 4) + addend - @intCast(i64, target_sym.n_value);
10361035 }
......@@ -1088,13 +1087,13 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {
10881087 const got_index = macho_file.got_entries_map.get(.{
10891088 .where = switch (rel.where) {
10901089 .local => .local,
1091 .import => .import,
1090 .undef => .undef,
10921091 },
10931092 .where_index = rel.where_index,
10941093 }) orelse {
10951094 const sym = switch (rel.where) {
10961095 .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],
10981097 };
10991098 log.err("expected GOT entry for symbol '{s}'", .{macho_file.getString(sym.n_strx)});
11001099 log.err(" this is an internal linker error", .{});
......@@ -1137,7 +1136,7 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {
11371136
11381137 break :blk sym.n_value;
11391138 },
1140 .import => {
1139 .undef => {
11411140 const stubs_index = macho_file.stubs_map.get(rel.where_index) orelse {
11421141 // TODO verify in TextBlock that the symbol is indeed dynamically bound.
11431142 break :blk 0; // Dynamically bound by dyld.