| ... | @@ -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) { // TODO | 1636 | 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]; |
| 1670 | | 1671 | |
| 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 | }, |
| 1705 | | 1706 | |
| 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 | }, |
| 1713 | | 1714 | |
| 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: relax | 1721 | // 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 | }, |
| 1735 | | 1736 | |
| 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 | }, |
| 1740 | | 1741 | |
| 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 | }, |
| 1759 | | 1760 | |
| 1760 | .TLSLE_ADD_TPREL_HI12 => { | 1761 | .TLSLE_ADD_TPREL_HI12 => { |
| 1761 | const value = math.cast(i12, (S + A - TP) >> 12) orelse | 1762 | 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 | }, |
| 1765 | | 1766 | |
| 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 | }, |
| 1770 | | 1771 | |
| 1771 | .TLSDESC_ADR_PAGE21 => { | 1772 | .TLSDESC_ADR_PAGE21 => { |
| 1772 | assert(target.flags.has_tlsdesc); // TODO relax | 1773 | 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 | }, |
| 1780 | | 1785 | |
| 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 | }, |
| 1788 | | 1798 | |
| 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 | }, |
| 1796 | | 1819 | |
| 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 | }, |
| 1800 | | 1832 | |
| 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 | } |
| 1831 | | 1863 | |
| 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 | }; |
| 1834 | | 1868 | |
| 1835 | const riscv = struct { | 1869 | const riscv = struct { |