| ... | @@ -106,10 +106,14 @@ got_section_index: ?u16 = null, | ... | @@ -106,10 +106,14 @@ got_section_index: ?u16 = null, |
| 106 | | 106 | |
| 107 | entry_addr: ?u64 = null, | 107 | entry_addr: ?u64 = null, |
| 108 | | 108 | |
| 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). |
| 111 | local_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 111 | local_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| | 112 | /// Table of all defined global symbols |
| 112 | global_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 113 | global_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| | 114 | /// Table of all undefined symbols |
| | 115 | undef_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| | 116 | dyld_stub_binder_index: ?u16 = null, |
| 113 | | 117 | |
| 114 | /// Table of symbol names aka the string table. | 118 | /// Table of symbol names aka the string table. |
| 115 | string_table: std.ArrayListUnmanaged(u8) = .{}, | 119 | string_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 allow | 239 | // 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(); |
| 238 | | 243 | |
| 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 { |
| 253 | | 258 | |
| 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 { |
| 1296 | fn writeAllGlobalSymbols(self: *MachO) !void { | 1351 | fn 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 | } |
| 1302 | | 1358 | |
| | 1359 | fn 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 bookkeeping | 1370 | /// Should be invoked last as it needs up-to-date values of ncmds and sizeof_cmds bookkeeping |
| 1305 | /// variables. | 1371 | /// variables. |