aboutsummaryrefslogtreecommitdiff
path: root/src/client/linux/minidump_writer
diff options
context:
space:
mode:
authorgordana.cmiljanovic@imgtec.com <gordana.cmiljanovic@imgtec.com@4c0a9323-5329-0410-9bdc-e9ce6186880e>2013-09-11 11:37:04 +0000
committergordana.cmiljanovic@imgtec.com <gordana.cmiljanovic@imgtec.com@4c0a9323-5329-0410-9bdc-e9ce6186880e>2013-09-11 11:37:04 +0000
commitf78839c15730533fc433c50ea83a3afea835c245 (patch)
tree9b3136dd94e663af23394356679b78467fddd5b7 /src/client/linux/minidump_writer
parentFixing minidump_dump to handle nacl dumps. (diff)
downloadbreakpad-f78839c15730533fc433c50ea83a3afea835c245.tar.xz
Adding support for mips.
Support for mips cpu is added to all breakapad targets including unittests. BUG=none TEST=unittests Review URL: https://breakpad.appspot.com/614002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1212 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/client/linux/minidump_writer')
-rw-r--r--src/client/linux/minidump_writer/linux_core_dumper.cc3
-rw-r--r--src/client/linux/minidump_writer/linux_dumper.h8
-rw-r--r--src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc2
-rw-r--r--src/client/linux/minidump_writer/linux_ptrace_dumper.cc14
-rw-r--r--src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc5
-rw-r--r--src/client/linux/minidump_writer/minidump_writer.cc85
-rw-r--r--src/client/linux/minidump_writer/minidump_writer_unittest.cc6
7 files changed, 118 insertions, 5 deletions
diff --git a/src/client/linux/minidump_writer/linux_core_dumper.cc b/src/client/linux/minidump_writer/linux_core_dumper.cc
index 47cc26c0..f5b19d10 100644
--- a/src/client/linux/minidump_writer/linux_core_dumper.cc
+++ b/src/client/linux/minidump_writer/linux_core_dumper.cc
@@ -99,6 +99,9 @@ bool LinuxCoreDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
#elif defined(__ARM_EABI__)
memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
+#elif defined(__mips__)
+ stack_pointer =
+ reinterpret_cast<uint8_t*>(info->regs.regs[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_dumper.h b/src/client/linux/minidump_writer/linux_dumper.h
index a4a3ab5a..2bb4cac7 100644
--- a/src/client/linux/minidump_writer/linux_dumper.h
+++ b/src/client/linux/minidump_writer/linux_dumper.h
@@ -54,7 +54,7 @@ typedef typeof(((struct user*) 0)->u_debugreg[0]) debugreg_t;
#endif
// Typedef for our parsing of the auxv variables in /proc/pid/auxv.
-#if defined(__i386) || defined(__ARM_EABI__)
+#if defined(__i386) || defined(__ARM_EABI__) || defined(__mips__)
typedef Elf32_auxv_t elf_aux_entry;
#elif defined(__x86_64)
typedef Elf64_auxv_t elf_aux_entry;
@@ -88,6 +88,12 @@ struct ThreadInfo {
// Mimicking how strace does this(see syscall.c, search for GETREGS)
struct user_regs regs;
struct user_fpregs fpregs;
+#elif defined(__mips__)
+ user_regs_struct regs;
+ user_fpregs_struct fpregs;
+ uint32_t hi[3];
+ uint32_t lo[3];
+ uint32_t dsp_control;
#endif
};
diff --git a/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc b/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
index 68020694..461a6cfe 100644
--- a/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
+++ b/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
@@ -47,6 +47,8 @@
#define TID_PTR_REGISTER "ecx"
#elif defined(__x86_64)
#define TID_PTR_REGISTER "rcx"
+#elif defined(__mips__)
+#define TID_PTR_REGISTER "$1"
#else
#error This test has not been ported to this platform.
#endif
diff --git a/src/client/linux/minidump_writer/linux_ptrace_dumper.cc b/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
index 45d0f48f..3256f532 100644
--- a/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
+++ b/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
@@ -208,6 +208,17 @@ 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);
+#endif
+
const uint8_t* stack_pointer;
#if defined(__i386)
my_memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp));
@@ -215,6 +226,9 @@ bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
my_memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
#elif defined(__ARM_EABI__)
my_memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
+#elif defined(__mips__)
+ stack_pointer =
+ reinterpret_cast<uint8_t*>(info->regs.regs[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 bc7eae61..15a66ce2 100644
--- a/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
+++ b/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
@@ -266,7 +266,7 @@ TEST_F(LinuxPtraceDumperChildTest, BuildProcPath) {
EXPECT_FALSE(dumper.BuildProcPath(maps_path, 123, long_node));
}
-#if !defined(__ARM_EABI__)
+#if !defined(__ARM_EABI__) && !defined(__mips__)
// Ensure that the linux-gate VDSO is included in the mapping list.
TEST_F(LinuxPtraceDumperChildTest, MappingsIncludeLinuxGate) {
LinuxPtraceDumper dumper(getppid());
@@ -437,6 +437,9 @@ TEST(LinuxPtraceDumperTest, VerifyStackReadWithMultipleThreads) {
pid_t* process_tid_location = (pid_t*)(one_thread.regs.ecx);
#elif defined(__x86_64)
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]);
#else
#error This test has not been ported to this platform.
#endif
diff --git a/src/client/linux/minidump_writer/minidump_writer.cc b/src/client/linux/minidump_writer/minidump_writer.cc
index 2cbf4352..413e0807 100644
--- a/src/client/linux/minidump_writer/minidump_writer.cc
+++ b/src/client/linux/minidump_writer/minidump_writer.cc
@@ -374,6 +374,67 @@ void CPUFillFromUContext(MDRawContextARM* out, const ucontext* uc,
my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
}
+#elif defined(__mips__)
+typedef MDRawContextMIPS RawContextCPU;
+
+static void CPUFillFromThreadInfo(MDRawContextMIPS* out,
+ const google_breakpad::ThreadInfo& info) {
+ out->context_flags = MD_CONTEXT_MIPS_FULL;
+
+ for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
+ out->iregs[i] = info.regs.regs[i];
+
+ out->mdhi = info.regs.hi;
+ out->mdlo = info.regs.lo;
+
+ for (int i = 0; i < MD_CONTEXT_MIPS_DSP_COUNT; ++i) {
+ out->hi[i] = info.hi[i];
+ out->lo[i] = info.lo[i];
+ }
+ out->dsp_control = info.dsp_control;
+
+ out->epc = info.regs.epc;
+ out->badvaddr = info.regs.badvaddr;
+ out->status = info.regs.status;
+ out->cause = info.regs.cause;
+
+ for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
+ out->float_save.regs[i] = info.fpregs.regs[i];
+
+ out->float_save.fpcsr = info.fpregs.fpcsr;
+ out->float_save.fir = info.fpregs.fir;
+}
+
+static void CPUFillFromUContext(MDRawContextMIPS* out, const ucontext* uc,
+ const struct _libc_fpstate* fpregs) {
+ out->context_flags = MD_CONTEXT_MIPS_FULL;
+
+ for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
+ out->iregs[i] = uc->uc_mcontext.gregs[i];
+
+ out->mdhi = uc->uc_mcontext.mdhi;
+ out->mdlo = uc->uc_mcontext.mdlo;
+
+ out->hi[0] = uc->uc_mcontext.hi1;
+ out->hi[1] = uc->uc_mcontext.hi2;
+ out->hi[2] = uc->uc_mcontext.hi3;
+ out->lo[0] = uc->uc_mcontext.lo1;
+ out->lo[1] = uc->uc_mcontext.lo2;
+ out->lo[2] = uc->uc_mcontext.lo3;
+ out->dsp_control = uc->uc_mcontext.dsp;
+
+ out->epc = uc->uc_mcontext.pc;
+ out->badvaddr = 0; // Not reported in signal context.
+ out->status = 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)
+ out->float_save.regs[i] = uc->uc_mcontext.fpregs.fp_r.fp_dregs[i];
+
+ out->float_save.fpcsr = uc->uc_mcontext.fpc_csr;
+ out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused.
+}
+
#else
#error "This code has not been ported to your platform yet."
#endif
@@ -405,7 +466,7 @@ class MinidumpWriter {
: fd_(minidump_fd),
path_(minidump_path),
ucontext_(context ? &context->context : NULL),
-#if !defined(__ARM_EABI__)
+#if !defined(__ARM_EABI__) && !defined(__mips__)
float_state_(context ? &context->float_state : NULL),
#else
// TODO: fix this after fixing ExceptionHandler
@@ -1206,6 +1267,18 @@ class MinidumpWriter {
uintptr_t GetInstructionPointer(const ThreadInfo& info) {
return info.regs.uregs[15];
}
+#elif defined(__mips__)
+ uintptr_t GetStackPointer() {
+ return ucontext_->uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP];
+ }
+
+ uintptr_t GetInstructionPointer() {
+ return ucontext_->uc_mcontext.pc;
+ }
+
+ uintptr_t GetInstructionPointer(const ThreadInfo& info) {
+ return info.regs.epc;
+ }
#else
#error "This code has not been ported to your platform yet."
#endif
@@ -1216,7 +1289,7 @@ class MinidumpWriter {
dirent->location.rva = 0;
}
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
bool WriteCPUInformation(MDRawSystemInfo* sys_info) {
char vendor_id[sizeof(sys_info->cpu.x86_cpu_info.vendor_id) + 1] = {0};
static const char vendor_id_name[] = "vendor_id";
@@ -1227,14 +1300,18 @@ class MinidumpWriter {
bool found;
} cpu_info_table[] = {
{ "processor", -1, false },
+#if !defined(__mips__)
{ "model", 0, false },
{ "stepping", 0, false },
{ "cpu family", 0, false },
+#endif
};
// processor_architecture should always be set, do this first
sys_info->processor_architecture =
-#if defined(__i386__)
+#if defined(__mips__)
+ MD_CPU_ARCHITECTURE_MIPS;
+#elif defined(__i386__)
MD_CPU_ARCHITECTURE_X86;
#else
MD_CPU_ARCHITECTURE_AMD64;
@@ -1297,9 +1374,11 @@ class MinidumpWriter {
cpu_info_table[0].value++;
sys_info->number_of_processors = cpu_info_table[0].value;
+#if !defined(__mips__)
sys_info->processor_level = cpu_info_table[3].value;
sys_info->processor_revision = cpu_info_table[1].value << 8 |
cpu_info_table[2].value;
+#endif
if (vendor_id[0] != '\0') {
my_memcpy(sys_info->cpu.x86_cpu_info.vendor_id, vendor_id,
diff --git a/src/client/linux/minidump_writer/minidump_writer_unittest.cc b/src/client/linux/minidump_writer/minidump_writer_unittest.cc
index 9b7d73c0..1ef064b1 100644
--- a/src/client/linux/minidump_writer/minidump_writer_unittest.cc
+++ b/src/client/linux/minidump_writer/minidump_writer_unittest.cc
@@ -540,6 +540,12 @@ TEST(MinidumpWriterTest, InvalidStackPointer) {
uintptr_t invalid_stack_pointer =
reinterpret_cast<uintptr_t>(&context) - 1024*1024;
context.context.uc_mcontext.arm_sp = invalid_stack_pointer;
+#elif defined(__mips__)
+ // Try 1MB below the current stack.
+ uintptr_t invalid_stack_pointer =
+ reinterpret_cast<uintptr_t>(&context) - 1024 * 1024;
+ context.context.uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP] =
+ invalid_stack_pointer;
#else
# error "This code has not been ported to your platform yet."
#endif