summaryrefslogtreecommitdiffstats
path: root/third_party/rust/crash-context/src/linux/getcontext/x86.rs
blob: cb823e1182301eeec5af213fa5f6df679c88683e (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
// Unfortunately, the asm! macro has a few really annoying limitations at the
// moment
//
// 1. const operands are unstable
// 2. cfg attributes can't be used inside the asm macro at all
//
// and the worst part is we need it for literally only 1 thing, using a different
// offset to the fpstate in ucontext depending on whether we are targeting android
// or not :(
macro_rules! asm_func {
    ($offset:expr) => {
        std::arch::global_asm! {
            ".text",
            ".global crash_context_getcontext",
            ".hidden crash_context_getcontext",
            ".align 4",
            ".type crash_context_getcontext, @function",
        "crash_context_getcontext:",
            "movl 4(%esp), %eax",   // eax = uc

            // Save register values
            "movl %ecx, 0x3c(%eax)",
            "movl %edx, 0x38(%eax)",
            "movl %ebx, 0x34(%eax)",
            "movl %edi, 0x24(%eax)",
            "movl %esi, 0x28(%eax)",
            "movl %ebp, 0x2c(%eax)",

            "movl (%esp), %edx",   /* return address */
            "lea  4(%esp), %ecx",  /* exclude return address from stack */
            "mov  %edx, 0x4c(%eax)",
            "mov  %ecx, 0x30(%eax)",

            "xorl %ecx, %ecx",
            "movw %fs, %cx",
            "mov  %ecx, 0x18(%eax)",

            "movl $0, 0x40(%eax)",

            // Save floating point state to fpregstate, then update
            // the fpregs pointer to point to it
            stringify!(leal $offset(%eax),%ecx),
            "fnstenv (%ecx)",
            "fldenv  (%ecx)",
            "mov %ecx, 0x60(%eax)",

            // Save signal mask: sigprocmask(SIGBLOCK, NULL, &uc->uc_sigmask)
            "leal 0x6c(%eax), %edx",
            "xorl %ecx, %ecx",
            "push %edx",   /* &uc->uc_sigmask */
            "push %ecx",   /* NULL */
            "push %ecx",   /* SIGBLOCK == 0 on i386 */
            "call sigprocmask@PLT",
            "addl $12, %esp",

            "movl $0, %eax",
            "ret",

            ".size crash_context_getcontext, . - crash_context_getcontext",
            options(att_syntax)
        }
    };
}

#[cfg(target_os = "linux")]
asm_func!(0xec);
#[cfg(target_os = "android")]
asm_func!(0x74);