mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 14:25:32 +00:00
Add sig* syscalls
This commit is contained in:
parent
ad426fb5e3
commit
88589a9cbc
@ -127,7 +127,7 @@
|
|||||||
```rust
|
```rust
|
||||||
|
|
||||||
```
|
```
|
||||||
- **dup** (\_\_\_syscall63) [:top:](#host-apis)
|
- **dup2** (\_\_\_syscall63) [:top:](#host-apis)
|
||||||
```rust
|
```rust
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
}
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user