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 35 namespace 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 43 uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) { 44 return uc->uc_mcontext.gregs[REG_ESP]; 45 } 46 47 uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { 48 return uc->uc_mcontext.gregs[REG_EIP]; 49 } 50 51 void 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 91 uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) { 92 return uc->uc_mcontext.gregs[REG_RSP]; 93 } 94 95 uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { 96 return uc->uc_mcontext.gregs[REG_RIP]; 97 } 98 99 void 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 148 uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) { 149 return uc->uc_mcontext.arm_sp; 150 } 151 152 uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { 153 return uc->uc_mcontext.arm_pc; 154 } 155 156 void 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 187 uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) { 188 return uc->uc_mcontext.sp; 189 } 190 191 uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { 192 return uc->uc_mcontext.pc; 193 } 194 195 void 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 213 uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) { 214 return uc->uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP]; 215 } 216 217 uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) { 218 return uc->uc_mcontext.pc; 219 } 220 221 void 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