David 'Digit' Turner c124baaf29 libc: Provide ucontext_t/mcontext_t/<sys/ucontext.h>
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
2012-10-17 15:59:23 +02:00

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_ */