authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-01-07 20:49:07+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-01-13 23:54:31+01:00
log2f7cd7119387b517b07e5feb02a13e69651fe9eb
treefbcef081c1c13775f6778b443cd47aafcdb67842
parentbb691ea16b89c29d98cc2d36bf2af029c5dd1844

macho: fully working PoC with main and exit


2 files changed, 48 insertions(+), 23 deletions(-)

src/link/MachO.zig+45-19
...@@ -1263,9 +1263,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1263,9 +1263,10 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1263 const stub_h = &text_segment.sections.items[self.stub_helper_section_index.?];1263 const stub_h = &text_segment.sections.items[self.stub_helper_section_index.?];
1264 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;1264 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1265 const la_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];1265 const la_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];
1266 while (self.stub_fixups.popOrNull()) |fixup| {1266 for (self.stub_fixups.items) |fixup, idx| {
1267 const i = @intCast(u32, idx);
1267 // TODO increment offset for stub writing1268 // TODO increment offset for stub writing
1268 const stub_addr = stubs.addr;1269 const stub_addr = stubs.addr + i * stubs.reserved2;
1269 const text_addr = symbol.n_value + fixup.start;1270 const text_addr = symbol.n_value + fixup.start;
1270 const displacement = @intCast(u32, stub_addr - text_addr);1271 const displacement = @intCast(u32, stub_addr - text_addr);
1271 var placeholder = code_buffer.items[fixup.start..][0..fixup.len];1272 var placeholder = code_buffer.items[fixup.start..][0..fixup.len];
...@@ -1274,17 +1275,16 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1274,17 +1275,16 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1274 const end = stub_h.addr + self.next_stub_helper_off.? - stub_h.offset;1275 const end = stub_h.addr + self.next_stub_helper_off.? - stub_h.offset;
1275 var buf: [@sizeOf(u64)]u8 = undefined;1276 var buf: [@sizeOf(u64)]u8 = undefined;
1276 mem.writeIntLittle(u64, &buf, end);1277 mem.writeIntLittle(u64, &buf, end);
1277 try self.base.file.?.pwriteAll(&buf, la_ptr.offset);1278 try self.base.file.?.pwriteAll(&buf, la_ptr.offset + i * @sizeOf(u64));
12781279
1279 const displacement2 = la_ptr.addr - stubs.addr;1280 const la_ptr_addr = la_ptr.addr + i * @sizeOf(u64);
1281 const displacement2 = la_ptr_addr - stub_addr;
1280 var ccode: [2 * @sizeOf(u32)]u8 = undefined;1282 var ccode: [2 * @sizeOf(u32)]u8 = undefined;
1281 mem.writeIntLittle(u32, ccode[0..4], aarch64.Instruction.ldr(.x16, .{1283 mem.writeIntLittle(u32, ccode[0..4], aarch64.Instruction.ldr(.x16, .{
1282 .literal = @intCast(u19, displacement2 / 4),1284 .literal = @intCast(u19, displacement2 / 4),
1283 }).toU32());1285 }).toU32());
1284 mem.writeIntLittle(u32, ccode[4..8], aarch64.Instruction.br(.x16).toU32());1286 mem.writeIntLittle(u32, ccode[4..8], aarch64.Instruction.br(.x16).toU32());
1285 try self.base.file.?.pwriteAll(&ccode, stubs.offset);1287 try self.base.file.?.pwriteAll(&ccode, stubs.offset + i * stubs.reserved2);
1286 stubs.size = 2 * @sizeOf(u32);
1287 stubs.reserved2 = 2 * @sizeOf(u32);
12881288
1289 const displacement3 = @intCast(i64, stub_h.addr) - @intCast(i64, end + 4);1289 const displacement3 = @intCast(i64, stub_h.addr) - @intCast(i64, end + 4);
1290 var cccode: [3 * @sizeOf(u32)]u8 = undefined;1290 var cccode: [3 * @sizeOf(u32)]u8 = undefined;
...@@ -1292,13 +1292,13 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1292,13 +1292,13 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1292 .literal = 0x2,1292 .literal = 0x2,
1293 }).toU32());1293 }).toU32());
1294 mem.writeIntLittle(u32, cccode[4..8], aarch64.Instruction.b(@intCast(i28, displacement3)).toU32());1294 mem.writeIntLittle(u32, cccode[4..8], aarch64.Instruction.b(@intCast(i28, displacement3)).toU32());
1295 mem.writeIntLittle(u32, cccode[8..12], 0);1295 mem.writeIntLittle(u32, cccode[8..12], i * 0xd);
1296 try self.base.file.?.pwriteAll(&cccode, self.next_stub_helper_off.?);1296 try self.base.file.?.pwriteAll(&cccode, self.next_stub_helper_off.?);
1297 self.next_stub_helper_off = self.next_stub_helper_off.? + 3 * @sizeOf(u32);1297 self.next_stub_helper_off = self.next_stub_helper_off.? + 3 * @sizeOf(u32);
12981298
1299 try self.rebase_info_table.symbols.append(self.base.allocator, .{1299 try self.rebase_info_table.symbols.append(self.base.allocator, .{
1300 .segment = 3,1300 .segment = 3,
1301 .offset = 0,1301 .offset = i * stubs.reserved2,
1302 });1302 });
1303 self.rebase_info_dirty = true;1303 self.rebase_info_dirty = true;
13041304
...@@ -1308,12 +1308,13 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1308,12 +1308,13 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1308 mem.copy(u8, name, name_str);1308 mem.copy(u8, name, name_str);
1309 try self.lazy_binding_info_table.symbols.append(self.base.allocator, .{1309 try self.lazy_binding_info_table.symbols.append(self.base.allocator, .{
1310 .segment = 3,1310 .segment = 3,
1311 .offset = 0,1311 .offset = i * @sizeOf(u64),
1312 .dylib_ordinal = 1,1312 .dylib_ordinal = 1,
1313 .name = name,1313 .name = name,
1314 });1314 });
1315 self.lazy_binding_info_dirty = true;1315 self.lazy_binding_info_dirty = true;
1316 }1316 }
1317 self.stub_fixups.shrinkRetainingCapacity(0);
13171318
1318 const text_section = text_segment.sections.items[self.text_section_index.?];1319 const text_section = text_segment.sections.items[self.text_section_index.?];
1319 const section_offset = symbol.n_value - text_section.addr;1320 const section_offset = symbol.n_value - text_section.addr;
...@@ -1634,7 +1635,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1634,7 +1635,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1634 .nreloc = 0,1635 .nreloc = 0,
1635 .flags = flags,1636 .flags = flags,
1636 .reserved1 = 0,1637 .reserved1 = 0,
1637 .reserved2 = 0,1638 .reserved2 = 2 * @sizeOf(u32),
1638 .reserved3 = 0,1639 .reserved3 = 0,
1639 });1640 });
1640 self.header_dirty = true;1641 self.header_dirty = true;
...@@ -2539,20 +2540,45 @@ fn writeIndirectSymbolTable(self: *MachO) !void {...@@ -2539,20 +2540,45 @@ fn writeIndirectSymbolTable(self: *MachO) !void {
2539 const la = &data_seg.sections.items[self.la_symbol_ptr_section_index.?];2540 const la = &data_seg.sections.items[self.la_symbol_ptr_section_index.?];
2540 const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;2541 const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
2541 dysymtab.nindirectsyms = 0;2542 dysymtab.nindirectsyms = 0;
2543
2544 var buf: [@sizeOf(u32)]u8 = undefined;
2545 var off = dysymtab.indirectsymoff;
2546 var idx: u32 = 0;
2547
2548 stubs.reserved1 = 0;
2542 for (self.undef_symbols.items) |sym, i| {2549 for (self.undef_symbols.items) |sym, i| {
2543 const idx = @intCast(u32, dysymtab.iundefsym + i);2550 if (i == self.dyld_stub_binder_index.?) {
2544 var buf: [@sizeOf(u32)]u8 = undefined;2551 continue;
2545 mem.writeIntLittle(u32, &buf, idx);2552 }
2546 try self.base.file.?.pwriteAll(&buf, dysymtab.indirectsymoff + i * @sizeOf(u32));2553 const symtab_idx = @intCast(u32, dysymtab.iundefsym + i);
2554 mem.writeIntLittle(u32, &buf, symtab_idx);
2555 try self.base.file.?.pwriteAll(&buf, off);
2556 off += @sizeOf(u32);
2557 dysymtab.nindirectsyms += 1;
2558 idx += 1;
2559 }
2560
2561 got.reserved1 = @intCast(u32, self.undef_symbols.items.len - 1);
2562 if (self.dyld_stub_binder_index) |i| {
2563 const symtab_idx = i + dysymtab.iundefsym;
2564 mem.writeIntLittle(u32, &buf, symtab_idx);
2565 try self.base.file.?.pwriteAll(&buf, off);
2566 off += @sizeOf(u32);
2547 dysymtab.nindirectsyms += 1;2567 dysymtab.nindirectsyms += 1;
2568 idx += 1;
2569 }
2570
2571 la.reserved1 = got.reserved1 + 1;
2572 for (self.undef_symbols.items) |sym, i| {
2548 if (i == self.dyld_stub_binder_index.?) {2573 if (i == self.dyld_stub_binder_index.?) {
2549 got.reserved1 = @intCast(u32, i);
2550 continue;2574 continue;
2551 }2575 }
2552 stubs.reserved1 = @intCast(u32, i);2576 const symtab_idx = @intCast(u32, dysymtab.iundefsym + i);
2553 try self.base.file.?.pwriteAll(&buf, dysymtab.indirectsymoff + (i + 1) * @sizeOf(u32));2577 mem.writeIntLittle(u32, &buf, symtab_idx);
2554 la.reserved1 = @intCast(u32, i + 1);2578 try self.base.file.?.pwriteAll(&buf, off);
2579 off += @sizeOf(u32);
2555 dysymtab.nindirectsyms += 1;2580 dysymtab.nindirectsyms += 1;
2581 idx += 1;
2556 }2582 }
2557}2583}
25582584
src/link/MachO/imports.zig+3-4
...@@ -21,9 +21,8 @@ pub const RebaseInfoTable = struct {...@@ -21,9 +21,8 @@ pub const RebaseInfoTable = struct {
2121
22 /// Write the rebase info table to byte stream.22 /// Write the rebase info table to byte stream.
23 pub fn write(self: RebaseInfoTable, writer: anytype) !void {23 pub fn write(self: RebaseInfoTable, writer: anytype) !void {
24 try writer.writeByte(macho.REBASE_OPCODE_SET_TYPE_IMM | @truncate(u4, self.rebase_type));
25
26 for (self.symbols.items) |symbol| {24 for (self.symbols.items) |symbol| {
25 try writer.writeByte(macho.REBASE_OPCODE_SET_TYPE_IMM | @truncate(u4, self.rebase_type));
27 try writer.writeByte(macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment));26 try writer.writeByte(macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment));
28 try leb.writeILEB128(writer, symbol.offset);27 try leb.writeILEB128(writer, symbol.offset);
29 try writer.writeByte(macho.REBASE_OPCODE_DO_REBASE_IMM_TIMES | @truncate(u4, 1));28 try writer.writeByte(macho.REBASE_OPCODE_DO_REBASE_IMM_TIMES | @truncate(u4, 1));
...@@ -36,10 +35,10 @@ pub const RebaseInfoTable = struct {...@@ -36,10 +35,10 @@ pub const RebaseInfoTable = struct {
36 pub fn calcSize(self: *RebaseInfoTable) !u64 {35 pub fn calcSize(self: *RebaseInfoTable) !u64 {
37 var stream = std.io.countingWriter(std.io.null_writer);36 var stream = std.io.countingWriter(std.io.null_writer);
38 var writer = stream.writer();37 var writer = stream.writer();
39 var size: u64 = 1;38 var size: u64 = 0;
4039
41 for (self.symbols.items) |symbol| {40 for (self.symbols.items) |symbol| {
42 size += 1;41 size += 2;
43 try leb.writeILEB128(writer, symbol.offset);42 try leb.writeILEB128(writer, symbol.offset);
44 size += 1;43 size += 1;
45 }44 }