Add sig* syscalls

This commit is contained in:
Lachlan Sneff 2018-11-27 19:10:43 -05:00
parent ad426fb5e3
commit 88589a9cbc
6 changed files with 115 additions and 14 deletions

View File

@ -127,7 +127,7 @@
```rust
```
- **dup** (\_\_\_syscall63)     [:top:](#host-apis)
- **dup2** (\_\_\_syscall63)     [:top:](#host-apis)
```rust
```

View File

@ -224,6 +224,11 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
"___syscall180",
ImportValue::Func(syscalls::___syscall180 as _),
);
import_object.set(
"env",
"___syscall181",
ImportValue::Func(syscalls::___syscall181 as _),
);
import_object.set(
"env",
"___syscall39",
@ -264,6 +269,11 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
"___syscall192",
ImportValue::Func(syscalls::___syscall192 as _),
);
import_object.set(
"env",
"___syscall63",
ImportValue::Func(syscalls::___syscall63 as _),
);
// Process
import_object.set(
@ -281,6 +291,27 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
"abortStackOverflow",
ImportValue::Func(process::abort_stack_overflow as _),
);
import_object.set(
"env",
"_sigemptyset",
ImportValue::Func(process::_sigemptyset as _),
);
import_object.set(
"env",
"_sigaddset",
ImportValue::Func(process::_sigaddset as _),
);
import_object.set(
"env",
"_sigprocmask",
ImportValue::Func(process::_sigprocmask as _),
);
import_object.set(
"env",
"_sigaction",
ImportValue::Func(process::_sigaction as _),
);
// Memory
import_object.set(
"env",
@ -384,10 +415,10 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
mock_external!(import_object, _sysconf);
// mock_external!(import_object, _strftime);
mock_external!(import_object, _sigsuspend);
mock_external!(import_object, _sigprocmask);
mock_external!(import_object, _sigemptyset);
mock_external!(import_object, _sigaddset);
mock_external!(import_object, _sigaction);
// mock_external!(import_object, _sigprocmask);
// mock_external!(import_object, _sigemptyset);
// mock_external!(import_object, _sigaddset);
// mock_external!(import_object, _sigaction);
mock_external!(import_object, _setitimer);
mock_external!(import_object, _setgroups);
mock_external!(import_object, _setgrent);
@ -418,7 +449,7 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
mock_external!(import_object, ___syscall75);
mock_external!(import_object, ___syscall66);
// mock_external!(import_object, ___syscall64);
mock_external!(import_object, ___syscall63);
// mock_external!(import_object, ___syscall63);
mock_external!(import_object, ___syscall60);
// mock_external!(import_object, ___syscall54);
// mock_external!(import_object, ___syscall39);
@ -439,7 +470,7 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
// mock_external!(import_object, ___syscall195);
mock_external!(import_object, ___syscall194);
mock_external!(import_object, ___syscall191);
mock_external!(import_object, ___syscall181);
// mock_external!(import_object, ___syscall181);
// mock_external!(import_object, ___syscall180);
mock_external!(import_object, ___syscall168);
// mock_external!(import_object, ___syscall146);

View File

@ -33,3 +33,29 @@ pub extern "C" fn abort_stack_overflow() {
// TODO: Message incomplete. Need to finish em runtime data first
abort_with_message("Stack overflow! Attempted to allocate some bytes on the stack");
}
pub extern "C" fn _sigemptyset(set: u32, instance: &mut Instance) -> i32 {
debug!("emscripten::_sigemptyset");
let set_addr = instance.memory_offset_addr(0, set as _) as *mut u32;
unsafe {
*set_addr = 0;
}
0
}
pub extern "C" fn _sigaction(_signum: u32, act: u32, oldact: u32) -> i32 {
debug!("emscripten::_sigaction");
0
}
pub extern "C" fn _sigaddset(set: u32, signum: u32, instance: &mut Instance) -> i32 {
let set_addr = instance.memory_offset_addr(0, set as _) as *mut u32;
unsafe {
*set_addr |= 1 << (signum - 1);
}
0
}
pub extern "C" fn _sigprocmask() -> i32 {
0
}

View File

@ -29,6 +29,7 @@ use libc::{
open,
pid_t,
pread,
pwrite,
read,
readv,
recvfrom,
@ -49,6 +50,7 @@ use libc::{
in_port_t,
in_addr_t,
c_char,
dup2,
};
/// sys_exit
@ -470,6 +472,27 @@ pub extern "C" fn ___syscall180(
unsafe { pread(fd, buf_ptr, count as _, offset) as _ }
}
// sys_pwrite
pub extern "C" fn ___syscall181(
_which: c_int,
mut varargs: VarArgs,
instance: &mut Instance,
) -> c_int {
debug!("emscripten::___syscall181");
let fd: i32 = varargs.get(instance);
let buf: u32 = varargs.get(instance);
let count: u32 = varargs.get(instance);
{
let zero: u32 = varargs.get(instance);
assert_eq!(zero, 0);
}
let offset: i64 = varargs.get(instance);
let buf_ptr = instance.memory_offset_addr(0, buf as _) as _;
unsafe { pwrite(fd, buf_ptr, count as _, offset) as _ }
}
// sys_stat64
pub extern "C" fn ___syscall195(
_which: c_int,
@ -587,3 +610,18 @@ pub extern "C" fn ___syscall340(
0
}
// sys_dup2
pub extern "C" fn ___syscall63(
_which: c_int,
mut varargs: VarArgs,
instance: &mut Instance,
) -> c_int {
debug!("emscripten::___syscall63");
let src: i32 = varargs.get(instance);
let dst: i32 = varargs.get(instance);
unsafe {
dup2(src, dst)
}
}

View File

@ -4,7 +4,8 @@
//! are very special, the async signal unsafety of Rust's TLS implementation generally does not affect the correctness here
//! unless you have memory unsafety elsewhere in your code.
use std::cell::UnsafeCell;
use std::cell::{Cell, UnsafeCell};
use nix::libc::siginfo_t;
extern "C" {
pub fn setjmp(env: *mut ::nix::libc::c_void) -> ::nix::libc::c_int;
@ -15,6 +16,7 @@ const SETJMP_BUFFER_LEN: usize = 27;
thread_local! {
pub static SETJMP_BUFFER: UnsafeCell<[::nix::libc::c_int; SETJMP_BUFFER_LEN]> = UnsafeCell::new([0; SETJMP_BUFFER_LEN]);
pub static CAUGHT_ADDRESS: Cell<usize> = Cell::new(0);
}
// We need a macro since the arguments we will provide to the funciton
@ -28,7 +30,7 @@ thread_local! {
macro_rules! call_protected {
($x:expr) => {
unsafe {
use crate::recovery::{setjmp, SETJMP_BUFFER};
use crate::recovery::{setjmp, SETJMP_BUFFER, CAUGHT_ADDRESS};
use crate::sighandler::install_sighandler;
use crate::webassembly::ErrorKind;
@ -42,6 +44,8 @@ macro_rules! call_protected {
let signum = setjmp(jmp_buf as *mut ::nix::libc::c_void);
if signum != 0 {
*jmp_buf = prev_jmp_buf;
let addr = CAUGHT_ADDRESS.with(|cell| cell.get());
let signal = match Signal::from_c_int(signum) {
Ok(SIGFPE) => "floating-point exception",
Ok(SIGILL) => "illegal instruction",
@ -50,7 +54,7 @@ macro_rules! call_protected {
Err(_) => "error while getting the Signal",
_ => "unkown trapped signal",
};
Err(ErrorKind::RuntimeError(format!("trap - {}", signal)))
Err(ErrorKind::RuntimeError(format!("trap at {:#x} - {}", addr, signal)))
} else {
let ret = $x; // TODO: Switch stack?
*jmp_buf = prev_jmp_buf;
@ -61,7 +65,7 @@ macro_rules! call_protected {
}
/// Unwinds to last protected_call.
pub unsafe fn do_unwind(signum: i32) -> ! {
pub unsafe fn do_unwind(signum: i32, siginfo: *mut siginfo_t) -> ! {
// Since do_unwind is only expected to get called from WebAssembly code which doesn't hold any host resources (locks etc.)
// itself, accessing TLS here is safe. In case any other code calls this, it often indicates a memory safety bug and you should
// temporarily disable the signal handlers to debug it.
@ -70,6 +74,7 @@ pub unsafe fn do_unwind(signum: i32) -> ! {
if *jmp_buf == [0; SETJMP_BUFFER_LEN] {
::std::process::abort();
}
CAUGHT_ADDRESS.with(|cell| cell.set((*siginfo).si_addr as _));
longjmp(jmp_buf as *mut ::nix::libc::c_void, signum)
}

View File

@ -8,10 +8,11 @@ use super::recovery;
use nix::sys::signal::{
sigaction, SaFlags, SigAction, SigHandler, SigSet, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
};
use nix::libc::{siginfo_t, c_void};
pub unsafe fn install_sighandler() {
let sa = SigAction::new(
SigHandler::Handler(signal_trap_handler),
SigHandler::SigAction(signal_trap_handler),
SaFlags::SA_ONSTACK,
SigSet::empty(),
);
@ -21,8 +22,8 @@ pub unsafe fn install_sighandler() {
sigaction(SIGBUS, &sa).unwrap();
}
extern "C" fn signal_trap_handler(signum: ::nix::libc::c_int) {
extern "C" fn signal_trap_handler(signum: ::nix::libc::c_int, siginfo: *mut siginfo_t, _ucontext: *mut c_void) {
unsafe {
recovery::do_unwind(signum);
recovery::do_unwind(signum, siginfo);
}
}