Source code

Revision control

Copy as Markdown

Other Tools

// 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);