authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-03-08 14:30:06+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-03-08 22:46:17+01:00
logd9069cbe2cf88634eb556b3063ede5af4a5cced4
tree9f31a51a05820db7ec5b680c562227f24c4c296d
parent310cef09724067f4df38b42c928cb120fdc09df8

elf+aarch64: relax TLSDESC for executables


1 files changed, 62 insertions(+), 28 deletions(-)

src/link/Elf/Atom.zig+62-28
...@@ -1633,7 +1633,7 @@ const aarch64 = struct {...@@ -1633,7 +1633,7 @@ const aarch64 = struct {
1633 .TLSDESC_ADD_LO12,1633 .TLSDESC_ADD_LO12,
1634 => {1634 => {
1635 const should_relax = elf_file.base.isStatic() or (!is_dyn_lib and !symbol.flags.import);1635 const should_relax = elf_file.base.isStatic() or (!is_dyn_lib and !symbol.flags.import);
1636 if (!should_relax and true) { // TODO1636 if (!should_relax) {
1637 symbol.flags.needs_tlsdesc = true;1637 symbol.flags.needs_tlsdesc = true;
1638 }1638 }
1639 },1639 },
...@@ -1659,7 +1659,7 @@ const aarch64 = struct {...@@ -1659,7 +1659,7 @@ const aarch64 = struct {
1659 target: *const Symbol,1659 target: *const Symbol,
1660 args: ResolveArgs,1660 args: ResolveArgs,
1661 it: *RelocsIterator,1661 it: *RelocsIterator,
1662 code: []u8,1662 code_buffer: []u8,
1663 stream: anytype,1663 stream: anytype,
1664 ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void {1664 ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void {
1665 _ = it;1665 _ = it;
...@@ -1667,6 +1667,7 @@ const aarch64 = struct {...@@ -1667,6 +1667,7 @@ const aarch64 = struct {
1667 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());1667 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
1668 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;1668 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
1669 const cwriter = stream.writer();1669 const cwriter = stream.writer();
1670 const code = code_buffer[rel.r_offset..][0..4];
16701671
1671 const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args;1672 const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args;
1672 _ = DTP;1673 _ = DTP;
...@@ -1700,7 +1701,7 @@ const aarch64 = struct {...@@ -1700,7 +1701,7 @@ const aarch64 = struct {
1700 });1701 });
1701 return;1702 return;
1702 };1703 };
1703 aarch64_util.writeBranchImm(disp, code[r_offset..][0..4]);1704 aarch64_util.writeBranchImm(disp, code);
1704 },1705 },
17051706
1706 .ADR_PREL_PG_HI21 => {1707 .ADR_PREL_PG_HI21 => {
...@@ -1708,14 +1709,14 @@ const aarch64 = struct {...@@ -1708,14 +1709,14 @@ const aarch64 = struct {
1708 const saddr = @as(u64, @intCast(P));1709 const saddr = @as(u64, @intCast(P));
1709 const taddr = @as(u64, @intCast(S + A));1710 const taddr = @as(u64, @intCast(S + A));
1710 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));1711 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));
1711 aarch64_util.writeAdrpInst(pages, code[r_offset..][0..4]);1712 aarch64_util.writeAdrpInst(pages, code);
1712 },1713 },
17131714
1714 .ADR_GOT_PAGE => if (target.flags.has_got) {1715 .ADR_GOT_PAGE => if (target.flags.has_got) {
1715 const saddr = @as(u64, @intCast(P));1716 const saddr = @as(u64, @intCast(P));
1716 const taddr = @as(u64, @intCast(G + GOT + A));1717 const taddr = @as(u64, @intCast(G + GOT + A));
1717 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));1718 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));
1718 aarch64_util.writeAdrpInst(pages, code[r_offset..][0..4]);1719 aarch64_util.writeAdrpInst(pages, code);
1719 } else {1720 } else {
1720 // TODO: relax1721 // TODO: relax
1721 var err = try elf_file.addErrorWithNotes(1);1722 var err = try elf_file.addErrorWithNotes(1);
...@@ -1730,12 +1731,12 @@ const aarch64 = struct {...@@ -1730,12 +1731,12 @@ const aarch64 = struct {
1730 .LD64_GOT_LO12_NC => {1731 .LD64_GOT_LO12_NC => {
1731 assert(target.flags.has_got);1732 assert(target.flags.has_got);
1732 const taddr = @as(u64, @intCast(G + GOT + A));1733 const taddr = @as(u64, @intCast(G + GOT + A));
1733 aarch64_util.writeLoadStoreRegInst(@divExact(@as(u12, @truncate(taddr)), 8), code[rel.r_offset..][0..4]);1734 aarch64_util.writeLoadStoreRegInst(@divExact(@as(u12, @truncate(taddr)), 8), code);
1734 },1735 },
17351736
1736 .ADD_ABS_LO12_NC => {1737 .ADD_ABS_LO12_NC => {
1737 const taddr = @as(u64, @intCast(S + A));1738 const taddr = @as(u64, @intCast(S + A));
1738 aarch64_util.writeAddImmInst(@truncate(taddr), code[rel.r_offset..][0..4]);1739 aarch64_util.writeAddImmInst(@truncate(taddr), code);
1739 },1740 },
17401741
1741 .LDST8_ABS_LO12_NC,1742 .LDST8_ABS_LO12_NC,
...@@ -1754,48 +1755,79 @@ const aarch64 = struct {...@@ -1754,48 +1755,79 @@ const aarch64 = struct {
1754 .LDST128_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 16),1755 .LDST128_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 16),
1755 else => unreachable,1756 else => unreachable,
1756 };1757 };
1757 aarch64_util.writeLoadStoreRegInst(offset, code[rel.r_offset..][0..4]);1758 aarch64_util.writeLoadStoreRegInst(offset, code);
1758 },1759 },
17591760
1760 .TLSLE_ADD_TPREL_HI12 => {1761 .TLSLE_ADD_TPREL_HI12 => {
1761 const value = math.cast(i12, (S + A - TP) >> 12) orelse1762 const value = math.cast(i12, (S + A - TP) >> 12) orelse
1762 return error.Overflow;1763 return error.Overflow;
1763 aarch64_util.writeAddImmInst(@bitCast(value), code[rel.r_offset..][0..4]);1764 aarch64_util.writeAddImmInst(@bitCast(value), code);
1764 },1765 },
17651766
1766 .TLSLE_ADD_TPREL_LO12_NC => {1767 .TLSLE_ADD_TPREL_LO12_NC => {
1767 const value: i12 = @truncate(S + A - TP);1768 const value: i12 = @truncate(S + A - TP);
1768 aarch64_util.writeAddImmInst(@bitCast(value), code[rel.r_offset..][0..4]);1769 aarch64_util.writeAddImmInst(@bitCast(value), code);
1769 },1770 },
17701771
1771 .TLSDESC_ADR_PAGE21 => {1772 .TLSDESC_ADR_PAGE21 => {
1772 assert(target.flags.has_tlsdesc); // TODO relax1773 if (target.flags.has_tlsdesc) {
1773 const S_: i64 = @intCast(target.tlsDescAddress(elf_file));1774 const S_: i64 = @intCast(target.tlsDescAddress(elf_file));
1774 const saddr: u64 = @intCast(P);1775 const saddr: u64 = @intCast(P);
1775 const taddr: u64 = @intCast(S_ + A);1776 const taddr: u64 = @intCast(S_ + A);
1776 relocs_log.debug(" [{x} => {x}]", .{ P, taddr });1777 relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
1777 const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr));1778 const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr));
1778 aarch64_util.writeAdrpInst(pages, code[rel.r_offset..][0..4]);1779 aarch64_util.writeAdrpInst(pages, code);
1780 } else {
1781 relocs_log.debug(" relaxing adrp => nop", .{});
1782 mem.writeInt(u32, code, Instruction.nop().toU32(), .little);
1783 }
1779 },1784 },
17801785
1781 .TLSDESC_LD64_LO12 => {1786 .TLSDESC_LD64_LO12 => {
1782 const S_: i64 = @intCast(target.tlsDescAddress(elf_file));1787 if (target.flags.has_tlsdesc) {
1783 const taddr: u64 = @intCast(S_ + A);1788 const S_: i64 = @intCast(target.tlsDescAddress(elf_file));
1784 relocs_log.debug(" [{x} => {x}]", .{ P, taddr });1789 const taddr: u64 = @intCast(S_ + A);
1785 const offset: u12 = try math.divExact(u12, @truncate(taddr), 8);1790 relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
1786 aarch64_util.writeLoadStoreRegInst(offset, code[rel.r_offset..][0..4]);1791 const offset: u12 = try math.divExact(u12, @truncate(taddr), 8);
1792 aarch64_util.writeLoadStoreRegInst(offset, code);
1793 } else {
1794 relocs_log.debug(" relaxing ldr => nop", .{});
1795 mem.writeInt(u32, code, Instruction.nop().toU32(), .little);
1796 }
1787 },1797 },
17881798
1789 .TLSDESC_ADD_LO12 => {1799 .TLSDESC_ADD_LO12 => {
1790 const S_: i64 = @intCast(target.tlsDescAddress(elf_file));1800 if (target.flags.has_tlsdesc) {
1791 const taddr: u64 = @intCast(S_ + A);1801 const S_: i64 = @intCast(target.tlsDescAddress(elf_file));
1792 relocs_log.debug(" [{x} => {x}]", .{ P, taddr });1802 const taddr: u64 = @intCast(S_ + A);
1793 const offset: u12 = @truncate(taddr);1803 relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
1794 aarch64_util.writeAddImmInst(offset, code[rel.r_offset..][0..4]);1804 const offset: u12 = @truncate(taddr);
1805 aarch64_util.writeAddImmInst(offset, code);
1806 } else {
1807 const old_inst = Instruction{
1808 .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload(
1809 Instruction,
1810 Instruction.add_subtract_immediate,
1811 ), code),
1812 };
1813 const rd: Register = @enumFromInt(old_inst.add_subtract_immediate.rd);
1814 relocs_log.debug(" relaxing add({s}) => movz(x0, {x})", .{ @tagName(rd), S + A - TP });
1815 const value: u16 = @bitCast(math.cast(i16, (S + A - TP) >> 16) orelse return error.Overflow);
1816 mem.writeInt(u32, code, Instruction.movz(.x0, value, 16).toU32(), .little);
1817 }
1795 },1818 },
17961819
1797 .TLSDESC_CALL => if (!target.flags.has_tlsdesc) {1820 .TLSDESC_CALL => if (!target.flags.has_tlsdesc) {
1798 mem.writeInt(u32, code[rel.r_offset..][0..4], aarch64_util.Instruction.nop().toU32(), .little);1821 const old_inst = Instruction{
1822 .unconditional_branch_register = mem.bytesToValue(std.meta.TagPayload(
1823 Instruction,
1824 Instruction.unconditional_branch_register,
1825 ), code),
1826 };
1827 const rn: Register = @enumFromInt(old_inst.unconditional_branch_register.rn);
1828 relocs_log.debug(" relaxing br({s}) => movk(x0, {x})", .{ @tagName(rn), S + A - TP });
1829 const value: u16 = @bitCast(@as(i16, @truncate(S + A - TP)));
1830 mem.writeInt(u32, code, Instruction.movk(.x0, value, 0).toU32(), .little);
1799 },1831 },
18001832
1801 else => try atom.reportUnhandledRelocError(rel, elf_file),1833 else => try atom.reportUnhandledRelocError(rel, elf_file),
...@@ -1830,6 +1862,8 @@ const aarch64 = struct {...@@ -1830,6 +1862,8 @@ const aarch64 = struct {
1830 }1862 }
18311863
1832 const aarch64_util = @import("../aarch64.zig");1864 const aarch64_util = @import("../aarch64.zig");
1865 const Instruction = aarch64_util.Instruction;
1866 const Register = aarch64_util.Register;
1833};1867};
18341868
1835const riscv = struct {1869const riscv = struct {