@@ -74,8 +74,10 @@ class DwarfInstructions {
7474 __builtin_unreachable ();
7575 }
7676#if defined(_LIBUNWIND_TARGET_AARCH64)
77- static bool getRA_SIGN_STATE (A &addressSpace, R registers, pint_t cfa,
78- PrologInfo &prolog);
77+ static bool isReturnAddressSigned (A &addressSpace, R registers, pint_t cfa,
78+ PrologInfo &prolog);
79+ static bool isReturnAddressSignedWithPC (A &addressSpace, R registers,
80+ pint_t cfa, PrologInfo &prolog);
7981#endif
8082};
8183
@@ -173,8 +175,9 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister(
173175}
174176#if defined(_LIBUNWIND_TARGET_AARCH64)
175177template <typename A, typename R>
176- bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers,
177- pint_t cfa, PrologInfo &prolog) {
178+ bool DwarfInstructions<A, R>::isReturnAddressSigned(A &addressSpace,
179+ R registers, pint_t cfa,
180+ PrologInfo &prolog) {
178181 pint_t raSignState;
179182 auto regloc = prolog.savedRegisters [UNW_AARCH64_RA_SIGN_STATE];
180183 if (regloc.location == CFI_Parser<A>::kRegisterUnused )
@@ -185,6 +188,22 @@ bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers,
185188 // Only bit[0] is meaningful.
186189 return raSignState & 0x01 ;
187190}
191+
192+ template <typename A, typename R>
193+ bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace,
194+ R registers,
195+ pint_t cfa,
196+ PrologInfo &prolog) {
197+ pint_t raSignState;
198+ auto regloc = prolog.savedRegisters [UNW_AARCH64_RA_SIGN_STATE];
199+ if (regloc.location == CFI_Parser<A>::kRegisterUnused )
200+ raSignState = static_cast <pint_t >(regloc.value );
201+ else
202+ raSignState = getSavedRegister (addressSpace, registers, cfa, regloc);
203+
204+ // Only bit[1] is meaningful.
205+ return raSignState & 0x02 ;
206+ }
188207#endif
189208
190209template <typename A, typename R>
@@ -288,21 +307,32 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
288307 // restored. autia1716 is used instead of autia as autia1716 assembles
289308 // to a NOP on pre-v8.3a architectures.
290309 if ((R::getArch () == REGISTERS_ARM64) &&
291- getRA_SIGN_STATE (addressSpace, registers, cfa, prolog) &&
310+ isReturnAddressSigned (addressSpace, registers, cfa, prolog) &&
292311 returnAddress != 0 ) {
293312#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
294313 return UNW_ECROSSRASIGNING;
295314#else
296315 register unsigned long long x17 __asm (" x17" ) = returnAddress;
297316 register unsigned long long x16 __asm (" x16" ) = cfa;
298317
299- // These are the autia1716/autib1716 instructions. The hint instructions
300- // are used here as gcc does not assemble autia1716/autib1716 for pre
301- // armv8.3a targets.
302- if (cieInfo.addressesSignedWithBKey )
303- asm (" hint 0xe" : " +r" (x17) : " r" (x16)); // autib1716
304- else
305- asm (" hint 0xc" : " +r" (x17) : " r" (x16)); // autia1716
318+ // We use the hint versions of the authentication instructions below to
319+ // ensure they're assembled by the compiler even for targets with no
320+ // FEAT_PAuth/FEAT_PAuth_LR support.
321+ if (isReturnAddressSignedWithPC (addressSpace, registers, cfa, prolog)) {
322+ register unsigned long long x15 __asm (" x15" ) = prolog.ptrAuthDiversifier ;
323+ if (cieInfo.addressesSignedWithBKey ) {
324+ asm (" hint 0x27\n\t " // pacm
325+ " hint 0xe" : " +r" (x17) : " r" (x16), " r" (x15)); // autib1716
326+ } else {
327+ asm (" hint 0x27\n\t " // pacm
328+ " hint 0xc" : " +r" (x17) : " r" (x16), " r" (x15)); // autia1716
329+ }
330+ } else {
331+ if (cieInfo.addressesSignedWithBKey )
332+ asm (" hint 0xe" : " +r" (x17) : " r" (x16)); // autib1716
333+ else
334+ asm (" hint 0xc" : " +r" (x17) : " r" (x16)); // autia1716
335+ }
306336 returnAddress = x17;
307337#endif
308338 }
0 commit comments