mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2024-11-24 04:55:45 +01:00
Adding mips support for Android.
Mips linux support has been added previously in r1212. Some additional changes are required to make breakpad functional on Android. BUG=none TEST=build, unittests, chrome test application Review URL: https://breakpad.appspot.com/632002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1215 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
ab52ca7d6e
commit
db877a13bb
@ -76,7 +76,12 @@ void FlushInstructionCache(const char* memory, uint32_t memory_size) {
|
|||||||
# error "Your operating system is not supported yet"
|
# error "Your operating system is not supported yet"
|
||||||
# endif
|
# endif
|
||||||
#elif defined(__mips__)
|
#elif defined(__mips__)
|
||||||
# if defined(__linux__)
|
# if defined(__ANDROID__)
|
||||||
|
// Provided by Android's <unistd.h>
|
||||||
|
long begin = reinterpret_cast<long>(memory);
|
||||||
|
long end = begin + static_cast<long>(memory_size);
|
||||||
|
cacheflush(begin, end, 0);
|
||||||
|
# elif defined(__linux__)
|
||||||
// See http://www.linux-mips.org/wiki/Cacheflush_Syscall.
|
// See http://www.linux-mips.org/wiki/Cacheflush_Syscall.
|
||||||
cacheflush(const_cast<char*>(memory), memory_size, ICACHE);
|
cacheflush(const_cast<char*>(memory), memory_size, ICACHE);
|
||||||
# else
|
# else
|
||||||
|
@ -429,7 +429,11 @@ static void CPUFillFromUContext(MDRawContextMIPS* out, const ucontext* uc,
|
|||||||
out->cause = 0; // Not reported in signal context.
|
out->cause = 0; // Not reported in signal context.
|
||||||
|
|
||||||
for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
|
for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
|
||||||
|
#if defined (__ANDROID__)
|
||||||
|
out->float_save.regs[i] = uc->uc_mcontext.fpregs[i];
|
||||||
|
#else
|
||||||
out->float_save.regs[i] = uc->uc_mcontext.fpregs.fp_r.fp_dregs[i];
|
out->float_save.regs[i] = uc->uc_mcontext.fpregs.fp_r.fp_dregs[i];
|
||||||
|
#endif
|
||||||
|
|
||||||
out->float_save.fpcsr = uc->uc_mcontext.fpc_csr;
|
out->float_save.fpcsr = uc->uc_mcontext.fpc_csr;
|
||||||
out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused.
|
out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused.
|
||||||
|
@ -140,6 +140,85 @@ breakpad_getcontext:
|
|||||||
|
|
||||||
.size breakpad_getcontext, . - breakpad_getcontext
|
.size breakpad_getcontext, . - breakpad_getcontext
|
||||||
|
|
||||||
|
#elif defined(__mips__)
|
||||||
|
|
||||||
|
#if _MIPS_SIM != _ABIO32
|
||||||
|
#error "Unsupported mips ISA. Only mips o32 is supported."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This implementation is inspired by implementation of getcontext in glibc.
|
||||||
|
#include <asm/asm.h>
|
||||||
|
#include <asm/regdef.h>
|
||||||
|
#include <asm/fpregdef.h>
|
||||||
|
#include <asm/unistd.h> // for __NR_rt_sigprocmask
|
||||||
|
|
||||||
|
#define _NSIG8 128 / 8
|
||||||
|
#define SIG_BLOCK 1
|
||||||
|
|
||||||
|
|
||||||
|
.text
|
||||||
|
LOCALS_NUM = 2 // save gp and ra on stack
|
||||||
|
FRAME_SIZE = ((LOCALS_NUM * SZREG) + ALSZ) & ALMASK
|
||||||
|
RA_FRAME_OFFSET = FRAME_SIZE - (1 * SZREG)
|
||||||
|
GP_FRAME_OFFSET = FRAME_SIZE - (2 * SZREG)
|
||||||
|
MCONTEXT_REG_SIZE = 8
|
||||||
|
|
||||||
|
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
|
||||||
|
sw ra, RA_FRAME_OFFSET(sp)
|
||||||
|
sw gp, GP_FRAME_OFFSET(sp)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
lw ra, RA_FRAME_OFFSET(sp)
|
||||||
|
lw gp, GP_FRAME_OFFSET(sp)
|
||||||
|
addiu sp, FRAME_SIZE
|
||||||
|
jr ra
|
||||||
|
|
||||||
|
END (breakpad_getcontext)
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "This file has not been ported for your CPU!"
|
#error "This file has not been ported for your CPU!"
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,6 +69,19 @@ TEST(AndroidUContext, GRegsOffset) {
|
|||||||
|
|
||||||
ASSERT_EQ(static_cast<size_t>(UCONTEXT_FPREGS_MEM_OFFSET),
|
ASSERT_EQ(static_cast<size_t>(UCONTEXT_FPREGS_MEM_OFFSET),
|
||||||
offsetof(ucontext_t,__fpregs_mem));
|
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));
|
||||||
#else
|
#else
|
||||||
ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
|
ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
|
||||||
offsetof(ucontext_t,uc_mcontext.gregs));
|
offsetof(ucontext_t,uc_mcontext.gregs));
|
||||||
|
@ -128,7 +128,6 @@ typedef struct ucontext {
|
|||||||
|
|
||||||
#elif defined(__mips__)
|
#elif defined(__mips__)
|
||||||
|
|
||||||
// Not supported by Google Breakpad at this point, but just in case.
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t regmask;
|
uint32_t regmask;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
|
@ -120,8 +120,23 @@ struct user {
|
|||||||
|
|
||||||
#elif defined(__mips__)
|
#elif defined(__mips__)
|
||||||
|
|
||||||
// TODO: Provide some useful definitions here, once the rest of Breakpad
|
#define _ASM_USER_H 1 // Prevent <asm/user.h> conflicts
|
||||||
// requires them.
|
|
||||||
|
struct user_regs_struct {
|
||||||
|
unsigned long long regs[32];
|
||||||
|
unsigned long long lo;
|
||||||
|
unsigned long long hi;
|
||||||
|
unsigned long long epc;
|
||||||
|
unsigned long long badvaddr;
|
||||||
|
unsigned long long status;
|
||||||
|
unsigned long long cause;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct user_fpregs_struct {
|
||||||
|
unsigned long long regs[32];
|
||||||
|
unsigned int fpcsr;
|
||||||
|
unsigned int fir;
|
||||||
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# error "Unsupported Android CPU ABI"
|
# error "Unsupported Android CPU ABI"
|
||||||
|
@ -75,8 +75,11 @@
|
|||||||
|
|
||||||
#elif defined(__mips__)
|
#elif defined(__mips__)
|
||||||
|
|
||||||
#define MCONTEXT_GREGS_OFFSET 0
|
#define MCONTEXT_PC_OFFSET 32
|
||||||
#define UCONTEXT_SIGMASK_OFFSET 0
|
#define MCONTEXT_GREGS_OFFSET 40
|
||||||
|
#define MCONTEXT_FPREGS_OFFSET 296
|
||||||
|
#define MCONTEXT_FPC_CSR 556
|
||||||
|
#define UCONTEXT_SIGMASK_OFFSET 616
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "This header has not been ported for your CPU"
|
#error "This header has not been ported for your CPU"
|
||||||
|
@ -617,7 +617,7 @@ bool LoadSymbols(const string& obj_file,
|
|||||||
// Linux C++ exception handling information can also provide
|
// Linux C++ exception handling information can also provide
|
||||||
// unwinding data.
|
// unwinding data.
|
||||||
const Shdr* eh_frame_section =
|
const Shdr* eh_frame_section =
|
||||||
FindElfSectionByName<ElfClass>(".eh_frame", debug_section_type,
|
FindElfSectionByName<ElfClass>(".eh_frame", SHT_PROGBITS,
|
||||||
sections, names, names_end,
|
sections, names, names_end,
|
||||||
elf_header->e_shnum);
|
elf_header->e_shnum);
|
||||||
if (eh_frame_section) {
|
if (eh_frame_section) {
|
||||||
|
@ -66,7 +66,7 @@
|
|||||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__
|
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__
|
||||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__
|
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__
|
||||||
|
|
||||||
#ifdef __mips__
|
#if defined(__mips__) && !defined(__ANDROID__)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t regs[32];
|
uint64_t regs[32];
|
||||||
uint64_t lo;
|
uint64_t lo;
|
||||||
|
Loading…
Reference in New Issue
Block a user