| ... | ... | @@ -1633,7 +1633,7 @@ const aarch64 = struct { |
| 1633 | 1633 | .TLSDESC_ADD_LO12, |
| 1634 | 1634 | => { |
| 1635 | 1635 | const should_relax = elf_file.base.isStatic() or (!is_dyn_lib and !symbol.flags.import); |
| 1636 | | if (!should_relax and true) { // TODO |
| 1636 | if (!should_relax) { |
| 1637 | 1637 | symbol.flags.needs_tlsdesc = true; |
| 1638 | 1638 | } |
| 1639 | 1639 | }, |
| ... | ... | @@ -1659,7 +1659,7 @@ const aarch64 = struct { |
| 1659 | 1659 | target: *const Symbol, |
| 1660 | 1660 | args: ResolveArgs, |
| 1661 | 1661 | it: *RelocsIterator, |
| 1662 | | code: []u8, |
| 1662 | code_buffer: []u8, |
| 1663 | 1663 | stream: anytype, |
| 1664 | 1664 | ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void { |
| 1665 | 1665 | _ = it; |
| ... | ... | @@ -1667,6 +1667,7 @@ const aarch64 = struct { |
| 1667 | 1667 | const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type()); |
| 1668 | 1668 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; |
| 1669 | 1669 | const cwriter = stream.writer(); |
| 1670 | const code = code_buffer[rel.r_offset..][0..4]; |
| 1670 | 1671 | |
| 1671 | 1672 | const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args; |
| 1672 | 1673 | _ = DTP; |
| ... | ... | @@ -1700,7 +1701,7 @@ const aarch64 = struct { |
| 1700 | 1701 | }); |
| 1701 | 1702 | return; |
| 1702 | 1703 | }; |
| 1703 | | aarch64_util.writeBranchImm(disp, code[r_offset..][0..4]); |
| 1704 | aarch64_util.writeBranchImm(disp, code); |
| 1704 | 1705 | }, |
| 1705 | 1706 | |
| 1706 | 1707 | .ADR_PREL_PG_HI21 => { |
| ... | ... | @@ -1708,14 +1709,14 @@ const aarch64 = struct { |
| 1708 | 1709 | const saddr = @as(u64, @intCast(P)); |
| 1709 | 1710 | const taddr = @as(u64, @intCast(S + A)); |
| 1710 | 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 | }, |
| 1713 | 1714 | |
| 1714 | 1715 | .ADR_GOT_PAGE => if (target.flags.has_got) { |
| 1715 | 1716 | const saddr = @as(u64, @intCast(P)); |
| 1716 | 1717 | const taddr = @as(u64, @intCast(G + GOT + A)); |
| 1717 | 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 | 1720 | } else { |
| 1720 | 1721 | // TODO: relax |
| 1721 | 1722 | var err = try elf_file.addErrorWithNotes(1); |
| ... | ... | @@ -1730,12 +1731,12 @@ const aarch64 = struct { |
| 1730 | 1731 | .LD64_GOT_LO12_NC => { |
| 1731 | 1732 | assert(target.flags.has_got); |
| 1732 | 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 | }, |
| 1735 | 1736 | |
| 1736 | 1737 | .ADD_ABS_LO12_NC => { |
| 1737 | 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 | }, |
| 1740 | 1741 | |
| 1741 | 1742 | .LDST8_ABS_LO12_NC, |
| ... | ... | @@ -1754,48 +1755,79 @@ const aarch64 = struct { |
| 1754 | 1755 | .LDST128_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 16), |
| 1755 | 1756 | else => unreachable, |
| 1756 | 1757 | }; |
| 1757 | | aarch64_util.writeLoadStoreRegInst(offset, code[rel.r_offset..][0..4]); |
| 1758 | aarch64_util.writeLoadStoreRegInst(offset, code); |
| 1758 | 1759 | }, |
| 1759 | 1760 | |
| 1760 | 1761 | .TLSLE_ADD_TPREL_HI12 => { |
| 1761 | 1762 | const value = math.cast(i12, (S + A - TP) >> 12) orelse |
| 1762 | 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 | }, |
| 1765 | 1766 | |
| 1766 | 1767 | .TLSLE_ADD_TPREL_LO12_NC => { |
| 1767 | 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 | }, |
| 1770 | 1771 | |
| 1771 | 1772 | .TLSDESC_ADR_PAGE21 => { |
| 1772 | | assert(target.flags.has_tlsdesc); // TODO relax |
| 1773 | | const S_: i64 = @intCast(target.tlsDescAddress(elf_file)); |
| 1774 | | const saddr: u64 = @intCast(P); |
| 1775 | | const taddr: u64 = @intCast(S_ + A); |
| 1776 | | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); |
| 1777 | | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)); |
| 1778 | | aarch64_util.writeAdrpInst(pages, code[rel.r_offset..][0..4]); |
| 1773 | if (target.flags.has_tlsdesc) { |
| 1774 | const S_: i64 = @intCast(target.tlsDescAddress(elf_file)); |
| 1775 | const saddr: u64 = @intCast(P); |
| 1776 | const taddr: u64 = @intCast(S_ + A); |
| 1777 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); |
| 1778 | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)); |
| 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 | }, |
| 1780 | 1785 | |
| 1781 | 1786 | .TLSDESC_LD64_LO12 => { |
| 1782 | | const S_: i64 = @intCast(target.tlsDescAddress(elf_file)); |
| 1783 | | const taddr: u64 = @intCast(S_ + A); |
| 1784 | | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); |
| 1785 | | const offset: u12 = try math.divExact(u12, @truncate(taddr), 8); |
| 1786 | | aarch64_util.writeLoadStoreRegInst(offset, code[rel.r_offset..][0..4]); |
| 1787 | if (target.flags.has_tlsdesc) { |
| 1788 | const S_: i64 = @intCast(target.tlsDescAddress(elf_file)); |
| 1789 | const taddr: u64 = @intCast(S_ + A); |
| 1790 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); |
| 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 | }, |
| 1788 | 1798 | |
| 1789 | 1799 | .TLSDESC_ADD_LO12 => { |
| 1790 | | const S_: i64 = @intCast(target.tlsDescAddress(elf_file)); |
| 1791 | | const taddr: u64 = @intCast(S_ + A); |
| 1792 | | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); |
| 1793 | | const offset: u12 = @truncate(taddr); |
| 1794 | | aarch64_util.writeAddImmInst(offset, code[rel.r_offset..][0..4]); |
| 1800 | if (target.flags.has_tlsdesc) { |
| 1801 | const S_: i64 = @intCast(target.tlsDescAddress(elf_file)); |
| 1802 | const taddr: u64 = @intCast(S_ + A); |
| 1803 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); |
| 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 | }, |
| 1796 | 1819 | |
| 1797 | 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 | }, |
| 1800 | 1832 | |
| 1801 | 1833 | else => try atom.reportUnhandledRelocError(rel, elf_file), |
| ... | ... | @@ -1830,6 +1862,8 @@ const aarch64 = struct { |
| 1830 | 1862 | } |
| 1831 | 1863 | |
| 1832 | 1864 | const aarch64_util = @import("../aarch64.zig"); |
| 1865 | const Instruction = aarch64_util.Instruction; |
| 1866 | const Register = aarch64_util.Register; |
| 1833 | 1867 | }; |
| 1834 | 1868 | |
| 1835 | 1869 | const riscv = struct { |