diff options
-rw-r--r-- | src/client/linux/handler/exception_handler_unittest.cc | 7 | ||||
-rw-r--r-- | src/client/linux/minidump_writer/minidump_writer.cc | 4 | ||||
-rw-r--r-- | src/common/android/breakpad_getcontext.S | 79 | ||||
-rw-r--r-- | src/common/android/breakpad_getcontext_unittest.cc | 13 | ||||
-rw-r--r-- | src/common/android/include/sys/ucontext.h | 1 | ||||
-rw-r--r-- | src/common/android/include/sys/user.h | 19 | ||||
-rw-r--r-- | src/common/android/ucontext_constants.h | 7 | ||||
-rw-r--r-- | src/common/linux/dump_symbols.cc | 2 | ||||
-rw-r--r-- | src/google_breakpad/common/minidump_cpu_mips.h | 2 |
9 files changed, 126 insertions, 8 deletions
diff --git a/src/client/linux/handler/exception_handler_unittest.cc b/src/client/linux/handler/exception_handler_unittest.cc index 702a3adb..cfd50bb3 100644 --- a/src/client/linux/handler/exception_handler_unittest.cc +++ b/src/client/linux/handler/exception_handler_unittest.cc @@ -76,7 +76,12 @@ void FlushInstructionCache(const char* memory, uint32_t memory_size) { # error "Your operating system is not supported yet" # endif #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. cacheflush(const_cast<char*>(memory), memory_size, ICACHE); # else diff --git a/src/client/linux/minidump_writer/minidump_writer.cc b/src/client/linux/minidump_writer/minidump_writer.cc index 413e0807..ee759274 100644 --- a/src/client/linux/minidump_writer/minidump_writer.cc +++ b/src/client/linux/minidump_writer/minidump_writer.cc @@ -429,7 +429,11 @@ static void CPUFillFromUContext(MDRawContextMIPS* out, const ucontext* uc, out->cause = 0; // Not reported in signal context. 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]; +#endif out->float_save.fpcsr = uc->uc_mcontext.fpc_csr; out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused. diff --git a/src/common/android/breakpad_getcontext.S b/src/common/android/breakpad_getcontext.S index 13ccd46b..13f242d8 100644 --- a/src/common/android/breakpad_getcontext.S +++ b/src/common/android/breakpad_getcontext.S @@ -140,6 +140,85 @@ 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 #error "This file has not been ported for your CPU!" #endif diff --git a/src/common/android/breakpad_getcontext_unittest.cc b/src/common/android/breakpad_getcontext_unittest.cc index 3bafb9a6..c1b69c25 100644 --- a/src/common/android/breakpad_getcontext_unittest.cc +++ b/src/common/android/breakpad_getcontext_unittest.cc @@ -69,6 +69,19 @@ TEST(AndroidUContext, GRegsOffset) { 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)); #else ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET), offsetof(ucontext_t,uc_mcontext.gregs)); diff --git a/src/common/android/include/sys/ucontext.h b/src/common/android/include/sys/ucontext.h index 4a4e77c1..85c69ebd 100644 --- a/src/common/android/include/sys/ucontext.h +++ b/src/common/android/include/sys/ucontext.h @@ -128,7 +128,6 @@ typedef struct ucontext { #elif defined(__mips__) -// Not supported by Google Breakpad at this point, but just in case. typedef struct { uint32_t regmask; uint32_t status; diff --git a/src/common/android/include/sys/user.h b/src/common/android/include/sys/user.h index d13e5f6e..bc275bbe 100644 --- a/src/common/android/include/sys/user.h +++ b/src/common/android/include/sys/user.h @@ -120,8 +120,23 @@ struct user { #elif defined(__mips__) -// TODO: Provide some useful definitions here, once the rest of Breakpad -// requires them. +#define _ASM_USER_H 1 // Prevent <asm/user.h> conflicts + +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 # error "Unsupported Android CPU ABI" diff --git a/src/common/android/ucontext_constants.h b/src/common/android/ucontext_constants.h index 9c7a6971..c99c51fa 100644 --- a/src/common/android/ucontext_constants.h +++ b/src/common/android/ucontext_constants.h @@ -75,8 +75,11 @@ #elif defined(__mips__) -#define MCONTEXT_GREGS_OFFSET 0 -#define UCONTEXT_SIGMASK_OFFSET 0 +#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 #error "This header has not been ported for your CPU" diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc index 1f58d10f..75dcfd4c 100644 --- a/src/common/linux/dump_symbols.cc +++ b/src/common/linux/dump_symbols.cc @@ -617,7 +617,7 @@ bool LoadSymbols(const string& obj_file, // Linux C++ exception handling information can also provide // unwinding data. const Shdr* eh_frame_section = - FindElfSectionByName<ElfClass>(".eh_frame", debug_section_type, + FindElfSectionByName<ElfClass>(".eh_frame", SHT_PROGBITS, sections, names, names_end, elf_header->e_shnum); if (eh_frame_section) { diff --git a/src/google_breakpad/common/minidump_cpu_mips.h b/src/google_breakpad/common/minidump_cpu_mips.h index 7a6d0495..4378aac2 100644 --- a/src/google_breakpad/common/minidump_cpu_mips.h +++ b/src/google_breakpad/common/minidump_cpu_mips.h @@ -66,7 +66,7 @@ #ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__ #define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__ -#ifdef __mips__ +#if defined(__mips__) && !defined(__ANDROID__) typedef struct { uint64_t regs[32]; uint64_t lo; |