mirror of
https://github.com/ziglang/zig.git
synced 2026-01-12 02:15:12 +00:00
link: introduce common set of aarch64 abstractions
This commit is contained in:
parent
60a8f9b989
commit
ee364d542a
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user