1// Copyright (c) 2014, Google Inc. 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: 7// 8// * Redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer. 10// * Redistributions in binary form must reproduce the above 11// copyright notice, this list of conditions and the following disclaimer 12// in the documentation and/or other materials provided with the 13// distribution. 14// * Neither the name of Google Inc. nor the names of its 15// contributors may be used to endorse or promote products derived from 16// this software without specific prior written permission. 17// 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30#include "client/linux/dump_writer_common/ucontext_reader.h" 31 32#include "common/linux/linux_libc_support.h" 33#include "google_breakpad/common/minidump_format.h" 34 35namespace google_breakpad { 36 37// Minidump defines register structures which are different from the raw 38// structures which we get from the kernel. These are platform specific 39// functions to juggle the ucontext and user structures into minidump format. 40 41#if defined(__i386__) 42 43uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) { 44 return uc->uc_mcontext.gregs[REG_ESP]; 45} 46 47uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { 48 return uc->uc_mcontext.gregs[REG_EIP]; 49} 50 51void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc, 52 const struct _libc_fpstate* fp) { 53 const greg_t* regs = uc->uc_mcontext.gregs; 54 55 out->context_flags = MD_CONTEXT_X86_FULL | 56 MD_CONTEXT_X86_FLOATING_POINT; 57 58 out->gs = regs[REG_GS]; 59 out->fs = regs[REG_FS]; 60 out->es = regs[REG_ES]; 61 out->ds = regs[REG_DS]; 62 63 out->edi = regs[REG_EDI]; 64 out->esi = regs[REG_ESI]; 65 out->ebx = regs[REG_EBX]; 66 out->edx = regs[REG_EDX]; 67 out->ecx = regs[REG_ECX]; 68 out->eax = regs[REG_EAX]; 69 70 out->ebp = regs[REG_EBP]; 71 out->eip = regs[REG_EIP]; 72 out->cs = regs[REG_CS]; 73 out->eflags = regs[REG_EFL]; 74 out->esp = regs[REG_UESP]; 75 out->ss = regs[REG_SS]; 76 77 out->float_save.control_word = fp->cw; 78 out->float_save.status_word = fp->sw; 79 out->float_save.tag_word = fp->tag; 80 out->float_save.error_offset = fp->ipoff; 81 out->float_save.error_selector = fp->cssel; 82 out->float_save.data_offset = fp->dataoff; 83 out->float_save.data_selector = fp->datasel; 84 85 // 8 registers * 10 bytes per register. 86 my_memcpy(out->float_save.register_area, fp->_st, 10 * 8); 87} 88 89#elif defined(__x86_64) 90 91uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) { 92 return uc->uc_mcontext.gregs[REG_RSP]; 93} 94 95uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { 96 return uc->uc_mcontext.gregs[REG_RIP]; 97} 98 99void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc, 100 const struct _libc_fpstate* fpregs) { 101 const greg_t* regs = uc->uc_mcontext.gregs; 102 103 out->context_flags = MD_CONTEXT_AMD64_FULL; 104 105 out->cs = regs[REG_CSGSFS] & 0xffff; 106 107 out->fs = (regs[REG_CSGSFS] >> 32) & 0xffff; 108 out->gs = (regs[REG_CSGSFS] >> 16) & 0xffff; 109 110 out->eflags = regs[REG_EFL]; 111 112 out->rax = regs[REG_RAX]; 113 out->rcx = regs[REG_RCX]; 114 out->rdx = regs[REG_RDX]; 115 out->rbx = regs[REG_RBX]; 116 117 out->rsp = regs[REG_RSP]; 118 out->rbp = regs[REG_RBP]; 119 out->rsi = regs[REG_RSI]; 120 out->rdi = regs[REG_RDI]; 121 out->r8 = regs[REG_R8]; 122 out->r9 = regs[REG_R9]; 123 out->r10 = regs[REG_R10]; 124 out->r11 = regs[REG_R11]; 125 out->r12 = regs[REG_R12]; 126 out->r13 = regs[REG_R13]; 127 out->r14 = regs[REG_R14]; 128 out->r15 = regs[REG_R15]; 129 130 out->rip = regs[REG_RIP]; 131 132 out->flt_save.control_word = fpregs->cwd; 133 out->flt_save.status_word = fpregs->swd; 134 out->flt_save.tag_word = fpregs->ftw; 135 out->flt_save.error_opcode = fpregs->fop; 136 out->flt_save.error_offset = fpregs->rip; 137 out->flt_save.data_offset = fpregs->rdp; 138 out->flt_save.error_selector = 0; // We don't have this. 139 out->flt_save.data_selector = 0; // We don't have this. 140 out->flt_save.mx_csr = fpregs->mxcsr; 141 out->flt_save.mx_csr_mask = fpregs->mxcr_mask; 142 my_memcpy(&out->flt_save.float_registers, &fpregs->_st, 8 * 16); 143 my_memcpy(&out->flt_save.xmm_registers, &fpregs->_xmm, 16 * 16); 144} 145 146#elif defined(__ARM_EABI__) 147 148uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) { 149 return uc->uc_mcontext.arm_sp; 150} 151 152uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { 153 return uc->uc_mcontext.arm_pc; 154} 155 156void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc) { 157 out->context_flags = MD_CONTEXT_ARM_FULL; 158 159 out->iregs[0] = uc->uc_mcontext.arm_r0; 160 out->iregs[1] = uc->uc_mcontext.arm_r1; 161 out->iregs[2] = uc->uc_mcontext.arm_r2; 162 out->iregs[3] = uc->uc_mcontext.arm_r3; 163 out->iregs[4] = uc->uc_mcontext.arm_r4; 164 out->iregs[5] = uc->uc_mcontext.arm_r5; 165 out->iregs[6] = uc->uc_mcontext.arm_r6; 166 out->iregs[7] = uc->uc_mcontext.arm_r7; 167 out->iregs[8] = uc->uc_mcontext.arm_r8; 168 out->iregs[9] = uc->uc_mcontext.arm_r9; 169 out->iregs[10] = uc->uc_mcontext.arm_r10; 170 171 out->iregs[11] = uc->uc_mcontext.arm_fp; 172 out->iregs[12] = uc->uc_mcontext.arm_ip; 173 out->iregs[13] = uc->uc_mcontext.arm_sp; 174 out->iregs[14] = uc->uc_mcontext.arm_lr; 175 out->iregs[15] = uc->uc_mcontext.arm_pc; 176 177 out->cpsr = uc->uc_mcontext.arm_cpsr; 178 179 // TODO: fix this after fixing ExceptionHandler 180 out->float_save.fpscr = 0; 181 my_memset(&out->float_save.regs, 0, sizeof(out->float_save.regs)); 182 my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra)); 183} 184 185#elif defined(__aarch64__) 186 187uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) { 188 return uc->uc_mcontext.sp; 189} 190 191uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { 192 return uc->uc_mcontext.pc; 193} 194 195void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc, 196 const struct fpsimd_context* fpregs) { 197 out->context_flags = MD_CONTEXT_ARM64_FULL; 198 199 out->cpsr = static_cast<uint32_t>(uc->uc_mcontext.pstate); 200 for (int i = 0; i < MD_CONTEXT_ARM64_REG_SP; ++i) 201 out->iregs[i] = uc->uc_mcontext.regs[i]; 202 out->iregs[MD_CONTEXT_ARM64_REG_SP] = uc->uc_mcontext.sp; 203 out->iregs[MD_CONTEXT_ARM64_REG_PC] = uc->uc_mcontext.pc; 204 205 out->float_save.fpsr = fpregs->fpsr; 206 out->float_save.fpcr = fpregs->fpcr; 207 my_memcpy(&out->float_save.regs, &fpregs->vregs, 208 MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT * 16); 209} 210 211#elif defined(__mips__) 212 213uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) { 214 return uc->uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP]; 215} 216 217uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { 218 return uc->uc_mcontext.pc; 219} 220 221void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc) { 222 out->context_flags = MD_CONTEXT_MIPS_FULL; 223 224 for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i) 225 out->iregs[i] = uc->uc_mcontext.gregs[i]; 226 227 out->mdhi = uc->uc_mcontext.mdhi; 228 out->mdlo = uc->uc_mcontext.mdlo; 229 230 out->hi[0] = uc->uc_mcontext.hi1; 231 out->hi[1] = uc->uc_mcontext.hi2; 232 out->hi[2] = uc->uc_mcontext.hi3; 233 out->lo[0] = uc->uc_mcontext.lo1; 234 out->lo[1] = uc->uc_mcontext.lo2; 235 out->lo[2] = uc->uc_mcontext.lo3; 236 out->dsp_control = uc->uc_mcontext.dsp; 237 238 out->epc = uc->uc_mcontext.pc; 239 out->badvaddr = 0; // Not reported in signal context. 240 out->status = 0; // Not reported in signal context. 241 out->cause = 0; // Not reported in signal context. 242 243 for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i) 244 out->float_save.regs[i] = uc->uc_mcontext.fpregs.fp_r.fp_dregs[i]; 245 246 out->float_save.fpcsr = uc->uc_mcontext.fpc_csr; 247#if _MIPS_SIM == _ABIO32 248 out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused. 249#endif 250} 251#endif 252 253} // namespace google_breakpad 254