aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-08-03 13:37:48 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-08-12 10:20:57 +0200
commitda57d6df320cb6bd9ce09bef192f201d59a50b28 (patch)
tree96deedef1ca153086d9326433c1f398937121d0d /src/link
parent493822ac3bab344821aad180aae27b629eb920c1 (diff)
downloadzig-da57d6df320cb6bd9ce09bef192f201d59a50b28.tar.gz
zig-da57d6df320cb6bd9ce09bef192f201d59a50b28.zip
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.
Diffstat (limited to 'src/link')
-rw-r--r--src/link/MachO.zig263
-rw-r--r--src/link/MachO/TextBlock.zig21
2 files changed, 136 insertions, 148 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 6fbe3bc150..26a581a22a 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -134,9 +134,7 @@ objc_data_section_index: ?u16 = null,
locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
globals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
-imports: std.ArrayListUnmanaged(macho.nlist_64) = .{},
undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{},
-tentatives: std.ArrayListUnmanaged(macho.nlist_64) = .{},
symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{},
locals_free_list: std.ArrayListUnmanaged(u32) = .{},
@@ -252,9 +250,7 @@ const SymbolWithLoc = struct {
// Table where the symbol can be found.
where: enum {
global,
- import,
undef,
- tentative,
},
where_index: u32,
local_sym_index: u32 = 0,
@@ -264,22 +260,11 @@ const SymbolWithLoc = struct {
pub const GotIndirectionKey = struct {
where: enum {
local,
- import,
+ undef,
},
where_index: u32,
};
-pub const PIEFixup = struct {
- /// Target VM address of this relocation.
- target_addr: u64,
-
- /// Offset within the byte stream.
- offset: usize,
-
- /// Size of the relocation.
- size: usize,
-};
-
/// When allocating, the ideal_capacity is calculated by
/// actual_capacity + (actual_capacity / ideal_factor)
const ideal_factor = 2;
@@ -960,7 +945,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
const got_index = @intCast(u32, self.got_entries.items.len);
const got_entry = GotIndirectionKey{
- .where = .import,
+ .where = .undef,
.where_index = resolv.where_index,
};
try self.got_entries.append(self.base.allocator, got_entry);
@@ -1991,7 +1976,7 @@ fn writeStubHelperCommon(self: *MachO) !void {
}) orelse unreachable;
const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
const got_index = self.got_entries_map.get(.{
- .where = .import,
+ .where = .undef,
.where_index = resolv.where_index,
}) orelse unreachable;
const addr = got.addr + got_index * @sizeOf(u64);
@@ -2042,7 +2027,7 @@ fn writeStubHelperCommon(self: *MachO) !void {
}) orelse unreachable;
const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
const got_index = self.got_entries_map.get(.{
- .where = .import,
+ .where = .undef,
.where_index = resolv.where_index,
}) orelse unreachable;
const this_addr = stub_helper.addr + 3 * @sizeOf(u32);
@@ -2106,7 +2091,12 @@ fn writeStubHelperCommon(self: *MachO) !void {
}
}
-fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
+fn resolveSymbolsInObject(
+ self: *MachO,
+ object_id: u16,
+ tentatives: *std.ArrayList(u32),
+ unresolved: *std.ArrayList(u32),
+) !void {
const object = &self.objects.items[object_id];
log.debug("resolving symbols in '{s}'", .{object.name});
@@ -2174,7 +2164,6 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
};
switch (resolv.where) {
- .import => unreachable,
.global => {
const global = &self.globals.items[resolv.where_index];
@@ -2186,8 +2175,16 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
log.err(" next definition in '{s}'", .{object.name});
return error.MultipleSymbolDefinitions;
}
-
if (symbolIsWeakDef(sym) or symbolIsPext(sym)) continue; // Current symbol is weak, so skip it.
+ if (symbolIsTentative(global.*)) {
+ var i: usize = 0;
+ while (i < tentatives.items.len) : (i += 1) {
+ if (tentatives.items[i] == resolv.where_index) {
+ _ = tentatives.swapRemove(i);
+ break;
+ }
+ }
+ }
// Otherwise, update the resolver and the global symbol.
global.n_type = sym.n_type;
@@ -2205,16 +2202,14 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
.n_desc = 0,
.n_value = 0,
};
- },
- .tentative => {
- const tentative = &self.tentatives.items[resolv.where_index];
- tentative.* = .{
- .n_strx = 0,
- .n_type = macho.N_UNDF,
- .n_sect = 0,
- .n_desc = 0,
- .n_value = 0,
- };
+
+ var i: usize = 0;
+ while (i < unresolved.items.len) : (i += 1) {
+ if (unresolved.items[i] == resolv.where_index) {
+ _ = unresolved.swapRemove(i);
+ break;
+ }
+ }
},
}
@@ -2235,8 +2230,8 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
} else if (symbolIsTentative(sym)) {
// Symbol is a tentative definition.
const resolv = self.symbol_resolver.getPtr(n_strx) orelse {
- const tent_sym_index = @intCast(u32, self.tentatives.items.len);
- try self.tentatives.append(self.base.allocator, .{
+ const global_sym_index = @intCast(u32, self.globals.items.len);
+ try self.globals.append(self.base.allocator, .{
.n_strx = try self.makeString(sym_name),
.n_type = sym.n_type,
.n_sect = 0,
@@ -2244,29 +2239,38 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
.n_value = sym.n_value,
});
try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
- .where = .tentative,
- .where_index = tent_sym_index,
+ .where = .global,
+ .where_index = global_sym_index,
.file = object_id,
});
+ try tentatives.append(global_sym_index);
continue;
};
switch (resolv.where) {
- .import => unreachable,
- .global => {},
+ .global => {
+ const global = &self.globals.items[resolv.where_index];
+ if (!symbolIsTentative(global.*)) continue;
+ if (global.n_value >= sym.n_value) continue;
+
+ global.n_desc = sym.n_desc;
+ global.n_value = sym.n_value;
+ resolv.file = object_id;
+ },
.undef => {
const undef = &self.undefs.items[resolv.where_index];
- const tent_sym_index = @intCast(u32, self.tentatives.items.len);
- try self.tentatives.append(self.base.allocator, .{
+ const global_sym_index = @intCast(u32, self.globals.items.len);
+ try self.globals.append(self.base.allocator, .{
.n_strx = undef.n_strx,
.n_type = sym.n_type,
.n_sect = 0,
.n_desc = sym.n_desc,
.n_value = sym.n_value,
});
+ try tentatives.append(global_sym_index);
resolv.* = .{
- .where = .tentative,
- .where_index = tent_sym_index,
+ .where = .global,
+ .where_index = global_sym_index,
.file = object_id,
};
undef.* = .{
@@ -2276,14 +2280,13 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
.n_desc = 0,
.n_value = 0,
};
- },
- .tentative => {
- const tentative = &self.tentatives.items[resolv.where_index];
- if (tentative.n_value >= sym.n_value) continue;
-
- tentative.n_desc = sym.n_desc;
- tentative.n_value = sym.n_value;
- resolv.file = object_id;
+ var i: usize = 0;
+ while (i < unresolved.items.len) : (i += 1) {
+ if (unresolved.items[i] == resolv.where_index) {
+ _ = unresolved.swapRemove(i);
+ break;
+ }
+ }
},
}
} else {
@@ -2303,24 +2306,27 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void {
.where_index = undef_sym_index,
.file = object_id,
});
+ try unresolved.append(undef_sym_index);
}
}
}
fn resolveSymbols(self: *MachO) !void {
+ var tentatives = std.ArrayList(u32).init(self.base.allocator);
+ defer tentatives.deinit();
+
+ var unresolved = std.ArrayList(u32).init(self.base.allocator);
+ defer unresolved.deinit();
+
// First pass, resolve symbols in provided objects.
for (self.objects.items) |_, object_id| {
- try self.resolveSymbolsInObject(@intCast(u16, object_id));
+ try self.resolveSymbolsInObject(@intCast(u16, object_id), &tentatives, &unresolved);
}
// Second pass, resolve symbols in static libraries.
var next_sym: usize = 0;
- loop: while (true) : (next_sym += 1) {
- if (next_sym == self.undefs.items.len) break;
-
- const sym = self.undefs.items[next_sym];
- if (symbolIsNull(sym)) continue;
-
+ loop: while (next_sym < unresolved.items.len) {
+ const sym = self.undefs.items[unresolved.items[next_sym]];
const sym_name = self.getString(sym.n_strx);
for (self.archives.items) |archive| {
@@ -2334,17 +2340,18 @@ fn resolveSymbols(self: *MachO) !void {
const object_id = @intCast(u16, self.objects.items.len);
const object = try self.objects.addOne(self.base.allocator);
object.* = try archive.parseObject(self.base.allocator, self.base.options.target, offsets.items[0]);
- try self.resolveSymbolsInObject(object_id);
+ try self.resolveSymbolsInObject(object_id, &tentatives, &unresolved);
continue :loop;
}
+
+ next_sym += 1;
}
// Convert any tentative definition into a regular symbol and allocate
// text blocks for each tentative defintion.
- for (self.tentatives.items) |sym| {
- if (symbolIsNull(sym)) continue;
-
+ while (tentatives.popOrNull()) |index| {
+ const sym = &self.globals.items[index];
const match: MatchingSection = blk: {
if (self.common_section_index == null) {
const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
@@ -2366,24 +2373,17 @@ fn resolveSymbols(self: *MachO) !void {
mem.set(u8, code, 0);
const alignment = (sym.n_desc >> 8) & 0x0f;
- const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable;
+ sym.n_value = 0;
+ sym.n_desc = 0;
+ sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
+ var local_sym = sym.*;
+ local_sym.n_type = macho.N_SECT;
+
const local_sym_index = @intCast(u32, self.locals.items.len);
- var nlist = macho.nlist_64{
- .n_strx = sym.n_strx,
- .n_type = macho.N_SECT,
- .n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1),
- .n_desc = 0,
- .n_value = 0,
- };
- try self.locals.append(self.base.allocator, nlist);
- const global_sym_index = @intCast(u32, self.globals.items.len);
- nlist.n_type |= macho.N_EXT;
- try self.globals.append(self.base.allocator, nlist);
- resolv.* = .{
- .where = .global,
- .where_index = global_sym_index,
- .local_sym_index = local_sym_index,
- };
+ try self.locals.append(self.base.allocator, local_sym);
+
+ const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable;
+ resolv.local_sym_index = local_sym_index;
const block = try self.base.allocator.create(TextBlock);
block.* = TextBlock.empty;
@@ -2430,13 +2430,15 @@ fn resolveSymbols(self: *MachO) !void {
.where = .undef,
.where_index = undef_sym_index,
});
+ try unresolved.append(undef_sym_index);
}
- loop: for (self.undefs.items) |sym| {
- if (symbolIsNull(sym)) continue;
-
+ next_sym = 0;
+ loop: while (next_sym < unresolved.items.len) {
+ const sym = self.undefs.items[unresolved.items[next_sym]];
const sym_name = self.getString(sym.n_strx);
- for (self.dylibs.items) |*dylib, id| {
+
+ for (self.dylibs.items) |dylib, id| {
if (!dylib.symbols.contains(sym_name)) continue;
const dylib_id = @intCast(u16, id);
@@ -2447,28 +2449,15 @@ fn resolveSymbols(self: *MachO) !void {
const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable;
const resolv = self.symbol_resolver.getPtr(sym.n_strx) orelse unreachable;
const undef = &self.undefs.items[resolv.where_index];
- const import_sym_index = @intCast(u32, self.imports.items.len);
- try self.imports.append(self.base.allocator, .{
- .n_strx = undef.n_strx,
- .n_type = macho.N_UNDF | macho.N_EXT,
- .n_sect = 0,
- .n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER,
- .n_value = 0,
- });
- resolv.* = .{
- .where = .import,
- .where_index = import_sym_index,
- };
- undef.* = .{
- .n_strx = 0,
- .n_type = macho.N_UNDF,
- .n_sect = 0,
- .n_desc = 0,
- .n_value = 0,
- };
+ undef.n_type |= macho.N_EXT;
+ undef.n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER;
+
+ _ = unresolved.swapRemove(next_sym);
continue :loop;
}
+
+ next_sym += 1;
}
// Fourth pass, handle synthetic symbols and flag any undefined references.
@@ -2497,6 +2486,14 @@ fn resolveSymbols(self: *MachO) !void {
nlist.n_desc = macho.N_WEAK_DEF;
try self.globals.append(self.base.allocator, nlist);
+ var i: usize = 0;
+ while (i < unresolved.items.len) : (i += 1) {
+ if (unresolved.items[i] == resolv.where_index) {
+ _ = unresolved.swapRemove(i);
+ break;
+ }
+ }
+
undef.* = .{
.n_strx = 0,
.n_type = macho.N_UNDF,
@@ -2529,19 +2526,17 @@ fn resolveSymbols(self: *MachO) !void {
}
}
- var has_undefined = false;
- for (self.undefs.items) |sym| {
- if (symbolIsNull(sym)) continue;
-
+ for (unresolved.items) |index| {
+ const sym = self.undefs.items[index];
const sym_name = self.getString(sym.n_strx);
const resolv = self.symbol_resolver.get(sym.n_strx) orelse unreachable;
log.err("undefined reference to symbol '{s}'", .{sym_name});
log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name});
- has_undefined = true;
}
- if (has_undefined) return error.UndefinedSymbolReference;
+ if (unresolved.items.len > 0)
+ return error.UndefinedSymbolReference;
}
fn parseTextBlocks(self: *MachO) !void {
@@ -3006,7 +3001,7 @@ fn writeGotEntries(self: *MachO) !void {
for (self.got_entries.items) |key| {
const address: u64 = switch (key.where) {
.local => self.locals.items[key.where_index].n_value,
- .import => 0,
+ .undef => 0,
};
try writer.writeIntLittle(u64, address);
}
@@ -3075,7 +3070,7 @@ fn writeRebaseInfoTableZld(self: *MachO) !void {
const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
for (self.got_entries.items) |entry, i| {
- if (entry.where == .import) continue;
+ if (entry.where == .undef) continue;
try pointers.append(.{
.offset = base_offset + i * @sizeOf(u64),
@@ -3132,7 +3127,7 @@ fn writeBindInfoTableZld(self: *MachO) !void {
for (self.got_entries.items) |entry, i| {
if (entry.where == .local) continue;
- const sym = self.imports.items[entry.where_index];
+ const sym = self.undefs.items[entry.where_index];
try pointers.append(.{
.offset = base_offset + i * @sizeOf(u64),
.segment_id = segment_id,
@@ -3157,7 +3152,7 @@ fn writeBindInfoTableZld(self: *MachO) !void {
const base_offset = sym.n_value - seg.inner.vmaddr;
for (block.bindings.items) |binding| {
- const bind_sym = self.imports.items[binding.local_sym_index];
+ const bind_sym = self.undefs.items[binding.local_sym_index];
try pointers.append(.{
.offset = binding.offset + base_offset,
.segment_id = match.seg,
@@ -3204,7 +3199,7 @@ fn writeLazyBindInfoTableZld(self: *MachO) !void {
try pointers.ensureUnusedCapacity(self.stubs.items.len);
for (self.stubs.items) |import_id, i| {
- const sym = self.imports.items[import_id];
+ const sym = self.undefs.items[import_id];
pointers.appendAssumeCapacity(.{
.offset = base_offset + i * @sizeOf(u64),
.segment_id = segment_id,
@@ -3338,7 +3333,7 @@ fn writeSymbolTable(self: *MachO) !void {
const nlocals = locals.items.len;
const nexports = self.globals.items.len;
- const nundefs = self.imports.items.len;
+ const nundefs = self.undefs.items.len;
const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);
const locals_size = nlocals * @sizeOf(macho.nlist_64);
@@ -3353,7 +3348,7 @@ fn writeSymbolTable(self: *MachO) !void {
const undefs_off = exports_off + exports_size;
const undefs_size = nundefs * @sizeOf(macho.nlist_64);
log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });
- try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.imports.items), undefs_off);
+ try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.undefs.items), undefs_off);
symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);
seg.inner.filesize += locals_size + exports_size + undefs_size;
@@ -3401,7 +3396,7 @@ fn writeSymbolTable(self: *MachO) !void {
got.reserved1 = nstubs;
for (self.got_entries.items) |entry| {
switch (entry.where) {
- .import => {
+ .undef => {
try writer.writeIntLittle(u32, dysymtab.iundefsym + entry.where_index);
},
.local => {
@@ -3437,8 +3432,6 @@ pub fn deinit(self: *MachO) void {
self.strtab_dir.deinit(self.base.allocator);
self.strtab.deinit(self.base.allocator);
self.undefs.deinit(self.base.allocator);
- self.tentatives.deinit(self.base.allocator);
- self.imports.deinit(self.base.allocator);
self.globals.deinit(self.base.allocator);
self.globals_free_list.deinit(self.base.allocator);
self.locals.deinit(self.base.allocator);
@@ -4517,9 +4510,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {
if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{
.strtab = &self.strtab,
})) {
- const import_sym_index = @intCast(u32, self.imports.items.len);
+ const import_sym_index = @intCast(u32, self.undefs.items.len);
const n_strx = try self.makeString("dyld_stub_binder");
- try self.imports.append(self.base.allocator, .{
+ try self.undefs.append(self.base.allocator, .{
.n_strx = n_strx,
.n_type = macho.N_UNDF | macho.N_EXT,
.n_sect = 0,
@@ -4527,11 +4520,11 @@ pub fn populateMissingMetadata(self: *MachO) !void {
.n_value = 0,
});
try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
- .where = .import,
+ .where = .undef,
.where_index = import_sym_index,
});
const got_key = GotIndirectionKey{
- .where = .import,
+ .where = .undef,
.where_index = import_sym_index,
};
const got_index = @intCast(u32, self.got_entries.items.len);
@@ -4663,9 +4656,9 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
}
log.debug("adding new extern function '{s}' with dylib ordinal 1", .{sym_name});
- const import_sym_index = @intCast(u32, self.imports.items.len);
+ const import_sym_index = @intCast(u32, self.undefs.items.len);
const n_strx = try self.makeString(sym_name);
- try self.imports.append(self.base.allocator, .{
+ try self.undefs.append(self.base.allocator, .{
.n_strx = n_strx,
.n_type = macho.N_UNDF | macho.N_EXT,
.n_sect = 0,
@@ -4673,7 +4666,7 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
.n_value = 0,
});
try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
- .where = .import,
+ .where = .undef,
.where_index = import_sym_index,
});
@@ -4856,7 +4849,7 @@ fn writeGotEntry(self: *MachO, index: usize) !void {
const got_entry = self.got_entries.items[index];
const sym = switch (got_entry.where) {
.local => self.locals.items[got_entry.where_index],
- .import => self.imports.items[got_entry.where_index],
+ .undef => self.undefs.items[got_entry.where_index],
};
log.debug("writing offset table entry [ 0x{x} => 0x{x} ({s}) ]", .{
off,
@@ -5140,7 +5133,7 @@ fn relocateSymbolTable(self: *MachO) !void {
const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
const nlocals = self.locals.items.len;
const nglobals = self.globals.items.len;
- const nundefs = self.imports.items.len;
+ const nundefs = self.undefs.items.len;
const nsyms = nlocals + nglobals + nundefs;
if (symtab.nsyms < nsyms) {
@@ -5185,7 +5178,7 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {
const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
const nlocals = self.locals.items.len;
const nglobals = self.globals.items.len;
- const nundefs = self.imports.items.len;
+ const nundefs = self.undefs.items.len;
const locals_off = symtab.symoff;
const locals_size = nlocals * @sizeOf(macho.nlist_64);
@@ -5198,7 +5191,7 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {
const undefs_off = globals_off + globals_size;
const undefs_size = nundefs * @sizeOf(macho.nlist_64);
log.debug("writing extern symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });
- try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.imports.items), undefs_off);
+ try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.undefs.items), undefs_off);
// Update dynamic symbol table.
const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
@@ -5253,7 +5246,7 @@ fn writeIndirectSymbolTable(self: *MachO) !void {
got.reserved1 = nstubs;
for (self.got_entries.items) |entry| {
switch (entry.where) {
- .import => {
+ .undef => {
try writer.writeIntLittle(u32, dysymtab.iundefsym + entry.where_index);
},
.local => {
@@ -5478,7 +5471,7 @@ fn writeRebaseInfoTable(self: *MachO) !void {
const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
for (self.got_entries.items) |entry, i| {
- if (entry.where == .import) continue;
+ if (entry.where == .undef) continue;
try pointers.append(.{
.offset = base_offset + i * @sizeOf(u64),
@@ -5547,7 +5540,7 @@ fn writeBindInfoTable(self: *MachO) !void {
for (self.got_entries.items) |entry, i| {
if (entry.where == .local) continue;
- const sym = self.imports.items[entry.where_index];
+ const sym = self.undefs.items[entry.where_index];
try pointers.append(.{
.offset = base_offset + i * @sizeOf(u64),
.segment_id = segment_id,
@@ -5572,7 +5565,7 @@ fn writeBindInfoTable(self: *MachO) !void {
const base_offset = sym.n_value - seg.inner.vmaddr;
for (block.bindings.items) |binding| {
- const bind_sym = self.imports.items[binding.local_sym_index];
+ const bind_sym = self.undefs.items[binding.local_sym_index];
try pointers.append(.{
.offset = binding.offset + base_offset,
.segment_id = match.seg,
@@ -5631,7 +5624,7 @@ fn writeLazyBindInfoTable(self: *MachO) !void {
try pointers.ensureUnusedCapacity(self.stubs.items.len);
for (self.stubs.items) |import_id, i| {
- const sym = self.imports.items[import_id];
+ const sym = self.undefs.items[import_id];
pointers.appendAssumeCapacity(.{
.offset = base_offset + i * @sizeOf(u64),
.segment_id = segment_id,
@@ -5967,10 +5960,6 @@ pub fn symbolIsTentative(sym: macho.nlist_64) bool {
return sym.n_value != 0;
}
-pub fn symbolIsNull(sym: macho.nlist_64) bool {
- 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;
-}
-
pub fn symbolIsTemp(sym: macho.nlist_64, sym_name: []const u8) bool {
if (!symbolIsSect(sym)) return false;
if (symbolIsExt(sym)) return false;
diff --git a/src/link/MachO/TextBlock.zig b/src/link/MachO/TextBlock.zig
index 55dc2db471..4788487d3b 100644
--- a/src/link/MachO/TextBlock.zig
+++ b/src/link/MachO/TextBlock.zig
@@ -165,7 +165,7 @@ pub const Relocation = struct {
where: enum {
local,
- import,
+ undef,
},
where_index: u32,
@@ -665,11 +665,10 @@ fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Reloc
parsed_rel.where = .local;
parsed_rel.where_index = resolv.local_sym_index;
},
- .import => {
- parsed_rel.where = .import;
+ .undef => {
+ parsed_rel.where = .undef;
parsed_rel.where_index = resolv.where_index;
},
- else => unreachable,
}
}
}
@@ -825,7 +824,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
const key = MachO.GotIndirectionKey{
.where = switch (parsed_rel.where) {
.local => .local,
- .import => .import,
+ .undef => .undef,
},
.where_index = parsed_rel.where_index,
};
@@ -836,7 +835,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
try context.macho_file.got_entries_map.putNoClobber(context.allocator, key, got_index);
} else if (parsed_rel.payload == .unsigned) {
switch (parsed_rel.where) {
- .import => {
+ .undef => {
try self.bindings.append(context.allocator, .{
.local_sym_index = parsed_rel.where_index,
.offset = parsed_rel.offset,
@@ -886,7 +885,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
},
}
} else if (parsed_rel.payload == .branch) blk: {
- if (parsed_rel.where != .import) break :blk;
+ if (parsed_rel.where != .undef) break :blk;
if (context.macho_file.stubs_map.contains(parsed_rel.where_index)) break :blk;
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
const source_sym = context.macho_file.locals.items[self.local_sym_index];
const target_sym = switch (out.where) {
.local => context.macho_file.locals.items[out.where_index],
- .import => context.macho_file.imports.items[out.where_index],
+ .undef => context.macho_file.undefs.items[out.where_index],
};
addend = @intCast(i64, source_sym.n_value + out.offset + 4) + addend - @intCast(i64, target_sym.n_value);
}
@@ -1088,13 +1087,13 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {
const got_index = macho_file.got_entries_map.get(.{
.where = switch (rel.where) {
.local => .local,
- .import => .import,
+ .undef => .undef,
},
.where_index = rel.where_index,
}) orelse {
const sym = switch (rel.where) {
.local => macho_file.locals.items[rel.where_index],
- .import => macho_file.imports.items[rel.where_index],
+ .undef => macho_file.undefs.items[rel.where_index],
};
log.err("expected GOT entry for symbol '{s}'", .{macho_file.getString(sym.n_strx)});
log.err(" this is an internal linker error", .{});
@@ -1137,7 +1136,7 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {
break :blk sym.n_value;
},
- .import => {
+ .undef => {
const stubs_index = macho_file.stubs_map.get(rel.where_index) orelse {
// TODO verify in TextBlock that the symbol is indeed dynamically bound.
break :blk 0; // Dynamically bound by dyld.