diff options
Diffstat (limited to 'third_party/rust/minidump-writer/src/linux/crash_context')
4 files changed, 221 insertions, 0 deletions
diff --git a/third_party/rust/minidump-writer/src/linux/crash_context/aarch64.rs b/third_party/rust/minidump-writer/src/linux/crash_context/aarch64.rs new file mode 100644 index 0000000000..c53c37720c --- /dev/null +++ b/third_party/rust/minidump-writer/src/linux/crash_context/aarch64.rs @@ -0,0 +1,34 @@ +use super::CrashContext; +use crate::{ + minidump_cpu::{RawContextCPU, FP_REG_COUNT, GP_REG_COUNT}, + minidump_format::format, +}; + +impl CrashContext { + pub fn get_instruction_pointer(&self) -> usize { + self.inner.context.uc_mcontext.pc as usize + } + + pub fn get_stack_pointer(&self) -> usize { + self.inner.context.uc_mcontext.sp as usize + } + + pub fn fill_cpu_context(&self, out: &mut RawContextCPU) { + out.context_flags = format::ContextFlagsArm64Old::CONTEXT_ARM64_OLD_FULL.bits() as u64; + + { + let gregs = &self.inner.context.uc_mcontext; + out.cpsr = gregs.pstate as u32; + out.iregs[..GP_REG_COUNT].copy_from_slice(&gregs.regs[..GP_REG_COUNT]); + out.sp = gregs.sp; + out.pc = gregs.pc; + } + + { + let fs = &self.inner.float_state; + out.fpsr = fs.fpsr; + out.fpcr = fs.fpcr; + out.float_regs[..FP_REG_COUNT].copy_from_slice(&fs.vregs[..FP_REG_COUNT]); + } + } +} diff --git a/third_party/rust/minidump-writer/src/linux/crash_context/arm.rs b/third_party/rust/minidump-writer/src/linux/crash_context/arm.rs new file mode 100644 index 0000000000..e4e40216e2 --- /dev/null +++ b/third_party/rust/minidump-writer/src/linux/crash_context/arm.rs @@ -0,0 +1,47 @@ +use super::CrashContext; +use crate::minidump_cpu::RawContextCPU; + +impl CrashContext { + pub fn get_instruction_pointer(&self) -> usize { + self.inner.context.uc_mcontext.arm_pc as usize + } + + pub fn get_stack_pointer(&self) -> usize { + self.inner.context.uc_mcontext.arm_sp as usize + } + + pub fn fill_cpu_context(&self, out: &mut RawContextCPU) { + out.context_flags = + crate::minidump_format::format::ContextFlagsArm::CONTEXT_ARM_FULL.bits(); + + { + let iregs = &mut out.iregs; + let gregs = &self.inner.context.uc_mcontext; + iregs[0] = gregs.arm_r0; + iregs[1] = gregs.arm_r1; + iregs[2] = gregs.arm_r2; + iregs[3] = gregs.arm_r3; + iregs[4] = gregs.arm_r4; + iregs[5] = gregs.arm_r5; + iregs[6] = gregs.arm_r6; + iregs[7] = gregs.arm_r7; + iregs[8] = gregs.arm_r8; + iregs[9] = gregs.arm_r9; + iregs[10] = gregs.arm_r10; + + iregs[11] = gregs.arm_fp; + iregs[12] = gregs.arm_ip; + iregs[13] = gregs.arm_sp; + iregs[14] = gregs.arm_lr; + iregs[15] = gregs.arm_pc; + + out.cpsr = gregs.arm_cpsr; + } + + // TODO: this todo has been in breakpad for years.... + // TODO: fix this after fixing ExceptionHandler + //out.float_save.fpscr = 0; + //out.float_save.regs = [0; MD_FLOATINGSAVEAREA_ARM_FPR_COUNT]; + //out.float_save.extra = [0; MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT]; + } +} diff --git a/third_party/rust/minidump-writer/src/linux/crash_context/x86.rs b/third_party/rust/minidump-writer/src/linux/crash_context/x86.rs new file mode 100644 index 0000000000..7f092716bd --- /dev/null +++ b/third_party/rust/minidump-writer/src/linux/crash_context/x86.rs @@ -0,0 +1,62 @@ +use super::CrashContext; +use crate::{minidump_cpu::RawContextCPU, minidump_format::format::ContextFlagsX86}; +use libc::{ + REG_CS, REG_DS, REG_EAX, REG_EBP, REG_EBX, REG_ECX, REG_EDI, REG_EDX, REG_EFL, REG_EIP, REG_ES, + REG_ESI, REG_ESP, REG_FS, REG_GS, REG_SS, REG_UESP, +}; +impl CrashContext { + pub fn get_instruction_pointer(&self) -> usize { + self.inner.context.uc_mcontext.gregs[REG_EIP as usize] as usize + } + + pub fn get_stack_pointer(&self) -> usize { + self.inner.context.uc_mcontext.gregs[REG_ESP as usize] as usize + } + + pub fn fill_cpu_context(&self, out: &mut RawContextCPU) { + out.context_flags = ContextFlagsX86::CONTEXT_X86_FULL.bits() + | ContextFlagsX86::CONTEXT_X86_FLOATING_POINT.bits(); + + { + let gregs = &self.inner.context.uc_mcontext.gregs; + out.gs = gregs[REG_GS as usize] as u32; + out.fs = gregs[REG_FS as usize] as u32; + out.es = gregs[REG_ES as usize] as u32; + out.ds = gregs[REG_DS as usize] as u32; + + out.edi = gregs[REG_EDI as usize] as u32; + out.esi = gregs[REG_ESI as usize] as u32; + out.ebx = gregs[REG_EBX as usize] as u32; + out.edx = gregs[REG_EDX as usize] as u32; + out.ecx = gregs[REG_ECX as usize] as u32; + out.eax = gregs[REG_EAX as usize] as u32; + + out.ebp = gregs[REG_EBP as usize] as u32; + out.eip = gregs[REG_EIP as usize] as u32; + out.cs = gregs[REG_CS as usize] as u32; + out.eflags = gregs[REG_EFL as usize] as u32; + out.esp = gregs[REG_UESP as usize] as u32; + out.ss = gregs[REG_SS as usize] as u32; + } + + { + let fs = &self.inner.float_state; + let mut out = &mut out.float_save; + out.control_word = fs.cw; + out.status_word = fs.sw; + out.tag_word = fs.tag; + out.error_offset = fs.ipoff; + out.error_selector = fs.cssel; + out.data_offset = fs.dataoff; + out.data_selector = fs.datasel; + + debug_assert_eq!(fs._st.len() * std::mem::size_of::<libc::_libc_fpreg>(), 80); + out.register_area.copy_from_slice(unsafe { + std::slice::from_raw_parts( + fs._st.as_ptr().cast(), + fs._st.len() * std::mem::size_of::<libc::_libc_fpreg>(), + ) + }); + } + } +} diff --git a/third_party/rust/minidump-writer/src/linux/crash_context/x86_64.rs b/third_party/rust/minidump-writer/src/linux/crash_context/x86_64.rs new file mode 100644 index 0000000000..e559692679 --- /dev/null +++ b/third_party/rust/minidump-writer/src/linux/crash_context/x86_64.rs @@ -0,0 +1,78 @@ +use super::CrashContext; +use crate::{ + minidump_cpu::RawContextCPU, minidump_format::format, thread_info::copy_u32_registers, +}; +use libc::{ + REG_CSGSFS, REG_EFL, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_R8, REG_R9, + REG_RAX, REG_RBP, REG_RBX, REG_RCX, REG_RDI, REG_RDX, REG_RIP, REG_RSI, REG_RSP, +}; +use scroll::Pwrite; + +impl CrashContext { + pub fn get_instruction_pointer(&self) -> usize { + self.inner.context.uc_mcontext.gregs[REG_RIP as usize] as usize + } + + pub fn get_stack_pointer(&self) -> usize { + self.inner.context.uc_mcontext.gregs[REG_RSP as usize] as usize + } + + pub fn fill_cpu_context(&self, out: &mut RawContextCPU) { + out.context_flags = format::ContextFlagsAmd64::CONTEXT_AMD64_FULL.bits(); + + { + let gregs = &self.inner.context.uc_mcontext.gregs; + out.cs = (gregs[REG_CSGSFS as usize] & 0xffff) as u16; + + out.fs = ((gregs[REG_CSGSFS as usize] >> 32) & 0xffff) as u16; + out.gs = ((gregs[REG_CSGSFS as usize] >> 16) & 0xffff) as u16; + + out.eflags = gregs[REG_EFL as usize] as u32; + + out.rax = gregs[REG_RAX as usize] as u64; + out.rcx = gregs[REG_RCX as usize] as u64; + out.rdx = gregs[REG_RDX as usize] as u64; + out.rbx = gregs[REG_RBX as usize] as u64; + + out.rsp = gregs[REG_RSP as usize] as u64; + out.rbp = gregs[REG_RBP as usize] as u64; + out.rsi = gregs[REG_RSI as usize] as u64; + out.rdi = gregs[REG_RDI as usize] as u64; + out.r8 = gregs[REG_R8 as usize] as u64; + out.r9 = gregs[REG_R9 as usize] as u64; + out.r10 = gregs[REG_R10 as usize] as u64; + out.r11 = gregs[REG_R11 as usize] as u64; + out.r12 = gregs[REG_R12 as usize] as u64; + out.r13 = gregs[REG_R13 as usize] as u64; + out.r14 = gregs[REG_R14 as usize] as u64; + out.r15 = gregs[REG_R15 as usize] as u64; + + out.rip = gregs[REG_RIP as usize] as u64; + } + + { + let fs = &self.inner.float_state; + + let mut float_save = format::XMM_SAVE_AREA32 { + control_word: fs.cwd, + status_word: fs.swd, + tag_word: fs.ftw as u8, + error_opcode: fs.fop, + error_offset: fs.rip as u32, + data_offset: fs.rdp as u32, + error_selector: 0, // We don't have this. + data_selector: 0, // We don't have this. + mx_csr: fs.mxcsr, + mx_csr_mask: fs.mxcr_mask, + ..Default::default() + }; + + copy_u32_registers(&mut float_save.float_registers, &fs.st_space); + copy_u32_registers(&mut float_save.xmm_registers, &fs.xmm_space); + + out.float_save + .pwrite_with(float_save, 0, scroll::Endian::Little) + .expect("this is impossible"); + } + } +} |