authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-09-30 09:21:11+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-04 15:31:47+02:00
log5a7105401cda94fa82f07630672559659d875854
treec2f0c7b481d7c35ffda765fc460b545bf0af8e8c
parent635984abc7ab508b8e81448bb081be41aad046d0

First hacked together, working MachO exe!


1 files changed, 52 insertions(+), 17 deletions(-)

src/link/MachO.zig+52-17
...@@ -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 });
987991
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;
991996
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}
13811406
1382fn writeExportTrie(self: *MachO) !void {1407fn writeExportTrie(self: *MachO) !void {
1383 // TODO1408 // TODO implement mechanism for generating a prefix tree of the exported symbols
1384 // single branch export trie1409 // single branch export trie
1385 var buf = [_]u8{0} ** 24;1410 var buf = [_]u8{0} ** 24;
1386 buf[0] = 0; // root node1411 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}
13961427
1397fn writeStringTable(self: *MachO) !void {1428fn 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 });
14101441
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}
14131448
1414/// Writes Mach-O file header.1449/// Writes Mach-O file header.