summaryrefslogtreecommitdiffstats
path: root/third_party/rust/minidump-writer/src/linux/crash_context/x86_64.rs
blob: e559692679adc764ee7db52b2ad95fafbace1e98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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");
        }
    }
}