aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/linux/handler/exception_handler_unittest.cc7
-rw-r--r--src/client/linux/minidump_writer/minidump_writer.cc4
-rw-r--r--src/common/android/breakpad_getcontext.S79
-rw-r--r--src/common/android/breakpad_getcontext_unittest.cc13
-rw-r--r--src/common/android/include/sys/ucontext.h1
-rw-r--r--src/common/android/include/sys/user.h19
-rw-r--r--src/common/android/ucontext_constants.h7
-rw-r--r--src/common/linux/dump_symbols.cc2
-rw-r--r--src/google_breakpad/common/minidump_cpu_mips.h2
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;