
This patch updates the C library headers to provide ucontext_t definitions for three architectures. + Fix <signal.h> to always define 'struct sigcontext'. The new declarations are announced with new macros defined in <sys/cdefs.h> in order to make it easier to adapt client code that already defines its own, incompatible, versions of the structures seen here. http://code.google.com/p/android/issues/detail?id=34784 Change-Id: Ie78c48690a4ce61c50593f6c39639be7fead3596
171 lines
7.3 KiB
C
171 lines
7.3 KiB
C
/*
|
|
* Copyright (C) 2012 The Android Open Source Project
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
#ifndef _ARCH_ARM_SYS_UCONTEXT_H_
|
|
#define _ARCH_ARM_SYS_UCONTEXT_H_
|
|
|
|
#include <stdint.h>
|
|
#include <sys/cdefs.h>
|
|
#include <sys/types.h>
|
|
#include <machine/signal.h>
|
|
|
|
__BEGIN_DECLS
|
|
|
|
/* Technical note:
|
|
*
|
|
* There are similarities and differences in the way GLibc and the ARM Linux
|
|
* kernel declare ucontext_t. Here are the details:
|
|
*
|
|
* - Both declare mcontext_t as a typedef for 'struct sigcontext'. This goes
|
|
* against the GLibc convention of providing a custom mcontext_t declaration
|
|
* for all other platforms.
|
|
*
|
|
* One notable difference on ARM is that to access register values, one
|
|
* has to use named fields like "arm_r0", "arm_sp", "arm_pc".
|
|
*
|
|
* On other platforms, GLibc mcontext_t provides a gregs[] array of
|
|
* 32-bit values to access the value of core registers instead. Plus
|
|
* some helper enums + macros to index it (e.g. REG_EBP on i386).
|
|
*
|
|
* Note that some client code, when ported to Android, provide custom
|
|
* mcontext_t declaration that use the gregs[] convention. For the sake
|
|
* of portability, this header follows the ARM GLibc convention of using
|
|
* explicit field names. This means that such client code will need to be
|
|
* adapted. Possibly by checking against __BIONIC_HAVE_UCONTEXT_T defined
|
|
* in <sys/cdefs.h>
|
|
*
|
|
* - On ARM, the floating-point state is not stored in mcontext_t.
|
|
* Instead, it is stored in the ucontext_t structure, in the '_uc_regspace'
|
|
* field at the end, but both the Kernel and GLibc use a different
|
|
* convention for exact layout:
|
|
*
|
|
* * The state saved by the kernel (which would be accessible from the
|
|
* ucontext_t received from a SA_SIGINGO handler) has a layout that
|
|
* depends on the exact kernel configuration. For more details see
|
|
* the "struct aux_sigframe" declaration in the kernel's ucontext.h
|
|
* which defines the format. It is *not* exposed by this header.
|
|
*
|
|
* * The FP state saved by GLibc's getcontext()/setcontext() functions
|
|
* uses a different custom storage scheme that depends on the reported
|
|
* ELF HWCAPs. If VFP is enabled, only registers d8-d15 are saved to
|
|
* the storage space, in addition to some status/exception registers.
|
|
* This is not surprising because d0-d7 are callee-saved in the
|
|
* ARM EABI.
|
|
*
|
|
* It also looks like this implementation cannot handle VFPv3-D32/NEON
|
|
* by saving/restoring the state of d16-d31 available on these CPUs.
|
|
*
|
|
* Note that client code that needs to access the FP state typically
|
|
* does so through ptrace() using the special PTRACE_GETVFPREGS op.
|
|
* This is what gdbserver and debuggerd use to extract that information.
|
|
*
|
|
* In conclusion, there is no reliable way to extract the FP state from
|
|
* a ucontext_t on ARM.
|
|
*
|
|
* - The ARM GLibc ucontext.h defines a 'struct _libc_fpstate' structure
|
|
* that is never used by GLibc source code, and which doesn't seem to
|
|
* match either the kernel of getcontext/setcontext() layout.
|
|
*
|
|
* It was introduced by the following patch, reason is unclear but may be
|
|
* related to the GLibc test suite:
|
|
*
|
|
* http://www.cygwin.com/ml/libc-ports/2011-12/msg00032.html
|
|
*
|
|
* This header does *not* define this type, or fpregset_t either.
|
|
*
|
|
* Reference source files:
|
|
* $KERNEL/arch/arm/include/asm/fpstate.h
|
|
* $KERNEL/arch/arm/include/asm/sigcontext.h
|
|
* $KERNEL/arch/arm/include/asm/ucontext.h
|
|
* $KERNEL/arch/arm/include/asm/user.h
|
|
*
|
|
* $GLIBC/ports/sysdeps/unix/sysv/linux/arm/getcontext.S
|
|
* $GLIBC/ports/sysdeps/unix/sysv/linux/arm/setcontext.S
|
|
* $GLIBC/ports/sysdeps/unix/sysv/linux/arm/sys/ucontext.h
|
|
*/
|
|
|
|
/* First, the kernel-compatible version, for reference. */
|
|
typedef struct __kernel_ucontext {
|
|
unsigned long uc_flags;
|
|
struct __kernel_ucontext* uc_link;
|
|
stack_t uc_stack;
|
|
struct sigcontext uc_mcontext;
|
|
__kernel_sigset_t uc_sigmask;
|
|
/* The kernel reserves 1024 bits for the signal mask, even if it only
|
|
* uses the first 64 ones. */
|
|
int _unused[32 - (sizeof(__kernel_sigset_t) / sizeof(int))];
|
|
/* Used to store coprocessor + VFP register state on ARMv7-A */
|
|
unsigned long uc_regspace[128] __attribute__((__aligned__(8)));
|
|
} __kernel_ucontext_t;
|
|
|
|
/* Second, the GLibc-compatible version */
|
|
|
|
/* On ARM, GLibc mcontext_t is a simple typedef to 'struct sigcontext',
|
|
* just like the kernel does. This means that to access register values,
|
|
* you will need to use the specific named field (e.g. 'arm_r0', 'arm_pc').
|
|
*
|
|
* Note that on all other platforms, GLibc uses a gregs[] array instead.
|
|
* Follow the GLibc logic, or lack of, for ease of portability.
|
|
*
|
|
* Curiously, GLibc also defines enums and macros for REG_R0 .. REG_R15,
|
|
* plus the gregset_t type, NREGS macro, fpregset_t types, etc.. while they
|
|
* are never used by any code. They are *not* declared here.
|
|
*
|
|
* This also means there is no 'official' or 'documented' way to access
|
|
* the state of the FP registers (while the GLibc implementation does
|
|
* save/restore them in getcontext()/swapcontext()).
|
|
*/
|
|
typedef struct sigcontext mcontext_t;
|
|
|
|
/* Technical note:
|
|
*
|
|
* GLibc defines an ARM-specific 'struct _libc_fpstate' that seems to match
|
|
* the FPU state stored in uc_regspace[] below. However, its declaration does
|
|
* not match either the kernel declaration, or the actual GLibc
|
|
* implementation of *context() functions.
|
|
*
|
|
* It is suspected that this is a remnant of the obsolete VFPv1 era that
|
|
* was never updated. As such, client code shall *not* rely on this and
|
|
* there is no definition for it provided here.
|
|
*/
|
|
|
|
typedef struct ucontext {
|
|
uint32_t uc_flags;
|
|
struct ucontext* uc_link;
|
|
stack_t uc_stack;
|
|
mcontext_t uc_mcontext;
|
|
/* Only expose the 32 non-realtime signals in Bionic's 32-bit sigset_t
|
|
* The _unused field is required padding from the kernel. */
|
|
sigset_t uc_sigmask;
|
|
int _unused[32 - sizeof(sigset_t)/sizeof(int)];
|
|
uint32_t uc_regspace[128] __attribute__((__aligned__(8)));
|
|
} ucontext_t;
|
|
|
|
__END_DECLS
|
|
|
|
#endif /* _ARCH_ARM_SYS_UCONTEXT_H_ */
|