authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-25 11:10:17+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-26 11:50:09+01:00
log10942e3f86c03d30833cc221371f30b78a4bd710
tree69b9d317cf8d9fe7b58e4a8f67c4250c1911365a
parent2cd84b1b3f0a6e3f030da723ec51f0be33b7a1ed

stage2 macho: Hello, Silicon!


2 files changed, 50 insertions(+), 19 deletions(-)

src/codegen.zig+22-4
......@@ -1689,6 +1689,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
16891689 },
16901690 .aarch64 => {
16911691 try self.genSetReg(inst.base.src, .x30, .{ .memory = got_addr });
1692 // blr x30
16921693 writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32());
16931694 },
16941695 else => unreachable, // unsupported architecture on MachO
......@@ -2583,10 +2584,27 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
25832584 },
25842585 .register => return self.fail(src, "TODO implement genSetReg for aarch64 {}", .{mcv}),
25852586 .memory => |addr| {
2586 // The value is in memory at a hard-coded address.
2587 // If the type is a pointer, it means the pointer address is at this memory location.
2588 try self.genSetReg(src, reg, .{ .immediate = addr });
2589 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(reg, .{ .rn = reg }).toU32());
2587 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
2588 // For MachO, the binary, with the exception of object files, has to be a PIE.
2589 // Therefore we cannot load an absolute address.
2590 // Instead, we need to make use of PC-relative addressing.
2591 // if (reg.id() == 0) { // x0 is special-cased
2592 try self.mod_fn.owner_decl.link.macho.addPieFixup(self.bin_file.allocator, .{
2593 .address = addr,
2594 .start = self.code.items.len,
2595 .len = 4,
2596 });
2597 // bl [label]
2598 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.bl(0).toU32());
2599 // } else {
2600 // unreachable; // TODO
2601 // }
2602 } else {
2603 // The value is in memory at a hard-coded address.
2604 // If the type is a pointer, it means the pointer address is at this memory location.
2605 try self.genSetReg(src, reg, .{ .immediate = addr });
2606 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(reg, .{ .rn = reg }).toU32());
2607 }
25902608 },
25912609 else => return self.fail(src, "TODO implement genSetReg for aarch64 {}", .{mcv}),
25922610 },
src/link/MachO.zig+28-15
......@@ -7,6 +7,7 @@ const fs = std.fs;
77const log = std.log.scoped(.link);
88const macho = std.macho;
99const codegen = @import("../codegen.zig");
10const aarch64 = @import("../codegen/aarch64.zig");
1011const math = std.math;
1112const mem = std.mem;
1213
......@@ -1020,9 +1021,15 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
10201021 while (decl.link.macho.pie_fixups.popOrNull()) |fixup| {
10211022 const target_addr = fixup.address;
10221023 const this_addr = symbol.n_value + fixup.start;
1023 const displacement = @intCast(u32, target_addr - this_addr - fixup.len);
1024 var placeholder = code_buffer.items[fixup.start + fixup.len - @sizeOf(u32) ..][0..@sizeOf(u32)];
1025 mem.writeIntSliceLittle(u32, placeholder, displacement);
1024 if (self.base.options.target.cpu.arch == .x86_64) {
1025 const displacement = @intCast(u32, target_addr - this_addr - fixup.len);
1026 var placeholder = code_buffer.items[fixup.start + fixup.len - @sizeOf(u32) ..][0..@sizeOf(u32)];
1027 mem.writeIntSliceLittle(u32, placeholder, displacement);
1028 } else {
1029 const displacement = @intCast(u27, target_addr - this_addr);
1030 var placeholder = code_buffer.items[fixup.start..][0..fixup.len];
1031 mem.writeIntSliceLittle(u32, placeholder, aarch64.Instruction.bl(@intCast(i28, displacement)).toU32());
1032 }
10261033 }
10271034
10281035 const text_section = self.sections.items[self.text_section_index.?];
......@@ -1646,22 +1653,28 @@ fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u16) u64 {
16461653
16471654fn writeOffsetTableEntry(self: *MachO, index: usize) !void {
16481655 const sect = &self.sections.items[self.got_section_index.?];
1649 const endian = self.base.options.target.cpu.arch.endian();
1650
16511656 const off = sect.offset + @sizeOf(u64) * index;
16521657 const vmaddr = sect.addr + @sizeOf(u64) * index;
1653 const pos_symbol_off = @truncate(u31, vmaddr - self.offset_table.items[index] + 7);
1654 const symbol_off = @bitCast(u32, @intCast(i32, pos_symbol_off) * -1);
16551658
16561659 var code: [8]u8 = undefined;
1657 // lea %rax, [rip - disp]
1658 code[0] = 0x48;
1659 code[1] = 0x8D;
1660 code[2] = 0x5;
1661 mem.writeInt(u32, code[3..7], symbol_off, endian);
1662 // ret
1663 code[7] = 0xC3;
1664
1660 if (self.base.options.target.cpu.arch == .x86_64) {
1661 const pos_symbol_off = @intCast(u31, vmaddr - self.offset_table.items[index] + 7);
1662 const symbol_off = @bitCast(u32, @intCast(i32, pos_symbol_off) * -1);
1663 // lea %rax, [rip - disp]
1664 code[0] = 0x48;
1665 code[1] = 0x8D;
1666 code[2] = 0x5;
1667 mem.writeIntLittle(u32, code[3..7], symbol_off);
1668 // ret
1669 code[7] = 0xC3;
1670 } else {
1671 const pos_symbol_off = @intCast(u20, vmaddr - self.offset_table.items[index]);
1672 const symbol_off = @intCast(i21, pos_symbol_off) * -1;
1673 // adr .x0 [-disp]
1674 mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adr(.x1, symbol_off).toU32());
1675 // ret
1676 mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.ret(null).toU32());
1677 }
16651678 log.debug("writing offset table entry 0x{x} at 0x{x}\n", .{ self.offset_table.items[index], off });
16661679 try self.base.file.?.pwriteAll(&code, off);
16671680}