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 {
262262 dysymtab.iundefsym = nlocals + nglobals;
263263 dysymtab.nundefsym = nundefs;
264264 }
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 }
265271 {
266272 var last_cmd_offset: usize = @sizeOf(macho.mach_header_64);
267273 for (self.load_commands.items) |cmd| {
......@@ -817,8 +823,6 @@ pub fn updateDeclExports(
817823 .Strong => blk: {
818824 if (mem.eql(u8, exp.options.name, "_start")) {
819825 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;
822826 }
823827 break :blk macho.REFERENCE_FLAG_DEFINED;
824828 },
......@@ -985,8 +989,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {
985989 .reserved3 = 0,
986990 });
987991
988 data_segment.vmsize = file_size;
989 data_segment.filesize = file_size;
992 const segment_size = mem.alignForwardGeneric(u64, file_size, 0x1000);
993 data_segment.vmsize = segment_size;
994 data_segment.filesize = segment_size;
990995 data_segment.fileoff = off;
991996
992997 log.debug("initial got section {}\n", .{self.sections.items[self.got_section_index.?]});
......@@ -1131,6 +1136,24 @@ pub fn populateMissingMetadata(self: *MachO) !void {
11311136 .n_value = 0,
11321137 });
11331138 }
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 }
11341157 {
11351158 const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
11361159 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
......@@ -1141,12 +1164,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
11411164 log.debug("found symbol table free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
11421165 symtab.symoff = off;
11431166 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});
11501167 }
11511168 if (symtab.stroff == 0) {
11521169 try self.string_table.append(self.base.allocator, 0);
......@@ -1155,11 +1172,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
11551172 log.debug("found string table free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
11561173 symtab.stroff = off;
11571174 symtab.strsize = file_size;
1158
1159 linkedit.vmsize += file_size;
1160 linkedit.filesize += file_size;
1161
1162 log.debug("updated linkedit segment {}\n", .{linkedit});
11631175 }
11641176 }
11651177}
......@@ -1291,6 +1303,15 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 {
12911303 return test_end;
12921304 }
12931305 }
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 }
12941315 if (self.symtab_cmd_index) |symtab_index| {
12951316 const symtab = self.load_commands.items[symtab_index].Symtab;
12961317 {
......@@ -1324,6 +1345,10 @@ fn allocatedSize(self: *MachO, start: u64) u64 {
13241345 if (section.offset <= start) continue;
13251346 if (section.offset < min_pos) min_pos = section.offset;
13261347 }
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 }
13271352 if (self.symtab_cmd_index) |symtab_index| {
13281353 const symtab = self.load_commands.items[symtab_index].Symtab;
13291354 if (symtab.symoff > start and symtab.symoff < min_pos) min_pos = symtab.symoff;
......@@ -1380,7 +1405,7 @@ fn writeAllUndefSymbols(self: *MachO) !void {
13801405}
13811406
13821407fn writeExportTrie(self: *MachO) !void {
1383 // TODO
1408 // TODO implement mechanism for generating a prefix tree of the exported symbols
13841409 // single branch export trie
13851410 var buf = [_]u8{0} ** 24;
13861411 buf[0] = 0; // root node
......@@ -1388,10 +1413,16 @@ fn writeExportTrie(self: *MachO) !void {
13881413 mem.copy(u8, buf[2..], "_start");
13891414 buf[8] = 0;
13901415 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);
13921420 buf[10] = @intCast(u8, written) + 1;
13931421 buf[11] = 0;
13941422 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);
13951426}
13961427
13971428fn writeStringTable(self: *MachO) !void {
......@@ -1409,6 +1440,10 @@ fn writeStringTable(self: *MachO) !void {
14091440 log.debug("writing string table from 0x{x} to 0x{x}\n", .{ symtab.stroff, symtab.stroff + symtab.strsize });
14101441
14111442 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;
14121447}
14131448
14141449/// Writes Mach-O file header.