mirror of
https://git.suyu.dev/suyu/breakpad.git
synced 2026-01-03 13:14:45 +01:00
[MIPS]: Use mcontext_t structure for MIPS
This change removes user_regs_struct and user_fpregs_struct structures for mips and uses mcontext_t instead. R=fdegans@chromium.org, mark@chromium.org, rmcilroy@chromium.org Review URL: https://breakpad.appspot.com/3744002 Patch from Gordana Cmiljanovic <Gordana.Cmiljanovic@imgtec.com>. git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1452 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
9c6af3e29c
commit
0f27af628f
9 changed files with 134 additions and 160 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue