authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-05 08:23:46+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-13 11:47:51+02:00
logeba280ce20d308ec0abb17719ab4cc43a27901eb
treeb9bbac734e4c82bb2487f0921e26fce627291578
parent1795b8eb4e8db95cb639349c6c1bc4b0b82741bb

macho: refactor relocation type in incremental linker


5 files changed, 118 insertions(+), 190 deletions(-)

src/arch/aarch64/Emit.zig+10-19
......@@ -673,7 +673,7 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
673673 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
674674 const target = macho_file.getGlobalByIndex(relocation.sym_index);
675675 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
676 .type = @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_BRANCH26),
676 .type = .branch,
677677 .target = target,
678678 .offset = offset,
679679 .addend = 0,
......@@ -883,41 +883,32 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
883883 }
884884
885885 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
886 const Atom = link.File.MachO.Atom;
887 const Relocation = Atom.Relocation;
886888 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = data.atom_index, .file = null }).?;
887 // TODO this causes segfault in stage1
888 // try atom.addRelocations(macho_file, 2, .{
889 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
889 try Atom.addRelocations(macho_file, atom_index, &[_]Relocation{ .{
890890 .target = .{ .sym_index = data.sym_index, .file = null },
891891 .offset = offset,
892892 .addend = 0,
893893 .pcrel = true,
894894 .length = 2,
895895 .type = switch (tag) {
896 .load_memory_got,
897 .load_memory_ptr_got,
898 => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21),
899 .load_memory_direct,
900 .load_memory_ptr_direct,
901 => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGE21),
896 .load_memory_got, .load_memory_ptr_got => Relocation.Type.got_page,
897 .load_memory_direct, .load_memory_ptr_direct => Relocation.Type.page,
902898 else => unreachable,
903899 },
904 });
905 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
900 }, .{
906901 .target = .{ .sym_index = data.sym_index, .file = null },
907902 .offset = offset + 4,
908903 .addend = 0,
909904 .pcrel = false,
910905 .length = 2,
911906 .type = switch (tag) {
912 .load_memory_got,
913 .load_memory_ptr_got,
914 => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGEOFF12),
915 .load_memory_direct,
916 .load_memory_ptr_direct,
917 => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12),
907 .load_memory_got, .load_memory_ptr_got => Relocation.Type.got_pageoff,
908 .load_memory_direct, .load_memory_ptr_direct => Relocation.Type.pageoff,
918909 else => unreachable,
919910 },
920 });
911 } });
921912 } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
922913 const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = data.atom_index, .file = null }).?;
923914 const target = switch (tag) {
src/arch/x86_64/Emit.zig+6-7
......@@ -42,7 +42,7 @@ pub fn emitMir(emit: *Emit) Error!void {
4242 ).?;
4343 const target = macho_file.getGlobalByIndex(inst.data.relocation.sym_index);
4444 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
45 .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
45 .type = .branch,
4646 .target = target,
4747 .offset = end_offset - 4,
4848 .addend = 0,
......@@ -68,17 +68,16 @@ pub fn emitMir(emit: *Emit) Error!void {
6868 .mov_linker, .lea_linker => if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
6969 const metadata =
7070 emit.lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data;
71 const reloc_type = switch (inst.ops) {
72 .got_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT),
73 .direct_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
74 else => unreachable,
75 };
7671 const atom_index = macho_file.getAtomIndexForSymbol(.{
7772 .sym_index = metadata.atom_index,
7873 .file = null,
7974 }).?;
8075 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
81 .type = reloc_type,
76 .type = switch (inst.ops) {
77 .got_reloc => .got,
78 .direct_reloc => .signed,
79 else => unreachable,
80 },
8281 .target = .{ .sym_index = metadata.sym_index, .file = null },
8382 .offset = @intCast(u32, end_offset - 4),
8483 .addend = 0,
src/link/MachO.zig+17-51
......@@ -1250,11 +1250,7 @@ pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !Atom.Index {
12501250 log.debug("allocated GOT atom at 0x{x}", .{sym.n_value});
12511251
12521252 try Atom.addRelocation(self, atom_index, .{
1253 .type = switch (self.base.options.target.cpu.arch) {
1254 .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED),
1255 .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED),
1256 else => unreachable,
1257 },
1253 .type = .unsigned,
12581254 .target = target,
12591255 .offset = 0,
12601256 .addend = 0,
......@@ -1336,15 +1332,15 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {
13361332 code[9] = 0xff;
13371333 code[10] = 0x25;
13381334
1339 try Atom.addRelocations(self, atom_index, 2, .{ .{
1340 .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
1335 try Atom.addRelocations(self, atom_index, &[_]Relocation{ .{
1336 .type = .signed,
13411337 .target = dyld_private,
13421338 .offset = 3,
13431339 .addend = 0,
13441340 .pcrel = true,
13451341 .length = 2,
13461342 }, .{
1347 .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_GOT),
1343 .type = .got,
13481344 .target = dyld_stub_binder,
13491345 .offset = 11,
13501346 .addend = 0,
......@@ -1376,29 +1372,29 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {
13761372 // br x16
13771373 mem.writeIntLittle(u32, code[20..][0..4], aarch64.Instruction.br(.x16).toU32());
13781374
1379 try Atom.addRelocations(self, atom_index, 4, .{ .{
1380 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21),
1375 try Atom.addRelocations(self, atom_index, &[_]Relocation{ .{
1376 .type = .page,
13811377 .target = dyld_private,
13821378 .offset = 0,
13831379 .addend = 0,
13841380 .pcrel = true,
13851381 .length = 2,
13861382 }, .{
1387 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12),
1383 .type = .pageoff,
13881384 .target = dyld_private,
13891385 .offset = 4,
13901386 .addend = 0,
13911387 .pcrel = false,
13921388 .length = 2,
13931389 }, .{
1394 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21),
1390 .type = .got_page,
13951391 .target = dyld_stub_binder,
13961392 .offset = 12,
13971393 .addend = 0,
13981394 .pcrel = true,
13991395 .length = 2,
14001396 }, .{
1401 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGEOFF12),
1397 .type = .got_pageoff,
14021398 .target = dyld_stub_binder,
14031399 .offset = 16,
14041400 .addend = 0,
......@@ -1456,7 +1452,7 @@ fn createStubHelperAtom(self: *MachO) !Atom.Index {
14561452 code[5] = 0xe9;
14571453
14581454 try Atom.addRelocation(self, atom_index, .{
1459 .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
1455 .type = .branch,
14601456 .target = .{ .sym_index = stub_helper_preamble_atom_sym_index, .file = null },
14611457 .offset = 6,
14621458 .addend = 0,
......@@ -1479,7 +1475,7 @@ fn createStubHelperAtom(self: *MachO) !Atom.Index {
14791475 // Next 4 bytes 8..12 are just a placeholder populated in `populateLazyBindOffsetsInStubHelper`.
14801476
14811477 try Atom.addRelocation(self, atom_index, .{
1482 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_BRANCH26),
1478 .type = .branch,
14831479 .target = .{ .sym_index = stub_helper_preamble_atom_sym_index, .file = null },
14841480 .offset = 4,
14851481 .addend = 0,
......@@ -1507,11 +1503,7 @@ fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLo
15071503 sym.n_sect = self.la_symbol_ptr_section_index.? + 1;
15081504
15091505 try Atom.addRelocation(self, atom_index, .{
1510 .type = switch (self.base.options.target.cpu.arch) {
1511 .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED),
1512 .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED),
1513 else => unreachable,
1514 },
1506 .type = .unsigned,
15151507 .target = .{ .sym_index = stub_sym_index, .file = null },
15161508 .offset = 0,
15171509 .addend = 0,
......@@ -1565,7 +1557,7 @@ fn createStubAtom(self: *MachO, laptr_sym_index: u32) !Atom.Index {
15651557 code[1] = 0x25;
15661558
15671559 try Atom.addRelocation(self, atom_index, .{
1568 .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
1560 .type = .branch,
15691561 .target = .{ .sym_index = laptr_sym_index, .file = null },
15701562 .offset = 2,
15711563 .addend = 0,
......@@ -1585,9 +1577,9 @@ fn createStubAtom(self: *MachO, laptr_sym_index: u32) !Atom.Index {
15851577 // br x16
15861578 mem.writeIntLittle(u32, code[8..12], aarch64.Instruction.br(.x16).toU32());
15871579
1588 try Atom.addRelocations(self, atom_index, 2, .{
1580 try Atom.addRelocations(self, atom_index, &[_]Relocation{
15891581 .{
1590 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21),
1582 .type = .page,
15911583 .target = .{ .sym_index = laptr_sym_index, .file = null },
15921584 .offset = 0,
15931585 .addend = 0,
......@@ -1595,7 +1587,7 @@ fn createStubAtom(self: *MachO, laptr_sym_index: u32) !Atom.Index {
15951587 .length = 2,
15961588 },
15971589 .{
1598 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12),
1590 .type = .pageoff,
15991591 .target = .{ .sym_index = laptr_sym_index, .file = null },
16001592 .offset = 4,
16011593 .addend = 0,
......@@ -2663,11 +2655,7 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil
26632655 const sym_index = self.getAtom(this_atom_index).getSymbolIndex().?;
26642656 const atom_index = self.getAtomIndexForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?;
26652657 try Atom.addRelocation(self, atom_index, .{
2666 .type = switch (self.base.options.target.cpu.arch) {
2667 .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED),
2668 .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED),
2669 else => unreachable,
2670 },
2658 .type = .unsigned,
26712659 .target = .{ .sym_index = sym_index, .file = null },
26722660 .offset = @intCast(u32, reloc_info.offset),
26732661 .addend = reloc_info.addend,
......@@ -3115,28 +3103,6 @@ fn allocateAtom(self: *MachO, atom_index: Atom.Index, new_atom_size: u64, alignm
31153103 return vaddr;
31163104}
31173105
3118fn getSectionPrecedence(header: macho.section_64) u4 {
3119 if (header.isCode()) {
3120 if (mem.eql(u8, "__text", header.sectName())) return 0x0;
3121 if (header.type() == macho.S_SYMBOL_STUBS) return 0x1;
3122 return 0x2;
3123 }
3124 switch (header.type()) {
3125 macho.S_NON_LAZY_SYMBOL_POINTERS,
3126 macho.S_LAZY_SYMBOL_POINTERS,
3127 => return 0x0,
3128 macho.S_MOD_INIT_FUNC_POINTERS => return 0x1,
3129 macho.S_MOD_TERM_FUNC_POINTERS => return 0x2,
3130 macho.S_ZEROFILL => return 0xf,
3131 macho.S_THREAD_LOCAL_REGULAR => return 0xd,
3132 macho.S_THREAD_LOCAL_ZEROFILL => return 0xe,
3133 else => if (mem.eql(u8, "__eh_frame", header.sectName()))
3134 return 0xf
3135 else
3136 return 0x3,
3137 }
3138}
3139
31403106pub fn getGlobalSymbol(self: *MachO, name: []const u8, lib_name: ?[]const u8) !u32 {
31413107 _ = lib_name;
31423108 const gpa = self.base.allocator;
src/link/MachO/Atom.zig+5-11
......@@ -14,7 +14,7 @@ const trace = @import("../../tracy.zig").trace;
1414const Allocator = mem.Allocator;
1515const Arch = std.Target.Cpu.Arch;
1616const MachO = @import("../MachO.zig");
17const Relocation = @import("Relocation.zig");
17pub const Relocation = @import("Relocation.zig");
1818const SymbolWithLoc = MachO.SymbolWithLoc;
1919
2020/// Each decl always gets a local symbol with the fully qualified name.
......@@ -113,25 +113,19 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
113113}
114114
115115pub fn addRelocation(macho_file: *MachO, atom_index: Index, reloc: Relocation) !void {
116 return addRelocations(macho_file, atom_index, 1, .{reloc});
116 return addRelocations(macho_file, atom_index, &[_]Relocation{reloc});
117117}
118118
119pub fn addRelocations(
120 macho_file: *MachO,
121 atom_index: Index,
122 comptime count: comptime_int,
123 relocs: [count]Relocation,
124) !void {
119pub fn addRelocations(macho_file: *MachO, atom_index: Index, relocs: []Relocation) !void {
125120 const gpa = macho_file.base.allocator;
126 const target = macho_file.base.options.target;
127121 const gop = try macho_file.relocs.getOrPut(gpa, atom_index);
128122 if (!gop.found_existing) {
129123 gop.value_ptr.* = .{};
130124 }
131 try gop.value_ptr.ensureUnusedCapacity(gpa, count);
125 try gop.value_ptr.ensureUnusedCapacity(gpa, relocs.len);
132126 for (relocs) |reloc| {
133127 log.debug(" (adding reloc of type {s} to target %{d})", .{
134 reloc.fmtType(target),
128 @tagName(reloc.type),
135129 reloc.target.sym_index,
136130 });
137131 gop.value_ptr.appendAssumeCapacity(reloc);
src/link/MachO/Relocation.zig+80-102
......@@ -1,19 +1,7 @@
1const Relocation = @This();
2
3const std = @import("std");
4const aarch64 = @import("../../arch/aarch64/bits.zig");
5const assert = std.debug.assert;
6const log = std.log.scoped(.link);
7const macho = std.macho;
8const math = std.math;
9const mem = std.mem;
10const meta = std.meta;
11
12const Atom = @import("Atom.zig");
13const MachO = @import("../MachO.zig");
14const SymbolWithLoc = MachO.SymbolWithLoc;
1//! Relocation used by the self-hosted backends to instruct the linker where and how to
2//! fixup the values when flushing the contents to file and/or memory.
153
16type: u4,
4type: Type,
175target: SymbolWithLoc,
186offset: u32,
197addend: i64,
......@@ -21,36 +9,46 @@ pcrel: bool,
219length: u2,
2210dirty: bool = true,
2311
12pub const Type = enum {
13 // x86, x86_64
14 /// RIP-relative displacement to a GOT pointer
15 got,
16 /// RIP-relative displacement
17 signed,
18 /// RIP-relative displacemen to threadlocal variable descriptor
19 tlv,
20
21 // aarch64
22 /// PC-relative distance to target page in GOT section
23 got_page,
24 /// Offset to a GOT pointer relative to the start of a page in GOT section
25 got_pageoff,
26 /// PC-relative distance to target page in a section
27 page,
28 /// Offset to a pointer relative to the start of a page in a section
29 pageoff,
30 /// PC-relative distance to target page in TLV section
31 tlv_page,
32 /// Offset to a pointer relative to the start of a page in TLV section
33 tlv_pageoff,
34
35 // common
36 /// PC/RIP-relative displacement B/BL/CALL
37 branch,
38 /// Absolute pointer value
39 unsigned,
40};
41
2442/// Returns true if and only if the reloc is dirty AND the target address is available.
2543pub fn isResolvable(self: Relocation, macho_file: *MachO) bool {
2644 _ = self.getTargetAtomIndex(macho_file) orelse return false;
2745 return self.dirty;
2846}
2947
30pub fn fmtType(self: Relocation, target: std.Target) []const u8 {
31 switch (target.cpu.arch) {
32 .aarch64 => return @tagName(@intToEnum(macho.reloc_type_arm64, self.type)),
33 .x86_64 => return @tagName(@intToEnum(macho.reloc_type_x86_64, self.type)),
34 else => unreachable,
35 }
36}
37
3848pub fn getTargetAtomIndex(self: Relocation, macho_file: *MachO) ?Atom.Index {
39 switch (macho_file.base.options.target.cpu.arch) {
40 .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, self.type)) {
41 .ARM64_RELOC_GOT_LOAD_PAGE21,
42 .ARM64_RELOC_GOT_LOAD_PAGEOFF12,
43 .ARM64_RELOC_POINTER_TO_GOT,
44 => return macho_file.getGotAtomIndexForSymbol(self.target),
45 else => {},
46 },
47 .x86_64 => switch (@intToEnum(macho.reloc_type_x86_64, self.type)) {
48 .X86_64_RELOC_GOT,
49 .X86_64_RELOC_GOT_LOAD,
50 => return macho_file.getGotAtomIndexForSymbol(self.target),
51 else => {},
52 },
53 else => unreachable,
49 switch (self.type) {
50 .got, .got_page, .got_pageoff => return macho_file.getGotAtomIndexForSymbol(self.target),
51 else => {},
5452 }
5553 if (macho_file.getStubsAtomIndexForSymbol(self.target)) |stubs_atom| return stubs_atom;
5654 return macho_file.getAtomIndexForSymbol(self.target);
......@@ -70,7 +68,7 @@ pub fn resolve(self: Relocation, macho_file: *MachO, atom_index: Atom.Index, cod
7068 source_addr,
7169 target_addr,
7270 macho_file.getSymbolName(self.target),
73 self.fmtType(macho_file.base.options.target),
71 @tagName(self.type),
7472 });
7573
7674 switch (arch) {
......@@ -81,18 +79,9 @@ pub fn resolve(self: Relocation, macho_file: *MachO, atom_index: Atom.Index, cod
8179}
8280
8381fn resolveAarch64(self: Relocation, source_addr: u64, target_addr: i64, code: []u8) void {
84 const rel_type = @intToEnum(macho.reloc_type_arm64, self.type);
85 if (rel_type == .ARM64_RELOC_UNSIGNED) {
86 return switch (self.length) {
87 2 => mem.writeIntLittle(u32, code[self.offset..][0..4], @truncate(u32, @bitCast(u64, target_addr))),
88 3 => mem.writeIntLittle(u64, code[self.offset..][0..8], @bitCast(u64, target_addr)),
89 else => unreachable,
90 };
91 }
92
93 var buffer = code[self.offset..][0..4];
94 switch (rel_type) {
95 .ARM64_RELOC_BRANCH26 => {
82 var buffer = code[self.offset..];
83 switch (self.type) {
84 .branch => {
9685 const displacement = math.cast(
9786 i28,
9887 @intCast(i64, target_addr) - @intCast(i64, source_addr),
......@@ -101,15 +90,12 @@ fn resolveAarch64(self: Relocation, source_addr: u64, target_addr: i64, code: []
10190 .unconditional_branch_immediate = mem.bytesToValue(meta.TagPayload(
10291 aarch64.Instruction,
10392 aarch64.Instruction.unconditional_branch_immediate,
104 ), buffer),
93 ), buffer[0..4]),
10594 };
10695 inst.unconditional_branch_immediate.imm26 = @truncate(u26, @bitCast(u28, displacement >> 2));
107 mem.writeIntLittle(u32, buffer, inst.toU32());
96 mem.writeIntLittle(u32, buffer[0..4], inst.toU32());
10897 },
109 .ARM64_RELOC_PAGE21,
110 .ARM64_RELOC_GOT_LOAD_PAGE21,
111 .ARM64_RELOC_TLVP_LOAD_PAGE21,
112 => {
98 .page, .got_page, .tlv_page => {
11399 const source_page = @intCast(i32, source_addr >> 12);
114100 const target_page = @intCast(i32, target_addr >> 12);
115101 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));
......@@ -117,31 +103,29 @@ fn resolveAarch64(self: Relocation, source_addr: u64, target_addr: i64, code: []
117103 .pc_relative_address = mem.bytesToValue(meta.TagPayload(
118104 aarch64.Instruction,
119105 aarch64.Instruction.pc_relative_address,
120 ), buffer),
106 ), buffer[0..4]),
121107 };
122108 inst.pc_relative_address.immhi = @truncate(u19, pages >> 2);
123109 inst.pc_relative_address.immlo = @truncate(u2, pages);
124 mem.writeIntLittle(u32, buffer, inst.toU32());
110 mem.writeIntLittle(u32, buffer[0..4], inst.toU32());
125111 },
126 .ARM64_RELOC_PAGEOFF12,
127 .ARM64_RELOC_GOT_LOAD_PAGEOFF12,
128 => {
112 .pageoff, .got_pageoff => {
129113 const narrowed = @truncate(u12, @intCast(u64, target_addr));
130 if (isArithmeticOp(buffer)) {
114 if (isArithmeticOp(buffer[0..4])) {
131115 var inst = aarch64.Instruction{
132116 .add_subtract_immediate = mem.bytesToValue(meta.TagPayload(
133117 aarch64.Instruction,
134118 aarch64.Instruction.add_subtract_immediate,
135 ), buffer),
119 ), buffer[0..4]),
136120 };
137121 inst.add_subtract_immediate.imm12 = narrowed;
138 mem.writeIntLittle(u32, buffer, inst.toU32());
122 mem.writeIntLittle(u32, buffer[0..4], inst.toU32());
139123 } else {
140124 var inst = aarch64.Instruction{
141125 .load_store_register = mem.bytesToValue(meta.TagPayload(
142126 aarch64.Instruction,
143127 aarch64.Instruction.load_store_register,
144 ), buffer),
128 ), buffer[0..4]),
145129 };
146130 const offset: u12 = blk: {
147131 if (inst.load_store_register.size == 0) {
......@@ -157,21 +141,21 @@ fn resolveAarch64(self: Relocation, source_addr: u64, target_addr: i64, code: []
157141 }
158142 };
159143 inst.load_store_register.offset = offset;
160 mem.writeIntLittle(u32, buffer, inst.toU32());
144 mem.writeIntLittle(u32, buffer[0..4], inst.toU32());
161145 }
162146 },
163 .ARM64_RELOC_TLVP_LOAD_PAGEOFF12 => {
147 .tlv_pageoff => {
164148 const RegInfo = struct {
165149 rd: u5,
166150 rn: u5,
167151 size: u2,
168152 };
169153 const reg_info: RegInfo = blk: {
170 if (isArithmeticOp(buffer)) {
154 if (isArithmeticOp(buffer[0..4])) {
171155 const inst = mem.bytesToValue(meta.TagPayload(
172156 aarch64.Instruction,
173157 aarch64.Instruction.add_subtract_immediate,
174 ), buffer);
158 ), buffer[0..4]);
175159 break :blk .{
176160 .rd = inst.rd,
177161 .rn = inst.rn,
......@@ -181,7 +165,7 @@ fn resolveAarch64(self: Relocation, source_addr: u64, target_addr: i64, code: []
181165 const inst = mem.bytesToValue(meta.TagPayload(
182166 aarch64.Instruction,
183167 aarch64.Instruction.load_store_register,
184 ), buffer);
168 ), buffer[0..4]);
185169 break :blk .{
186170 .rd = inst.rt,
187171 .rn = inst.rn,
......@@ -201,45 +185,24 @@ fn resolveAarch64(self: Relocation, source_addr: u64, target_addr: i64, code: []
201185 .sf = @truncate(u1, reg_info.size),
202186 },
203187 };
204 mem.writeIntLittle(u32, buffer, inst.toU32());
188 mem.writeIntLittle(u32, buffer[0..4], inst.toU32());
205189 },
206 .ARM64_RELOC_POINTER_TO_GOT => {
207 const result = @intCast(i32, @intCast(i64, target_addr) - @intCast(i64, source_addr));
208 mem.writeIntLittle(i32, buffer, result);
190 .unsigned => switch (self.length) {
191 2 => mem.writeIntLittle(u32, buffer[0..4], @truncate(u32, @bitCast(u64, target_addr))),
192 3 => mem.writeIntLittle(u64, buffer[0..8], @bitCast(u64, target_addr)),
193 else => unreachable,
209194 },
210 .ARM64_RELOC_SUBTRACTOR => unreachable,
211 .ARM64_RELOC_ADDEND => unreachable,
212 .ARM64_RELOC_UNSIGNED => unreachable,
195 .got, .signed, .tlv => unreachable, // Invalid target architecture.
213196 }
214197}
215198
216199fn resolveX8664(self: Relocation, source_addr: u64, target_addr: i64, code: []u8) void {
217 const rel_type = @intToEnum(macho.reloc_type_x86_64, self.type);
218 switch (rel_type) {
219 .X86_64_RELOC_BRANCH,
220 .X86_64_RELOC_GOT,
221 .X86_64_RELOC_GOT_LOAD,
222 .X86_64_RELOC_TLV,
223 => {
200 switch (self.type) {
201 .branch, .got, .tlv, .signed => {
224202 const displacement = @intCast(i32, @intCast(i64, target_addr) - @intCast(i64, source_addr) - 4);
225203 mem.writeIntLittle(u32, code[self.offset..][0..4], @bitCast(u32, displacement));
226204 },
227 .X86_64_RELOC_SIGNED,
228 .X86_64_RELOC_SIGNED_1,
229 .X86_64_RELOC_SIGNED_2,
230 .X86_64_RELOC_SIGNED_4,
231 => {
232 const correction: u3 = switch (rel_type) {
233 .X86_64_RELOC_SIGNED => 0,
234 .X86_64_RELOC_SIGNED_1 => 1,
235 .X86_64_RELOC_SIGNED_2 => 2,
236 .X86_64_RELOC_SIGNED_4 => 4,
237 else => unreachable,
238 };
239 const displacement = @intCast(i32, target_addr - @intCast(i64, source_addr + correction + 4));
240 mem.writeIntLittle(u32, code[self.offset..][0..4], @bitCast(u32, displacement));
241 },
242 .X86_64_RELOC_UNSIGNED => {
205 .unsigned => {
243206 switch (self.length) {
244207 2 => {
245208 mem.writeIntLittle(u32, code[self.offset..][0..4], @truncate(u32, @bitCast(u64, target_addr)));
......@@ -250,7 +213,7 @@ fn resolveX8664(self: Relocation, source_addr: u64, target_addr: i64, code: []u8
250213 else => unreachable,
251214 }
252215 },
253 .X86_64_RELOC_SUBTRACTOR => unreachable,
216 .got_page, .got_pageoff, .page, .pageoff, .tlv_page, .tlv_pageoff => unreachable, // Invalid target architecture.
254217 }
255218}
256219
......@@ -258,3 +221,18 @@ inline fn isArithmeticOp(inst: *const [4]u8) bool {
258221 const group_decode = @truncate(u5, inst[3]);
259222 return ((group_decode >> 2) == 4);
260223}
224
225const Relocation = @This();
226
227const std = @import("std");
228const aarch64 = @import("../../arch/aarch64/bits.zig");
229const assert = std.debug.assert;
230const log = std.log.scoped(.link);
231const macho = std.macho;
232const math = std.math;
233const mem = std.mem;
234const meta = std.meta;
235
236const Atom = @import("Atom.zig");
237const MachO = @import("../MachO.zig");
238const SymbolWithLoc = MachO.SymbolWithLoc;