mirror of https://github.com/NekoX-Dev/NekoX.git
254 lines
8.5 KiB
C++
254 lines
8.5 KiB
C++
// 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)
|
|
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
|