authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-09-29 22:31:12+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-04 15:31:47+02:00
logccf9bba61f4134d9f57e50d64cef201c064d6b9a
tree4b4866bccc63e8a5b088f3c43d031f8aba84af25
parenta927f242019f22bda95fb4a74020966ac2bdb54e

Write out LC_DYSYMTAB together with dyld_stub_binder undef symbol


2 files changed, 75 insertions(+), 3 deletions(-)

lib/std/macho.zig+6
...@@ -1295,3 +1295,9 @@ pub const N_WEAK_REF: u16 = 0x40;...@@ -1295,3 +1295,9 @@ pub const N_WEAK_REF: u16 = 0x40;
1295/// another (non-weak) definition for this symbol, the weak definition is ignored. Only symbols in a1295/// another (non-weak) definition for this symbol, the weak definition is ignored. Only symbols in a
1296/// coalesced section (page 23) can be marked as a weak definition.1296/// coalesced section (page 23) can be marked as a weak definition.
1297pub const N_WEAK_DEF: u16 = 0x80;1297pub const N_WEAK_DEF: u16 = 0x80;
1298
1299/// The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the
1300/// that the function is actually a resolver function and should
1301/// be called to get the address of the real function to use.
1302/// This bit is only available in .o files (MH_OBJECT filetype)
1303pub const N_SYMBOL_RESOLVER: u16 = 0x100;
src/link/MachO.zig+69-3
...@@ -106,10 +106,14 @@ got_section_index: ?u16 = null,...@@ -106,10 +106,14 @@ got_section_index: ?u16 = null,
106106
107entry_addr: ?u64 = null,107entry_addr: ?u64 = null,
108108
109/// Table of all local symbols used.109/// Table of all local symbols
110/// Internally references string table for names (which are optional).110/// Internally references string table for names (which are optional).
111local_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},111local_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},
112/// Table of all defined global symbols
112global_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},113global_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},
114/// Table of all undefined symbols
115undef_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},
116dyld_stub_binder_index: ?u16 = null,
113117
114/// Table of symbol names aka the string table.118/// Table of symbol names aka the string table.
115string_table: std.ArrayListUnmanaged(u8) = .{},119string_table: std.ArrayListUnmanaged(u8) = .{},
...@@ -235,10 +239,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -235,10 +239,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
235 // Unfortunately these have to be buffered and done at the end because ELF does not allow239 // Unfortunately these have to be buffered and done at the end because ELF does not allow
236 // mixing local and global symbols within a symbol table.240 // mixing local and global symbols within a symbol table.
237 try self.writeAllGlobalSymbols();241 try self.writeAllGlobalSymbols();
242 try self.writeAllUndefSymbols();
238243
239 {244 {
240 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;245 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
241 symtab.nsyms = @intCast(u32, self.local_symbols.items.len + self.global_symbols.items.len);246 symtab.nsyms = @intCast(u32, self.local_symbols.items.len + self.global_symbols.items.len + self.undef_symbols.items.len);
242 const allocated_size = self.allocatedSize(symtab.stroff);247 const allocated_size = self.allocatedSize(symtab.stroff);
243 const needed_size = self.string_table.items.len;248 const needed_size = self.string_table.items.len;
244 log.debug("allocated_size = 0x{x}, needed_size = 0x{x}\n", .{ allocated_size, needed_size });249 log.debug("allocated_size = 0x{x}, needed_size = 0x{x}\n", .{ allocated_size, needed_size });
...@@ -253,6 +258,17 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -253,6 +258,17 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
253258
254 try self.base.file.?.pwriteAll(self.string_table.items, symtab.stroff);259 try self.base.file.?.pwriteAll(self.string_table.items, symtab.stroff);
255 }260 }
261 {
262 const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
263 const nlocals = @intCast(u32, self.local_symbols.items.len);
264 const nglobals = @intCast(u32, self.global_symbols.items.len);
265 const nundefs = @intCast(u32, self.undef_symbols.items.len);
266 dysymtab.nlocalsym = nlocals;
267 dysymtab.iextdefsym = nlocals;
268 dysymtab.nextdefsym = nglobals;
269 dysymtab.iundefsym = nlocals + nglobals;
270 dysymtab.nundefsym = nundefs;
271 }
256 {272 {
257 var last_cmd_offset: usize = @sizeOf(macho.mach_header_64);273 var last_cmd_offset: usize = @sizeOf(macho.mach_header_64);
258 for (self.load_commands.items) |cmd| {274 for (self.load_commands.items) |cmd| {
...@@ -1018,6 +1034,34 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1018,6 +1034,34 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1018 });1034 });
1019 self.cmd_table_dirty = true;1035 self.cmd_table_dirty = true;
1020 }1036 }
1037 if (self.dysymtab_cmd_index == null) {
1038 self.dysymtab_cmd_index = @intCast(u16, self.load_commands.items.len);
1039 try self.load_commands.append(self.base.allocator, .{
1040 .Dysymtab = .{
1041 .cmd = macho.LC_DYSYMTAB,
1042 .cmdsize = @sizeOf(macho.dysymtab_command),
1043 .ilocalsym = 0,
1044 .nlocalsym = 0,
1045 .iextdefsym = 0,
1046 .nextdefsym = 0,
1047 .iundefsym = 0,
1048 .nundefsym = 0,
1049 .tocoff = 0,
1050 .ntoc = 0,
1051 .modtaboff = 0,
1052 .nmodtab = 0,
1053 .extrefsymoff = 0,
1054 .nextrefsyms = 0,
1055 .indirectsymoff = 0,
1056 .nindirectsyms = 0,
1057 .extreloff = 0,
1058 .nextrel = 0,
1059 .locreloff = 0,
1060 .nlocrel = 0,
1061 },
1062 });
1063 self.cmd_table_dirty = true;
1064 }
1021 if (self.dylinker_cmd_index == null) {1065 if (self.dylinker_cmd_index == null) {
1022 self.dylinker_cmd_index = @intCast(u16, self.load_commands.items.len);1066 self.dylinker_cmd_index = @intCast(u16, self.load_commands.items.len);
1023 const cmdsize = commandSize(@sizeOf(macho.dylinker_command) + mem.lenZ(DEFAULT_DYLD_PATH));1067 const cmdsize = commandSize(@sizeOf(macho.dylinker_command) + mem.lenZ(DEFAULT_DYLD_PATH));
...@@ -1063,6 +1107,17 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1063,6 +1107,17 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1063 });1107 });
1064 self.cmd_table_dirty = true;1108 self.cmd_table_dirty = true;
1065 }1109 }
1110 if (self.dyld_stub_binder_index == null) {
1111 self.dyld_stub_binder_index = @intCast(u16, self.undef_symbols.items.len);
1112 const name = try self.makeString("dyld_stub_binder");
1113 try self.undef_symbols.append(self.base.allocator, .{
1114 .n_strx = name,
1115 .n_type = macho.N_UNDF | macho.N_EXT,
1116 .n_sect = 0,
1117 .n_desc = macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | macho.N_SYMBOL_RESOLVER,
1118 .n_value = 0,
1119 });
1120 }
1066 {1121 {
1067 const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;1122 const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
1068 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;1123 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
...@@ -1296,10 +1351,21 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void {...@@ -1296,10 +1351,21 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void {
1296fn writeAllGlobalSymbols(self: *MachO) !void {1351fn writeAllGlobalSymbols(self: *MachO) !void {
1297 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;1352 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
1298 const off = symtab.symoff + self.local_symbols.items.len * @sizeOf(macho.nlist_64);1353 const off = symtab.symoff + self.local_symbols.items.len * @sizeOf(macho.nlist_64);
1299 log.debug("writing global symbols from 0x{x} to 0x{x}\n", .{ off, self.global_symbols.items.len + off });1354 const file_size = self.global_symbols.items.len * @sizeOf(macho.nlist_64);
1355 log.debug("writing global symbols from 0x{x} to 0x{x}\n", .{ off, file_size + off });
1300 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.global_symbols.items), off);1356 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.global_symbols.items), off);
1301}1357}
13021358
1359fn writeAllUndefSymbols(self: *MachO) !void {
1360 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
1361 const nlocals = self.local_symbols.items.len;
1362 const nglobals = self.global_symbols.items.len;
1363 const off = symtab.symoff + (nlocals + nglobals) * @sizeOf(macho.nlist_64);
1364 const file_size = self.undef_symbols.items.len * @sizeOf(macho.nlist_64);
1365 log.debug("writing undef symbols from 0x{x} to 0x{x}\n", .{ off, file_size + off });
1366 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.undef_symbols.items), off);
1367}
1368
1303/// Writes Mach-O file header.1369/// Writes Mach-O file header.
1304/// Should be invoked last as it needs up-to-date values of ncmds and sizeof_cmds bookkeeping1370/// Should be invoked last as it needs up-to-date values of ncmds and sizeof_cmds bookkeeping
1305/// variables.1371/// variables.