diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-02-21 22:00:28 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-02-21 22:00:28 +0100 |
| commit | ee364d542a91293fc048ea47dd8530f824916e5a (patch) | |
| tree | bcfb7fa83567e36ea4aafc42ab4f37e61c744422 /src | |
| parent | 60a8f9b989d64bb6dfbb9e85cd0dd4e1b41750e1 (diff) | |
| download | zig-ee364d542a91293fc048ea47dd8530f824916e5a.tar.gz zig-ee364d542a91293fc048ea47dd8530f824916e5a.zip | |
link: introduce common set of aarch64 abstractions
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/MachO/Atom.zig | 70 | ||||
| -rw-r--r-- | src/link/MachO/Relocation.zig | 32 | ||||
| -rw-r--r-- | src/link/MachO/synthetic.zig | 23 | ||||
| -rw-r--r-- | src/link/MachO/thunks.zig | 6 |
4 files changed, 24 insertions, 107 deletions
diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index 98e0b0c4b6..2c3f360ec2 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -699,14 +699,7 @@ fn resolveRelocInner( const S_: i64 = @intCast(thunk.getTargetAddress(rel.target, macho_file)); break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow; }; - var inst = aarch64.Instruction{ - .unconditional_branch_immediate = mem.bytesToValue(std.meta.TagPayload( - aarch64.Instruction, - aarch64.Instruction.unconditional_branch_immediate, - ), code[rel_offset..][0..4]), - }; - inst.unconditional_branch_immediate.imm26 = @as(u26, @truncate(@as(u28, @bitCast(disp >> 2)))); - try writer.writeInt(u32, inst.toU32(), .little); + try aarch64.writeBranchImm(disp, code[rel_offset..][0..4]); }, else => unreachable, } @@ -776,16 +769,8 @@ fn resolveRelocInner( }; break :target math.cast(u64, target) orelse return error.Overflow; }; - const pages = @as(u21, @bitCast(try Relocation.calcNumberOfPages(source, target))); - var inst = aarch64.Instruction{ - .pc_relative_address = mem.bytesToValue(std.meta.TagPayload( - aarch64.Instruction, - aarch64.Instruction.pc_relative_address, - ), code[rel_offset..][0..4]), - }; - inst.pc_relative_address.immhi = @as(u19, @truncate(pages >> 2)); - inst.pc_relative_address.immlo = @as(u2, @truncate(pages)); - try writer.writeInt(u32, inst.toU32(), .little); + const pages = @as(u21, @bitCast(try aarch64.calcNumberOfPages(source, target))); + try aarch64.writePages(pages, code[rel_offset..][0..4]); }, .pageoff => { @@ -794,35 +779,8 @@ fn resolveRelocInner( assert(!rel.meta.pcrel); const target = math.cast(u64, S + A) orelse return error.Overflow; const inst_code = code[rel_offset..][0..4]; - if (Relocation.isArithmeticOp(inst_code)) { - const off = try Relocation.calcPageOffset(target, .arithmetic); - var inst = aarch64.Instruction{ - .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload( - aarch64.Instruction, - aarch64.Instruction.add_subtract_immediate, - ), inst_code), - }; - inst.add_subtract_immediate.imm12 = off; - try writer.writeInt(u32, inst.toU32(), .little); - } else { - var inst = aarch64.Instruction{ - .load_store_register = mem.bytesToValue(std.meta.TagPayload( - aarch64.Instruction, - aarch64.Instruction.load_store_register, - ), inst_code), - }; - const off = try Relocation.calcPageOffset(target, switch (inst.load_store_register.size) { - 0 => if (inst.load_store_register.v == 1) - Relocation.PageOffsetInstKind.load_store_128 - else - Relocation.PageOffsetInstKind.load_store_8, - 1 => .load_store_16, - 2 => .load_store_32, - 3 => .load_store_64, - }); - inst.load_store_register.offset = off; - try writer.writeInt(u32, inst.toU32(), .little); - } + const kind = aarch64.classifyInst(inst_code); + try aarch64.writePageOffset(kind, target, inst_code); }, .got_load_pageoff => { @@ -830,15 +788,7 @@ fn resolveRelocInner( assert(rel.meta.length == 2); assert(!rel.meta.pcrel); const target = math.cast(u64, G + A) orelse return error.Overflow; - const off = try Relocation.calcPageOffset(target, .load_store_64); - var inst: aarch64.Instruction = .{ - .load_store_register = mem.bytesToValue(std.meta.TagPayload( - aarch64.Instruction, - aarch64.Instruction.load_store_register, - ), code[rel_offset..][0..4]), - }; - inst.load_store_register.offset = off; - try writer.writeInt(u32, inst.toU32(), .little); + try aarch64.writePageOffset(.load_store_64, target, code[rel_offset..][0..4]); }, .tlvp_pageoff => { @@ -863,7 +813,7 @@ fn resolveRelocInner( const inst_code = code[rel_offset..][0..4]; const reg_info: RegInfo = blk: { - if (Relocation.isArithmeticOp(inst_code)) { + if (aarch64.isArithmeticOp(inst_code)) { const inst = mem.bytesToValue(std.meta.TagPayload( aarch64.Instruction, aarch64.Instruction.add_subtract_immediate, @@ -890,7 +840,7 @@ fn resolveRelocInner( .load_store_register = .{ .rt = reg_info.rd, .rn = reg_info.rn, - .offset = try Relocation.calcPageOffset(target, .load_store_64), + .offset = try aarch64.calcPageOffset(.load_store_64, target), .opc = 0b01, .op1 = 0b01, .v = 0, @@ -900,7 +850,7 @@ fn resolveRelocInner( .add_subtract_immediate = .{ .rd = reg_info.rd, .rn = reg_info.rn, - .imm12 = try Relocation.calcPageOffset(target, .arithmetic), + .imm12 = try aarch64.calcPageOffset(.arithmetic, target), .sh = 0, .s = 0, .op = 0, @@ -1183,7 +1133,7 @@ pub const Loc = struct { pub const Alignment = @import("../../InternPool.zig").Alignment; -const aarch64 = @import("../../arch/aarch64/bits.zig"); +const aarch64 = @import("../aarch64.zig"); const assert = std.debug.assert; const bind = @import("dyld_info/bind.zig"); const macho = std.macho; diff --git a/src/link/MachO/Relocation.zig b/src/link/MachO/Relocation.zig index e350684eac..2df9355de9 100644 --- a/src/link/MachO/Relocation.zig +++ b/src/link/MachO/Relocation.zig @@ -60,38 +60,6 @@ pub fn lessThan(ctx: void, lhs: Relocation, rhs: Relocation) bool { return lhs.offset < rhs.offset; } -pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 { - const spage = math.cast(i32, saddr >> 12) orelse return error.Overflow; - const tpage = math.cast(i32, taddr >> 12) orelse return error.Overflow; - const pages = math.cast(i21, tpage - spage) orelse return error.Overflow; - return pages; -} - -pub const PageOffsetInstKind = enum { - arithmetic, - load_store_8, - load_store_16, - load_store_32, - load_store_64, - load_store_128, -}; - -pub fn calcPageOffset(taddr: u64, kind: PageOffsetInstKind) !u12 { - const narrowed = @as(u12, @truncate(taddr)); - return switch (kind) { - .arithmetic, .load_store_8 => narrowed, - .load_store_16 => try math.divExact(u12, narrowed, 2), - .load_store_32 => try math.divExact(u12, narrowed, 4), - .load_store_64 => try math.divExact(u12, narrowed, 8), - .load_store_128 => try math.divExact(u12, narrowed, 16), - }; -} - -pub inline fn isArithmeticOp(inst: *const [4]u8) bool { - const group_decode = @as(u5, @truncate(inst[3])); - return ((group_decode >> 2) == 4); -} - pub const Type = enum { // x86_64 /// RIP-relative displacement (X86_64_RELOC_SIGNED) diff --git a/src/link/MachO/synthetic.zig b/src/link/MachO/synthetic.zig index 774fbe0d27..0536026633 100644 --- a/src/link/MachO/synthetic.zig +++ b/src/link/MachO/synthetic.zig @@ -267,9 +267,9 @@ pub const StubsSection = struct { }, .aarch64 => { // TODO relax if possible - const pages = try Relocation.calcNumberOfPages(source, target); + const pages = try aarch64.calcNumberOfPages(source, target); try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); - const off = try Relocation.calcPageOffset(target, .load_store_64); + const off = try aarch64.calcPageOffset(.load_store_64, target); try writer.writeInt( u32, aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(), @@ -411,9 +411,9 @@ pub const StubsHelperSection = struct { .aarch64 => { { // TODO relax if possible - const pages = try Relocation.calcNumberOfPages(sect.addr, dyld_private_addr); + const pages = try aarch64.calcNumberOfPages(sect.addr, dyld_private_addr); try writer.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little); - const off = try Relocation.calcPageOffset(dyld_private_addr, .arithmetic); + const off = try aarch64.calcPageOffset(.arithmetic, dyld_private_addr); try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little); } try writer.writeInt(u32, aarch64.Instruction.stp( @@ -424,9 +424,9 @@ pub const StubsHelperSection = struct { ).toU32(), .little); { // TODO relax if possible - const pages = try Relocation.calcNumberOfPages(sect.addr + 12, dyld_stub_binder_addr); + const pages = try aarch64.calcNumberOfPages(sect.addr + 12, dyld_stub_binder_addr); try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); - const off = try Relocation.calcPageOffset(dyld_stub_binder_addr, .load_store_64); + const off = try aarch64.calcPageOffset(.load_store_64, dyld_stub_binder_addr); try writer.writeInt(u32, aarch64.Instruction.ldr( .x16, .x16, @@ -679,9 +679,9 @@ pub const ObjcStubsSection = struct { { const target = sym.getObjcSelrefsAddress(macho_file); const source = addr; - const pages = try Relocation.calcNumberOfPages(source, target); + const pages = try aarch64.calcNumberOfPages(source, target); try writer.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little); - const off = try Relocation.calcPageOffset(target, .load_store_64); + const off = try aarch64.calcPageOffset(.load_store_64, target); try writer.writeInt( u32, aarch64.Instruction.ldr(.x1, .x1, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(), @@ -692,9 +692,9 @@ pub const ObjcStubsSection = struct { const target_sym = macho_file.getSymbol(macho_file.objc_msg_send_index.?); const target = target_sym.getGotAddress(macho_file); const source = addr + 2 * @sizeOf(u32); - const pages = try Relocation.calcNumberOfPages(source, target); + const pages = try aarch64.calcNumberOfPages(source, target); try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); - const off = try Relocation.calcPageOffset(target, .load_store_64); + const off = try aarch64.calcPageOffset(.load_store_64, target); try writer.writeInt( u32, aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(), @@ -778,7 +778,7 @@ pub const WeakBindSection = bind.WeakBind; pub const LazyBindSection = bind.LazyBind; pub const ExportTrieSection = Trie; -const aarch64 = @import("../../arch/aarch64/bits.zig"); +const aarch64 = @import("../aarch64.zig"); const assert = std.debug.assert; const bind = @import("dyld_info/bind.zig"); const math = std.math; @@ -788,6 +788,5 @@ const trace = @import("../../tracy.zig").trace; const Allocator = std.mem.Allocator; const MachO = @import("../MachO.zig"); const Rebase = @import("dyld_info/Rebase.zig"); -const Relocation = @import("Relocation.zig"); const Symbol = @import("Symbol.zig"); const Trie = @import("dyld_info/Trie.zig"); diff --git a/src/link/MachO/thunks.zig b/src/link/MachO/thunks.zig index cd9ea20c86..e3f98c655c 100644 --- a/src/link/MachO/thunks.zig +++ b/src/link/MachO/thunks.zig @@ -99,9 +99,9 @@ pub const Thunk = struct { const sym = macho_file.getSymbol(sym_index); const saddr = thunk.getAddress(macho_file) + i * trampoline_size; const taddr = sym.getAddress(.{}, macho_file); - const pages = try Relocation.calcNumberOfPages(saddr, taddr); + const pages = try aarch64.calcNumberOfPages(saddr, taddr); try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); - const off = try Relocation.calcPageOffset(taddr, .arithmetic); + const off = try aarch64.calcPageOffset(.arithmetic, taddr); try writer.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little); try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little); } @@ -164,7 +164,7 @@ const max_distance = (1 << (jump_bits - 1)); /// and assume margin to be 5MiB. const max_allowed_distance = max_distance - 0x500_000; -const aarch64 = @import("../../arch/aarch64/bits.zig"); +const aarch64 = @import("../aarch64.zig"); const assert = std.debug.assert; const log = std.log.scoped(.link); const macho = std.macho; |
