diff options
-rw-r--r-- | src/client/linux/dump_writer_common/thread_info.cc | 65 | ||||
-rw-r--r-- | src/client/linux/dump_writer_common/thread_info.h | 13 | ||||
-rw-r--r-- | src/client/linux/minidump_writer/linux_core_dumper.cc | 27 | ||||
-rw-r--r-- | src/client/linux/minidump_writer/linux_ptrace_dumper.cc | 38 | ||||
-rw-r--r-- | src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc | 2 | ||||
-rw-r--r-- | src/common/android/include/sys/procfs.h | 3 | ||||
-rw-r--r-- | src/common/android/include/sys/user.h | 78 | ||||
-rw-r--r-- | src/google_breakpad/common/minidump_cpu_mips.h | 22 | ||||
-rw-r--r-- | src/tools/linux/md2core/minidump-2-core.cc | 46 |
9 files changed, 134 insertions, 160 deletions
diff --git a/src/client/linux/dump_writer_common/thread_info.cc b/src/client/linux/dump_writer_common/thread_info.cc index a3072b6c..9956d445 100644 --- a/src/client/linux/dump_writer_common/thread_info.cc +++ b/src/client/linux/dump_writer_common/thread_info.cc @@ -30,6 +30,7 @@ #include "client/linux/dump_writer_common/thread_info.h" #include <string.h> +#include <assert.h> #include "common/linux/linux_libc_support.h" #include "google_breakpad/common/minidump_format.h" @@ -230,37 +231,69 @@ void ThreadInfo::FillCPUContext(RawContextCPU* out) const { #elif defined(__mips__) uintptr_t ThreadInfo::GetInstructionPointer() const { - return regs.epc; + return mcontext.pc; } void ThreadInfo::FillCPUContext(RawContextCPU* out) const { out->context_flags = MD_CONTEXT_MIPS_FULL; for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i) - out->iregs[i] = regs.regs[i]; + out->iregs[i] = mcontext.gregs[i]; - out->mdhi = regs.hi; - out->mdlo = regs.lo; + out->mdhi = mcontext.mdhi; + out->mdlo = mcontext.mdlo; + out->dsp_control = mcontext.dsp; - for (int i = 0; i < MD_CONTEXT_MIPS_DSP_COUNT; ++i) { - out->hi[i] = hi[i]; - out->lo[i] = lo[i]; - } - out->dsp_control = dsp_control; + out->hi[0] = mcontext.hi1; + out->lo[0] = mcontext.lo1; + out->hi[1] = mcontext.hi2; + out->lo[1] = mcontext.lo2; + out->hi[2] = mcontext.hi3; + out->lo[2] = mcontext.lo3; - out->epc = regs.epc; - out->badvaddr = regs.badvaddr; - out->status = regs.status; - out->cause = regs.cause; + out->epc = mcontext.pc; + out->badvaddr = 0; // Not stored in mcontext + out->status = 0; // Not stored in mcontext + out->cause = 0; // Not stored in mcontext for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i) - out->float_save.regs[i] = fpregs.regs[i]; + out->float_save.regs[i] = mcontext.fpregs.fp_r.fp_fregs[i]._fp_fregs; - out->float_save.fpcsr = fpregs.fpcsr; + out->float_save.fpcsr = mcontext.fpc_csr; #if _MIPS_SIM == _ABIO32 - out->float_save.fir = fpregs.fir; + out->float_save.fir = mcontext.fpc_eir; #endif } +#endif // __mips__ + +void ThreadInfo::GetGeneralPurposeRegisters(void** gp_regs, size_t* size) { + assert(gp_regs || size); +#if defined(__mips__) + if (gp_regs) + *gp_regs = mcontext.gregs; + if (size) + *size = sizeof(mcontext.gregs); +#else + if (gp_regs) + *gp_regs = ®s; + if (size) + *size = sizeof(regs); #endif +} + +void ThreadInfo::GetFloatingPointRegisters(void** fp_regs, size_t* size) { + assert(fp_regs || size); +#if defined(__mips__) + if (fp_regs) + *fp_regs = &mcontext.fpregs; + if (size) + *size = sizeof(mcontext.fpregs); +#else + if (fp_regs) + *fp_regs = &fpregs; + if (size) + *size = sizeof(fpregs); +#endif +} } // namespace google_breakpad diff --git a/src/client/linux/dump_writer_common/thread_info.h b/src/client/linux/dump_writer_common/thread_info.h index cf6d0101..a05ffea2 100644 --- a/src/client/linux/dump_writer_common/thread_info.h +++ b/src/client/linux/dump_writer_common/thread_info.h @@ -69,11 +69,8 @@ struct ThreadInfo { struct user_pt_regs regs; struct user_fpsimd_state fpregs; #elif defined(__mips__) - user_regs_struct regs; - user_fpregs_struct fpregs; - uint32_t hi[3]; - uint32_t lo[3]; - uint32_t dsp_control; + // Use the structure defined in <sys/ucontext.h>. + mcontext_t mcontext; #endif // Returns the instruction pointer (platform-dependent impl.). @@ -81,6 +78,12 @@ struct ThreadInfo { // Fills a RawContextCPU using the context in the ThreadInfo object. void FillCPUContext(RawContextCPU* out) const; + + // Returns the pointer and size of general purpose register area. + void GetGeneralPurposeRegisters(void** gp_regs, size_t* size); + + // Returns the pointer and size of float point register area. + void GetFloatingPointRegisters(void** fp_regs, size_t* size); }; } // namespace google_breakpad diff --git a/src/client/linux/minidump_writer/linux_core_dumper.cc b/src/client/linux/minidump_writer/linux_core_dumper.cc index b8d90af6..d7328245 100644 --- a/src/client/linux/minidump_writer/linux_core_dumper.cc +++ b/src/client/linux/minidump_writer/linux_core_dumper.cc @@ -38,6 +38,10 @@ #include <stdio.h> #include <string.h> #include <sys/procfs.h> +#if defined(__mips__) && defined(__ANDROID__) +// To get register definitions. +#include <asm/reg.h> +#endif #include "common/linux/linux_libc_support.h" @@ -105,7 +109,7 @@ bool LinuxCoreDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) { memcpy(&stack_pointer, &info->regs.sp, sizeof(info->regs.sp)); #elif defined(__mips__) stack_pointer = - reinterpret_cast<uint8_t*>(info->regs.regs[MD_CONTEXT_MIPS_REG_SP]); + reinterpret_cast<uint8_t*>(info->mcontext.gregs[MD_CONTEXT_MIPS_REG_SP]); #else #error "This code hasn't been ported to your platform yet." #endif @@ -191,18 +195,19 @@ bool LinuxCoreDumper::EnumerateThreads() { info.tgid = status->pr_pgrp; info.ppid = status->pr_ppid; #if defined(__mips__) +#if defined(__ANDROID__) + for (int i = EF_R0; i <= EF_R31; i++) + info.mcontext.gregs[i - EF_R0] = status->pr_reg[i]; +#else // __ANDROID__ for (int i = EF_REG0; i <= EF_REG31; i++) - info.regs.regs[i - EF_REG0] = status->pr_reg[i]; - - info.regs.lo = status->pr_reg[EF_LO]; - info.regs.hi = status->pr_reg[EF_HI]; - info.regs.epc = status->pr_reg[EF_CP0_EPC]; - info.regs.badvaddr = status->pr_reg[EF_CP0_BADVADDR]; - info.regs.status = status->pr_reg[EF_CP0_STATUS]; - info.regs.cause = status->pr_reg[EF_CP0_CAUSE]; -#else + info.mcontext.gregs[i - EF_REG0] = status->pr_reg[i]; +#endif // __ANDROID__ + info.mcontext.mdlo = status->pr_reg[EF_LO]; + info.mcontext.mdhi = status->pr_reg[EF_HI]; + info.mcontext.pc = status->pr_reg[EF_CP0_EPC]; +#else // __mips__ memcpy(&info.regs, status->pr_reg, sizeof(info.regs)); -#endif +#endif // __mips__ if (first_thread) { crash_thread_ = pid; crash_signal_ = status->pr_info.si_signo; diff --git a/src/client/linux/minidump_writer/linux_ptrace_dumper.cc b/src/client/linux/minidump_writer/linux_ptrace_dumper.cc index 7a2cfb9f..5ea0050d 100644 --- a/src/client/linux/minidump_writer/linux_ptrace_dumper.cc +++ b/src/client/linux/minidump_writer/linux_ptrace_dumper.cc @@ -190,23 +190,25 @@ bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) { #ifdef PTRACE_GETREGSET struct iovec io; - io.iov_base = &info->regs; - io.iov_len = sizeof(info->regs); + info->GetGeneralPurposeRegisters(&io.iov_base, &io.iov_len); if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_PRSTATUS, (void*)&io) == -1) { return false; } - io.iov_base = &info->fpregs; - io.iov_len = sizeof(info->fpregs); + info->GetFloatingPointRegisters(&io.iov_base, &io.iov_len); if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_FPREGSET, (void*)&io) == -1) { return false; } -#else - if (sys_ptrace(PTRACE_GETREGS, tid, NULL, &info->regs) == -1) { +#else // PTRACE_GETREGSET + void* gp_addr; + info->GetGeneralPurposeRegisters(&gp_addr, NULL); + if (sys_ptrace(PTRACE_GETREGS, tid, NULL, gp_addr) == -1) { return false; } - if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, &info->fpregs) == -1) { + void* fp_addr; + info->GetFloatingPointRegisters(&fp_addr, NULL); + if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, fp_addr) == -1) { return false; } #endif @@ -241,14 +243,20 @@ bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) { #endif #if defined(__mips__) - for (int i = 0; i < 3; ++i) { - sys_ptrace(PTRACE_PEEKUSER, tid, - reinterpret_cast<void*>(DSP_BASE + (i * 2)), &info->hi[i]); - sys_ptrace(PTRACE_PEEKUSER, tid, - reinterpret_cast<void*>(DSP_BASE + (i * 2) + 1), &info->lo[i]); - } sys_ptrace(PTRACE_PEEKUSER, tid, - reinterpret_cast<void*>(DSP_CONTROL), &info->dsp_control); + reinterpret_cast<void*>(DSP_BASE), &info->mcontext.hi1); + sys_ptrace(PTRACE_PEEKUSER, tid, + reinterpret_cast<void*>(DSP_BASE + 1), &info->mcontext.lo1); + sys_ptrace(PTRACE_PEEKUSER, tid, + reinterpret_cast<void*>(DSP_BASE + 2), &info->mcontext.hi2); + sys_ptrace(PTRACE_PEEKUSER, tid, + reinterpret_cast<void*>(DSP_BASE + 3), &info->mcontext.lo2); + sys_ptrace(PTRACE_PEEKUSER, tid, + reinterpret_cast<void*>(DSP_BASE + 4), &info->mcontext.hi3); + sys_ptrace(PTRACE_PEEKUSER, tid, + reinterpret_cast<void*>(DSP_BASE + 5), &info->mcontext.lo3); + sys_ptrace(PTRACE_PEEKUSER, tid, + reinterpret_cast<void*>(DSP_CONTROL), &info->mcontext.dsp); #endif const uint8_t* stack_pointer; @@ -262,7 +270,7 @@ bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) { my_memcpy(&stack_pointer, &info->regs.sp, sizeof(info->regs.sp)); #elif defined(__mips__) stack_pointer = - reinterpret_cast<uint8_t*>(info->regs.regs[MD_CONTEXT_MIPS_REG_SP]); + reinterpret_cast<uint8_t*>(info->mcontext.gregs[MD_CONTEXT_MIPS_REG_SP]); #else #error "This code hasn't been ported to your platform yet." #endif diff --git a/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc b/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc index 010ec67c..838ea5f6 100644 --- a/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc +++ b/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc @@ -441,7 +441,7 @@ TEST(LinuxPtraceDumperTest, VerifyStackReadWithMultipleThreads) { pid_t* process_tid_location = (pid_t*)(one_thread.regs.rcx); #elif defined(__mips__) pid_t* process_tid_location = - reinterpret_cast<pid_t*>(one_thread.regs.regs[1]); + reinterpret_cast<pid_t*>(one_thread.mcontext.gregs[1]); #else #error This test has not been ported to this platform. #endif diff --git a/src/common/android/include/sys/procfs.h b/src/common/android/include/sys/procfs.h index bedae34a..27223ea3 100644 --- a/src/common/android/include/sys/procfs.h +++ b/src/common/android/include/sys/procfs.h @@ -38,6 +38,9 @@ #include <asm/ptrace.h> #include <sys/cdefs.h> +#if defined (__mips__) +#include <sys/types.h> +#endif #include <sys/user.h> #include <unistd.h> diff --git a/src/common/android/include/sys/user.h b/src/common/android/include/sys/user.h index 05b22ced..24a0243a 100644 --- a/src/common/android/include/sys/user.h +++ b/src/common/android/include/sys/user.h @@ -33,88 +33,12 @@ // The purpose of this file is to glue the mismatching headers (Android NDK vs // glibc) and therefore avoid doing otherwise awkward #ifdefs in the code. // The following quirks are currently handled by this file: -// - MIPS: Keep using forked definitions of user.h structs. The definition in -// the NDK is completely different. Internal bug b/18097715 // - i386: Use the Android NDK but alias user_fxsr_struct > user_fpxregs_struct. // - x86_64: Override a typo in user_fpregs_struct (mxcsr_mask -> mxcr_mask). // The typo has been fixed in NDK r10d, but a preprocessor workaround is // required to make breakpad build with r10c and lower (more details below). // - Other platforms: Just use the Android NDK unchanged. -#ifdef __mips__ -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -#define EF_REG0 6 -#define EF_REG1 7 -#define EF_REG2 8 -#define EF_REG3 9 -#define EF_REG4 10 -#define EF_REG5 11 -#define EF_REG6 12 -#define EF_REG7 13 -#define EF_REG8 14 -#define EF_REG9 15 -#define EF_REG10 16 -#define EF_REG11 17 -#define EF_REG12 18 -#define EF_REG13 19 -#define EF_REG14 20 -#define EF_REG15 21 -#define EF_REG16 22 -#define EF_REG17 23 -#define EF_REG18 24 -#define EF_REG19 25 -#define EF_REG20 26 -#define EF_REG21 27 -#define EF_REG22 28 -#define EF_REG23 29 -#define EF_REG24 30 -#define EF_REG25 31 - -/* - * k0/k1 unsaved - */ -#define EF_REG26 32 -#define EF_REG27 33 -#define EF_REG28 34 -#define EF_REG29 35 -#define EF_REG30 36 -#define EF_REG31 37 - -/* - * Saved special registers - */ -#define EF_LO 38 -#define EF_HI 39 -#define EF_CP0_EPC 40 -#define EF_CP0_BADVADDR 41 -#define EF_CP0_STATUS 42 -#define EF_CP0_CAUSE 43 - -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; -}; - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#else // __mips__ - // TODO(primiano): remove this after Chromium has stably rolled to NDK r10d. // Historical context: NDK releases < r10d had a typo in sys/user.h (mxcsr_mask // instead of mxcr_mask), which is fixed in r10d. However, just switching to use @@ -143,6 +67,4 @@ typedef struct user_fxsr_struct user_fpxregs_struct; #endif // __cplusplus #endif // __i386__ -#endif // __mips__ - #endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_USER_H diff --git a/src/google_breakpad/common/minidump_cpu_mips.h b/src/google_breakpad/common/minidump_cpu_mips.h index 4378aac2..6cbe3023 100644 --- a/src/google_breakpad/common/minidump_cpu_mips.h +++ b/src/google_breakpad/common/minidump_cpu_mips.h @@ -66,24 +66,6 @@ #ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__ #define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__ -#if defined(__mips__) && !defined(__ANDROID__) -typedef struct { - uint64_t regs[32]; - uint64_t lo; - uint64_t hi; - uint64_t epc; - uint64_t badvaddr; - uint64_t status; - uint64_t cause; -} user_regs_struct; - -typedef struct { - uint64_t regs[32]; - uint32_t fpcsr; - uint32_t fir; -} user_fpregs_struct; -#endif - #define MD_CONTEXT_MIPS_GPR_COUNT 32 #define MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT 32 #define MD_CONTEXT_MIPS_DSP_COUNT 3 @@ -112,8 +94,8 @@ typedef struct { /* 32 64-bit integer registers, r0..r31. * Note the following fixed uses: - * r30 is the stack pointer. - * r31 is the return address (link register). + * r29 is the stack pointer. + * r31 is the return address. */ uint64_t iregs[MD_CONTEXT_MIPS_GPR_COUNT]; diff --git a/src/tools/linux/md2core/minidump-2-core.cc b/src/tools/linux/md2core/minidump-2-core.cc index bcb0076e..21d410bc 100644 --- a/src/tools/linux/md2core/minidump-2-core.cc +++ b/src/tools/linux/md2core/minidump-2-core.cc @@ -81,6 +81,9 @@ // containing core registers, while they use 'user_regs_struct' on other // architectures. This file-local typedef simplifies the source code. typedef user_regs user_regs_struct; +#elif defined (__mips__) +// This file-local typedef simplifies the source code. +typedef gregset_t user_regs_struct; #endif using google_breakpad::MDTypeHelper; @@ -208,13 +211,17 @@ struct CrashedProcess { struct Thread { pid_t tid; +#if defined(__mips__) + mcontext_t mcontext; +#else // __mips__ user_regs_struct regs; -#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) +#if defined(__i386__) || defined(__x86_64__) user_fpregs_struct fpregs; -#endif +#endif // __i386__ || __x86_64__ #if defined(__i386__) user_fpxregs_struct fpxregs; -#endif +#endif // __i386__ +#endif // __mips__ uintptr_t stack_addr; const uint8_t* stack; size_t stack_length; @@ -371,21 +378,28 @@ ParseThreadRegisters(CrashedProcess::Thread* thread, const MDRawContextMIPS* rawregs = range.GetData<MDRawContextMIPS>(0); for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i) - thread->regs.regs[i] = rawregs->iregs[i]; + thread->mcontext.gregs[i] = rawregs->iregs[i]; + + thread->mcontext.pc = rawregs->epc; - thread->regs.lo = rawregs->mdlo; - thread->regs.hi = rawregs->mdhi; - thread->regs.epc = rawregs->epc; - thread->regs.badvaddr = rawregs->badvaddr; - thread->regs.status = rawregs->status; - thread->regs.cause = rawregs->cause; + thread->mcontext.mdlo = rawregs->mdlo; + thread->mcontext.mdhi = rawregs->mdhi; - for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i) - thread->fpregs.regs[i] = rawregs->float_save.regs[i]; + thread->mcontext.hi1 = rawregs->hi[0]; + thread->mcontext.lo1 = rawregs->lo[0]; + thread->mcontext.hi2 = rawregs->hi[1]; + thread->mcontext.lo2 = rawregs->lo[1]; + thread->mcontext.hi3 = rawregs->hi[2]; + thread->mcontext.lo3 = rawregs->lo[2]; - thread->fpregs.fpcsr = rawregs->float_save.fpcsr; + for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i) { + thread->mcontext.fpregs.fp_r.fp_fregs[i]._fp_fregs = + rawregs->float_save.regs[i]; + } + + thread->mcontext.fpc_csr = rawregs->float_save.fpcsr; #if _MIPS_SIM == _ABIO32 - thread->fpregs.fir = rawregs->float_save.fir; + thread->mcontext.fpc_eir = rawregs->float_save.fir; #endif } #else @@ -751,7 +765,11 @@ WriteThread(const CrashedProcess::Thread& thread, int fatal_signal) { pr.pr_info.si_signo = fatal_signal; pr.pr_cursig = fatal_signal; pr.pr_pid = thread.tid; +#if defined(__mips__) + memcpy(&pr.pr_reg, &thread.mcontext.gregs, sizeof(user_regs_struct)); +#else memcpy(&pr.pr_reg, &thread.regs, sizeof(user_regs_struct)); +#endif Nhdr nhdr; memset(&nhdr, 0, sizeof(nhdr)); |