| ... | @@ -262,6 +262,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -262,6 +262,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 262 | dysymtab.iundefsym = nlocals + nglobals; | 262 | dysymtab.iundefsym = nlocals + nglobals; |
| 263 | dysymtab.nundefsym = nundefs; | 263 | dysymtab.nundefsym = nundefs; |
| 264 | } | 264 | } |
| | 265 | { |
| | 266 | // update LC_MAIN with entry offset |
| | 267 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| | 268 | const main_cmd = &self.load_commands.items[self.main_cmd_index.?].EntryPoint; |
| | 269 | main_cmd.entryoff = self.entry_addr.? - text_segment.vmaddr; |
| | 270 | } |
| 265 | { | 271 | { |
| 266 | var last_cmd_offset: usize = @sizeOf(macho.mach_header_64); | 272 | var last_cmd_offset: usize = @sizeOf(macho.mach_header_64); |
| 267 | for (self.load_commands.items) |cmd| { | 273 | for (self.load_commands.items) |cmd| { |
| ... | @@ -817,8 +823,6 @@ pub fn updateDeclExports( | ... | @@ -817,8 +823,6 @@ pub fn updateDeclExports( |
| 817 | .Strong => blk: { | 823 | .Strong => blk: { |
| 818 | if (mem.eql(u8, exp.options.name, "_start")) { | 824 | if (mem.eql(u8, exp.options.name, "_start")) { |
| 819 | self.entry_addr = decl_sym.n_value; | 825 | self.entry_addr = decl_sym.n_value; |
| 820 | const cmd = &self.load_commands.items[self.main_cmd_index.?].EntryPoint; | | |
| 821 | cmd.entryoff = decl_sym.n_value; | | |
| 822 | } | 826 | } |
| 823 | break :blk macho.REFERENCE_FLAG_DEFINED; | 827 | break :blk macho.REFERENCE_FLAG_DEFINED; |
| 824 | }, | 828 | }, |
| ... | @@ -985,8 +989,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -985,8 +989,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 985 | .reserved3 = 0, | 989 | .reserved3 = 0, |
| 986 | }); | 990 | }); |
| 987 | | 991 | |
| 988 | data_segment.vmsize = file_size; | 992 | const segment_size = mem.alignForwardGeneric(u64, file_size, 0x1000); |
| 989 | data_segment.filesize = file_size; | 993 | data_segment.vmsize = segment_size; |
| | 994 | data_segment.filesize = segment_size; |
| 990 | data_segment.fileoff = off; | 995 | data_segment.fileoff = off; |
| 991 | | 996 | |
| 992 | log.debug("initial got section {}\n", .{self.sections.items[self.got_section_index.?]}); | 997 | log.debug("initial got section {}\n", .{self.sections.items[self.got_section_index.?]}); |
| ... | @@ -1131,6 +1136,24 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1131,6 +1136,24 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1131 | .n_value = 0, | 1136 | .n_value = 0, |
| 1132 | }); | 1137 | }); |
| 1133 | } | 1138 | } |
| | 1139 | { |
| | 1140 | const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| | 1141 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfo; |
| | 1142 | if (dyld_info.export_off == 0) { |
| | 1143 | const nsyms = self.base.options.symbol_count_hint; |
| | 1144 | const file_size = @sizeOf(u64) * nsyms; |
| | 1145 | const off = @intCast(u32, self.findFreeSpace(file_size, 0x1000)); |
| | 1146 | log.debug("found export trie free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); |
| | 1147 | dyld_info.export_off = off; |
| | 1148 | dyld_info.export_size = @intCast(u32, file_size); |
| | 1149 | |
| | 1150 | const segment_size = mem.alignForwardGeneric(u64, file_size, 0x1000); |
| | 1151 | linkedit.vmsize = 4 * segment_size; |
| | 1152 | linkedit.fileoff = off; |
| | 1153 | |
| | 1154 | log.debug("updated linkedit segment {}\n", .{linkedit}); |
| | 1155 | } |
| | 1156 | } |
| 1134 | { | 1157 | { |
| 1135 | const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | 1158 | const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 1136 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; | 1159 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| ... | @@ -1141,12 +1164,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1141,12 +1164,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1141 | log.debug("found symbol table free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | 1164 | log.debug("found symbol table free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); |
| 1142 | symtab.symoff = off; | 1165 | symtab.symoff = off; |
| 1143 | symtab.nsyms = @intCast(u32, nsyms); | 1166 | symtab.nsyms = @intCast(u32, nsyms); |
| 1144 | | | |
| 1145 | linkedit.vmsize += file_size; | | |
| 1146 | linkedit.fileoff = off; | | |
| 1147 | linkedit.filesize += file_size; | | |
| 1148 | | | |
| 1149 | log.debug("updated linkedit segment {}\n", .{linkedit}); | | |
| 1150 | } | 1167 | } |
| 1151 | if (symtab.stroff == 0) { | 1168 | if (symtab.stroff == 0) { |
| 1152 | try self.string_table.append(self.base.allocator, 0); | 1169 | try self.string_table.append(self.base.allocator, 0); |
| ... | @@ -1155,11 +1172,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1155,11 +1172,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1155 | log.debug("found string table free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | 1172 | log.debug("found string table free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); |
| 1156 | symtab.stroff = off; | 1173 | symtab.stroff = off; |
| 1157 | symtab.strsize = file_size; | 1174 | symtab.strsize = file_size; |
| 1158 | | | |
| 1159 | linkedit.vmsize += file_size; | | |
| 1160 | linkedit.filesize += file_size; | | |
| 1161 | | | |
| 1162 | log.debug("updated linkedit segment {}\n", .{linkedit}); | | |
| 1163 | } | 1175 | } |
| 1164 | } | 1176 | } |
| 1165 | } | 1177 | } |
| ... | @@ -1291,6 +1303,15 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 { | ... | @@ -1291,6 +1303,15 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 { |
| 1291 | return test_end; | 1303 | return test_end; |
| 1292 | } | 1304 | } |
| 1293 | } | 1305 | } |
| | 1306 | if (self.dyld_info_cmd_index) |dyld_info_index| { |
| | 1307 | const dyld_info = self.load_commands.items[dyld_info_index].DyldInfo; |
| | 1308 | const tight_size = dyld_info.export_size; |
| | 1309 | const increased_size = satMul(tight_size, alloc_num) / alloc_den; |
| | 1310 | const test_end = dyld_info.export_off + increased_size; |
| | 1311 | if (end > dyld_info.export_off and start < test_end) { |
| | 1312 | return test_end; |
| | 1313 | } |
| | 1314 | } |
| 1294 | if (self.symtab_cmd_index) |symtab_index| { | 1315 | if (self.symtab_cmd_index) |symtab_index| { |
| 1295 | const symtab = self.load_commands.items[symtab_index].Symtab; | 1316 | const symtab = self.load_commands.items[symtab_index].Symtab; |
| 1296 | { | 1317 | { |
| ... | @@ -1324,6 +1345,10 @@ fn allocatedSize(self: *MachO, start: u64) u64 { | ... | @@ -1324,6 +1345,10 @@ fn allocatedSize(self: *MachO, start: u64) u64 { |
| 1324 | if (section.offset <= start) continue; | 1345 | if (section.offset <= start) continue; |
| 1325 | if (section.offset < min_pos) min_pos = section.offset; | 1346 | if (section.offset < min_pos) min_pos = section.offset; |
| 1326 | } | 1347 | } |
| | 1348 | if (self.dyld_info_cmd_index) |dyld_info_index| { |
| | 1349 | const dyld_info = self.load_commands.items[dyld_info_index].DyldInfo; |
| | 1350 | if (dyld_info.export_off > start and dyld_info.export_off < min_pos) min_pos = dyld_info.export_off; |
| | 1351 | } |
| 1327 | if (self.symtab_cmd_index) |symtab_index| { | 1352 | if (self.symtab_cmd_index) |symtab_index| { |
| 1328 | const symtab = self.load_commands.items[symtab_index].Symtab; | 1353 | const symtab = self.load_commands.items[symtab_index].Symtab; |
| 1329 | if (symtab.symoff > start and symtab.symoff < min_pos) min_pos = symtab.symoff; | 1354 | if (symtab.symoff > start and symtab.symoff < min_pos) min_pos = symtab.symoff; |
| ... | @@ -1380,7 +1405,7 @@ fn writeAllUndefSymbols(self: *MachO) !void { | ... | @@ -1380,7 +1405,7 @@ fn writeAllUndefSymbols(self: *MachO) !void { |
| 1380 | } | 1405 | } |
| 1381 | | 1406 | |
| 1382 | fn writeExportTrie(self: *MachO) !void { | 1407 | fn writeExportTrie(self: *MachO) !void { |
| 1383 | // TODO | 1408 | // TODO implement mechanism for generating a prefix tree of the exported symbols |
| 1384 | // single branch export trie | 1409 | // single branch export trie |
| 1385 | var buf = [_]u8{0} ** 24; | 1410 | var buf = [_]u8{0} ** 24; |
| 1386 | buf[0] = 0; // root node | 1411 | buf[0] = 0; // root node |
| ... | @@ -1388,10 +1413,16 @@ fn writeExportTrie(self: *MachO) !void { | ... | @@ -1388,10 +1413,16 @@ fn writeExportTrie(self: *MachO) !void { |
| 1388 | mem.copy(u8, buf[2..], "_start"); | 1413 | mem.copy(u8, buf[2..], "_start"); |
| 1389 | buf[8] = 0; | 1414 | buf[8] = 0; |
| 1390 | buf[9] = 9 + 1; | 1415 | buf[9] = 9 + 1; |
| 1391 | const written = try std.debug.leb.writeULEB128Mem(buf[12..], self.entry_addr.?); | 1416 | |
| | 1417 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| | 1418 | const addr = self.entry_addr.? - text_segment.vmaddr; |
| | 1419 | const written = try std.debug.leb.writeULEB128Mem(buf[12..], addr); |
| 1392 | buf[10] = @intCast(u8, written) + 1; | 1420 | buf[10] = @intCast(u8, written) + 1; |
| 1393 | buf[11] = 0; | 1421 | buf[11] = 0; |
| 1394 | log.debug("WAT = {}, {x}\n", .{ written, buf[0..] }); | 1422 | log.debug("WAT = {}, {x}\n", .{ written, buf[0..] }); |
| | 1423 | |
| | 1424 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfo; |
| | 1425 | try self.base.file.?.pwriteAll(buf[0..], dyld_info.export_off); |
| 1395 | } | 1426 | } |
| 1396 | | 1427 | |
| 1397 | fn writeStringTable(self: *MachO) !void { | 1428 | fn writeStringTable(self: *MachO) !void { |
| ... | @@ -1409,6 +1440,10 @@ fn writeStringTable(self: *MachO) !void { | ... | @@ -1409,6 +1440,10 @@ fn writeStringTable(self: *MachO) !void { |
| 1409 | log.debug("writing string table from 0x{x} to 0x{x}\n", .{ symtab.stroff, symtab.stroff + symtab.strsize }); | 1440 | log.debug("writing string table from 0x{x} to 0x{x}\n", .{ symtab.stroff, symtab.stroff + symtab.strsize }); |
| 1410 | | 1441 | |
| 1411 | try self.base.file.?.pwriteAll(self.string_table.items, symtab.stroff); | 1442 | try self.base.file.?.pwriteAll(self.string_table.items, symtab.stroff); |
| | 1443 | |
| | 1444 | // FIXME |
| | 1445 | const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| | 1446 | linkedit.filesize = symtab.stroff + symtab.strsize - linkedit.fileoff; |
| 1412 | } | 1447 | } |
| 1413 | | 1448 | |
| 1414 | /// Writes Mach-O file header. | 1449 | /// Writes Mach-O file header. |