@@ -150,6 +150,12 @@ class AArch64AsmPrinter : public AsmPrinter {
150
150
// Emit the sequence for BRA/BLRA (authenticate + branch/call).
151
151
void emitPtrauthBranch (const MachineInstr *MI);
152
152
153
+ void emitPtrauthCheckAuthenticatedValue (Register TestedReg,
154
+ Register ScratchReg,
155
+ AArch64PACKey::ID Key,
156
+ bool ShouldTrap,
157
+ const MCSymbol *OnFailure);
158
+
153
159
// Emit the sequence for AUT or AUTPAC.
154
160
void emitPtrauthAuthResign (const MachineInstr *MI);
155
161
@@ -1719,45 +1725,37 @@ unsigned AArch64AsmPrinter::emitPtrauthDiscriminator(uint16_t Disc,
1719
1725
return AArch64::X17;
1720
1726
}
1721
1727
1722
- void AArch64AsmPrinter::emitPtrauthAuthResign (const MachineInstr *MI) {
1723
- const bool IsAUTPAC = MI->getOpcode () == AArch64::AUTPAC;
1724
-
1725
- // We can expand AUT/AUTPAC into 3 possible sequences:
1726
- // - unchecked:
1727
- // autia x16, x0
1728
- // pacib x16, x1 ; if AUTPAC
1728
+ // / Emits a code sequence to check an authenticated pointer value.
1729
+ // /
1730
+ // / If OnFailure argument is passed, jump there on check failure instead
1731
+ // / of proceeding to the next instruction (only if ShouldTrap is false).
1732
+ void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue (
1733
+ Register TestedReg, Register ScratchReg, AArch64PACKey::ID Key,
1734
+ bool ShouldTrap, const MCSymbol *OnFailure) {
1735
+ // Insert a sequence to check if authentication of TestedReg succeeded,
1736
+ // such as:
1729
1737
//
1730
1738
// - checked and clearing:
1731
- // mov x17, x0
1732
- // movk x17, #disc, lsl #48
1733
- // autia x16, x17
1739
+ // ; x16 is TestedReg, x17 is ScratchReg
1734
1740
// mov x17, x16
1735
1741
// xpaci x17
1736
1742
// cmp x16, x17
1737
1743
// b.eq Lsuccess
1738
1744
// mov x16, x17
1739
1745
// b Lend
1740
- // Lsuccess:
1741
- // mov x17, x1
1742
- // movk x17, #disc, lsl #48
1743
- // pacib x16, x17
1744
- // Lend:
1745
- // Where we only emit the AUT if we started with an AUT.
1746
+ // Lsuccess:
1747
+ // ; skipped if authentication failed
1748
+ // Lend:
1749
+ // ...
1746
1750
//
1747
1751
// - checked and trapping:
1748
- // mov x17, x0
1749
- // movk x17, #disc, lsl #48
1750
- // autia x16, x0
1751
1752
// mov x17, x16
1752
1753
// xpaci x17
1753
1754
// cmp x16, x17
1754
1755
// b.eq Lsuccess
1755
1756
// brk #<0xc470 + aut key>
1756
- // Lsuccess:
1757
- // mov x17, x1
1758
- // movk x17, #disc, lsl #48
1759
- // pacib x16, x17 ; if AUTPAC
1760
- // Where the b.eq skips over the trap if the PAC is valid.
1757
+ // Lsuccess:
1758
+ // ...
1761
1759
//
1762
1760
// This sequence is expensive, but we need more information to be able to
1763
1761
// do better.
@@ -1770,6 +1768,71 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) {
1770
1768
// Either way, we also don't always know whether TBI is enabled or not for
1771
1769
// the specific target environment.
1772
1770
1771
+ unsigned XPACOpc = getXPACOpcodeForKey (Key);
1772
+
1773
+ MCSymbol *SuccessSym = createTempSymbol (" auth_success_" );
1774
+
1775
+ // mov Xscratch, Xtested
1776
+ emitMovXReg (ScratchReg, TestedReg);
1777
+
1778
+ // xpac(i|d) Xscratch
1779
+ EmitToStreamer (MCInstBuilder (XPACOpc).addReg (ScratchReg).addReg (ScratchReg));
1780
+
1781
+ // cmp Xtested, Xscratch
1782
+ EmitToStreamer (MCInstBuilder (AArch64::SUBSXrs)
1783
+ .addReg (AArch64::XZR)
1784
+ .addReg (TestedReg)
1785
+ .addReg (ScratchReg)
1786
+ .addImm (0 ));
1787
+
1788
+ // b.eq Lsuccess
1789
+ EmitToStreamer (MCInstBuilder (AArch64::Bcc)
1790
+ .addImm (AArch64CC::EQ)
1791
+ .addExpr (MCSymbolRefExpr::create (SuccessSym, OutContext)));
1792
+
1793
+ if (ShouldTrap) {
1794
+ assert (!OnFailure && " Cannot specify OnFailure with ShouldTrap" );
1795
+ // Trapping sequences do a 'brk'.
1796
+ // brk #<0xc470 + aut key>
1797
+ EmitToStreamer (MCInstBuilder (AArch64::BRK).addImm (0xc470 | Key));
1798
+ } else {
1799
+ // Non-trapping checked sequences return the stripped result in TestedReg,
1800
+ // skipping over success-only code (such as re-signing the pointer) if
1801
+ // there is one.
1802
+ // Note that this can introduce an authentication oracle (such as based on
1803
+ // the high bits of the re-signed value).
1804
+
1805
+ // FIXME: Can we simply return the AUT result, already in TestedReg?
1806
+ // mov Xtested, Xscratch
1807
+ emitMovXReg (TestedReg, ScratchReg);
1808
+
1809
+ if (OnFailure) {
1810
+ // b Lend
1811
+ EmitToStreamer (
1812
+ MCInstBuilder (AArch64::B)
1813
+ .addExpr (MCSymbolRefExpr::create (OnFailure, OutContext)));
1814
+ }
1815
+ }
1816
+
1817
+ // If the auth check succeeds, we can continue.
1818
+ // Lsuccess:
1819
+ OutStreamer->emitLabel (SuccessSym);
1820
+ }
1821
+
1822
+ void AArch64AsmPrinter::emitPtrauthAuthResign (const MachineInstr *MI) {
1823
+ const bool IsAUTPAC = MI->getOpcode () == AArch64::AUTPAC;
1824
+
1825
+ // We expand AUT/AUTPAC into a sequence of the form
1826
+ //
1827
+ // ; authenticate x16
1828
+ // ; check pointer in x16
1829
+ // Lsuccess:
1830
+ // ; sign x16 (if AUTPAC)
1831
+ // Lend: ; if not trapping on failure
1832
+ //
1833
+ // with the checking sequence chosen depending on whether we should check
1834
+ // the pointer and whether we should trap on failure.
1835
+
1773
1836
// By default, auth/resign sequences check for auth failures.
1774
1837
bool ShouldCheck = true ;
1775
1838
// In the checked sequence, we only trap if explicitly requested.
@@ -1800,8 +1863,6 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) {
1800
1863
uint64_t AUTDisc = MI->getOperand (1 ).getImm ();
1801
1864
unsigned AUTAddrDisc = MI->getOperand (2 ).getReg ();
1802
1865
1803
- unsigned XPACOpc = getXPACOpcodeForKey (AUTKey);
1804
-
1805
1866
// Compute aut discriminator into x17
1806
1867
assert (isUInt<16 >(AUTDisc));
1807
1868
unsigned AUTDiscReg = emitPtrauthDiscriminator (AUTDisc, AUTAddrDisc);
@@ -1824,59 +1885,12 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) {
1824
1885
1825
1886
MCSymbol *EndSym = nullptr ;
1826
1887
1827
- // Checked sequences do an additional strip-and-compare.
1828
1888
if (ShouldCheck) {
1829
- MCSymbol *SuccessSym = createTempSymbol (" auth_success_" );
1830
-
1831
- // XPAC has tied src/dst: use x17 as a temporary copy.
1832
- // mov x17, x16
1833
- emitMovXReg (AArch64::X17, AArch64::X16);
1834
-
1835
- // xpaci x17
1836
- EmitToStreamer (
1837
- *OutStreamer,
1838
- MCInstBuilder (XPACOpc).addReg (AArch64::X17).addReg (AArch64::X17));
1839
-
1840
- // cmp x16, x17
1841
- EmitToStreamer (*OutStreamer, MCInstBuilder (AArch64::SUBSXrs)
1842
- .addReg (AArch64::XZR)
1843
- .addReg (AArch64::X16)
1844
- .addReg (AArch64::X17)
1845
- .addImm (0 ));
1846
-
1847
- // b.eq Lsuccess
1848
- EmitToStreamer (*OutStreamer, MCInstBuilder (AArch64::Bcc)
1849
- .addImm (AArch64CC::EQ)
1850
- .addExpr (MCSymbolRefExpr::create (
1851
- SuccessSym, OutContext)));
1852
-
1853
- if (ShouldTrap) {
1854
- // Trapping sequences do a 'brk'.
1855
- // brk #<0xc470 + aut key>
1856
- EmitToStreamer (*OutStreamer,
1857
- MCInstBuilder (AArch64::BRK).addImm (0xc470 | AUTKey));
1858
- } else {
1859
- // Non-trapping checked sequences return the stripped result in x16,
1860
- // skipping over the PAC if there is one.
1861
-
1862
- // FIXME: can we simply return the AUT result, already in x16? without..
1863
- // ..traps this is usable as an oracle anyway, based on high bits
1864
- // mov x17, x16
1865
- emitMovXReg (AArch64::X16, AArch64::X17);
1866
-
1867
- if (IsAUTPAC) {
1868
- EndSym = createTempSymbol (" resign_end_" );
1869
-
1870
- // b Lend
1871
- EmitToStreamer (*OutStreamer, MCInstBuilder (AArch64::B)
1872
- .addExpr (MCSymbolRefExpr::create (
1873
- EndSym, OutContext)));
1874
- }
1875
- }
1889
+ if (IsAUTPAC && !ShouldTrap)
1890
+ EndSym = createTempSymbol (" resign_end_" );
1876
1891
1877
- // If the auth check succeeds, we can continue.
1878
- // Lsuccess:
1879
- OutStreamer->emitLabel (SuccessSym);
1892
+ emitPtrauthCheckAuthenticatedValue (AArch64::X16, AArch64::X17, AUTKey,
1893
+ ShouldTrap, EndSym);
1880
1894
}
1881
1895
1882
1896
// We already emitted unchecked and checked-but-non-trapping AUTs.
0 commit comments