aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2020-12-11 18:24:07 +0100
committerJakub Konka <kubkon@jakubkonka.com>2020-12-17 10:04:53 +0100
commitb099fdff9374afef8921910970373ce80b804e2b (patch)
tree96bca74f48f919d1e5c2b2f96f1d6c9124d1a8bf /src/link
parentf5a0b9315b4920c5e9e9f886e29101dcc8ae7cc7 (diff)
downloadzig-b099fdff9374afef8921910970373ce80b804e2b.tar.gz
zig-b099fdff9374afef8921910970373ce80b804e2b.zip
macho: parse symbol and string tables
Diffstat (limited to 'src/link')
-rw-r--r--src/link/MachO.zig43
1 files changed, 41 insertions, 2 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 681c06b06d..fc96466e1e 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -801,6 +801,16 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
mem.copy(u8, dylib_cmd.data, mem.spanZ(LIB_SYSTEM_PATH));
try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
+ if (self.symtab_cmd_index == null or self.dysymtab_cmd_index == null) {
+ std.log.err("Incomplete Mach-O binary: no LC_SYMTAB or LC_DYSYMTAB load command found!", .{});
+ std.log.err("Without the symbol table, it is not possible to patch up the binary for cross-compilation.", .{});
+ return error.NoSymbolTable;
+ }
+
+ // Parse symbol and string tables.
+ try self.parseSymbolTable();
+ try self.parseStringTable();
+
// Parse dyld info
try self.parseBindingInfo();
try self.parseLazyBindingInfo();
@@ -2038,8 +2048,6 @@ fn parseFromFile(self: *MachO, file: fs.File) !void {
self.load_commands.appendAssumeCapacity(cmd);
}
self.header = header;
-
- // TODO Should we parse memory mapped segments here or as needed?
}
fn parseAndCmpName(name: []const u8, needle: []const u8) bool {
@@ -2047,6 +2055,37 @@ fn parseAndCmpName(name: []const u8, needle: []const u8) bool {
return mem.eql(u8, name[0..len], needle);
}
+fn parseSymbolTable(self: *MachO) !void {
+ const symtab = self.load_commands.items[self.symtab_cmd_index.?].Symtab;
+ const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
+
+ var buffer = try self.base.allocator.alloc(macho.nlist_64, symtab.nsyms);
+ defer self.base.allocator.free(buffer);
+ const nread = try self.base.file.?.preadAll(@ptrCast([*]u8, buffer)[0 .. symtab.nsyms * @sizeOf(macho.nlist_64)], symtab.symoff);
+ assert(@divExact(nread, @sizeOf(macho.nlist_64)) == buffer.len);
+
+ try self.local_symbols.ensureCapacity(self.base.allocator, dysymtab.nlocalsym);
+ try self.global_symbols.ensureCapacity(self.base.allocator, dysymtab.nextdefsym);
+ try self.undef_symbols.ensureCapacity(self.base.allocator, dysymtab.nundefsym);
+
+ self.local_symbols.appendSliceAssumeCapacity(buffer[dysymtab.ilocalsym .. dysymtab.ilocalsym + dysymtab.nlocalsym]);
+ self.global_symbols.appendSliceAssumeCapacity(buffer[dysymtab.iextdefsym .. dysymtab.iextdefsym + dysymtab.nextdefsym]);
+ self.undef_symbols.appendSliceAssumeCapacity(buffer[dysymtab.iundefsym .. dysymtab.iundefsym + dysymtab.nundefsym]);
+}
+
+fn parseStringTable(self: *MachO) !void {
+ const symtab = self.load_commands.items[self.symtab_cmd_index.?].Symtab;
+
+ var buffer = try self.base.allocator.alloc(u8, symtab.strsize);
+ defer self.base.allocator.free(buffer);
+ const nread = try self.base.file.?.preadAll(buffer, symtab.stroff);
+ assert(nread == buffer.len);
+
+ try self.string_table.ensureCapacity(self.base.allocator, symtab.strsize);
+
+ self.string_table.appendSliceAssumeCapacity(buffer);
+}
+
fn parseBindingInfo(self: *MachO) !void {
const dyld_info = self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
var buffer = try self.base.allocator.alloc(u8, dyld_info.bind_size);