authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-11 18:24:07+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-17 10:04:53+01:00
logb099fdff9374afef8921910970373ce80b804e2b
tree96bca74f48f919d1e5c2b2f96f1d6c9124d1a8bf
parentf5a0b9315b4920c5e9e9f886e29101dcc8ae7cc7

macho: parse symbol and string tables


1 files changed, 41 insertions(+), 2 deletions(-)

src/link/MachO.zig+41-2
...@@ -801,6 +801,16 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -801,6 +801,16 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
801 mem.copy(u8, dylib_cmd.data, mem.spanZ(LIB_SYSTEM_PATH));801 mem.copy(u8, dylib_cmd.data, mem.spanZ(LIB_SYSTEM_PATH));
802 try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });802 try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
803803
804 if (self.symtab_cmd_index == null or self.dysymtab_cmd_index == null) {
805 std.log.err("Incomplete Mach-O binary: no LC_SYMTAB or LC_DYSYMTAB load command found!", .{});
806 std.log.err("Without the symbol table, it is not possible to patch up the binary for cross-compilation.", .{});
807 return error.NoSymbolTable;
808 }
809
810 // Parse symbol and string tables.
811 try self.parseSymbolTable();
812 try self.parseStringTable();
813
804 // Parse dyld info814 // Parse dyld info
805 try self.parseBindingInfo();815 try self.parseBindingInfo();
806 try self.parseLazyBindingInfo();816 try self.parseLazyBindingInfo();
...@@ -2038,8 +2048,6 @@ fn parseFromFile(self: *MachO, file: fs.File) !void {...@@ -2038,8 +2048,6 @@ fn parseFromFile(self: *MachO, file: fs.File) !void {
2038 self.load_commands.appendAssumeCapacity(cmd);2048 self.load_commands.appendAssumeCapacity(cmd);
2039 }2049 }
2040 self.header = header;2050 self.header = header;
2041
2042 // TODO Should we parse memory mapped segments here or as needed?
2043}2051}
20442052
2045fn parseAndCmpName(name: []const u8, needle: []const u8) bool {2053fn parseAndCmpName(name: []const u8, needle: []const u8) bool {
...@@ -2047,6 +2055,37 @@ fn parseAndCmpName(name: []const u8, needle: []const u8) bool {...@@ -2047,6 +2055,37 @@ fn parseAndCmpName(name: []const u8, needle: []const u8) bool {
2047 return mem.eql(u8, name[0..len], needle);2055 return mem.eql(u8, name[0..len], needle);
2048}2056}
20492057
2058fn parseSymbolTable(self: *MachO) !void {
2059 const symtab = self.load_commands.items[self.symtab_cmd_index.?].Symtab;
2060 const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
2061
2062 var buffer = try self.base.allocator.alloc(macho.nlist_64, symtab.nsyms);
2063 defer self.base.allocator.free(buffer);
2064 const nread = try self.base.file.?.preadAll(@ptrCast([*]u8, buffer)[0 .. symtab.nsyms * @sizeOf(macho.nlist_64)], symtab.symoff);
2065 assert(@divExact(nread, @sizeOf(macho.nlist_64)) == buffer.len);
2066
2067 try self.local_symbols.ensureCapacity(self.base.allocator, dysymtab.nlocalsym);
2068 try self.global_symbols.ensureCapacity(self.base.allocator, dysymtab.nextdefsym);
2069 try self.undef_symbols.ensureCapacity(self.base.allocator, dysymtab.nundefsym);
2070
2071 self.local_symbols.appendSliceAssumeCapacity(buffer[dysymtab.ilocalsym .. dysymtab.ilocalsym + dysymtab.nlocalsym]);
2072 self.global_symbols.appendSliceAssumeCapacity(buffer[dysymtab.iextdefsym .. dysymtab.iextdefsym + dysymtab.nextdefsym]);
2073 self.undef_symbols.appendSliceAssumeCapacity(buffer[dysymtab.iundefsym .. dysymtab.iundefsym + dysymtab.nundefsym]);
2074}
2075
2076fn parseStringTable(self: *MachO) !void {
2077 const symtab = self.load_commands.items[self.symtab_cmd_index.?].Symtab;
2078
2079 var buffer = try self.base.allocator.alloc(u8, symtab.strsize);
2080 defer self.base.allocator.free(buffer);
2081 const nread = try self.base.file.?.preadAll(buffer, symtab.stroff);
2082 assert(nread == buffer.len);
2083
2084 try self.string_table.ensureCapacity(self.base.allocator, symtab.strsize);
2085
2086 self.string_table.appendSliceAssumeCapacity(buffer);
2087}
2088
2050fn parseBindingInfo(self: *MachO) !void {2089fn parseBindingInfo(self: *MachO) !void {
2051 const dyld_info = self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;2090 const dyld_info = self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
2052 var buffer = try self.base.allocator.alloc(u8, dyld_info.bind_size);2091 var buffer = try self.base.allocator.alloc(u8, dyld_info.bind_size);