| ... | @@ -236,33 +236,26 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -236,33 +236,26 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 236 | .Lib => return error.TODOImplementWritingLibFiles, | 236 | .Lib => return error.TODOImplementWritingLibFiles, |
| 237 | } | 237 | } |
| 238 | | 238 | |
| 239 | // Unfortunately these have to be buffered and done at the end because ELF does not allow | 239 | try self.writeExportTrie(); |
| 240 | // mixing local and global symbols within a symbol table. | 240 | |
| | 241 | // Unfortunately these have to be buffered and done at the end because MachO does not allow |
| | 242 | // mixing local, global and undefined symbols within a symbol table. |
| 241 | try self.writeAllGlobalSymbols(); | 243 | try self.writeAllGlobalSymbols(); |
| 242 | try self.writeAllUndefSymbols(); | 244 | try self.writeAllUndefSymbols(); |
| 243 | | 245 | |
| 244 | { | 246 | try self.writeStringTable(); |
| 245 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; | | |
| 246 | symtab.nsyms = @intCast(u32, self.local_symbols.items.len + self.global_symbols.items.len + self.undef_symbols.items.len); | | |
| 247 | const allocated_size = self.allocatedSize(symtab.stroff); | | |
| 248 | const needed_size = self.string_table.items.len; | | |
| 249 | log.debug("allocated_size = 0x{x}, needed_size = 0x{x}\n", .{ allocated_size, needed_size }); | | |
| 250 | | | |
| 251 | if (needed_size > allocated_size) { | | |
| 252 | symtab.strsize = 0; | | |
| 253 | symtab.stroff = @intCast(u32, self.findFreeSpace(needed_size, 1)); | | |
| 254 | } | | |
| 255 | symtab.strsize = @intCast(u32, needed_size); | | |
| 256 | | 247 | |
| 257 | log.debug("writing string table from 0x{x} to 0x{x}\n", .{ symtab.stroff, symtab.stroff + symtab.strsize }); | | |
| 258 | | | |
| 259 | try self.base.file.?.pwriteAll(self.string_table.items, symtab.stroff); | | |
| 260 | } | | |
| 261 | { | 248 | { |
| 262 | const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab; | 249 | // update Symtab and Dysymtab commands with symbol counts |
| | 250 | // TODO this could probably be done incrementally |
| 263 | const nlocals = @intCast(u32, self.local_symbols.items.len); | 251 | const nlocals = @intCast(u32, self.local_symbols.items.len); |
| 264 | const nglobals = @intCast(u32, self.global_symbols.items.len); | 252 | const nglobals = @intCast(u32, self.global_symbols.items.len); |
| 265 | const nundefs = @intCast(u32, self.undef_symbols.items.len); | 253 | const nundefs = @intCast(u32, self.undef_symbols.items.len); |
| | 254 | |
| | 255 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| | 256 | symtab.nsyms = nlocals + nglobals + nundefs; |
| | 257 | |
| | 258 | const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab; |
| 266 | dysymtab.nlocalsym = nlocals; | 259 | dysymtab.nlocalsym = nlocals; |
| 267 | dysymtab.iextdefsym = nlocals; | 260 | dysymtab.iextdefsym = nlocals; |
| 268 | dysymtab.nextdefsym = nglobals; | 261 | dysymtab.nextdefsym = nglobals; |
| ... | @@ -1020,6 +1013,26 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1020,6 +1013,26 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1020 | }); | 1013 | }); |
| 1021 | self.cmd_table_dirty = true; | 1014 | self.cmd_table_dirty = true; |
| 1022 | } | 1015 | } |
| | 1016 | if (self.dyld_info_cmd_index == null) { |
| | 1017 | self.dyld_info_cmd_index = @intCast(u16, self.load_commands.items.len); |
| | 1018 | try self.load_commands.append(self.base.allocator, .{ |
| | 1019 | .DyldInfo = .{ |
| | 1020 | .cmd = macho.LC_DYLD_INFO_ONLY, |
| | 1021 | .cmdsize = @sizeOf(macho.dyld_info_command), |
| | 1022 | .rebase_off = 0, |
| | 1023 | .rebase_size = 0, |
| | 1024 | .bind_off = 0, |
| | 1025 | .bind_size = 0, |
| | 1026 | .weak_bind_off = 0, |
| | 1027 | .weak_bind_size = 0, |
| | 1028 | .lazy_bind_off = 0, |
| | 1029 | .lazy_bind_size = 0, |
| | 1030 | .export_off = 0, |
| | 1031 | .export_size = 0, |
| | 1032 | }, |
| | 1033 | }); |
| | 1034 | self.cmd_table_dirty = true; |
| | 1035 | } |
| 1023 | if (self.symtab_cmd_index == null) { | 1036 | if (self.symtab_cmd_index == null) { |
| 1024 | self.symtab_cmd_index = @intCast(u16, self.load_commands.items.len); | 1037 | self.symtab_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 1025 | try self.load_commands.append(self.base.allocator, .{ | 1038 | try self.load_commands.append(self.base.allocator, .{ |
| ... | @@ -1366,6 +1379,38 @@ fn writeAllUndefSymbols(self: *MachO) !void { | ... | @@ -1366,6 +1379,38 @@ fn writeAllUndefSymbols(self: *MachO) !void { |
| 1366 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.undef_symbols.items), off); | 1379 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.undef_symbols.items), off); |
| 1367 | } | 1380 | } |
| 1368 | | 1381 | |
| | 1382 | fn writeExportTrie(self: *MachO) !void { |
| | 1383 | // TODO |
| | 1384 | // single branch export trie |
| | 1385 | var buf = [_]u8{0} ** 24; |
| | 1386 | buf[0] = 0; // root node |
| | 1387 | buf[1] = 1; // 1 branch from root |
| | 1388 | mem.copy(u8, buf[2..], "_start"); |
| | 1389 | buf[8] = 0; |
| | 1390 | buf[9] = 9 + 1; |
| | 1391 | const written = try std.debug.leb.writeULEB128Mem(buf[12..], self.entry_addr.?); |
| | 1392 | buf[10] = @intCast(u8, written) + 1; |
| | 1393 | buf[11] = 0; |
| | 1394 | log.debug("WAT = {}, {x}\n", .{ written, buf[0..] }); |
| | 1395 | } |
| | 1396 | |
| | 1397 | fn writeStringTable(self: *MachO) !void { |
| | 1398 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| | 1399 | const allocated_size = self.allocatedSize(symtab.stroff); |
| | 1400 | const needed_size = self.string_table.items.len; |
| | 1401 | log.debug("allocated_size = 0x{x}, needed_size = 0x{x}\n", .{ allocated_size, needed_size }); |
| | 1402 | |
| | 1403 | if (needed_size > allocated_size) { |
| | 1404 | symtab.strsize = 0; |
| | 1405 | symtab.stroff = @intCast(u32, self.findFreeSpace(needed_size, 1)); |
| | 1406 | } |
| | 1407 | symtab.strsize = @intCast(u32, needed_size); |
| | 1408 | |
| | 1409 | log.debug("writing string table from 0x{x} to 0x{x}\n", .{ symtab.stroff, symtab.stroff + symtab.strsize }); |
| | 1410 | |
| | 1411 | try self.base.file.?.pwriteAll(self.string_table.items, symtab.stroff); |
| | 1412 | } |
| | 1413 | |
| 1369 | /// Writes Mach-O file header. | 1414 | /// Writes Mach-O file header. |
| 1370 | /// Should be invoked last as it needs up-to-date values of ncmds and sizeof_cmds bookkeeping | 1415 | /// Should be invoked last as it needs up-to-date values of ncmds and sizeof_cmds bookkeeping |
| 1371 | /// variables. | 1416 | /// variables. |