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:
gordana.cmiljanovic@imgtec.com 2013-09-25 08:18:03 +00:00
parent ab52ca7d6e
commit db877a13bb
9 changed files with 126 additions and 8 deletions

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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));

View File

@ -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;

View File

@ -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"

View File

@ -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"

View File

@ -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) {

View File

@ -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;