diff --git a/redox-rt/src/arch/i686.rs b/redox-rt/src/arch/i686.rs index 27f1e55bce87fd910e6c306fd703aa60ffba311a..07d8ae05b74cea093bea1e17010c9a0c87d3acf4 100644 --- a/redox-rt/src/arch/i686.rs +++ b/redox-rt/src/arch/i686.rs @@ -3,7 +3,7 @@ use core::mem::offset_of; use syscall::*; use crate::proc::{fork_inner, FdGuard}; -use crate::signal::{inner_fastcall, RtSigarea}; +use crate::signal::{inner_fastcall, RtSigarea, SigStack}; // Setup a stack starting from the very end of the address space, and then growing downwards. pub(crate) const STACK_TOP: usize = 1 << 31; @@ -14,10 +14,30 @@ pub(crate) const STACK_SIZE: usize = 1024 * 1024; pub struct SigArea { pub altstack_top: usize, pub altstack_bottom: usize, - pub tmp: usize, + pub tmp_eip: usize, + pub tmp_esp: usize, + pub tmp_eax: usize, + pub tmp_edx: usize, pub onstack: u64, pub disable_signals_depth: u64, } +#[derive(Debug, Default)] +#[repr(C)] +pub struct ArchIntRegs { + pub _pad: [usize; 2], // make size divisible by 16 + + pub ebp: usize, + pub esi: usize, + pub edi: usize, + pub ebx: usize, + pub eax: usize, + pub ecx: usize, + pub edx: usize, + + pub eflags: usize, + pub eip: usize, + pub esp: usize, +} /// Deactive TLS, used before exec() on Redox to not trick target executable into thinking TLS /// is already initialized as if it was a thread. @@ -100,6 +120,7 @@ asmfunction!(__relibc_internal_fork_ret: [" ret "] <= [child_hook = sym child_hook]); asmfunction!(__relibc_internal_sigentry: [" + // Save some registers mov gs:[{tcb_sa_off} + {sa_tmp_esp}], esp mov gs:[{tcb_sa_off} + {sa_tmp_eax}], eax mov gs:[{tcb_sa_off} + {sa_tmp_edx}], edx @@ -136,33 +157,29 @@ asmfunction!(__relibc_internal_sigentry: [" mov esp, edx 4: // Now that we have a stack, we can finally start populating the signal stack. - push fs - .byte 0x66, 0x6a, 0x00 // pushw 0 - push ss - .byte 0x66, 0x6a, 0x00 // pushw 0 - push dword ptr gs:[{tcb_sa_off} + {sc_tmp_esp}] - push dword ptr gs:[{tcb_sc_off} + {sc_saved_eflags}] - push cs - .byte 0x66, 0x6a, 0x00 // pushw 0 + push dword ptr gs:[{tcb_sa_off} + {sa_tmp_esp}] push dword ptr gs:[{tcb_sc_off} + {sc_saved_eip}] + push dword ptr gs:[{tcb_sc_off} + {sc_saved_eflags}] - push dword ptr gs:[{tcb_sa_off} + {sc_tmp_edx}] + push dword ptr gs:[{tcb_sa_off} + {sa_tmp_edx}] push ecx - push dword ptr gs:[{tcb_sa_off} + {sc_tmp_eax}] + push dword ptr gs:[{tcb_sa_off} + {sa_tmp_eax}] push ebx push edi push esi push ebp + sub esp, 8 + push eax - sub esp, 512 + 8 + sub esp, 12 + 512 fxsave [esp] mov ecx, esp call {inner} fxrstor [esp] - add esp, 512 + 12 + add esp, 512 + 12 + 4 + 8 pop ebp pop esi @@ -172,10 +189,15 @@ asmfunction!(__relibc_internal_sigentry: [" pop ecx pop edx - pop dword ptr gs:[{tcb_sa_off} + {sa_tmp_eip}] - add esp, 4 popfd + pop dword ptr gs:[{tcb_sa_off} + {sa_tmp_eip}] + + .globl __relibc_internal_sigentry_crit_first +__relibc_internal_sigentry_crit_first: pop esp + + .globl __relibc_internal_sigentry_crit_second +__relibc_internal_sigentry_crit_second: jmp dword ptr gs:[{tcb_sa_off} + {sa_tmp_eip}] 7: ud2 @@ -218,3 +240,16 @@ asmfunction!(__relibc_internal_rlct_clone_ret -> usize: [" ret "] <= []); +extern "C" { + fn __relibc_internal_sigentry_crit_first(); + fn __relibc_internal_sigentry_crit_second(); +} +pub unsafe fn arch_pre(stack: &mut SigStack, area: &mut SigArea) { + if stack.regs.eip == __relibc_internal_sigentry_crit_first as usize { + let stack_ptr = stack.regs.esp as *const usize; + stack.regs.esp = stack_ptr.read(); + stack.regs.eip = stack_ptr.sub(1).read(); + } else if stack.regs.eip == __relibc_internal_sigentry_crit_second as usize { + stack.regs.eip = area.tmp_eip; + } +} diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index d328896d62fb73df93a7bcfbac9e62f6fe284ff2..8b7bf0ff495a0f219f2ba8d905c4469ce03ce0b9 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -29,19 +29,22 @@ pub fn sighandler_function() -> usize { #[repr(C)] pub struct SigStack { #[cfg(target_arch = "x86_64")] - fx: [u8; 4096], + fx: [u8; 4096], // 64 byte aligned #[cfg(target_arch = "x86")] - fx: [u8; 512], + fx: [u8; 512], // 16 byte aligned #[cfg(target_arch = "x86_64")] _pad: [usize; 3], // pad to 192 = 3 * 64 = 168 + 24 bytes #[cfg(target_arch = "x86")] - _pad: [usize; 2], // pad to 192 = 3 * 64 = 168 + 24 bytes + _pad: [usize; 3], // pad to 64 = 4 * 16 = 52 + 12 bytes sig_num: usize, - pub regs: ArchIntRegs, // 160 bytes currently + + // x86_64: 160 bytes + // i686: 48 bytes + pub regs: ArchIntRegs, } #[inline(always)]