Home | History | Annotate | Download | only in dump_writer_common
      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