summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/breakpad-client/linux/dump_writer_common
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /toolkit/crashreporter/breakpad-client/linux/dump_writer_common
parentInitial commit. (diff)
downloadthunderbird-upstream.tar.xz
thunderbird-upstream.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/crashreporter/breakpad-client/linux/dump_writer_common')
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/dump_writer_common/mapping_info.h75
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/dump_writer_common/raw_context_cpu.h53
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.cc305
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.h91
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.cc259
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.h65
6 files changed, 848 insertions, 0 deletions
diff --git a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/mapping_info.h b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/mapping_info.h
new file mode 100644
index 0000000000..c358539f58
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/mapping_info.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2014, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_LINUX_DUMP_WRITER_COMMON_MAPPING_INFO_H_
+#define CLIENT_LINUX_DUMP_WRITER_COMMON_MAPPING_INFO_H_
+
+#include <limits.h>
+#include <list>
+#include <stdint.h>
+#include <vector>
+
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+// One of these is produced for each mapping in the process (i.e. line in
+// /proc/$x/maps).
+struct MappingInfo {
+ // On Android, relocation packing can mean that the reported start
+ // address of the mapping must be adjusted by a bias in order to
+ // compensate for the compression of the relocation section. The
+ // following two members hold (after LateInit) the adjusted mapping
+ // range. See crbug.com/606972 for more information.
+ uintptr_t start_addr;
+ size_t size;
+ // When Android relocation packing causes |start_addr| and |size| to
+ // be modified with a load bias, we need to remember the unbiased
+ // address range. The following structure holds the original mapping
+ // address range as reported by the operating system.
+ struct {
+ uintptr_t start_addr;
+ uintptr_t end_addr;
+ } system_mapping_info;
+ size_t offset; // offset into the backed file.
+ bool exec; // true if the mapping has the execute bit set.
+ char name[NAME_MAX];
+};
+
+struct MappingEntry {
+ MappingInfo first;
+ std::vector<uint8_t> second;
+};
+
+// A list of <MappingInfo, GUID>
+typedef std::list<MappingEntry> MappingList;
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_DUMP_WRITER_COMMON_MAPPING_INFO_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/raw_context_cpu.h b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/raw_context_cpu.h
new file mode 100644
index 0000000000..07d9171a0a
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/raw_context_cpu.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2014, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_LINUX_DUMP_WRITER_COMMON_RAW_CONTEXT_CPU_H
+#define CLIENT_LINUX_DUMP_WRITER_COMMON_RAW_CONTEXT_CPU_H
+
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+#if defined(__i386__)
+typedef MDRawContextX86 RawContextCPU;
+#elif defined(__x86_64)
+typedef MDRawContextAMD64 RawContextCPU;
+#elif defined(__ARM_EABI__)
+typedef MDRawContextARM RawContextCPU;
+#elif defined(__aarch64__)
+typedef MDRawContextARM64_Old RawContextCPU;
+#elif defined(__mips__)
+typedef MDRawContextMIPS RawContextCPU;
+#else
+#error "This code has not been ported to your platform yet."
+#endif
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_DUMP_WRITER_COMMON_RAW_CONTEXT_CPU_H
diff --git a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.cc b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.cc
new file mode 100644
index 0000000000..5d9708c70c
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.cc
@@ -0,0 +1,305 @@
+// Copyright (c) 2014, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "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"
+
+namespace {
+
+#if defined(__i386__)
+// Write a uint16_t to memory
+// out: memory location to write to
+// v: value to write.
+void U16(void* out, uint16_t v) {
+ my_memcpy(out, &v, sizeof(v));
+}
+
+// Write a uint32_t to memory
+// out: memory location to write to
+// v: value to write.
+void U32(void* out, uint32_t v) {
+ my_memcpy(out, &v, sizeof(v));
+}
+#endif
+
+}
+
+namespace google_breakpad {
+
+#if defined(__i386__)
+
+uintptr_t ThreadInfo::GetInstructionPointer() const {
+ return regs.eip;
+}
+
+void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+ out->context_flags = MD_CONTEXT_X86_ALL;
+
+ out->dr0 = dregs[0];
+ out->dr1 = dregs[1];
+ out->dr2 = dregs[2];
+ out->dr3 = dregs[3];
+ // 4 and 5 deliberatly omitted because they aren't included in the minidump
+ // format.
+ out->dr6 = dregs[6];
+ out->dr7 = dregs[7];
+
+ out->gs = regs.xgs;
+ out->fs = regs.xfs;
+ out->es = regs.xes;
+ out->ds = regs.xds;
+
+ out->edi = regs.edi;
+ out->esi = regs.esi;
+ out->ebx = regs.ebx;
+ out->edx = regs.edx;
+ out->ecx = regs.ecx;
+ out->eax = regs.eax;
+
+ out->ebp = regs.ebp;
+ out->eip = regs.eip;
+ out->cs = regs.xcs;
+ out->eflags = regs.eflags;
+ out->esp = regs.esp;
+ out->ss = regs.xss;
+
+ out->float_save.control_word = fpregs.cwd;
+ out->float_save.status_word = fpregs.swd;
+ out->float_save.tag_word = fpregs.twd;
+ out->float_save.error_offset = fpregs.fip;
+ out->float_save.error_selector = fpregs.fcs;
+ out->float_save.data_offset = fpregs.foo;
+ out->float_save.data_selector = fpregs.fos;
+
+ // 8 registers * 10 bytes per register.
+ my_memcpy(out->float_save.register_area, fpregs.st_space, 10 * 8);
+
+ // This matches the Intel fpsave format.
+ U16(out->extended_registers + 0, fpregs.cwd);
+ U16(out->extended_registers + 2, fpregs.swd);
+ U16(out->extended_registers + 4, fpregs.twd);
+ U16(out->extended_registers + 6, fpxregs.fop);
+ U32(out->extended_registers + 8, fpxregs.fip);
+ U16(out->extended_registers + 12, fpxregs.fcs);
+ U32(out->extended_registers + 16, fpregs.foo);
+ U16(out->extended_registers + 20, fpregs.fos);
+ U32(out->extended_registers + 24, fpxregs.mxcsr);
+
+ my_memcpy(out->extended_registers + 32, &fpxregs.st_space, 128);
+ my_memcpy(out->extended_registers + 160, &fpxregs.xmm_space, 128);
+}
+
+#elif defined(__x86_64)
+
+uintptr_t ThreadInfo::GetInstructionPointer() const {
+ return regs.rip;
+}
+
+void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+ out->context_flags = MD_CONTEXT_AMD64_FULL |
+ MD_CONTEXT_AMD64_SEGMENTS;
+
+ out->cs = regs.cs;
+
+ out->ds = regs.ds;
+ out->es = regs.es;
+ out->fs = regs.fs;
+ out->gs = regs.gs;
+
+ out->ss = regs.ss;
+ out->eflags = regs.eflags;
+
+ out->dr0 = dregs[0];
+ out->dr1 = dregs[1];
+ out->dr2 = dregs[2];
+ out->dr3 = dregs[3];
+ // 4 and 5 deliberatly omitted because they aren't included in the minidump
+ // format.
+ out->dr6 = dregs[6];
+ out->dr7 = dregs[7];
+
+ out->rax = regs.rax;
+ out->rcx = regs.rcx;
+ out->rdx = regs.rdx;
+ out->rbx = regs.rbx;
+
+ out->rsp = regs.rsp;
+
+ out->rbp = regs.rbp;
+ out->rsi = regs.rsi;
+ out->rdi = regs.rdi;
+ out->r8 = regs.r8;
+ out->r9 = regs.r9;
+ out->r10 = regs.r10;
+ out->r11 = regs.r11;
+ out->r12 = regs.r12;
+ out->r13 = regs.r13;
+ out->r14 = regs.r14;
+ out->r15 = regs.r15;
+
+ out->rip = regs.rip;
+
+ out->flt_save.control_word = fpregs.cwd;
+ out->flt_save.status_word = fpregs.swd;
+ out->flt_save.tag_word = fpregs.ftw;
+ out->flt_save.error_opcode = fpregs.fop;
+ out->flt_save.error_offset = fpregs.rip;
+ out->flt_save.error_selector = 0; // We don't have this.
+ out->flt_save.data_offset = fpregs.rdp;
+ out->flt_save.data_selector = 0; // We don't have this.
+ out->flt_save.mx_csr = fpregs.mxcsr;
+ out->flt_save.mx_csr_mask = fpregs.mxcr_mask;
+
+ my_memcpy(&out->flt_save.float_registers, &fpregs.st_space, 8 * 16);
+ my_memcpy(&out->flt_save.xmm_registers, &fpregs.xmm_space, 16 * 16);
+}
+
+#elif defined(__ARM_EABI__)
+
+uintptr_t ThreadInfo::GetInstructionPointer() const {
+ return regs.uregs[15];
+}
+
+void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+ out->context_flags = MD_CONTEXT_ARM_FULL;
+
+ for (int i = 0; i < MD_CONTEXT_ARM_GPR_COUNT; ++i)
+ out->iregs[i] = regs.uregs[i];
+ // No CPSR register in ThreadInfo(it's not accessible via ptrace)
+ out->cpsr = 0;
+#if !defined(__ANDROID__)
+ out->float_save.fpscr = fpregs.fpsr |
+ (static_cast<uint64_t>(fpregs.fpcr) << 32);
+ // TODO: sort this out, actually collect floating point registers
+ my_memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
+ my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
+#endif
+}
+
+#elif defined(__aarch64__)
+
+uintptr_t ThreadInfo::GetInstructionPointer() const {
+ return regs.pc;
+}
+
+void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+ out->context_flags = MD_CONTEXT_ARM64_FULL_OLD;
+
+ out->cpsr = static_cast<uint32_t>(regs.pstate);
+ for (int i = 0; i < MD_CONTEXT_ARM64_REG_SP; ++i)
+ out->iregs[i] = regs.regs[i];
+ out->iregs[MD_CONTEXT_ARM64_REG_SP] = regs.sp;
+ out->iregs[MD_CONTEXT_ARM64_REG_PC] = regs.pc;
+
+ out->float_save.fpsr = fpregs.fpsr;
+ out->float_save.fpcr = fpregs.fpcr;
+ my_memcpy(&out->float_save.regs, &fpregs.vregs,
+ MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT * 16);
+}
+
+#elif defined(__mips__)
+
+uintptr_t ThreadInfo::GetInstructionPointer() const {
+ return mcontext.pc;
+}
+
+void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+#if _MIPS_SIM == _ABI64
+ out->context_flags = MD_CONTEXT_MIPS64_FULL;
+#elif _MIPS_SIM == _ABIO32
+ out->context_flags = MD_CONTEXT_MIPS_FULL;
+#else
+# error "This mips ABI is currently not supported (n32)"
+#endif
+
+ for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
+ out->iregs[i] = mcontext.gregs[i];
+
+ out->mdhi = mcontext.mdhi;
+ out->mdlo = mcontext.mdlo;
+ out->dsp_control = mcontext.dsp;
+
+ 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 = 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] = mcontext.fpregs.fp_r.fp_fregs[i]._fp_fregs;
+
+ out->float_save.fpcsr = mcontext.fpc_csr;
+#if _MIPS_SIM == _ABIO32
+ 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 = &regs;
+ 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/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.h b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.h
new file mode 100644
index 0000000000..4173d239c4
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.h
@@ -0,0 +1,91 @@
+// Copyright (c) 2014, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_LINUX_DUMP_WRITER_COMMON_THREAD_INFO_H_
+#define CLIENT_LINUX_DUMP_WRITER_COMMON_THREAD_INFO_H_
+
+#include <sys/ucontext.h>
+#include <sys/user.h>
+
+#include "linux/dump_writer_common/raw_context_cpu.h"
+#include "common/memory_allocator.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+#if defined(__i386) || defined(__x86_64)
+typedef __typeof__(((struct user*) 0)->u_debugreg[0]) debugreg_t;
+#endif
+
+// We produce one of these structures for each thread in the crashed process.
+struct ThreadInfo {
+ pid_t tgid; // thread group id
+ pid_t ppid; // parent process
+
+ uintptr_t stack_pointer; // thread stack pointer
+
+
+#if defined(__i386) || defined(__x86_64)
+ user_regs_struct regs;
+ user_fpregs_struct fpregs;
+ static const unsigned kNumDebugRegisters = 8;
+ debugreg_t dregs[8];
+#if defined(__i386)
+ user_fpxregs_struct fpxregs;
+#endif // defined(__i386)
+
+#elif defined(__ARM_EABI__)
+ // Mimicking how strace does this(see syscall.c, search for GETREGS)
+ struct user_regs regs;
+ struct user_fpregs fpregs;
+#elif defined(__aarch64__)
+ // Use the structures defined in <sys/user.h>
+ struct user_regs_struct regs;
+ struct user_fpsimd_struct fpregs;
+#elif defined(__mips__)
+ // Use the structure defined in <sys/ucontext.h>.
+ mcontext_t mcontext;
+#endif
+
+ // Returns the instruction pointer (platform-dependent impl.).
+ uintptr_t GetInstructionPointer() const;
+
+ // 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
+
+#endif // CLIENT_LINUX_DUMP_WRITER_COMMON_THREAD_INFO_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.cc b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.cc
new file mode 100644
index 0000000000..5145ede3d8
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.cc
@@ -0,0 +1,259 @@
+// Copyright (c) 2014, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "linux/dump_writer_common/ucontext_reader.h"
+
+#include "common/linux/linux_libc_support.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+// Minidump defines register structures which are different from the raw
+// structures which we get from the kernel. These are platform specific
+// functions to juggle the ucontext_t and user structures into minidump format.
+
+#if defined(__i386__)
+
+uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.gregs[REG_ESP];
+}
+
+uintptr_t UContextReader::GetInstructionPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.gregs[REG_EIP];
+}
+
+void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc,
+ const fpstate_t* fp) {
+ const greg_t* regs = uc->uc_mcontext.gregs;
+
+ out->context_flags = MD_CONTEXT_X86_FULL |
+ MD_CONTEXT_X86_FLOATING_POINT;
+
+ out->gs = regs[REG_GS];
+ out->fs = regs[REG_FS];
+ out->es = regs[REG_ES];
+ out->ds = regs[REG_DS];
+
+ out->edi = regs[REG_EDI];
+ out->esi = regs[REG_ESI];
+ out->ebx = regs[REG_EBX];
+ out->edx = regs[REG_EDX];
+ out->ecx = regs[REG_ECX];
+ out->eax = regs[REG_EAX];
+
+ out->ebp = regs[REG_EBP];
+ out->eip = regs[REG_EIP];
+ out->cs = regs[REG_CS];
+ out->eflags = regs[REG_EFL];
+ out->esp = regs[REG_UESP];
+ out->ss = regs[REG_SS];
+
+ out->float_save.control_word = fp->cw;
+ out->float_save.status_word = fp->sw;
+ out->float_save.tag_word = fp->tag;
+ out->float_save.error_offset = fp->ipoff;
+ out->float_save.error_selector = fp->cssel;
+ out->float_save.data_offset = fp->dataoff;
+ out->float_save.data_selector = fp->datasel;
+
+ // 8 registers * 10 bytes per register.
+ my_memcpy(out->float_save.register_area, fp->_st, 10 * 8);
+}
+
+#elif defined(__x86_64)
+
+uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.gregs[REG_RSP];
+}
+
+uintptr_t UContextReader::GetInstructionPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.gregs[REG_RIP];
+}
+
+void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc,
+ const fpstate_t* fpregs) {
+ const greg_t* regs = uc->uc_mcontext.gregs;
+
+ out->context_flags = MD_CONTEXT_AMD64_FULL;
+
+ out->cs = regs[REG_CSGSFS] & 0xffff;
+
+ out->fs = (regs[REG_CSGSFS] >> 32) & 0xffff;
+ out->gs = (regs[REG_CSGSFS] >> 16) & 0xffff;
+
+ out->eflags = regs[REG_EFL];
+
+ out->rax = regs[REG_RAX];
+ out->rcx = regs[REG_RCX];
+ out->rdx = regs[REG_RDX];
+ out->rbx = regs[REG_RBX];
+
+ out->rsp = regs[REG_RSP];
+ out->rbp = regs[REG_RBP];
+ out->rsi = regs[REG_RSI];
+ out->rdi = regs[REG_RDI];
+ out->r8 = regs[REG_R8];
+ out->r9 = regs[REG_R9];
+ out->r10 = regs[REG_R10];
+ out->r11 = regs[REG_R11];
+ out->r12 = regs[REG_R12];
+ out->r13 = regs[REG_R13];
+ out->r14 = regs[REG_R14];
+ out->r15 = regs[REG_R15];
+
+ out->rip = regs[REG_RIP];
+
+ out->flt_save.control_word = fpregs->cwd;
+ out->flt_save.status_word = fpregs->swd;
+ out->flt_save.tag_word = fpregs->ftw;
+ out->flt_save.error_opcode = fpregs->fop;
+ out->flt_save.error_offset = fpregs->rip;
+ out->flt_save.data_offset = fpregs->rdp;
+ out->flt_save.error_selector = 0; // We don't have this.
+ out->flt_save.data_selector = 0; // We don't have this.
+ out->flt_save.mx_csr = fpregs->mxcsr;
+ out->flt_save.mx_csr_mask = fpregs->mxcr_mask;
+ my_memcpy(&out->flt_save.float_registers, &fpregs->_st, 8 * 16);
+ my_memcpy(&out->flt_save.xmm_registers, &fpregs->_xmm, 16 * 16);
+}
+
+#elif defined(__ARM_EABI__)
+
+uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.arm_sp;
+}
+
+uintptr_t UContextReader::GetInstructionPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.arm_pc;
+}
+
+void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc) {
+ out->context_flags = MD_CONTEXT_ARM_FULL;
+
+ out->iregs[0] = uc->uc_mcontext.arm_r0;
+ out->iregs[1] = uc->uc_mcontext.arm_r1;
+ out->iregs[2] = uc->uc_mcontext.arm_r2;
+ out->iregs[3] = uc->uc_mcontext.arm_r3;
+ out->iregs[4] = uc->uc_mcontext.arm_r4;
+ out->iregs[5] = uc->uc_mcontext.arm_r5;
+ out->iregs[6] = uc->uc_mcontext.arm_r6;
+ out->iregs[7] = uc->uc_mcontext.arm_r7;
+ out->iregs[8] = uc->uc_mcontext.arm_r8;
+ out->iregs[9] = uc->uc_mcontext.arm_r9;
+ out->iregs[10] = uc->uc_mcontext.arm_r10;
+
+ out->iregs[11] = uc->uc_mcontext.arm_fp;
+ out->iregs[12] = uc->uc_mcontext.arm_ip;
+ out->iregs[13] = uc->uc_mcontext.arm_sp;
+ out->iregs[14] = uc->uc_mcontext.arm_lr;
+ out->iregs[15] = uc->uc_mcontext.arm_pc;
+
+ out->cpsr = uc->uc_mcontext.arm_cpsr;
+
+ // TODO: fix this after fixing ExceptionHandler
+ out->float_save.fpscr = 0;
+ my_memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
+ my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
+}
+
+#elif defined(__aarch64__)
+
+uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.sp;
+}
+
+uintptr_t UContextReader::GetInstructionPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.pc;
+}
+
+void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc,
+ const struct fpsimd_context* fpregs) {
+ out->context_flags = MD_CONTEXT_ARM64_FULL_OLD;
+
+ out->cpsr = static_cast<uint32_t>(uc->uc_mcontext.pstate);
+ for (int i = 0; i < MD_CONTEXT_ARM64_REG_SP; ++i)
+ out->iregs[i] = uc->uc_mcontext.regs[i];
+ out->iregs[MD_CONTEXT_ARM64_REG_SP] = uc->uc_mcontext.sp;
+ out->iregs[MD_CONTEXT_ARM64_REG_PC] = uc->uc_mcontext.pc;
+
+ out->float_save.fpsr = fpregs->fpsr;
+ out->float_save.fpcr = fpregs->fpcr;
+ my_memcpy(&out->float_save.regs, &fpregs->vregs,
+ MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT * 16);
+}
+
+#elif defined(__mips__)
+
+uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP];
+}
+
+uintptr_t UContextReader::GetInstructionPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.pc;
+}
+
+void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc) {
+#if _MIPS_SIM == _ABI64
+ out->context_flags = MD_CONTEXT_MIPS64_FULL;
+#elif _MIPS_SIM == _ABIO32
+ out->context_flags = MD_CONTEXT_MIPS_FULL;
+#else
+#error "This mips ABI is currently not supported (n32)"
+#endif
+
+ 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;
+#if _MIPS_SIM == _ABIO32
+ out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused.
+#endif
+}
+#endif
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.h b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.h
new file mode 100644
index 0000000000..390520be41
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2014, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_LINUX_DUMP_WRITER_COMMON_UCONTEXT_READER_H
+#define CLIENT_LINUX_DUMP_WRITER_COMMON_UCONTEXT_READER_H
+
+#include <sys/ucontext.h>
+#include <sys/user.h>
+
+#include "linux/dump_writer_common/raw_context_cpu.h"
+#include "linux/minidump_writer/minidump_writer.h"
+#include "common/memory_allocator.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+// Wraps platform-dependent implementations of accessors to ucontext_t structs.
+struct UContextReader {
+ static uintptr_t GetStackPointer(const ucontext_t* uc);
+
+ static uintptr_t GetInstructionPointer(const ucontext_t* uc);
+
+ // Juggle a arch-specific ucontext into a minidump format
+ // out: the minidump structure
+ // info: the collection of register structures.
+#if defined(__i386__) || defined(__x86_64)
+ static void FillCPUContext(RawContextCPU *out, const ucontext_t *uc,
+ const fpstate_t* fp);
+#elif defined(__aarch64__)
+ static void FillCPUContext(RawContextCPU *out, const ucontext_t *uc,
+ const struct fpsimd_context* fpregs);
+#else
+ static void FillCPUContext(RawContextCPU *out, const ucontext_t *uc);
+#endif
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_DUMP_WRITER_COMMON_UCONTEXT_READER_H