@@ -74,8 +74,10 @@ class DwarfInstructions {
74
74
__builtin_unreachable ();
75
75
}
76
76
#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);
79
81
#endif
80
82
};
81
83
@@ -173,8 +175,9 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister(
173
175
}
174
176
#if defined(_LIBUNWIND_TARGET_AARCH64)
175
177
template <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) {
178
181
pint_t raSignState;
179
182
auto regloc = prolog.savedRegisters [UNW_AARCH64_RA_SIGN_STATE];
180
183
if (regloc.location == CFI_Parser<A>::kRegisterUnused )
@@ -185,6 +188,22 @@ bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers,
185
188
// Only bit[0] is meaningful.
186
189
return raSignState & 0x01 ;
187
190
}
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
+ }
188
207
#endif
189
208
190
209
template <typename A, typename R>
@@ -288,21 +307,32 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
288
307
// restored. autia1716 is used instead of autia as autia1716 assembles
289
308
// to a NOP on pre-v8.3a architectures.
290
309
if ((R::getArch () == REGISTERS_ARM64) &&
291
- getRA_SIGN_STATE (addressSpace, registers, cfa, prolog) &&
310
+ isReturnAddressSigned (addressSpace, registers, cfa, prolog) &&
292
311
returnAddress != 0 ) {
293
312
#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
294
313
return UNW_ECROSSRASIGNING;
295
314
#else
296
315
register unsigned long long x17 __asm (" x17" ) = returnAddress;
297
316
register unsigned long long x16 __asm (" x16" ) = cfa;
298
317
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
+ }
306
336
returnAddress = x17;
307
337
#endif
308
338
}
0 commit comments