authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2025-11-29 19:16:11-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-01 19:17:52-08:00
log85053a6a36ac1d76ab226943ddecb849e21ef4c6
treefdb14a83e3de7083d5342ca7ddd5b9d7a6abe0e7
parentc4f5dda135616207c24a6009e221724f5a6fa6aa

link.Elf: implement aarch64 relocation


2 files changed, 13 insertions(+), 32 deletions(-)

src/link/Elf/Atom.zig+7-32
......@@ -1499,22 +1499,18 @@ const aarch64 = struct {
14991499 .ABS64 => {
15001500 try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);
15011501 },
1502
15031502 .ADR_PREL_PG_HI21 => {
15041503 try atom.scanReloc(symbol, rel, pcRelocAction(symbol, elf_file), elf_file);
15051504 },
1506
15071505 .ADR_GOT_PAGE => {
15081506 // TODO: relax if possible
15091507 symbol.flags.needs_got = true;
15101508 },
1511
15121509 .LD64_GOT_LO12_NC,
15131510 .LD64_GOTPAGE_LO15,
15141511 => {
15151512 symbol.flags.needs_got = true;
15161513 },
1517
15181514 .CALL26,
15191515 .JUMP26,
15201516 => {
......@@ -1522,25 +1518,21 @@ const aarch64 = struct {
15221518 symbol.flags.needs_plt = true;
15231519 }
15241520 },
1525
15261521 .TLSLE_ADD_TPREL_HI12,
15271522 .TLSLE_ADD_TPREL_LO12_NC,
15281523 => {
15291524 if (is_dyn_lib) try atom.reportPicError(symbol, rel, elf_file);
15301525 },
1531
15321526 .TLSIE_ADR_GOTTPREL_PAGE21,
15331527 .TLSIE_LD64_GOTTPREL_LO12_NC,
15341528 => {
15351529 symbol.flags.needs_gottp = true;
15361530 },
1537
15381531 .TLSGD_ADR_PAGE21,
15391532 .TLSGD_ADD_LO12_NC,
15401533 => {
15411534 symbol.flags.needs_tlsgd = true;
15421535 },
1543
15441536 .TLSDESC_ADR_PAGE21,
15451537 .TLSDESC_LD64_LO12,
15461538 .TLSDESC_ADD_LO12,
......@@ -1551,18 +1543,17 @@ const aarch64 = struct {
15511543 symbol.flags.needs_tlsdesc = true;
15521544 }
15531545 },
1554
15551546 .ADD_ABS_LO12_NC,
15561547 .ADR_PREL_LO21,
1557 .LDST8_ABS_LO12_NC,
1548 .CONDBR19,
1549 .LDST128_ABS_LO12_NC,
15581550 .LDST16_ABS_LO12_NC,
15591551 .LDST32_ABS_LO12_NC,
15601552 .LDST64_ABS_LO12_NC,
1561 .LDST128_ABS_LO12_NC,
1553 .LDST8_ABS_LO12_NC,
15621554 .PREL32,
15631555 .PREL64,
15641556 => {},
1565
15661557 else => try atom.reportUnhandledRelocError(rel, elf_file),
15671558 }
15681559 }
......@@ -1599,7 +1590,6 @@ const aarch64 = struct {
15991590 r_offset,
16001591 );
16011592 },
1602
16031593 .CALL26,
16041594 .JUMP26,
16051595 => {
......@@ -1611,27 +1601,26 @@ const aarch64 = struct {
16111601 };
16121602 util.writeBranchImm(disp, code);
16131603 },
1614
1604 .CONDBR19 => {
1605 const value = math.cast(i19, S + A - P) orelse return error.Overflow;
1606 util.writeCondBrImm(value, code);
1607 },
16151608 .PREL32 => {
16161609 const value = math.cast(i32, S + A - P) orelse return error.Overflow;
16171610 mem.writeInt(u32, code, @bitCast(value), .little);
16181611 },
1619
16201612 .PREL64 => {
16211613 const value = S + A - P;
16221614 mem.writeInt(u64, code_buffer[r_offset..][0..8], @bitCast(value), .little);
16231615 },
1624
16251616 .ADR_PREL_LO21 => {
16261617 const value = math.cast(i21, S + A - P) orelse return error.Overflow;
16271618 util.writeAdrInst(value, code);
16281619 },
1629
16301620 .ADR_PREL_PG_HI21 => {
16311621 // TODO: check for relaxation of ADRP+ADD
16321622 util.writeAdrInst(try util.calcNumberOfPages(P, S + A), code);
16331623 },
1634
16351624 .ADR_GOT_PAGE => if (target.flags.has_got) {
16361625 util.writeAdrInst(try util.calcNumberOfPages(P, G + GOT + A), code);
16371626 } else {
......@@ -1644,18 +1633,15 @@ const aarch64 = struct {
16441633 r_offset,
16451634 });
16461635 },
1647
16481636 .LD64_GOT_LO12_NC => {
16491637 assert(target.flags.has_got);
16501638 const taddr = @as(u64, @intCast(G + GOT + A));
16511639 util.writeLoadStoreRegInst(@divExact(@as(u12, @truncate(taddr)), 8), code);
16521640 },
1653
16541641 .ADD_ABS_LO12_NC => {
16551642 const taddr = @as(u64, @intCast(S + A));
16561643 util.writeAddImmInst(@truncate(taddr), code);
16571644 },
1658
16591645 .LDST8_ABS_LO12_NC,
16601646 .LDST16_ABS_LO12_NC,
16611647 .LDST32_ABS_LO12_NC,
......@@ -1674,44 +1660,37 @@ const aarch64 = struct {
16741660 };
16751661 util.writeLoadStoreRegInst(off, code);
16761662 },
1677
16781663 .TLSLE_ADD_TPREL_HI12 => {
16791664 const value = math.cast(i12, (S + A - TP) >> 12) orelse
16801665 return error.Overflow;
16811666 util.writeAddImmInst(@bitCast(value), code);
16821667 },
1683
16841668 .TLSLE_ADD_TPREL_LO12_NC => {
16851669 const value: i12 = @truncate(S + A - TP);
16861670 util.writeAddImmInst(@bitCast(value), code);
16871671 },
1688
16891672 .TLSIE_ADR_GOTTPREL_PAGE21 => {
16901673 const S_ = target.gotTpAddress(elf_file);
16911674 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
16921675 util.writeAdrInst(try util.calcNumberOfPages(P, S_ + A), code);
16931676 },
1694
16951677 .TLSIE_LD64_GOTTPREL_LO12_NC => {
16961678 const S_ = target.gotTpAddress(elf_file);
16971679 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
16981680 const off: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8);
16991681 util.writeLoadStoreRegInst(off, code);
17001682 },
1701
17021683 .TLSGD_ADR_PAGE21 => {
17031684 const S_ = target.tlsGdAddress(elf_file);
17041685 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
17051686 util.writeAdrInst(try util.calcNumberOfPages(P, S_ + A), code);
17061687 },
1707
17081688 .TLSGD_ADD_LO12_NC => {
17091689 const S_ = target.tlsGdAddress(elf_file);
17101690 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
17111691 const off: u12 = @truncate(@as(u64, @bitCast(S_ + A)));
17121692 util.writeAddImmInst(off, code);
17131693 },
1714
17151694 .TLSDESC_ADR_PAGE21 => {
17161695 if (target.flags.has_tlsdesc) {
17171696 const S_ = target.tlsDescAddress(elf_file);
......@@ -1722,7 +1701,6 @@ const aarch64 = struct {
17221701 util.encoding.Instruction.nop().write(code);
17231702 }
17241703 },
1725
17261704 .TLSDESC_LD64_LO12 => {
17271705 if (target.flags.has_tlsdesc) {
17281706 const S_ = target.tlsDescAddress(elf_file);
......@@ -1734,7 +1712,6 @@ const aarch64 = struct {
17341712 util.encoding.Instruction.nop().write(code);
17351713 }
17361714 },
1737
17381715 .TLSDESC_ADD_LO12 => {
17391716 if (target.flags.has_tlsdesc) {
17401717 const S_ = target.tlsDescAddress(elf_file);
......@@ -1747,13 +1724,11 @@ const aarch64 = struct {
17471724 util.encoding.Instruction.movz(.x0, value, .{ .lsl = .@"16" }).write(code);
17481725 }
17491726 },
1750
17511727 .TLSDESC_CALL => if (!target.flags.has_tlsdesc) {
17521728 relocs_log.debug(" relaxing br => movk(x0, {x})", .{S + A - TP});
17531729 const value: u16 = @bitCast(@as(i16, @truncate(S + A - TP)));
17541730 util.encoding.Instruction.movk(.x0, value, .{}).write(code);
17551731 },
1756
17571732 else => try atom.reportUnhandledRelocError(rel, elf_file),
17581733 }
17591734 }
src/link/aarch64.zig+6
......@@ -29,6 +29,12 @@ pub fn writeBranchImm(disp: i28, code: *[4]u8) void {
2929 inst.write(code);
3030}
3131
32pub fn writeCondBrImm(disp: i19, code: *[4]u8) void {
33 var inst: encoding.Instruction = .read(code);
34 inst.branch_exception_generating_system.conditional_branch_immediate.group.imm19 = @intCast(@shrExact(disp, 2));
35 inst.write(code);
36}
37
3238const assert = std.debug.assert;
3339const builtin = @import("builtin");
3440const math = std.math;