mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
elf+aarch64: relax TLSDESC for executables
This commit is contained in:
parent
310cef0972
commit
d9069cbe2c
@ -1633,7 +1633,7 @@ const aarch64 = struct {
|
||||
.TLSDESC_ADD_LO12,
|
||||
=> {
|
||||
const should_relax = elf_file.base.isStatic() or (!is_dyn_lib and !symbol.flags.import);
|
||||
if (!should_relax and true) { // TODO
|
||||
if (!should_relax) {
|
||||
symbol.flags.needs_tlsdesc = true;
|
||||
}
|
||||
},
|
||||
@ -1659,7 +1659,7 @@ const aarch64 = struct {
|
||||
target: *const Symbol,
|
||||
args: ResolveArgs,
|
||||
it: *RelocsIterator,
|
||||
code: []u8,
|
||||
code_buffer: []u8,
|
||||
stream: anytype,
|
||||
) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void {
|
||||
_ = it;
|
||||
@ -1667,6 +1667,7 @@ const aarch64 = struct {
|
||||
const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
|
||||
const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
|
||||
const cwriter = stream.writer();
|
||||
const code = code_buffer[rel.r_offset..][0..4];
|
||||
|
||||
const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args;
|
||||
_ = DTP;
|
||||
@ -1700,7 +1701,7 @@ const aarch64 = struct {
|
||||
});
|
||||
return;
|
||||
};
|
||||
aarch64_util.writeBranchImm(disp, code[r_offset..][0..4]);
|
||||
aarch64_util.writeBranchImm(disp, code);
|
||||
},
|
||||
|
||||
.ADR_PREL_PG_HI21 => {
|
||||
@ -1708,14 +1709,14 @@ const aarch64 = struct {
|
||||
const saddr = @as(u64, @intCast(P));
|
||||
const taddr = @as(u64, @intCast(S + A));
|
||||
const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));
|
||||
aarch64_util.writeAdrpInst(pages, code[r_offset..][0..4]);
|
||||
aarch64_util.writeAdrpInst(pages, code);
|
||||
},
|
||||
|
||||
.ADR_GOT_PAGE => if (target.flags.has_got) {
|
||||
const saddr = @as(u64, @intCast(P));
|
||||
const taddr = @as(u64, @intCast(G + GOT + A));
|
||||
const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));
|
||||
aarch64_util.writeAdrpInst(pages, code[r_offset..][0..4]);
|
||||
aarch64_util.writeAdrpInst(pages, code);
|
||||
} else {
|
||||
// TODO: relax
|
||||
var err = try elf_file.addErrorWithNotes(1);
|
||||
@ -1730,12 +1731,12 @@ const aarch64 = struct {
|
||||
.LD64_GOT_LO12_NC => {
|
||||
assert(target.flags.has_got);
|
||||
const taddr = @as(u64, @intCast(G + GOT + A));
|
||||
aarch64_util.writeLoadStoreRegInst(@divExact(@as(u12, @truncate(taddr)), 8), code[rel.r_offset..][0..4]);
|
||||
aarch64_util.writeLoadStoreRegInst(@divExact(@as(u12, @truncate(taddr)), 8), code);
|
||||
},
|
||||
|
||||
.ADD_ABS_LO12_NC => {
|
||||
const taddr = @as(u64, @intCast(S + A));
|
||||
aarch64_util.writeAddImmInst(@truncate(taddr), code[rel.r_offset..][0..4]);
|
||||
aarch64_util.writeAddImmInst(@truncate(taddr), code);
|
||||
},
|
||||
|
||||
.LDST8_ABS_LO12_NC,
|
||||
@ -1754,48 +1755,79 @@ const aarch64 = struct {
|
||||
.LDST128_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 16),
|
||||
else => unreachable,
|
||||
};
|
||||
aarch64_util.writeLoadStoreRegInst(offset, code[rel.r_offset..][0..4]);
|
||||
aarch64_util.writeLoadStoreRegInst(offset, code);
|
||||
},
|
||||
|
||||
.TLSLE_ADD_TPREL_HI12 => {
|
||||
const value = math.cast(i12, (S + A - TP) >> 12) orelse
|
||||
return error.Overflow;
|
||||
aarch64_util.writeAddImmInst(@bitCast(value), code[rel.r_offset..][0..4]);
|
||||
aarch64_util.writeAddImmInst(@bitCast(value), code);
|
||||
},
|
||||
|
||||
.TLSLE_ADD_TPREL_LO12_NC => {
|
||||
const value: i12 = @truncate(S + A - TP);
|
||||
aarch64_util.writeAddImmInst(@bitCast(value), code[rel.r_offset..][0..4]);
|
||||
aarch64_util.writeAddImmInst(@bitCast(value), code);
|
||||
},
|
||||
|
||||
.TLSDESC_ADR_PAGE21 => {
|
||||
assert(target.flags.has_tlsdesc); // TODO relax
|
||||
const S_: i64 = @intCast(target.tlsDescAddress(elf_file));
|
||||
const saddr: u64 = @intCast(P);
|
||||
const taddr: u64 = @intCast(S_ + A);
|
||||
relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
|
||||
const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr));
|
||||
aarch64_util.writeAdrpInst(pages, code[rel.r_offset..][0..4]);
|
||||
if (target.flags.has_tlsdesc) {
|
||||
const S_: i64 = @intCast(target.tlsDescAddress(elf_file));
|
||||
const saddr: u64 = @intCast(P);
|
||||
const taddr: u64 = @intCast(S_ + A);
|
||||
relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
|
||||
const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr));
|
||||
aarch64_util.writeAdrpInst(pages, code);
|
||||
} else {
|
||||
relocs_log.debug(" relaxing adrp => nop", .{});
|
||||
mem.writeInt(u32, code, Instruction.nop().toU32(), .little);
|
||||
}
|
||||
},
|
||||
|
||||
.TLSDESC_LD64_LO12 => {
|
||||
const S_: i64 = @intCast(target.tlsDescAddress(elf_file));
|
||||
const taddr: u64 = @intCast(S_ + A);
|
||||
relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
|
||||
const offset: u12 = try math.divExact(u12, @truncate(taddr), 8);
|
||||
aarch64_util.writeLoadStoreRegInst(offset, code[rel.r_offset..][0..4]);
|
||||
if (target.flags.has_tlsdesc) {
|
||||
const S_: i64 = @intCast(target.tlsDescAddress(elf_file));
|
||||
const taddr: u64 = @intCast(S_ + A);
|
||||
relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
|
||||
const offset: u12 = try math.divExact(u12, @truncate(taddr), 8);
|
||||
aarch64_util.writeLoadStoreRegInst(offset, code);
|
||||
} else {
|
||||
relocs_log.debug(" relaxing ldr => nop", .{});
|
||||
mem.writeInt(u32, code, Instruction.nop().toU32(), .little);
|
||||
}
|
||||
},
|
||||
|
||||
.TLSDESC_ADD_LO12 => {
|
||||
const S_: i64 = @intCast(target.tlsDescAddress(elf_file));
|
||||
const taddr: u64 = @intCast(S_ + A);
|
||||
relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
|
||||
const offset: u12 = @truncate(taddr);
|
||||
aarch64_util.writeAddImmInst(offset, code[rel.r_offset..][0..4]);
|
||||
if (target.flags.has_tlsdesc) {
|
||||
const S_: i64 = @intCast(target.tlsDescAddress(elf_file));
|
||||
const taddr: u64 = @intCast(S_ + A);
|
||||
relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
|
||||
const offset: u12 = @truncate(taddr);
|
||||
aarch64_util.writeAddImmInst(offset, code);
|
||||
} else {
|
||||
const old_inst = Instruction{
|
||||
.add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload(
|
||||
Instruction,
|
||||
Instruction.add_subtract_immediate,
|
||||
), code),
|
||||
};
|
||||
const rd: Register = @enumFromInt(old_inst.add_subtract_immediate.rd);
|
||||
relocs_log.debug(" relaxing add({s}) => movz(x0, {x})", .{ @tagName(rd), S + A - TP });
|
||||
const value: u16 = @bitCast(math.cast(i16, (S + A - TP) >> 16) orelse return error.Overflow);
|
||||
mem.writeInt(u32, code, Instruction.movz(.x0, value, 16).toU32(), .little);
|
||||
}
|
||||
},
|
||||
|
||||
.TLSDESC_CALL => if (!target.flags.has_tlsdesc) {
|
||||
mem.writeInt(u32, code[rel.r_offset..][0..4], aarch64_util.Instruction.nop().toU32(), .little);
|
||||
const old_inst = Instruction{
|
||||
.unconditional_branch_register = mem.bytesToValue(std.meta.TagPayload(
|
||||
Instruction,
|
||||
Instruction.unconditional_branch_register,
|
||||
), code),
|
||||
};
|
||||
const rn: Register = @enumFromInt(old_inst.unconditional_branch_register.rn);
|
||||
relocs_log.debug(" relaxing br({s}) => movk(x0, {x})", .{ @tagName(rn), S + A - TP });
|
||||
const value: u16 = @bitCast(@as(i16, @truncate(S + A - TP)));
|
||||
mem.writeInt(u32, code, Instruction.movk(.x0, value, 0).toU32(), .little);
|
||||
},
|
||||
|
||||
else => try atom.reportUnhandledRelocError(rel, elf_file),
|
||||
@ -1830,6 +1862,8 @@ const aarch64 = struct {
|
||||
}
|
||||
|
||||
const aarch64_util = @import("../aarch64.zig");
|
||||
const Instruction = aarch64_util.Instruction;
|
||||
const Register = aarch64_util.Register;
|
||||
};
|
||||
|
||||
const riscv = struct {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user