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 ```rust
``` ```
- **dup** (\_\_\_syscall63)     [:top:](#host-apis) - **dup2** (\_\_\_syscall63)     [:top:](#host-apis)
```rust ```rust
``` ```

View File

@ -224,6 +224,11 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
"___syscall180", "___syscall180",
ImportValue::Func(syscalls::___syscall180 as _), ImportValue::Func(syscalls::___syscall180 as _),
); );
import_object.set(
"env",
"___syscall181",
ImportValue::Func(syscalls::___syscall181 as _),
);
import_object.set( import_object.set(
"env", "env",
"___syscall39", "___syscall39",
@ -264,6 +269,11 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
"___syscall192", "___syscall192",
ImportValue::Func(syscalls::___syscall192 as _), ImportValue::Func(syscalls::___syscall192 as _),
); );
import_object.set(
"env",
"___syscall63",
ImportValue::Func(syscalls::___syscall63 as _),
);
// Process // Process
import_object.set( import_object.set(
@ -281,6 +291,27 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
"abortStackOverflow", "abortStackOverflow",
ImportValue::Func(process::abort_stack_overflow as _), 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 // Memory
import_object.set( import_object.set(
"env", "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, _sysconf);
// mock_external!(import_object, _strftime); // mock_external!(import_object, _strftime);
mock_external!(import_object, _sigsuspend); mock_external!(import_object, _sigsuspend);
mock_external!(import_object, _sigprocmask); // mock_external!(import_object, _sigprocmask);
mock_external!(import_object, _sigemptyset); // mock_external!(import_object, _sigemptyset);
mock_external!(import_object, _sigaddset); // mock_external!(import_object, _sigaddset);
mock_external!(import_object, _sigaction); // mock_external!(import_object, _sigaction);
mock_external!(import_object, _setitimer); mock_external!(import_object, _setitimer);
mock_external!(import_object, _setgroups); mock_external!(import_object, _setgroups);
mock_external!(import_object, _setgrent); 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, ___syscall75);
mock_external!(import_object, ___syscall66); mock_external!(import_object, ___syscall66);
// mock_external!(import_object, ___syscall64); // mock_external!(import_object, ___syscall64);
mock_external!(import_object, ___syscall63); // mock_external!(import_object, ___syscall63);
mock_external!(import_object, ___syscall60); mock_external!(import_object, ___syscall60);
// mock_external!(import_object, ___syscall54); // mock_external!(import_object, ___syscall54);
// mock_external!(import_object, ___syscall39); // 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, ___syscall195);
mock_external!(import_object, ___syscall194); mock_external!(import_object, ___syscall194);
mock_external!(import_object, ___syscall191); mock_external!(import_object, ___syscall191);
mock_external!(import_object, ___syscall181); // mock_external!(import_object, ___syscall181);
// mock_external!(import_object, ___syscall180); // mock_external!(import_object, ___syscall180);
mock_external!(import_object, ___syscall168); mock_external!(import_object, ___syscall168);
// mock_external!(import_object, ___syscall146); // 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 // TODO: Message incomplete. Need to finish em runtime data first
abort_with_message("Stack overflow! Attempted to allocate some bytes on the stack"); 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, open,
pid_t, pid_t,
pread, pread,
pwrite,
read, read,
readv, readv,
recvfrom, recvfrom,
@ -49,6 +50,7 @@ use libc::{
in_port_t, in_port_t,
in_addr_t, in_addr_t,
c_char, c_char,
dup2,
}; };
/// sys_exit /// sys_exit
@ -470,6 +472,27 @@ pub extern "C" fn ___syscall180(
unsafe { pread(fd, buf_ptr, count as _, offset) as _ } 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 // sys_stat64
pub extern "C" fn ___syscall195( pub extern "C" fn ___syscall195(
_which: c_int, _which: c_int,
@ -587,3 +610,18 @@ pub extern "C" fn ___syscall340(
0 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 //! 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. //! 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" { extern "C" {
pub fn setjmp(env: *mut ::nix::libc::c_void) -> ::nix::libc::c_int; 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! { thread_local! {
pub static SETJMP_BUFFER: UnsafeCell<[::nix::libc::c_int; SETJMP_BUFFER_LEN]> = UnsafeCell::new([0; SETJMP_BUFFER_LEN]); 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 // We need a macro since the arguments we will provide to the funciton
@ -28,7 +30,7 @@ thread_local! {
macro_rules! call_protected { macro_rules! call_protected {
($x:expr) => { ($x:expr) => {
unsafe { unsafe {
use crate::recovery::{setjmp, SETJMP_BUFFER}; use crate::recovery::{setjmp, SETJMP_BUFFER, CAUGHT_ADDRESS};
use crate::sighandler::install_sighandler; use crate::sighandler::install_sighandler;
use crate::webassembly::ErrorKind; use crate::webassembly::ErrorKind;
@ -42,6 +44,8 @@ macro_rules! call_protected {
let signum = setjmp(jmp_buf as *mut ::nix::libc::c_void); let signum = setjmp(jmp_buf as *mut ::nix::libc::c_void);
if signum != 0 { if signum != 0 {
*jmp_buf = prev_jmp_buf; *jmp_buf = prev_jmp_buf;
let addr = CAUGHT_ADDRESS.with(|cell| cell.get());
let signal = match Signal::from_c_int(signum) { let signal = match Signal::from_c_int(signum) {
Ok(SIGFPE) => "floating-point exception", Ok(SIGFPE) => "floating-point exception",
Ok(SIGILL) => "illegal instruction", Ok(SIGILL) => "illegal instruction",
@ -50,7 +54,7 @@ macro_rules! call_protected {
Err(_) => "error while getting the Signal", Err(_) => "error while getting the Signal",
_ => "unkown trapped signal", _ => "unkown trapped signal",
}; };
Err(ErrorKind::RuntimeError(format!("trap - {}", signal))) Err(ErrorKind::RuntimeError(format!("trap at {:#x} - {}", addr, signal)))
} else { } else {
let ret = $x; // TODO: Switch stack? let ret = $x; // TODO: Switch stack?
*jmp_buf = prev_jmp_buf; *jmp_buf = prev_jmp_buf;
@ -61,7 +65,7 @@ macro_rules! call_protected {
} }
/// Unwinds to last protected_call. /// 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.) // 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 // 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. // 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] { if *jmp_buf == [0; SETJMP_BUFFER_LEN] {
::std::process::abort(); ::std::process::abort();
} }
CAUGHT_ADDRESS.with(|cell| cell.set((*siginfo).si_addr as _));
longjmp(jmp_buf as *mut ::nix::libc::c_void, signum) longjmp(jmp_buf as *mut ::nix::libc::c_void, signum)
} }

View File

@ -8,10 +8,11 @@ use super::recovery;
use nix::sys::signal::{ use nix::sys::signal::{
sigaction, SaFlags, SigAction, SigHandler, SigSet, SIGBUS, SIGFPE, SIGILL, SIGSEGV, sigaction, SaFlags, SigAction, SigHandler, SigSet, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
}; };
use nix::libc::{siginfo_t, c_void};
pub unsafe fn install_sighandler() { pub unsafe fn install_sighandler() {
let sa = SigAction::new( let sa = SigAction::new(
SigHandler::Handler(signal_trap_handler), SigHandler::SigAction(signal_trap_handler),
SaFlags::SA_ONSTACK, SaFlags::SA_ONSTACK,
SigSet::empty(), SigSet::empty(),
); );
@ -21,8 +22,8 @@ pub unsafe fn install_sighandler() {
sigaction(SIGBUS, &sa).unwrap(); 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 { unsafe {
recovery::do_unwind(signum); recovery::do_unwind(signum, siginfo);
} }
} }