mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-01-10 18:57:50 +00:00
Add Arm64 version of breakpad_getcontext for Android.
This CL adds breakpad_getcontext support for Arm64 to Android. The assembly is based on getcontext.S in glibc. BUG=354405,335641 R=mark@chromium.org Review URL: https://breakpad.appspot.com/1384002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1302 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
83b9a28cf9
commit
410b7024e3
|
@ -398,8 +398,15 @@ bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) {
|
|||
CrashContext context;
|
||||
memcpy(&context.siginfo, info, sizeof(siginfo_t));
|
||||
memcpy(&context.context, uc, sizeof(struct ucontext));
|
||||
#if !defined(__ARM_EABI__) && !defined(__aarch64__) && !defined(__mips__)
|
||||
// FP state is not part of user ABI on ARM or ARM64 Linux.
|
||||
#if defined(__aarch64__)
|
||||
struct ucontext *uc_ptr = (struct ucontext*)uc;
|
||||
struct fpsimd_context *fp_ptr =
|
||||
(struct fpsimd_context*)&uc_ptr->uc_mcontext.__reserved;
|
||||
if (fp_ptr->head.magic == FPSIMD_MAGIC) {
|
||||
memcpy(&context.float_state, fp_ptr, sizeof(context.float_state));
|
||||
}
|
||||
#elif !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
// FP state is not part of user ABI on ARM Linux.
|
||||
// In case of MIPS Linux FP state is already part of struct ucontext
|
||||
// and 'float_state' is not a member of CrashContext.
|
||||
struct ucontext *uc_ptr = (struct ucontext*)uc;
|
||||
|
|
|
@ -190,11 +190,11 @@ class ExceptionHandler {
|
|||
siginfo_t siginfo;
|
||||
pid_t tid; // the crashing thread.
|
||||
struct ucontext context;
|
||||
#if !defined(__ARM_EABI__) && !defined(__aarch64__) && !defined(__mips__)
|
||||
// #ifdef this out because FP state is not part of user ABI for Linux ARM
|
||||
// or ARM64. In case of MIPS Linux FP state is already part of struct
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
// #ifdef this out because FP state is not part of user ABI for Linux ARM.
|
||||
// In case of MIPS Linux FP state is already part of struct
|
||||
// ucontext so 'float_state' is not required.
|
||||
struct _libc_fpstate float_state;
|
||||
fpstate_t float_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -344,8 +344,7 @@ void CPUFillFromThreadInfo(MDRawContextARM* out,
|
|||
#endif
|
||||
}
|
||||
|
||||
void CPUFillFromUContext(MDRawContextARM* out, const ucontext* uc,
|
||||
const struct _libc_fpstate* fpregs) {
|
||||
void CPUFillFromUContext(MDRawContextARM* out, const ucontext* uc) {
|
||||
out->context_flags = MD_CONTEXT_ARM_FULL;
|
||||
|
||||
out->iregs[0] = uc->uc_mcontext.arm_r0;
|
||||
|
@ -383,7 +382,7 @@ void CPUFillFromThreadInfo(MDRawContextARM64* out,
|
|||
}
|
||||
|
||||
void CPUFillFromUContext(MDRawContextARM64* out, const ucontext* uc,
|
||||
const struct _libc_fpstate* fpregs) {
|
||||
const struct fpsimd_context* fpregs) {
|
||||
// TODO(rmcilroy): Implement for arm64.
|
||||
}
|
||||
|
||||
|
@ -418,8 +417,7 @@ static void CPUFillFromThreadInfo(MDRawContextMIPS* out,
|
|||
out->float_save.fir = info.fpregs.fir;
|
||||
}
|
||||
|
||||
static void CPUFillFromUContext(MDRawContextMIPS* out, const ucontext* uc,
|
||||
const struct _libc_fpstate* fpregs) {
|
||||
static void CPUFillFromUContext(MDRawContextMIPS* out, const ucontext* uc) {
|
||||
out->context_flags = MD_CONTEXT_MIPS_FULL;
|
||||
|
||||
for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
|
||||
|
@ -483,11 +481,8 @@ class MinidumpWriter {
|
|||
: fd_(minidump_fd),
|
||||
path_(minidump_path),
|
||||
ucontext_(context ? &context->context : NULL),
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__) && !defined(__aarch64__)
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
float_state_(context ? &context->float_state : NULL),
|
||||
#else
|
||||
// TODO: fix this after fixing ExceptionHandler
|
||||
float_state_(NULL),
|
||||
#endif
|
||||
dumper_(dumper),
|
||||
minidump_size_limit_(-1),
|
||||
|
@ -848,7 +843,11 @@ class MinidumpWriter {
|
|||
if (!cpu.Allocate())
|
||||
return false;
|
||||
my_memset(cpu.get(), 0, sizeof(RawContextCPU));
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
CPUFillFromUContext(cpu.get(), ucontext_, float_state_);
|
||||
#else
|
||||
CPUFillFromUContext(cpu.get(), ucontext_);
|
||||
#endif
|
||||
if (stack_copy)
|
||||
PopSeccompStackFrame(cpu.get(), thread, stack_copy);
|
||||
thread.thread_context = cpu.location();
|
||||
|
@ -1756,7 +1755,9 @@ class MinidumpWriter {
|
|||
const char* path_; // Path to the file where the minidum should be written.
|
||||
|
||||
const struct ucontext* const ucontext_; // also from the signal handler
|
||||
const struct _libc_fpstate* const float_state_; // ditto
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
const google_breakpad::fpstate_t* const float_state_; // ditto
|
||||
#endif
|
||||
LinuxDumper* dumper_;
|
||||
MinidumpFileWriter minidump_writer_;
|
||||
off_t minidump_size_limit_;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ucontext.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <list>
|
||||
|
@ -52,6 +53,12 @@ struct MappingEntry {
|
|||
// A list of <MappingInfo, GUID>
|
||||
typedef std::list<MappingEntry> MappingList;
|
||||
|
||||
#if defined(__aarch64__)
|
||||
typedef struct fpsimd_context fpstate_t;
|
||||
#elif !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
typedef struct _libc_fpstate fpstate_t;
|
||||
#endif
|
||||
|
||||
// These entries store a list of memory regions that the client wants included
|
||||
// in the minidump.
|
||||
struct AppMemory {
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
/* int getcontext (ucontext_t *ucp) */
|
||||
|
||||
#ifdef __arm__
|
||||
#if defined(__arm__)
|
||||
|
||||
.text
|
||||
.global breakpad_getcontext
|
||||
|
@ -50,7 +50,7 @@ breakpad_getcontext:
|
|||
|
||||
/* r12 is a scratch register, don't save it */
|
||||
|
||||
/* Save sp and lr explicitely. */
|
||||
/* 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)]
|
||||
|
@ -59,7 +59,7 @@ breakpad_getcontext:
|
|||
/* Save the caller's address in 'pc' */
|
||||
str lr, [r0, #(MCONTEXT_GREGS_OFFSET + 15*4)]
|
||||
|
||||
/* Save ucontext_t* pointer accross next call */
|
||||
/* Save ucontext_t* pointer across next call */
|
||||
mov r4, r0
|
||||
|
||||
/* Call sigprocmask(SIG_BLOCK, NULL, &(ucontext->uc_sigmask)) */
|
||||
|
@ -88,6 +88,90 @@ breakpad_getcontext:
|
|||
.fnend
|
||||
.size breakpad_getcontext, . - breakpad_getcontext
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
.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
|
||||
|
@ -140,10 +224,6 @@ breakpad_getcontext:
|
|||
|
||||
.size breakpad_getcontext, . - breakpad_getcontext
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
// TODO(rmcilroy): Implement for arm64.
|
||||
|
||||
#elif defined(__mips__)
|
||||
|
||||
#if _MIPS_SIM != _ABIO32
|
||||
|
|
|
@ -47,8 +47,28 @@
|
|||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
#define MCONTEXT_GREGS_OFFSET 56
|
||||
#define UCONTEXT_SIGMASK_OFFSET 40
|
||||
#define UCONTEXT_SIGMASK_OFFSET 40
|
||||
|
||||
#define MCONTEXT_GREGS_OFFSET 56
|
||||
#define MCONTEXT_SP_OFFSET 304
|
||||
#define MCONTEXT_PC_OFFSET 312
|
||||
#define MCONTEXT_PSTATE_OFFSET 320
|
||||
#define MCONTEXT_EXTENSION_OFFSET 336
|
||||
|
||||
#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
|
||||
|
||||
#define _NSIG 64
|
||||
#define __NR_rt_sigprocmask 135
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
|
|
Loading…
Reference in a new issue