| author | |
| committer | |
| log | ee364d542a91293fc048ea47dd8530f824916e5a |
| tree | bcfb7fa83567e36ea4aafc42ab4f37e61c744422 |
| parent | 60a8f9b989d64bb6dfbb9e85cd0dd4e1b41750e1 |
4 files changed, 24 insertions(+), 107 deletions(-)
src/link/MachO/Atom.zig+10-60| ... | @@ -699,14 +699,7 @@ fn resolveRelocInner( | ... | @@ -699,14 +699,7 @@ fn resolveRelocInner( |
| 699 | const S_: i64 = @intCast(thunk.getTargetAddress(rel.target, macho_file)); | 699 | const S_: i64 = @intCast(thunk.getTargetAddress(rel.target, macho_file)); |
| 700 | break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow; | 700 | break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow; |
| 701 | }; | 701 | }; |
| 702 | var inst = aarch64.Instruction{ | 702 | try aarch64.writeBranchImm(disp, code[rel_offset..][0..4]); |
| 703 | .unconditional_branch_immediate = mem.bytesToValue(std.meta.TagPayload( | ||
| 704 | aarch64.Instruction, | ||
| 705 | aarch64.Instruction.unconditional_branch_immediate, | ||
| 706 | ), code[rel_offset..][0..4]), | ||
| 707 | }; | ||
| 708 | inst.unconditional_branch_immediate.imm26 = @as(u26, @truncate(@as(u28, @bitCast(disp >> 2)))); | ||
| 709 | try writer.writeInt(u32, inst.toU32(), .little); | ||
| 710 | }, | 703 | }, |
| 711 | else => unreachable, | 704 | else => unreachable, |
| 712 | } | 705 | } |
| ... | @@ -776,16 +769,8 @@ fn resolveRelocInner( | ... | @@ -776,16 +769,8 @@ fn resolveRelocInner( |
| 776 | }; | 769 | }; |
| 777 | break :target math.cast(u64, target) orelse return error.Overflow; | 770 | break :target math.cast(u64, target) orelse return error.Overflow; |
| 778 | }; | 771 | }; |
| 779 | const pages = @as(u21, @bitCast(try Relocation.calcNumberOfPages(source, target))); | 772 | const pages = @as(u21, @bitCast(try aarch64.calcNumberOfPages(source, target))); |
| 780 | var inst = aarch64.Instruction{ | 773 | try aarch64.writePages(pages, code[rel_offset..][0..4]); |
| 781 | .pc_relative_address = mem.bytesToValue(std.meta.TagPayload( | ||
| 782 | aarch64.Instruction, | ||
| 783 | aarch64.Instruction.pc_relative_address, | ||
| 784 | ), code[rel_offset..][0..4]), | ||
| 785 | }; | ||
| 786 | inst.pc_relative_address.immhi = @as(u19, @truncate(pages >> 2)); | ||
| 787 | inst.pc_relative_address.immlo = @as(u2, @truncate(pages)); | ||
| 788 | try writer.writeInt(u32, inst.toU32(), .little); | ||
| 789 | }, | 774 | }, |
| 790 | 775 | ||
| 791 | .pageoff => { | 776 | .pageoff => { |
| ... | @@ -794,35 +779,8 @@ fn resolveRelocInner( | ... | @@ -794,35 +779,8 @@ fn resolveRelocInner( |
| 794 | assert(!rel.meta.pcrel); | 779 | assert(!rel.meta.pcrel); |
| 795 | const target = math.cast(u64, S + A) orelse return error.Overflow; | 780 | const target = math.cast(u64, S + A) orelse return error.Overflow; |
| 796 | const inst_code = code[rel_offset..][0..4]; | 781 | const inst_code = code[rel_offset..][0..4]; |
| 797 | if (Relocation.isArithmeticOp(inst_code)) { | 782 | const kind = aarch64.classifyInst(inst_code); |
| 798 | const off = try Relocation.calcPageOffset(target, .arithmetic); | 783 | try aarch64.writePageOffset(kind, target, inst_code); |
| 799 | var inst = aarch64.Instruction{ | ||
| 800 | .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload( | ||
| 801 | aarch64.Instruction, | ||
| 802 | aarch64.Instruction.add_subtract_immediate, | ||
| 803 | ), inst_code), | ||
| 804 | }; | ||
| 805 | inst.add_subtract_immediate.imm12 = off; | ||
| 806 | try writer.writeInt(u32, inst.toU32(), .little); | ||
| 807 | } else { | ||
| 808 | var inst = aarch64.Instruction{ | ||
| 809 | .load_store_register = mem.bytesToValue(std.meta.TagPayload( | ||
| 810 | aarch64.Instruction, | ||
| 811 | aarch64.Instruction.load_store_register, | ||
| 812 | ), inst_code), | ||
| 813 | }; | ||
| 814 | const off = try Relocation.calcPageOffset(target, switch (inst.load_store_register.size) { | ||
| 815 | 0 => if (inst.load_store_register.v == 1) | ||
| 816 | Relocation.PageOffsetInstKind.load_store_128 | ||
| 817 | else | ||
| 818 | Relocation.PageOffsetInstKind.load_store_8, | ||
| 819 | 1 => .load_store_16, | ||
| 820 | 2 => .load_store_32, | ||
| 821 | 3 => .load_store_64, | ||
| 822 | }); | ||
| 823 | inst.load_store_register.offset = off; | ||
| 824 | try writer.writeInt(u32, inst.toU32(), .little); | ||
| 825 | } | ||
| 826 | }, | 784 | }, |
| 827 | 785 | ||
| 828 | .got_load_pageoff => { | 786 | .got_load_pageoff => { |
| ... | @@ -830,15 +788,7 @@ fn resolveRelocInner( | ... | @@ -830,15 +788,7 @@ fn resolveRelocInner( |
| 830 | assert(rel.meta.length == 2); | 788 | assert(rel.meta.length == 2); |
| 831 | assert(!rel.meta.pcrel); | 789 | assert(!rel.meta.pcrel); |
| 832 | const target = math.cast(u64, G + A) orelse return error.Overflow; | 790 | const target = math.cast(u64, G + A) orelse return error.Overflow; |
| 833 | const off = try Relocation.calcPageOffset(target, .load_store_64); | 791 | try aarch64.writePageOffset(.load_store_64, target, code[rel_offset..][0..4]); |
| 834 | var inst: aarch64.Instruction = .{ | ||
| 835 | .load_store_register = mem.bytesToValue(std.meta.TagPayload( | ||
| 836 | aarch64.Instruction, | ||
| 837 | aarch64.Instruction.load_store_register, | ||
| 838 | ), code[rel_offset..][0..4]), | ||
| 839 | }; | ||
| 840 | inst.load_store_register.offset = off; | ||
| 841 | try writer.writeInt(u32, inst.toU32(), .little); | ||
| 842 | }, | 792 | }, |
| 843 | 793 | ||
| 844 | .tlvp_pageoff => { | 794 | .tlvp_pageoff => { |
| ... | @@ -863,7 +813,7 @@ fn resolveRelocInner( | ... | @@ -863,7 +813,7 @@ fn resolveRelocInner( |
| 863 | 813 | ||
| 864 | const inst_code = code[rel_offset..][0..4]; | 814 | const inst_code = code[rel_offset..][0..4]; |
| 865 | const reg_info: RegInfo = blk: { | 815 | const reg_info: RegInfo = blk: { |
| 866 | if (Relocation.isArithmeticOp(inst_code)) { | 816 | if (aarch64.isArithmeticOp(inst_code)) { |
| 867 | const inst = mem.bytesToValue(std.meta.TagPayload( | 817 | const inst = mem.bytesToValue(std.meta.TagPayload( |
| 868 | aarch64.Instruction, | 818 | aarch64.Instruction, |
| 869 | aarch64.Instruction.add_subtract_immediate, | 819 | aarch64.Instruction.add_subtract_immediate, |
| ... | @@ -890,7 +840,7 @@ fn resolveRelocInner( | ... | @@ -890,7 +840,7 @@ fn resolveRelocInner( |
| 890 | .load_store_register = .{ | 840 | .load_store_register = .{ |
| 891 | .rt = reg_info.rd, | 841 | .rt = reg_info.rd, |
| 892 | .rn = reg_info.rn, | 842 | .rn = reg_info.rn, |
| 893 | .offset = try Relocation.calcPageOffset(target, .load_store_64), | 843 | .offset = try aarch64.calcPageOffset(.load_store_64, target), |
| 894 | .opc = 0b01, | 844 | .opc = 0b01, |
| 895 | .op1 = 0b01, | 845 | .op1 = 0b01, |
| 896 | .v = 0, | 846 | .v = 0, |
| ... | @@ -900,7 +850,7 @@ fn resolveRelocInner( | ... | @@ -900,7 +850,7 @@ fn resolveRelocInner( |
| 900 | .add_subtract_immediate = .{ | 850 | .add_subtract_immediate = .{ |
| 901 | .rd = reg_info.rd, | 851 | .rd = reg_info.rd, |
| 902 | .rn = reg_info.rn, | 852 | .rn = reg_info.rn, |
| 903 | .imm12 = try Relocation.calcPageOffset(target, .arithmetic), | 853 | .imm12 = try aarch64.calcPageOffset(.arithmetic, target), |
| 904 | .sh = 0, | 854 | .sh = 0, |
| 905 | .s = 0, | 855 | .s = 0, |
| 906 | .op = 0, | 856 | .op = 0, |
| ... | @@ -1183,7 +1133,7 @@ pub const Loc = struct { | ... | @@ -1183,7 +1133,7 @@ pub const Loc = struct { |
| 1183 | 1133 | ||
| 1184 | pub const Alignment = @import("../../InternPool.zig").Alignment; | 1134 | pub const Alignment = @import("../../InternPool.zig").Alignment; |
| 1185 | 1135 | ||
| 1186 | const aarch64 = @import("../../arch/aarch64/bits.zig"); | 1136 | const aarch64 = @import("../aarch64.zig"); |
| 1187 | const assert = std.debug.assert; | 1137 | const assert = std.debug.assert; |
| 1188 | const bind = @import("dyld_info/bind.zig"); | 1138 | const bind = @import("dyld_info/bind.zig"); |
| 1189 | const macho = std.macho; | 1139 | const macho = std.macho; |
src/link/MachO/Relocation.zig-32| ... | @@ -60,38 +60,6 @@ pub fn lessThan(ctx: void, lhs: Relocation, rhs: Relocation) bool { | ... | @@ -60,38 +60,6 @@ pub fn lessThan(ctx: void, lhs: Relocation, rhs: Relocation) bool { |
| 60 | return lhs.offset < rhs.offset; | 60 | return lhs.offset < rhs.offset; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 { | ||
| 64 | const spage = math.cast(i32, saddr >> 12) orelse return error.Overflow; | ||
| 65 | const tpage = math.cast(i32, taddr >> 12) orelse return error.Overflow; | ||
| 66 | const pages = math.cast(i21, tpage - spage) orelse return error.Overflow; | ||
| 67 | return pages; | ||
| 68 | } | ||
| 69 | |||
| 70 | pub const PageOffsetInstKind = enum { | ||
| 71 | arithmetic, | ||
| 72 | load_store_8, | ||
| 73 | load_store_16, | ||
| 74 | load_store_32, | ||
| 75 | load_store_64, | ||
| 76 | load_store_128, | ||
| 77 | }; | ||
| 78 | |||
| 79 | pub fn calcPageOffset(taddr: u64, kind: PageOffsetInstKind) !u12 { | ||
| 80 | const narrowed = @as(u12, @truncate(taddr)); | ||
| 81 | return switch (kind) { | ||
| 82 | .arithmetic, .load_store_8 => narrowed, | ||
| 83 | .load_store_16 => try math.divExact(u12, narrowed, 2), | ||
| 84 | .load_store_32 => try math.divExact(u12, narrowed, 4), | ||
| 85 | .load_store_64 => try math.divExact(u12, narrowed, 8), | ||
| 86 | .load_store_128 => try math.divExact(u12, narrowed, 16), | ||
| 87 | }; | ||
| 88 | } | ||
| 89 | |||
| 90 | pub inline fn isArithmeticOp(inst: *const [4]u8) bool { | ||
| 91 | const group_decode = @as(u5, @truncate(inst[3])); | ||
| 92 | return ((group_decode >> 2) == 4); | ||
| 93 | } | ||
| 94 | |||
| 95 | pub const Type = enum { | 63 | pub const Type = enum { |
| 96 | // x86_64 | 64 | // x86_64 |
| 97 | /// RIP-relative displacement (X86_64_RELOC_SIGNED) | 65 | /// RIP-relative displacement (X86_64_RELOC_SIGNED) |
src/link/MachO/synthetic.zig+11-12| ... | @@ -267,9 +267,9 @@ pub const StubsSection = struct { | ... | @@ -267,9 +267,9 @@ pub const StubsSection = struct { |
| 267 | }, | 267 | }, |
| 268 | .aarch64 => { | 268 | .aarch64 => { |
| 269 | // TODO relax if possible | 269 | // TODO relax if possible |
| 270 | const pages = try Relocation.calcNumberOfPages(source, target); | 270 | const pages = try aarch64.calcNumberOfPages(source, target); |
| 271 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); | 271 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); |
| 272 | const off = try Relocation.calcPageOffset(target, .load_store_64); | 272 | const off = try aarch64.calcPageOffset(.load_store_64, target); |
| 273 | try writer.writeInt( | 273 | try writer.writeInt( |
| 274 | u32, | 274 | u32, |
| 275 | aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(), | 275 | aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(), |
| ... | @@ -411,9 +411,9 @@ pub const StubsHelperSection = struct { | ... | @@ -411,9 +411,9 @@ pub const StubsHelperSection = struct { |
| 411 | .aarch64 => { | 411 | .aarch64 => { |
| 412 | { | 412 | { |
| 413 | // TODO relax if possible | 413 | // TODO relax if possible |
| 414 | const pages = try Relocation.calcNumberOfPages(sect.addr, dyld_private_addr); | 414 | const pages = try aarch64.calcNumberOfPages(sect.addr, dyld_private_addr); |
| 415 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little); | 415 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little); |
| 416 | const off = try Relocation.calcPageOffset(dyld_private_addr, .arithmetic); | 416 | const off = try aarch64.calcPageOffset(.arithmetic, dyld_private_addr); |
| 417 | try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little); | 417 | try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little); |
| 418 | } | 418 | } |
| 419 | try writer.writeInt(u32, aarch64.Instruction.stp( | 419 | try writer.writeInt(u32, aarch64.Instruction.stp( |
| ... | @@ -424,9 +424,9 @@ pub const StubsHelperSection = struct { | ... | @@ -424,9 +424,9 @@ pub const StubsHelperSection = struct { |
| 424 | ).toU32(), .little); | 424 | ).toU32(), .little); |
| 425 | { | 425 | { |
| 426 | // TODO relax if possible | 426 | // TODO relax if possible |
| 427 | const pages = try Relocation.calcNumberOfPages(sect.addr + 12, dyld_stub_binder_addr); | 427 | const pages = try aarch64.calcNumberOfPages(sect.addr + 12, dyld_stub_binder_addr); |
| 428 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); | 428 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); |
| 429 | const off = try Relocation.calcPageOffset(dyld_stub_binder_addr, .load_store_64); | 429 | const off = try aarch64.calcPageOffset(.load_store_64, dyld_stub_binder_addr); |
| 430 | try writer.writeInt(u32, aarch64.Instruction.ldr( | 430 | try writer.writeInt(u32, aarch64.Instruction.ldr( |
| 431 | .x16, | 431 | .x16, |
| 432 | .x16, | 432 | .x16, |
| ... | @@ -679,9 +679,9 @@ pub const ObjcStubsSection = struct { | ... | @@ -679,9 +679,9 @@ pub const ObjcStubsSection = struct { |
| 679 | { | 679 | { |
| 680 | const target = sym.getObjcSelrefsAddress(macho_file); | 680 | const target = sym.getObjcSelrefsAddress(macho_file); |
| 681 | const source = addr; | 681 | const source = addr; |
| 682 | const pages = try Relocation.calcNumberOfPages(source, target); | 682 | const pages = try aarch64.calcNumberOfPages(source, target); |
| 683 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little); | 683 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little); |
| 684 | const off = try Relocation.calcPageOffset(target, .load_store_64); | 684 | const off = try aarch64.calcPageOffset(.load_store_64, target); |
| 685 | try writer.writeInt( | 685 | try writer.writeInt( |
| 686 | u32, | 686 | u32, |
| 687 | aarch64.Instruction.ldr(.x1, .x1, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(), | 687 | aarch64.Instruction.ldr(.x1, .x1, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(), |
| ... | @@ -692,9 +692,9 @@ pub const ObjcStubsSection = struct { | ... | @@ -692,9 +692,9 @@ pub const ObjcStubsSection = struct { |
| 692 | const target_sym = macho_file.getSymbol(macho_file.objc_msg_send_index.?); | 692 | const target_sym = macho_file.getSymbol(macho_file.objc_msg_send_index.?); |
| 693 | const target = target_sym.getGotAddress(macho_file); | 693 | const target = target_sym.getGotAddress(macho_file); |
| 694 | const source = addr + 2 * @sizeOf(u32); | 694 | const source = addr + 2 * @sizeOf(u32); |
| 695 | const pages = try Relocation.calcNumberOfPages(source, target); | 695 | const pages = try aarch64.calcNumberOfPages(source, target); |
| 696 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); | 696 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); |
| 697 | const off = try Relocation.calcPageOffset(target, .load_store_64); | 697 | const off = try aarch64.calcPageOffset(.load_store_64, target); |
| 698 | try writer.writeInt( | 698 | try writer.writeInt( |
| 699 | u32, | 699 | u32, |
| 700 | aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(), | 700 | aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(), |
| ... | @@ -778,7 +778,7 @@ pub const WeakBindSection = bind.WeakBind; | ... | @@ -778,7 +778,7 @@ pub const WeakBindSection = bind.WeakBind; |
| 778 | pub const LazyBindSection = bind.LazyBind; | 778 | pub const LazyBindSection = bind.LazyBind; |
| 779 | pub const ExportTrieSection = Trie; | 779 | pub const ExportTrieSection = Trie; |
| 780 | 780 | ||
| 781 | const aarch64 = @import("../../arch/aarch64/bits.zig"); | 781 | const aarch64 = @import("../aarch64.zig"); |
| 782 | const assert = std.debug.assert; | 782 | const assert = std.debug.assert; |
| 783 | const bind = @import("dyld_info/bind.zig"); | 783 | const bind = @import("dyld_info/bind.zig"); |
| 784 | const math = std.math; | 784 | const math = std.math; |
| ... | @@ -788,6 +788,5 @@ const trace = @import("../../tracy.zig").trace; | ... | @@ -788,6 +788,5 @@ const trace = @import("../../tracy.zig").trace; |
| 788 | const Allocator = std.mem.Allocator; | 788 | const Allocator = std.mem.Allocator; |
| 789 | const MachO = @import("../MachO.zig"); | 789 | const MachO = @import("../MachO.zig"); |
| 790 | const Rebase = @import("dyld_info/Rebase.zig"); | 790 | const Rebase = @import("dyld_info/Rebase.zig"); |
| 791 | const Relocation = @import("Relocation.zig"); | ||
| 792 | const Symbol = @import("Symbol.zig"); | 791 | const Symbol = @import("Symbol.zig"); |
| 793 | const Trie = @import("dyld_info/Trie.zig"); | 792 | const Trie = @import("dyld_info/Trie.zig"); |
src/link/MachO/thunks.zig+3-3| ... | @@ -99,9 +99,9 @@ pub const Thunk = struct { | ... | @@ -99,9 +99,9 @@ pub const Thunk = struct { |
| 99 | const sym = macho_file.getSymbol(sym_index); | 99 | const sym = macho_file.getSymbol(sym_index); |
| 100 | const saddr = thunk.getAddress(macho_file) + i * trampoline_size; | 100 | const saddr = thunk.getAddress(macho_file) + i * trampoline_size; |
| 101 | const taddr = sym.getAddress(.{}, macho_file); | 101 | const taddr = sym.getAddress(.{}, macho_file); |
| 102 | const pages = try Relocation.calcNumberOfPages(saddr, taddr); | 102 | const pages = try aarch64.calcNumberOfPages(saddr, taddr); |
| 103 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); | 103 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); |
| 104 | const off = try Relocation.calcPageOffset(taddr, .arithmetic); | 104 | const off = try aarch64.calcPageOffset(.arithmetic, taddr); |
| 105 | try writer.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little); | 105 | try writer.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little); |
| 106 | try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little); | 106 | try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little); |
| 107 | } | 107 | } |
| ... | @@ -164,7 +164,7 @@ const max_distance = (1 << (jump_bits - 1)); | ... | @@ -164,7 +164,7 @@ const max_distance = (1 << (jump_bits - 1)); |
| 164 | /// and assume margin to be 5MiB. | 164 | /// and assume margin to be 5MiB. |
| 165 | const max_allowed_distance = max_distance - 0x500_000; | 165 | const max_allowed_distance = max_distance - 0x500_000; |
| 166 | 166 | ||
| 167 | const aarch64 = @import("../../arch/aarch64/bits.zig"); | 167 | const aarch64 = @import("../aarch64.zig"); |
| 168 | const assert = std.debug.assert; | 168 | const assert = std.debug.assert; |
| 169 | const log = std.log.scoped(.link); | 169 | const log = std.log.scoped(.link); |
| 170 | const macho = std.macho; | 170 | const macho = std.macho; |