glibc/sysdeps/aarch64/jmpbuf-offsets.h

122 lines
4.2 KiB
C
Raw Normal View History

/* Copyright (C) 2006-2025 Free Software Foundation, Inc.
2012-11-09 17:53:51 +00:00
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
Prefer https to http for gnu.org and fsf.org URLs Also, change sources.redhat.com to sourceware.org. This patch was automatically generated by running the following shell script, which uses GNU sed, and which avoids modifying files imported from upstream: sed -ri ' s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g ' \ $(find $(git ls-files) -prune -type f \ ! -name '*.po' \ ! -name 'ChangeLog*' \ ! -path COPYING ! -path COPYING.LIB \ ! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \ ! -path manual/texinfo.tex ! -path scripts/config.guess \ ! -path scripts/config.sub ! -path scripts/install-sh \ ! -path scripts/mkinstalldirs ! -path scripts/move-if-change \ ! -path INSTALL ! -path locale/programs/charmap-kw.h \ ! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \ ! '(' -name configure \ -execdir test -f configure.ac -o -f configure.in ';' ')' \ ! '(' -name preconfigure \ -execdir test -f preconfigure.ac ';' ')' \ -print) and then by running 'make dist-prepare' to regenerate files built from the altered files, and then executing the following to cleanup: chmod a+x sysdeps/unix/sysv/linux/riscv/configure # Omit irrelevant whitespace and comment-only changes, # perhaps from a slightly-different Autoconf version. git checkout -f \ sysdeps/csky/configure \ sysdeps/hppa/configure \ sysdeps/riscv/configure \ sysdeps/unix/sysv/linux/csky/configure # Omit changes that caused a pre-commit check to fail like this: # remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines git checkout -f \ sysdeps/powerpc/powerpc64/ppc-mcount.S \ sysdeps/unix/sysv/linux/s390/s390-64/syscall.S # Omit change that caused a pre-commit check to fail like this: # remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 05:40:42 +00:00
<https://www.gnu.org/licenses/>. */
2012-11-09 17:53:51 +00:00
#define JB_X19 0
#define JB_X20 1
#define JB_X21 2
#define JB_X22 3
#define JB_X23 4
#define JB_X24 5
#define JB_X25 6
#define JB_X26 7
#define JB_X27 8
#define JB_X28 9
#define JB_X29 10
#define JB_LR 11
#define JB_SP 13
#define JB_D8 14
#define JB_D9 15
#define JB_D10 16
#define JB_D11 17
#define JB_D12 18
#define JB_D13 19
#define JB_D14 20
#define JB_D15 21
aarch64: Define jmp_buf offset for GCS The target specific internal __longjmp is called with a __jmp_buf argument which has its size exposed in the ABI. On aarch64 this has no space left, so GCSPR cannot be restored in longjmp in the usual way, which is needed for the Guarded Control Stack (GCS) extension. setjmp is implemented via __sigsetjmp which has a jmp_buf argument however it is also called with __pthread_unwind_buf_t argument cast to jmp_buf (in cancellation cleanup code built with -fno-exception). The two types, jmp_buf and __pthread_unwind_buf_t, have common bits beyond the __jmp_buf field and there is unused space there which we can use for saving GCSPR. For this to work some bits of those two generic types have to be reserved for target specific use and the generic code in glibc has to ensure that __longjmp is always called with a __jmp_buf that is embedded into one of those two types. Morally __longjmp should be changed to take jmp_buf as argument, but that is an intrusive change across targets. Note: longjmp is never called with __pthread_unwind_buf_t from user code, only the internal __libc_longjmp is called with that type and thus the two types could have separate longjmp implementations on a target. We don't rely on this now (but might in the future given that cancellation unwind does not need to restore GCSPR). Given the above this patch finds an unused slot for GCSPR. This placement is not exposed in the ABI so it may change in the future. This is also very target ABI specific so the generic types cannot be easily changed to clearly mark the reserved fields. Reviewed-by: Carlos O'Donell <carlos@redhat.com> Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
2022-11-25 18:16:07 +00:00
/* The target specific part of jmp_buf has no space for expansion but
the public jmp_buf ABI type has. Unfortunately there is another type
that is used with setjmp APIs and exposed by thread cancellation (in
binaries built with -fno-exceptions) which complicates the situation.
// Internal layout of the public jmp_buf type on AArch64.
// This is passed to setjmp, longjmp, sigsetjmp, siglongjmp.
struct
{
uint64_t jmpbuf[22]; // Target specific part.
uint32_t mask_was_saved; // savemask bool used by sigsetjmp/siglongjmp.
uint32_t pad;
uint64_t saved_mask; // sigset_t bits used on linux.
uint64_t unused[15]; // sigset_t bits not used on linux.
};
// Internal layout of the public __pthread_unwind_buf_t type.
// This is passed to sigsetjmp with !savemask and to the internal
// __libc_longjmp (currently alias of longjmp on AArch64).
struct
{
uint64_t jmpbuf[22]; // Must match jmp_buf.
uint32_t mask_was_saved; // Must match jmp_buf, always 0.
uint32_t pad;
void *prev; // List for unwinding.
void *cleanup; // Cleanup handlers.
uint32_t canceltype; // 1 bit cancellation type.
uint32_t pad2;
void *pad3;
};
Ideally only the target specific part of jmp_buf (A) is accessed by
__setjmp and __longjmp. But that is always embedded into one of the
two types above so the bits that are unused in those types (B) may be
reused for target specific purposes. Setjmp can't distinguish between
jmp_buf and __pthread_unwind_buf_t, but longjmp can: only an internal
longjmp call uses the latter, so state that is not needed for cancel
cleanups can go to fields (C). If generic code is refactored then the
usage of additional fields can be optimized (D). And some fields are
only accessible in the savedmask case (E). Reusability of jmp_buf
fields on AArch64 for target purposes:
struct
{
uint64_t A[22]; // 0 .. 176
uint32_t D; // 176 .. 180
uint32_t B; // 180 .. 184
uint64_t D; // 184 .. 192
uint64_t C; // 192 .. 200
uint32_t C; // 200 .. 204
uint32_t B; // 204 .. 208
uint64_t B; // 208 .. 216
uint64_t E[12]; // 216 .. 312
}
The B fields can be used with minimal glibc code changes. We need a
64 bit field for the Guarded Control Stack pointer (GCSPR_EL0) which
can use a C field too as cancellation cleanup does not execute RET
for a previous BL of the cancelled thread, but that would require a
custom __libc_longjmp. This layout can change in the future. */
#define JB_GCSPR 208
#ifndef __ASSEMBLER__
#include <setjmp.h>
#include <stdint.h>
#include <sysdep.h>
#include <pointer_guard.h>
static inline uintptr_t __attribute__ ((unused))
_jmpbuf_sp (__jmp_buf jmpbuf)
{
uintptr_t sp = jmpbuf[JB_SP];
PTR_DEMANGLE (sp);
return sp;
}
#endif
2012-11-09 17:53:51 +00:00
/* Helper for generic ____longjmp_chk(). */
#define JB_FRAME_ADDRESS(buf) \
((void *) _jmpbuf_sp (buf))