diff options
author | primiano@chromium.org <primiano@chromium.org> | 2014-10-01 09:51:23 +0000 |
---|---|---|
committer | primiano@chromium.org <primiano@chromium.org> | 2014-10-01 09:51:23 +0000 |
commit | 9f150ee33e99b6c076f8047f1c33586e95ce9584 (patch) | |
tree | 944df97066057ea69ca3a7f00139816106d97595 /src/client/linux/dump_writer_common/ucontext_reader.cc | |
parent | Fix some nits raised by Timur for r1385. (diff) | |
download | breakpad-9f150ee33e99b6c076f8047f1c33586e95ce9584.tar.xz |
Microdumps: refactor out common parts of minidump_writer.cc
This change is a pure refactoring of the common bits of minidump_writer.cc
that will be shared soon with the upcoming microdump_writer.cc.
In particular, this CL is extracting the following classes:
- ThreadInfo: handles the state of the threads in the crashing process.
- RawContextCPU: typedef for arch-specific CPU context structure.
- UContextReader: Fills out a dump RawContextCPU structure from the
ucontext struct provided by the kernel (arch-dependent).
- SeccompUnwinder: cleans out the stack frames of the Seccomp sandbox
on the supported architectures.
- MappingInfo: handles information about mappings
BUG=chromium:410294
R=mmandlis@chromium.org
Review URL: https://breakpad.appspot.com/4684002
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1388 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/client/linux/dump_writer_common/ucontext_reader.cc')
-rw-r--r-- | src/client/linux/dump_writer_common/ucontext_reader.cc | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/src/client/linux/dump_writer_common/ucontext_reader.cc b/src/client/linux/dump_writer_common/ucontext_reader.cc new file mode 100644 index 00000000..f497ac2f --- /dev/null +++ b/src/client/linux/dump_writer_common/ucontext_reader.cc @@ -0,0 +1,255 @@ +// 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 "client/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 and user structures into minidump format. + +#if defined(__i386__) + +uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) { + return uc->uc_mcontext.gregs[REG_ESP]; +} + +uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { + return uc->uc_mcontext.gregs[REG_EIP]; +} + +void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc, + const struct _libc_fpstate* 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 struct ucontext* uc) { + return uc->uc_mcontext.gregs[REG_RSP]; +} + +uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { + return uc->uc_mcontext.gregs[REG_RIP]; +} + +void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc, + const struct _libc_fpstate* 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 struct ucontext* uc) { + return uc->uc_mcontext.arm_sp; +} + +uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { + return uc->uc_mcontext.arm_pc; +} + +void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *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 struct ucontext* uc) { + return uc->uc_mcontext.sp; +} + +uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { + return uc->uc_mcontext.pc; +} + +void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc, + const struct fpsimd_context* fpregs) { + out->context_flags = MD_CONTEXT_ARM64_FULL; + + 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 struct ucontext* uc) { + return uc->uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP]; +} + +uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { + return uc->uc_mcontext.pc; +} + +void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc) { + 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) +#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]; +#endif + + out->float_save.fpcsr = uc->uc_mcontext.fpc_csr; + out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused. +} +#endif + +} // namespace google_breakpad |