mirror of
https://git.suyu.dev/suyu/breakpad.git
synced 2025-12-31 11:44:48 +01:00
Use breakpad_getcontext on all Linux platforms missing getcontext
getcontext is also not available on musl libc, so generalize breakpad_getcontext so it can be used as a fallback for non-Android platforms as well. On x86_64 and i386, ucontext_t uses an Android-specific offset for storage of FP registers, since its sigset_t differs in size. So, make the definition of MCONTEXT_FPREGS_MEM and UCONTEXT_FPREGS_MEM_OFFSET conditional on whether we are building for Android. On glibc and musl, signal.h and asm/sigcontext.h can't be included together, so in breakpad_context_unittest.cc, only compare the libc and kernel _fpstate when on Android. Bug: google-breakpad:631 Change-Id: If81d73c4101bae946e9a3655b8d1c40a34ab6c38 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/2102135 Reviewed-by: Mike Frysinger <vapier@chromium.org>
This commit is contained in:
parent
02b7be4065
commit
e780d58fd7
14 changed files with 124 additions and 87 deletions
486
src/common/linux/breakpad_getcontext.S
Normal file
486
src/common/linux/breakpad_getcontext.S
Normal file
|
|
@ -0,0 +1,486 @@
|
|||
// Copyright (c) 2012, Google Inc.
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// A minimalistic implementation of getcontext() to be used by
|
||||
// Google Breakpad when getcontext() is not available in libc.
|
||||
|
||||
#include "common/linux/ucontext_constants.h"
|
||||
|
||||
/* int getcontext (ucontext_t *ucp) */
|
||||
|
||||
#if defined(__arm__)
|
||||
|
||||
.text
|
||||
.global breakpad_getcontext
|
||||
.hidden breakpad_getcontext
|
||||
.type breakpad_getcontext, #function
|
||||
.align 0
|
||||
.fnstart
|
||||
breakpad_getcontext:
|
||||
|
||||
/* First, save r4-r11 */
|
||||
add r1, r0, #(MCONTEXT_GREGS_OFFSET + 4*4)
|
||||
stm r1, {r4-r11}
|
||||
|
||||
/* r12 is a scratch register, don't save it */
|
||||
|
||||
/* Save sp and lr explicitly. */
|
||||
/* - sp can't be stored with stmia in Thumb-2 */
|
||||
/* - STM instructions that store sp and pc are deprecated in ARM */
|
||||
str sp, [r0, #(MCONTEXT_GREGS_OFFSET + 13*4)]
|
||||
str lr, [r0, #(MCONTEXT_GREGS_OFFSET + 14*4)]
|
||||
|
||||
/* Save the caller's address in 'pc' */
|
||||
str lr, [r0, #(MCONTEXT_GREGS_OFFSET + 15*4)]
|
||||
|
||||
/* Save ucontext_t* pointer across next call */
|
||||
mov r4, r0
|
||||
|
||||
/* Call sigprocmask(SIG_BLOCK, NULL, &(ucontext->uc_sigmask)) */
|
||||
mov r0, #0 /* SIG_BLOCK */
|
||||
mov r1, #0 /* NULL */
|
||||
add r2, r4, #UCONTEXT_SIGMASK_OFFSET
|
||||
bl sigprocmask(PLT)
|
||||
|
||||
/* Intentionally do not save the FPU state here. This is because on
|
||||
* Linux/ARM, one should instead use ptrace(PTRACE_GETFPREGS) or
|
||||
* ptrace(PTRACE_GETVFPREGS) to get it.
|
||||
*
|
||||
* Note that a real implementation of getcontext() would need to save
|
||||
* this here to allow setcontext()/swapcontext() to work correctly.
|
||||
*/
|
||||
|
||||
/* Restore the values of r4 and lr */
|
||||
mov r0, r4
|
||||
ldr lr, [r0, #(MCONTEXT_GREGS_OFFSET + 14*4)]
|
||||
ldr r4, [r0, #(MCONTEXT_GREGS_OFFSET + 4*4)]
|
||||
|
||||
/* Return 0 */
|
||||
mov r0, #0
|
||||
bx lr
|
||||
|
||||
.fnend
|
||||
.size breakpad_getcontext, . - breakpad_getcontext
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
#define _NSIG 64
|
||||
#define __NR_rt_sigprocmask 135
|
||||
|
||||
.text
|
||||
.global breakpad_getcontext
|
||||
.hidden breakpad_getcontext
|
||||
.type breakpad_getcontext, #function
|
||||
.align 4
|
||||
.cfi_startproc
|
||||
breakpad_getcontext:
|
||||
|
||||
/* The saved context will return to the getcontext() call point
|
||||
with a return value of 0 */
|
||||
str xzr, [x0, MCONTEXT_GREGS_OFFSET + 0 * REGISTER_SIZE]
|
||||
|
||||
stp x18, x19, [x0, MCONTEXT_GREGS_OFFSET + 18 * REGISTER_SIZE]
|
||||
stp x20, x21, [x0, MCONTEXT_GREGS_OFFSET + 20 * REGISTER_SIZE]
|
||||
stp x22, x23, [x0, MCONTEXT_GREGS_OFFSET + 22 * REGISTER_SIZE]
|
||||
stp x24, x25, [x0, MCONTEXT_GREGS_OFFSET + 24 * REGISTER_SIZE]
|
||||
stp x26, x27, [x0, MCONTEXT_GREGS_OFFSET + 26 * REGISTER_SIZE]
|
||||
stp x28, x29, [x0, MCONTEXT_GREGS_OFFSET + 28 * REGISTER_SIZE]
|
||||
str x30, [x0, MCONTEXT_GREGS_OFFSET + 30 * REGISTER_SIZE]
|
||||
|
||||
/* Place LR into the saved PC, this will ensure that when
|
||||
switching to this saved context with setcontext() control
|
||||
will pass back to the caller of getcontext(), we have
|
||||
already arranged to return the appropriate return value in x0
|
||||
above. */
|
||||
str x30, [x0, MCONTEXT_PC_OFFSET]
|
||||
|
||||
/* Save the current SP */
|
||||
mov x2, sp
|
||||
str x2, [x0, MCONTEXT_SP_OFFSET]
|
||||
|
||||
/* Initialize the pstate. */
|
||||
str xzr, [x0, MCONTEXT_PSTATE_OFFSET]
|
||||
|
||||
/* Figure out where to place the first context extension
|
||||
block. */
|
||||
add x2, x0, #MCONTEXT_EXTENSION_OFFSET
|
||||
|
||||
/* Write the context extension fpsimd header. */
|
||||
mov w3, #(FPSIMD_MAGIC & 0xffff)
|
||||
movk w3, #(FPSIMD_MAGIC >> 16), lsl #16
|
||||
str w3, [x2, #FPSIMD_CONTEXT_MAGIC_OFFSET]
|
||||
mov w3, #FPSIMD_CONTEXT_SIZE
|
||||
str w3, [x2, #FPSIMD_CONTEXT_SIZE_OFFSET]
|
||||
|
||||
/* Fill in the FP SIMD context. */
|
||||
add x3, x2, #(FPSIMD_CONTEXT_VREGS_OFFSET + 8 * SIMD_REGISTER_SIZE)
|
||||
stp d8, d9, [x3], #(2 * SIMD_REGISTER_SIZE)
|
||||
stp d10, d11, [x3], #(2 * SIMD_REGISTER_SIZE)
|
||||
stp d12, d13, [x3], #(2 * SIMD_REGISTER_SIZE)
|
||||
stp d14, d15, [x3], #(2 * SIMD_REGISTER_SIZE)
|
||||
|
||||
add x3, x2, FPSIMD_CONTEXT_FPSR_OFFSET
|
||||
|
||||
mrs x4, fpsr
|
||||
str w4, [x3]
|
||||
|
||||
mrs x4, fpcr
|
||||
str w4, [x3, FPSIMD_CONTEXT_FPCR_OFFSET - FPSIMD_CONTEXT_FPSR_OFFSET]
|
||||
|
||||
/* Write the termination context extension header. */
|
||||
add x2, x2, #FPSIMD_CONTEXT_SIZE
|
||||
|
||||
str xzr, [x2, #FPSIMD_CONTEXT_MAGIC_OFFSET]
|
||||
str xzr, [x2, #FPSIMD_CONTEXT_SIZE_OFFSET]
|
||||
|
||||
/* Grab the signal mask */
|
||||
/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
|
||||
add x2, x0, #UCONTEXT_SIGMASK_OFFSET
|
||||
mov x0, #0 /* SIG_BLOCK */
|
||||
mov x1, #0 /* NULL */
|
||||
mov x3, #(_NSIG / 8)
|
||||
mov x8, #__NR_rt_sigprocmask
|
||||
svc 0
|
||||
|
||||
/* Return x0 for success */
|
||||
mov x0, 0
|
||||
ret
|
||||
|
||||
.cfi_endproc
|
||||
.size breakpad_getcontext, . - breakpad_getcontext
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
.text
|
||||
.global breakpad_getcontext
|
||||
.hidden breakpad_getcontext
|
||||
.align 4
|
||||
.type breakpad_getcontext, @function
|
||||
|
||||
breakpad_getcontext:
|
||||
|
||||
movl 4(%esp), %eax /* eax = uc */
|
||||
|
||||
/* Save register values */
|
||||
movl %ecx, MCONTEXT_ECX_OFFSET(%eax)
|
||||
movl %edx, MCONTEXT_EDX_OFFSET(%eax)
|
||||
movl %ebx, MCONTEXT_EBX_OFFSET(%eax)
|
||||
movl %edi, MCONTEXT_EDI_OFFSET(%eax)
|
||||
movl %esi, MCONTEXT_ESI_OFFSET(%eax)
|
||||
movl %ebp, MCONTEXT_EBP_OFFSET(%eax)
|
||||
|
||||
movl (%esp), %edx /* return address */
|
||||
lea 4(%esp), %ecx /* exclude return address from stack */
|
||||
mov %edx, MCONTEXT_EIP_OFFSET(%eax)
|
||||
mov %ecx, MCONTEXT_ESP_OFFSET(%eax)
|
||||
|
||||
xorl %ecx, %ecx
|
||||
movw %fs, %cx
|
||||
mov %ecx, MCONTEXT_FS_OFFSET(%eax)
|
||||
|
||||
movl $0, MCONTEXT_EAX_OFFSET(%eax)
|
||||
|
||||
/* Save floating point state to fpregstate, then update
|
||||
* the fpregs pointer to point to it */
|
||||
leal UCONTEXT_FPREGS_MEM_OFFSET(%eax), %ecx
|
||||
fnstenv (%ecx)
|
||||
fldenv (%ecx)
|
||||
mov %ecx, UCONTEXT_FPREGS_OFFSET(%eax)
|
||||
|
||||
/* Save signal mask: sigprocmask(SIGBLOCK, NULL, &uc->uc_sigmask) */
|
||||
leal UCONTEXT_SIGMASK_OFFSET(%eax), %edx
|
||||
xorl %ecx, %ecx
|
||||
push %edx /* &uc->uc_sigmask */
|
||||
push %ecx /* NULL */
|
||||
push %ecx /* SIGBLOCK == 0 on i386 */
|
||||
call sigprocmask@PLT
|
||||
addl $12, %esp
|
||||
|
||||
movl $0, %eax
|
||||
ret
|
||||
|
||||
.size breakpad_getcontext, . - breakpad_getcontext
|
||||
|
||||
#elif defined(__mips__)
|
||||
|
||||
// This implementation is inspired by implementation of getcontext in glibc.
|
||||
#include <asm-mips/asm.h>
|
||||
#include <asm-mips/regdef.h>
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
#include <asm-mips/fpregdef.h>
|
||||
#endif
|
||||
|
||||
// from asm-mips/asm.h
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
#define ALSZ 7
|
||||
#define ALMASK ~7
|
||||
#define SZREG 4
|
||||
#else // _MIPS_SIM != _ABIO32
|
||||
#define ALSZ 15
|
||||
#define ALMASK ~15
|
||||
#define SZREG 8
|
||||
#endif
|
||||
|
||||
#include <asm/unistd.h> // for __NR_rt_sigprocmask
|
||||
|
||||
#define _NSIG8 128 / 8
|
||||
#define SIG_BLOCK 1
|
||||
|
||||
|
||||
.text
|
||||
LOCALS_NUM = 1 // save gp on stack
|
||||
FRAME_SIZE = ((LOCALS_NUM * SZREG) + ALSZ) & ALMASK
|
||||
|
||||
GP_FRAME_OFFSET = FRAME_SIZE - (1 * SZREG)
|
||||
MCONTEXT_REG_SIZE = 8
|
||||
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
|
||||
NESTED (breakpad_getcontext, FRAME_SIZE, ra)
|
||||
.mask 0x00000000, 0
|
||||
.fmask 0x00000000, 0
|
||||
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
.set reorder
|
||||
|
||||
move a2, sp
|
||||
#define _SP a2
|
||||
|
||||
addiu sp, -FRAME_SIZE
|
||||
.cprestore GP_FRAME_OFFSET
|
||||
|
||||
sw s0, (16 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s1, (17 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s2, (18 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s3, (19 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s4, (20 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s5, (21 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s6, (22 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s7, (23 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw _SP, (29 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw fp, (30 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw ra, (31 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw ra, MCONTEXT_PC_OFFSET(a0)
|
||||
|
||||
#ifdef __mips_hard_float
|
||||
s.d fs0, (20 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d fs1, (22 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d fs2, (24 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d fs3, (26 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d fs4, (28 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d fs5, (30 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
|
||||
cfc1 v1, fcr31
|
||||
sw v1, MCONTEXT_FPC_CSR(a0)
|
||||
#endif // __mips_hard_float
|
||||
|
||||
/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
|
||||
li a3, _NSIG8
|
||||
addu a2, a0, UCONTEXT_SIGMASK_OFFSET
|
||||
move a1, zero
|
||||
li a0, SIG_BLOCK
|
||||
li v0, __NR_rt_sigprocmask
|
||||
syscall
|
||||
|
||||
addiu sp, FRAME_SIZE
|
||||
jr ra
|
||||
|
||||
END (breakpad_getcontext)
|
||||
#else
|
||||
|
||||
#ifndef NESTED
|
||||
/*
|
||||
* NESTED - declare nested routine entry point
|
||||
*/
|
||||
#define NESTED(symbol, framesize, rpc) \
|
||||
.globl symbol; \
|
||||
.align 2; \
|
||||
.type symbol,@function; \
|
||||
.ent symbol,0; \
|
||||
symbol: .frame sp, framesize, rpc;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* END - mark end of function
|
||||
*/
|
||||
#ifndef END
|
||||
# define END(function) \
|
||||
.end function; \
|
||||
.size function,.-function
|
||||
#endif
|
||||
|
||||
/* int getcontext (ucontext_t *ucp) */
|
||||
|
||||
NESTED (breakpad_getcontext, FRAME_SIZE, ra)
|
||||
.mask 0x10000000, 0
|
||||
.fmask 0x00000000, 0
|
||||
|
||||
move a2, sp
|
||||
#define _SP a2
|
||||
move a3, gp
|
||||
#define _GP a3
|
||||
|
||||
daddiu sp, -FRAME_SIZE
|
||||
.cpsetup $25, GP_FRAME_OFFSET, breakpad_getcontext
|
||||
|
||||
/* Store a magic flag. */
|
||||
li v1, 1
|
||||
sd v1, (0 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) /* zero */
|
||||
|
||||
sd s0, (16 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s1, (17 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s2, (18 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s3, (19 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s4, (20 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s5, (21 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s6, (22 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s7, (23 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd _GP, (28 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd _SP, (29 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s8, (30 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd ra, (31 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd ra, MCONTEXT_PC_OFFSET(a0)
|
||||
|
||||
#ifdef __mips_hard_float
|
||||
s.d $f24, (24 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f25, (25 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f26, (26 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f27, (27 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f28, (28 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f29, (29 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f30, (30 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f31, (31 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
|
||||
cfc1 v1, $31
|
||||
sw v1, MCONTEXT_FPC_CSR(a0)
|
||||
#endif /* __mips_hard_float */
|
||||
|
||||
/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
|
||||
li a3, _NSIG8
|
||||
daddu a2, a0, UCONTEXT_SIGMASK_OFFSET
|
||||
move a1, zero
|
||||
li a0, SIG_BLOCK
|
||||
|
||||
li v0, __NR_rt_sigprocmask
|
||||
syscall
|
||||
|
||||
.cpreturn
|
||||
daddiu sp, FRAME_SIZE
|
||||
move v0, zero
|
||||
jr ra
|
||||
|
||||
END (breakpad_getcontext)
|
||||
#endif // _MIPS_SIM == _ABIO32
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
/* The x64 implementation of breakpad_getcontext was derived in part
|
||||
from the implementation of libunwind which requires the following
|
||||
notice. */
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 Google, Inc
|
||||
Contributed by Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
.text
|
||||
.global breakpad_getcontext
|
||||
.hidden breakpad_getcontext
|
||||
.align 4
|
||||
.type breakpad_getcontext, @function
|
||||
|
||||
breakpad_getcontext:
|
||||
.cfi_startproc
|
||||
|
||||
/* Callee saved: RBX, RBP, R12-R15 */
|
||||
movq %r12, MCONTEXT_GREGS_R12(%rdi)
|
||||
movq %r13, MCONTEXT_GREGS_R13(%rdi)
|
||||
movq %r14, MCONTEXT_GREGS_R14(%rdi)
|
||||
movq %r15, MCONTEXT_GREGS_R15(%rdi)
|
||||
movq %rbp, MCONTEXT_GREGS_RBP(%rdi)
|
||||
movq %rbx, MCONTEXT_GREGS_RBX(%rdi)
|
||||
|
||||
/* Save argument registers (not strictly needed, but setcontext
|
||||
restores them, so don't restore garbage). */
|
||||
movq %r8, MCONTEXT_GREGS_R8(%rdi)
|
||||
movq %r9, MCONTEXT_GREGS_R9(%rdi)
|
||||
movq %rdi, MCONTEXT_GREGS_RDI(%rdi)
|
||||
movq %rsi, MCONTEXT_GREGS_RSI(%rdi)
|
||||
movq %rdx, MCONTEXT_GREGS_RDX(%rdi)
|
||||
movq %rax, MCONTEXT_GREGS_RAX(%rdi)
|
||||
movq %rcx, MCONTEXT_GREGS_RCX(%rdi)
|
||||
|
||||
/* Save fp state (not needed, except for setcontext not
|
||||
restoring garbage). */
|
||||
leaq MCONTEXT_FPREGS_MEM(%rdi),%r8
|
||||
movq %r8, MCONTEXT_FPREGS_PTR(%rdi)
|
||||
fnstenv (%r8)
|
||||
stmxcsr FPREGS_OFFSET_MXCSR(%r8)
|
||||
|
||||
leaq 8(%rsp), %rax /* exclude this call. */
|
||||
movq %rax, MCONTEXT_GREGS_RSP(%rdi)
|
||||
|
||||
movq 0(%rsp), %rax
|
||||
movq %rax, MCONTEXT_GREGS_RIP(%rdi)
|
||||
|
||||
/* Save signal mask: sigprocmask(SIGBLOCK, NULL, &uc->uc_sigmask) */
|
||||
leaq UCONTEXT_SIGMASK_OFFSET(%rdi), %rdx // arg3
|
||||
xorq %rsi, %rsi // arg2 NULL
|
||||
xorq %rdi, %rdi // arg1 SIGBLOCK == 0
|
||||
call sigprocmask@PLT
|
||||
|
||||
/* Always return 0 for success, even if sigprocmask failed. */
|
||||
xorl %eax, %eax
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size breakpad_getcontext, . - breakpad_getcontext
|
||||
|
||||
#else
|
||||
#error "This file has not been ported for your CPU!"
|
||||
#endif
|
||||
56
src/common/linux/breakpad_getcontext.h
Normal file
56
src/common/linux/breakpad_getcontext.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) 2012, Google Inc.
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// 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 GOOGLE_BREAKPAD_COMMON_LINUX_INCLUDE_UCONTEXT_H
|
||||
#define GOOGLE_BREAKPAD_COMMON_LINUX_INCLUDE_UCONTEXT_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETCONTEXT
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// Provided by src/common/linux/breakpad_getcontext.S
|
||||
int breakpad_getcontext(ucontext_t* ucp);
|
||||
|
||||
#define getcontext(x) breakpad_getcontext(x)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // HAVE_GETCONTEXT
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_LINUX_INCLUDE_UCONTEXT_H
|
||||
194
src/common/linux/breakpad_getcontext_unittest.cc
Normal file
194
src/common/linux/breakpad_getcontext_unittest.cc
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
// Copyright (c) 2012, Google Inc.
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// asm/sigcontext.h can't be included with signal.h on glibc or
|
||||
// musl, so only compare _libc_fpstate and _fpstate on Android.
|
||||
#if defined(__ANDROID__) && defined(__x86_64__)
|
||||
#include <asm/sigcontext.h>
|
||||
#endif
|
||||
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "breakpad_googletest_includes.h"
|
||||
#include "common/linux/ucontext_constants.h"
|
||||
|
||||
template <int left, int right>
|
||||
struct CompileAssertEquals {
|
||||
// a compilation error here indicates left and right are not equal.
|
||||
char left_too_large[right - left];
|
||||
// a compilation error here indicates left and right are not equal.
|
||||
char right_too_large[left - right];
|
||||
};
|
||||
|
||||
#define COMPILE_ASSERT_EQ(left, right, tag) \
|
||||
CompileAssertEquals<left, right> tag;
|
||||
|
||||
TEST(AndroidUContext, GRegsOffset) {
|
||||
#if defined(__arm__)
|
||||
// There is no gregs[] array on ARM, so compare to the offset of
|
||||
// first register fields, since they're stored in order.
|
||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
|
||||
offsetof(ucontext_t,uc_mcontext.arm_r0));
|
||||
#elif defined(__aarch64__)
|
||||
// There is no gregs[] array on ARM, so compare to the offset of
|
||||
// first register fields, since they're stored in order.
|
||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
|
||||
offsetof(ucontext_t,uc_mcontext.regs[0]));
|
||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_SP_OFFSET),
|
||||
offsetof(ucontext_t,uc_mcontext.sp));
|
||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_PC_OFFSET),
|
||||
offsetof(ucontext_t,uc_mcontext.pc));
|
||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_PSTATE_OFFSET),
|
||||
offsetof(ucontext_t,uc_mcontext.pstate));
|
||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_EXTENSION_OFFSET),
|
||||
offsetof(ucontext_t,uc_mcontext.__reserved));
|
||||
#elif defined(__i386__)
|
||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
|
||||
offsetof(ucontext_t,uc_mcontext.gregs));
|
||||
#define CHECK_REG(x) \
|
||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_##x##_OFFSET), \
|
||||
offsetof(ucontext_t,uc_mcontext.gregs[REG_##x]))
|
||||
CHECK_REG(GS);
|
||||
CHECK_REG(FS);
|
||||
CHECK_REG(ES);
|
||||
CHECK_REG(DS);
|
||||
CHECK_REG(EDI);
|
||||
CHECK_REG(ESI);
|
||||
CHECK_REG(EBP);
|
||||
CHECK_REG(ESP);
|
||||
CHECK_REG(EBX);
|
||||
CHECK_REG(EDX);
|
||||
CHECK_REG(ECX);
|
||||
CHECK_REG(EAX);
|
||||
CHECK_REG(TRAPNO);
|
||||
CHECK_REG(ERR);
|
||||
CHECK_REG(EIP);
|
||||
CHECK_REG(CS);
|
||||
CHECK_REG(EFL);
|
||||
CHECK_REG(UESP);
|
||||
CHECK_REG(SS);
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(UCONTEXT_FPREGS_OFFSET),
|
||||
offsetof(ucontext_t,uc_mcontext.fpregs));
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(UCONTEXT_FPREGS_MEM_OFFSET),
|
||||
offsetof(ucontext_t,__fpregs_mem));
|
||||
#elif defined(__mips__)
|
||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
|
||||
offsetof(ucontext_t,uc_mcontext.gregs));
|
||||
|
||||
// PC for mips is not part of gregs.
|
||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_PC_OFFSET),
|
||||
offsetof(ucontext_t,uc_mcontext.pc));
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_FPREGS_OFFSET),
|
||||
offsetof(ucontext_t,uc_mcontext.fpregs));
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_FPC_CSR),
|
||||
offsetof(ucontext_t,uc_mcontext.fpc_csr));
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
COMPILE_ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
|
||||
offsetof(ucontext_t,uc_mcontext.gregs),
|
||||
mcontext_gregs_offset);
|
||||
#define CHECK_REG(x) \
|
||||
COMPILE_ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_##x), \
|
||||
offsetof(ucontext_t,uc_mcontext.gregs[REG_##x]), reg_##x)
|
||||
CHECK_REG(R8);
|
||||
CHECK_REG(R9);
|
||||
CHECK_REG(R10);
|
||||
CHECK_REG(R11);
|
||||
CHECK_REG(R12);
|
||||
CHECK_REG(R13);
|
||||
CHECK_REG(R14);
|
||||
CHECK_REG(R15);
|
||||
CHECK_REG(RDI);
|
||||
CHECK_REG(RSI);
|
||||
CHECK_REG(RBP);
|
||||
CHECK_REG(RBX);
|
||||
CHECK_REG(RDX);
|
||||
CHECK_REG(RAX);
|
||||
CHECK_REG(RCX);
|
||||
CHECK_REG(RSP);
|
||||
CHECK_REG(RIP);
|
||||
|
||||
// sigcontext is an analog to mcontext_t. The layout should be the same.
|
||||
COMPILE_ASSERT_EQ(offsetof(mcontext_t,fpregs),
|
||||
offsetof(sigcontext,fpstate), sigcontext_fpstate);
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
// Check that _fpstate from asm/sigcontext.h is essentially the same
|
||||
// as _libc_fpstate.
|
||||
COMPILE_ASSERT_EQ(sizeof(_libc_fpstate), sizeof(_fpstate),
|
||||
sigcontext_fpstate_size);
|
||||
COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,cwd),offsetof(_fpstate,cwd),
|
||||
sigcontext_fpstate_cwd);
|
||||
COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,swd),offsetof(_fpstate,swd),
|
||||
sigcontext_fpstate_swd);
|
||||
COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,ftw),offsetof(_fpstate,twd),
|
||||
sigcontext_fpstate_twd);
|
||||
COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,fop),offsetof(_fpstate,fop),
|
||||
sigcontext_fpstate_fop);
|
||||
COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,rip),offsetof(_fpstate,rip),
|
||||
sigcontext_fpstate_rip);
|
||||
COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,rdp),offsetof(_fpstate,rdp),
|
||||
sigcontext_fpstate_rdp);
|
||||
COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,mxcsr),offsetof(_fpstate,mxcsr),
|
||||
sigcontext_fpstate_mxcsr);
|
||||
COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,mxcr_mask),
|
||||
offsetof(_fpstate,mxcsr_mask),
|
||||
sigcontext_fpstate_mxcsr_mask);
|
||||
COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,_st), offsetof(_fpstate,st_space),
|
||||
sigcontext_fpstate_stspace);
|
||||
COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,_xmm), offsetof(_fpstate,xmm_space),
|
||||
sigcontext_fpstate_xmm_space);
|
||||
#endif
|
||||
|
||||
COMPILE_ASSERT_EQ(MCONTEXT_FPREGS_PTR,
|
||||
offsetof(ucontext_t,uc_mcontext.fpregs),
|
||||
mcontext_fpregs_ptr);
|
||||
COMPILE_ASSERT_EQ(MCONTEXT_FPREGS_MEM, offsetof(ucontext_t,__fpregs_mem),
|
||||
mcontext_fpregs_mem);
|
||||
COMPILE_ASSERT_EQ(FPREGS_OFFSET_MXCSR,
|
||||
offsetof(std::remove_pointer<fpregset_t>::type,mxcsr),
|
||||
fpregs_offset_mxcsr);
|
||||
COMPILE_ASSERT_EQ(UCONTEXT_SIGMASK_OFFSET, offsetof(ucontext_t, uc_sigmask),
|
||||
ucontext_sigmask);
|
||||
#else
|
||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
|
||||
offsetof(ucontext_t,uc_mcontext.gregs));
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(AndroidUContext, SigmakOffset) {
|
||||
ASSERT_EQ(static_cast<size_t>(UCONTEXT_SIGMASK_OFFSET),
|
||||
offsetof(ucontext_t,uc_sigmask));
|
||||
}
|
||||
153
src/common/linux/ucontext_constants.h
Normal file
153
src/common/linux/ucontext_constants.h
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
// Copyright (c) 2012, Google Inc.
|
||||
// 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.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// This header can be included either from a C, C++ or Assembly file.
|
||||
// Its purpose is to contain constants that must match the offsets of
|
||||
// various fields in ucontext_t.
|
||||
//
|
||||
// They should match the definitions from signal.h.
|
||||
//
|
||||
// Used by src/common/linux/breakpad_getcontext.S
|
||||
// Tested by src/common/linux/breakpad_getcontext_unittest.cc
|
||||
//
|
||||
// This header should not be used by anything else.
|
||||
|
||||
#ifndef GOOGLEBREAKPAD_COMMON_LINUX_UCONTEXT_CONSTANTS_H
|
||||
#define GOOGLEBREAKPAD_COMMON_LINUX_UCONTEXT_CONSTANTS_H
|
||||
|
||||
#if defined(__arm__)
|
||||
|
||||
#define MCONTEXT_GREGS_OFFSET 32
|
||||
#define UCONTEXT_SIGMASK_OFFSET 104
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
#define UCONTEXT_SIGMASK_OFFSET 40
|
||||
|
||||
#define MCONTEXT_GREGS_OFFSET 184
|
||||
#define MCONTEXT_SP_OFFSET 432
|
||||
#define MCONTEXT_PC_OFFSET 440
|
||||
#define MCONTEXT_PSTATE_OFFSET 448
|
||||
#define MCONTEXT_EXTENSION_OFFSET 464
|
||||
|
||||
#define FPSIMD_MAGIC 0x46508001
|
||||
|
||||
#define FPSIMD_CONTEXT_MAGIC_OFFSET 0
|
||||
#define FPSIMD_CONTEXT_SIZE_OFFSET 4
|
||||
#define FPSIMD_CONTEXT_FPSR_OFFSET 8
|
||||
#define FPSIMD_CONTEXT_FPCR_OFFSET 12
|
||||
#define FPSIMD_CONTEXT_VREGS_OFFSET 16
|
||||
#define FPSIMD_CONTEXT_SIZE 528
|
||||
|
||||
#define REGISTER_SIZE 8
|
||||
#define SIMD_REGISTER_SIZE 16
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
#define MCONTEXT_GREGS_OFFSET 20
|
||||
#define MCONTEXT_GS_OFFSET (MCONTEXT_GREGS_OFFSET + 0*4)
|
||||
#define MCONTEXT_FS_OFFSET (MCONTEXT_GREGS_OFFSET + 1*4)
|
||||
#define MCONTEXT_ES_OFFSET (MCONTEXT_GREGS_OFFSET + 2*4)
|
||||
#define MCONTEXT_DS_OFFSET (MCONTEXT_GREGS_OFFSET + 3*4)
|
||||
#define MCONTEXT_EDI_OFFSET (MCONTEXT_GREGS_OFFSET + 4*4)
|
||||
#define MCONTEXT_ESI_OFFSET (MCONTEXT_GREGS_OFFSET + 5*4)
|
||||
#define MCONTEXT_EBP_OFFSET (MCONTEXT_GREGS_OFFSET + 6*4)
|
||||
#define MCONTEXT_ESP_OFFSET (MCONTEXT_GREGS_OFFSET + 7*4)
|
||||
#define MCONTEXT_EBX_OFFSET (MCONTEXT_GREGS_OFFSET + 8*4)
|
||||
#define MCONTEXT_EDX_OFFSET (MCONTEXT_GREGS_OFFSET + 9*4)
|
||||
#define MCONTEXT_ECX_OFFSET (MCONTEXT_GREGS_OFFSET + 10*4)
|
||||
#define MCONTEXT_EAX_OFFSET (MCONTEXT_GREGS_OFFSET + 11*4)
|
||||
#define MCONTEXT_TRAPNO_OFFSET (MCONTEXT_GREGS_OFFSET + 12*4)
|
||||
#define MCONTEXT_ERR_OFFSET (MCONTEXT_GREGS_OFFSET + 13*4)
|
||||
#define MCONTEXT_EIP_OFFSET (MCONTEXT_GREGS_OFFSET + 14*4)
|
||||
#define MCONTEXT_CS_OFFSET (MCONTEXT_GREGS_OFFSET + 15*4)
|
||||
#define MCONTEXT_EFL_OFFSET (MCONTEXT_GREGS_OFFSET + 16*4)
|
||||
#define MCONTEXT_UESP_OFFSET (MCONTEXT_GREGS_OFFSET + 17*4)
|
||||
#define MCONTEXT_SS_OFFSET (MCONTEXT_GREGS_OFFSET + 18*4)
|
||||
|
||||
#define UCONTEXT_SIGMASK_OFFSET 108
|
||||
|
||||
#define UCONTEXT_FPREGS_OFFSET 96
|
||||
#if defined(__BIONIC__)
|
||||
#define UCONTEXT_FPREGS_MEM_OFFSET 116
|
||||
#else
|
||||
#define UCONTEXT_FPREGS_MEM_OFFSET 236
|
||||
#endif
|
||||
|
||||
#elif defined(__mips__)
|
||||
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
#define MCONTEXT_PC_OFFSET 32
|
||||
#define MCONTEXT_GREGS_OFFSET 40
|
||||
#define MCONTEXT_FPREGS_OFFSET 296
|
||||
#define MCONTEXT_FPC_CSR 556
|
||||
#define UCONTEXT_SIGMASK_OFFSET 616
|
||||
#else
|
||||
#define MCONTEXT_GREGS_OFFSET 40
|
||||
#define MCONTEXT_FPREGS_OFFSET 296
|
||||
#define MCONTEXT_PC_OFFSET 616
|
||||
#define MCONTEXT_FPC_CSR 624
|
||||
#define UCONTEXT_SIGMASK_OFFSET 640
|
||||
#endif
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
#define MCONTEXT_GREGS_OFFSET 40
|
||||
#define UCONTEXT_SIGMASK_OFFSET 296
|
||||
|
||||
#define MCONTEXT_GREGS_R8 40
|
||||
#define MCONTEXT_GREGS_R9 48
|
||||
#define MCONTEXT_GREGS_R10 56
|
||||
#define MCONTEXT_GREGS_R11 64
|
||||
#define MCONTEXT_GREGS_R12 72
|
||||
#define MCONTEXT_GREGS_R13 80
|
||||
#define MCONTEXT_GREGS_R14 88
|
||||
#define MCONTEXT_GREGS_R15 96
|
||||
#define MCONTEXT_GREGS_RDI 104
|
||||
#define MCONTEXT_GREGS_RSI 112
|
||||
#define MCONTEXT_GREGS_RBP 120
|
||||
#define MCONTEXT_GREGS_RBX 128
|
||||
#define MCONTEXT_GREGS_RDX 136
|
||||
#define MCONTEXT_GREGS_RAX 144
|
||||
#define MCONTEXT_GREGS_RCX 152
|
||||
#define MCONTEXT_GREGS_RSP 160
|
||||
#define MCONTEXT_GREGS_RIP 168
|
||||
#define MCONTEXT_FPREGS_PTR 224
|
||||
#if defined(__BIONIC__)
|
||||
#define MCONTEXT_FPREGS_MEM 304
|
||||
#else
|
||||
#define MCONTEXT_FPREGS_MEM 424
|
||||
#endif
|
||||
#define FPREGS_OFFSET_MXCSR 24
|
||||
|
||||
#else
|
||||
#error "This header has not been ported for your CPU"
|
||||
#endif
|
||||
|
||||
#endif // GOOGLEBREAKPAD_COMMON_ANDROID_UCONTEXT_CONSTANTS_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue