| author | |
| committer | |
| log | 71bbc5efc9c35e4d862dba4f40e5bafe165fcbe4 |
| tree | 079f4683ca39675d86ff2763a3090ad327d851d8 |
| parent | 78b441e8deeb4e779335c09b865a497c13531657 |
2 files changed, 72 insertions(+), 6 deletions(-)
src/link/MachO/Atom.zig+19-6| ... | ... | @@ -660,6 +660,19 @@ fn resolveRelocInner( |
| 660 | 660 | // Address of the __got_zig table entry if any. |
| 661 | 661 | const ZIG_GOT = @as(i64, @intCast(rel.getZigGotTargetAddress(macho_file))); |
| 662 | 662 | |
| 663 | const divExact = struct { | |
| 664 | fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 { | |
| 665 | return math.divExact(u12, num, den) catch { | |
| 666 | try ctx.reportParseError2(atom.getFile(ctx).getIndex(), "{s}: unexpected remainder when resolving {s} at offset 0x{x}", .{ | |
| 667 | atom.getName(ctx), | |
| 668 | r.fmtPretty(ctx.getTarget().cpu.arch), | |
| 669 | r.offset, | |
| 670 | }); | |
| 671 | return error.UnexpectedRemainder; | |
| 672 | }; | |
| 673 | } | |
| 674 | }.divExact; | |
| 675 | ||
| 663 | 676 | switch (rel.tag) { |
| 664 | 677 | .local => relocs_log.debug(" {x}<+{d}>: {s}: [=> {x}] atom({d})", .{ |
| 665 | 678 | P, |
| ... | ... | @@ -831,12 +844,12 @@ fn resolveRelocInner( |
| 831 | 844 | }; |
| 832 | 845 | inst.load_store_register.offset = switch (inst.load_store_register.size) { |
| 833 | 846 | 0 => if (inst.load_store_register.v == 1) |
| 834 | try math.divExact(u12, @truncate(target), 16) | |
| 847 | try divExact(self, rel, @truncate(target), 16, macho_file) | |
| 835 | 848 | else |
| 836 | 849 | @truncate(target), |
| 837 | 1 => try math.divExact(u12, @truncate(target), 2), | |
| 838 | 2 => try math.divExact(u12, @truncate(target), 4), | |
| 839 | 3 => try math.divExact(u12, @truncate(target), 8), | |
| 850 | 1 => try divExact(self, rel, @truncate(target), 2, macho_file), | |
| 851 | 2 => try divExact(self, rel, @truncate(target), 4, macho_file), | |
| 852 | 3 => try divExact(self, rel, @truncate(target), 8, macho_file), | |
| 840 | 853 | }; |
| 841 | 854 | try writer.writeInt(u32, inst.toU32(), .little); |
| 842 | 855 | } |
| ... | ... | @@ -847,7 +860,7 @@ fn resolveRelocInner( |
| 847 | 860 | assert(rel.meta.length == 2); |
| 848 | 861 | assert(!rel.meta.pcrel); |
| 849 | 862 | const target = math.cast(u64, G + A) orelse return error.Overflow; |
| 850 | aarch64.writeLoadStoreRegInst(try math.divExact(u12, @truncate(target), 8), code[rel_offset..][0..4]); | |
| 863 | aarch64.writeLoadStoreRegInst(try divExact(self, rel, @truncate(target), 8, macho_file), code[rel_offset..][0..4]); | |
| 851 | 864 | }, |
| 852 | 865 | |
| 853 | 866 | .tlvp_pageoff => { |
| ... | ... | @@ -899,7 +912,7 @@ fn resolveRelocInner( |
| 899 | 912 | .load_store_register = .{ |
| 900 | 913 | .rt = reg_info.rd, |
| 901 | 914 | .rn = reg_info.rn, |
| 902 | .offset = try math.divExact(u12, @truncate(target), 8), | |
| 915 | .offset = try divExact(self, rel, @truncate(target), 8, macho_file), | |
| 903 | 916 | .opc = 0b01, |
| 904 | 917 | .op1 = 0b01, |
| 905 | 918 | .v = 0, |
src/link/MachO/Relocation.zig+53| ... | ... | @@ -60,6 +60,59 @@ pub fn lessThan(ctx: void, lhs: Relocation, rhs: Relocation) bool { |
| 60 | 60 | return lhs.offset < rhs.offset; |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | const FormatCtx = struct { Relocation, std.Target.Cpu.Arch }; | |
| 64 | ||
| 65 | pub fn fmtPretty(rel: Relocation, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatter(formatPretty) { | |
| 66 | return .{ .data = .{ rel, cpu_arch } }; | |
| 67 | } | |
| 68 | ||
| 69 | fn formatPretty( | |
| 70 | ctx: FormatCtx, | |
| 71 | comptime unused_fmt_string: []const u8, | |
| 72 | options: std.fmt.FormatOptions, | |
| 73 | writer: anytype, | |
| 74 | ) !void { | |
| 75 | _ = options; | |
| 76 | _ = unused_fmt_string; | |
| 77 | const rel, const cpu_arch = ctx; | |
| 78 | const str = switch (rel.type) { | |
| 79 | .signed => "X86_64_RELOC_SIGNED", | |
| 80 | .signed1 => "X86_64_RELOC_SIGNED_1", | |
| 81 | .signed2 => "X86_64_RELOC_SIGNED_2", | |
| 82 | .signed4 => "X86_64_RELOC_SIGNED_4", | |
| 83 | .got_load => "X86_64_RELOC_GOT_LOAD", | |
| 84 | .tlv => "X86_64_RELOC_TLV", | |
| 85 | .zig_got_load => "ZIG_GOT_LOAD", | |
| 86 | .page => "ARM64_RELOC_PAGE21", | |
| 87 | .pageoff => "ARM64_RELOC_PAGEOFF12", | |
| 88 | .got_load_page => "ARM64_RELOC_GOT_LOAD_PAGE21", | |
| 89 | .got_load_pageoff => "ARM64_RELOC_GOT_LOAD_PAGEOFF12", | |
| 90 | .tlvp_page => "ARM64_RELOC_TLVP_LOAD_PAGE21", | |
| 91 | .tlvp_pageoff => "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", | |
| 92 | .branch => switch (cpu_arch) { | |
| 93 | .x86_64 => "X86_64_RELOC_BRANCH", | |
| 94 | .aarch64 => "ARM64_RELOC_BRANCH26", | |
| 95 | else => unreachable, | |
| 96 | }, | |
| 97 | .got => switch (cpu_arch) { | |
| 98 | .x86_64 => "X86_64_RELOC_GOT", | |
| 99 | .aarch64 => "ARM64_RELOC_POINTER_TO_GOT", | |
| 100 | else => unreachable, | |
| 101 | }, | |
| 102 | .subtractor => switch (cpu_arch) { | |
| 103 | .x86_64 => "X86_64_RELOC_SUBTRACTOR", | |
| 104 | .aarch64 => "ARM64_RELOC_SUBTRACTOR", | |
| 105 | else => unreachable, | |
| 106 | }, | |
| 107 | .unsigned => switch (cpu_arch) { | |
| 108 | .x86_64 => "X86_64_RELOC_UNSIGNED", | |
| 109 | .aarch64 => "ARM64_RELOC_UNSIGNED", | |
| 110 | else => unreachable, | |
| 111 | }, | |
| 112 | }; | |
| 113 | try writer.writeAll(str); | |
| 114 | } | |
| 115 | ||
| 63 | 116 | pub const Type = enum { |
| 64 | 117 | // x86_64 |
| 65 | 118 | /// RIP-relative displacement (X86_64_RELOC_SIGNED) |