diff options
| author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2025-03-28 14:27:45 -0300 |
|---|---|---|
| committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2025-03-31 10:08:06 -0300 |
| commit | 4352e2cc934b2874dba37397157bf890fcee455a (patch) | |
| tree | 5bcc9ff6e6cef71333269d05bca4627f6d568c24 /sysdeps/aarch64 | |
| parent | 145097dff170507fe73190e8e41194f5b5f7e6bf (diff) | |
| download | glibc-4352e2cc934b2874dba37397157bf890fcee455a.tar.xz glibc-4352e2cc934b2874dba37397157bf890fcee455a.zip | |
aarch64: Fix _dl_tlsdesc_dynamic unwind for pac-ret (BZ 32612)
When libgcc is built with pac-ret, it requires to autenticate the
unwinding frame based on CFI information. The _dl_tlsdesc_dynamic
uses a custom calling convention, where it is responsible to save
and restore all registers it might use (even volatile).
The pac-ret support added by 1be3d6eb823d8b952fa54b7bbc90cbecb8981380
was added only on the slow-path, but the fast path also adds DWARF
Register Rule Instruction (cfi_adjust_cfa_offset) since it requires
to save/restore some auxiliary register. It seems that this is not
fully supported neither by libgcc nor AArch64 ABI [1].
Instead, move paciasp/autiasp to function prologue/epilogue to be
used on both fast and slow paths.
I also corrected the _dl_tlsdesc_dynamic comment description, it was
copied from i386 implementation without any adjustment.
Checked on aarch64-linux-gnu with a toolchain built with
--enable-standard-branch-protection on a system with pac-ret
support.
[1] https://github.com/ARM-software/abi-aa/blob/main/aadwarf64/aadwarf64.rst#id1
Reviewed-by: Yury Khrustalev <yury.khrustalev@arm.com>
Diffstat (limited to 'sysdeps/aarch64')
| -rw-r--r-- | sysdeps/aarch64/dl-tlsdesc.S | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/sysdeps/aarch64/dl-tlsdesc.S b/sysdeps/aarch64/dl-tlsdesc.S index 68afc443f7..fc40d66c07 100644 --- a/sysdeps/aarch64/dl-tlsdesc.S +++ b/sysdeps/aarch64/dl-tlsdesc.S @@ -119,20 +119,19 @@ _dl_tlsdesc_undefweak: object referenced by the argument. ptrdiff_t - __attribute__ ((__regparm__ (1))) _dl_tlsdesc_dynamic (struct tlsdesc *tdp) { struct tlsdesc_dynamic_arg *td = tdp->arg; - dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer + TCBHEAD_DTV); + dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer() + TCBHEAD_DTV); if (__builtin_expect (td->gen_count <= dtv[0].counter && (dtv[td->tlsinfo.ti_module].pointer.val != TLS_DTV_UNALLOCATED), 1)) return dtv[td->tlsinfo.ti_module].pointer.val + td->tlsinfo.ti_offset - - __thread_pointer; + - __thread_pointer(); - return ___tls_get_addr (&td->tlsinfo) - __thread_pointer; + return __tls_get_addr (&td->tlsinfo) - __thread_pointer(); } */ @@ -142,7 +141,12 @@ _dl_tlsdesc_undefweak: cfi_startproc .align 2 _dl_tlsdesc_dynamic: +# if HAVE_AARCH64_PAC_RET + PACIASP + cfi_window_save +# else BTI_C +# endif /* Save just enough registers to support fast path, if we fall into slow path we will save additional registers. */ @@ -173,6 +177,10 @@ _dl_tlsdesc_dynamic: 1: ldp x3, x4, [sp, #16] ldp x1, x2, [sp], #32 +# if HAVE_AARCH64_PAC_RET + AUTIASP + cfi_window_save +# endif cfi_adjust_cfa_offset (-32) RET 2: @@ -182,10 +190,6 @@ _dl_tlsdesc_dynamic: /* Save the remaining registers that we must treat as caller save. */ cfi_restore_state -# if HAVE_AARCH64_PAC_RET - PACIASP - cfi_window_save -# endif # define NSAVEXREGPAIRS 8 stp x29, x30, [sp,#-16*NSAVEXREGPAIRS]! cfi_adjust_cfa_offset (16*NSAVEXREGPAIRS) @@ -236,10 +240,6 @@ _dl_tlsdesc_dynamic: cfi_adjust_cfa_offset (-16*NSAVEXREGPAIRS) cfi_restore (x29) cfi_restore (x30) -# if HAVE_AARCH64_PAC_RET - AUTIASP - cfi_window_save -# endif b 1b cfi_endproc .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic |
