mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 06:15:33 +00:00
Add support for argc/argv
This commit is contained in:
parent
fbc2fc9c50
commit
2b3c87e80c
@ -19,7 +19,7 @@ mod utils;
|
||||
mod varargs;
|
||||
|
||||
pub use self::storage::{align_memory, static_alloc};
|
||||
pub use self::utils::is_emscripten_module;
|
||||
pub use self::utils::{is_emscripten_module, copy_cstr_array_into_wasm};
|
||||
|
||||
// TODO: Magic number - how is this calculated?
|
||||
const TOTAL_STACK: u32 = 5242880;
|
||||
|
@ -829,7 +829,7 @@ pub extern "C" fn ___syscall63(
|
||||
unsafe { dup2(src, dst) }
|
||||
}
|
||||
|
||||
// newselect
|
||||
// select
|
||||
pub extern "C" fn ___syscall142(
|
||||
_which: c_int,
|
||||
mut varargs: VarArgs,
|
||||
|
@ -2,7 +2,7 @@ use byteorder::{ByteOrder, LittleEndian};
|
||||
use crate::webassembly::module::Module;
|
||||
use crate::webassembly::Instance;
|
||||
use libc::stat;
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::os::raw::c_char;
|
||||
use std::slice;
|
||||
|
||||
@ -16,7 +16,7 @@ pub fn is_emscripten_module(module: &Module) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
pub unsafe fn copy_cstr_into_wasm(instance: &mut Instance, cstr: *const c_char) -> u32 {
|
||||
pub unsafe fn copy_cstr_into_wasm(instance: &Instance, cstr: *const c_char) -> u32 {
|
||||
let s = CStr::from_ptr(cstr).to_str().unwrap();
|
||||
let space_offset = (instance.emscripten_data.as_ref().unwrap().malloc)(s.len() as _, instance);
|
||||
let raw_memory = instance.memory_offset_addr(0, space_offset as _) as *mut u8;
|
||||
@ -28,6 +28,24 @@ pub unsafe fn copy_cstr_into_wasm(instance: &mut Instance, cstr: *const c_char)
|
||||
space_offset
|
||||
}
|
||||
|
||||
pub unsafe fn copy_cstr_array_into_wasm(array_count: u32, array: *mut *mut c_char, instance: &Instance) -> u32 {
|
||||
let array_offset = (instance.emscripten_data.as_ref().unwrap().malloc)(array_count as _, instance);
|
||||
|
||||
let array_addr = instance.memory_offset_addr(0, array_offset as _) as *mut u32;
|
||||
for i in 0..array_count {
|
||||
let offset = copy_cstr_into_wasm(
|
||||
instance,
|
||||
*array.offset(i as isize)
|
||||
);
|
||||
*array_addr.offset(i as isize) = offset;
|
||||
}
|
||||
|
||||
// let first_arg_addr = instance.memory_offset_addr(0, *array_addr.offset(0) as _) as *const i8;
|
||||
// debug!("###### argv[0] = {:?}", CStr::from_ptr(first_arg_addr));
|
||||
|
||||
array_offset
|
||||
}
|
||||
|
||||
pub unsafe fn copy_terminated_array_of_cstrs(
|
||||
_instance: &mut Instance,
|
||||
cstrs: *mut *mut c_char,
|
||||
|
@ -1,4 +1,4 @@
|
||||
pub mod emscripten;
|
||||
pub mod host;
|
||||
|
||||
pub use self::emscripten::{align_memory, generate_emscripten_env, is_emscripten_module};
|
||||
pub use self::emscripten::{align_memory, generate_emscripten_env, is_emscripten_module, copy_cstr_array_into_wasm};
|
||||
|
@ -7,6 +7,7 @@ use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
use std::process::exit;
|
||||
|
||||
use apis::emscripten::copy_cstr_array_into_wasm;
|
||||
use structopt::StructOpt;
|
||||
|
||||
use wasmer::*;
|
||||
@ -28,11 +29,17 @@ enum CLIOptions {
|
||||
struct Run {
|
||||
#[structopt(short = "d", long = "debug")]
|
||||
debug: bool,
|
||||
|
||||
/// Input file
|
||||
#[structopt(parse(from_os_str))]
|
||||
path: PathBuf,
|
||||
|
||||
/// Application arguments
|
||||
#[structopt(name = "--", raw(multiple="true"))]
|
||||
args: Vec<String>,
|
||||
}
|
||||
|
||||
|
||||
/// Read the contents of a file
|
||||
fn read_file_contents(path: &PathBuf) -> Result<Vec<u8>, io::Error> {
|
||||
let mut buffer: Vec<u8> = Vec::new();
|
||||
@ -42,18 +49,22 @@ fn read_file_contents(path: &PathBuf) -> Result<Vec<u8>, io::Error> {
|
||||
}
|
||||
|
||||
/// Execute a WASM/WAT file
|
||||
fn execute_wasm(wasm_path: PathBuf) -> Result<(), String> {
|
||||
let mut wasm_binary: Vec<u8> = read_file_contents(&wasm_path).map_err(|err| {
|
||||
fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
let wasm_path = &options.path;
|
||||
|
||||
let mut wasm_binary: Vec<u8> = read_file_contents(wasm_path).map_err(|err| {
|
||||
format!(
|
||||
"Can't read the file {}: {}",
|
||||
wasm_path.as_os_str().to_string_lossy(),
|
||||
err
|
||||
)
|
||||
})?;
|
||||
|
||||
if !webassembly::utils::is_wasm_binary(&wasm_binary) {
|
||||
wasm_binary = wabt::wat2wasm(wasm_binary)
|
||||
.map_err(|err| format!("Can't convert from wast to wasm: {:?}", err))?;
|
||||
}
|
||||
|
||||
// TODO: We should instantiate after compilation, so we provide the
|
||||
// emscripten environment conditionally based on the module
|
||||
let import_object = apis::generate_emscripten_env();
|
||||
@ -62,6 +73,7 @@ fn execute_wasm(wasm_path: PathBuf) -> Result<(), String> {
|
||||
.map_err(|err| format!("Can't instantiate the WebAssembly module: {}", err))?;
|
||||
|
||||
if apis::emscripten::is_emscripten_module(&module) {
|
||||
|
||||
// Emscripten __ATINIT__
|
||||
if let Some(&webassembly::Export::Function(environ_constructor_index)) = module.info.exports.get("___emscripten_environ_constructor") {
|
||||
debug!("emscripten::___emscripten_environ_constructor");
|
||||
@ -69,14 +81,47 @@ fn execute_wasm(wasm_path: PathBuf) -> Result<(), String> {
|
||||
get_instance_function!(instance, environ_constructor_index);
|
||||
call_protected!(___emscripten_environ_constructor(&instance)).map_err(|err| format!("{}", err))?;
|
||||
};
|
||||
|
||||
// TODO: We also need to handle TTY.init() and SOCKFS.root = FS.mount(SOCKFS, {}, null)
|
||||
let func_index = match module.info.exports.get("_main") {
|
||||
Some(&webassembly::Export::Function(index)) => index,
|
||||
_ => panic!("_main emscripten function not found"),
|
||||
};
|
||||
|
||||
let main: extern "C" fn(u32, u32, &webassembly::Instance) =
|
||||
get_instance_function!(instance, func_index);
|
||||
return call_protected!(main(0, 0, &instance)).map_err(|err| format!("{}", err));
|
||||
|
||||
// Application Arguments
|
||||
let mut arg_values: Vec<String> = Vec::new();
|
||||
let mut arg_addrs: Vec<*const u8> = Vec::new();
|
||||
let arg_length = options.args.len() + 1;
|
||||
|
||||
arg_values.reserve_exact(arg_length);
|
||||
arg_addrs.reserve_exact(arg_length);
|
||||
|
||||
// Push name of wasm file
|
||||
arg_values.push(format!("{}\0", options.path.to_str().unwrap()));
|
||||
arg_addrs.push(arg_values[0].as_ptr());
|
||||
|
||||
// Push additional arguments
|
||||
for (i, arg) in options.args.iter().enumerate() {
|
||||
arg_values.push(format!("{}\0", arg));
|
||||
arg_addrs.push(arg_values[i + 1].as_ptr());
|
||||
}
|
||||
|
||||
// Get argument count and pointer to addresses
|
||||
let argv = arg_addrs.as_ptr() as *mut *mut i8;
|
||||
let argc = arg_length as u32;
|
||||
|
||||
// Copy the the arguments into the wasm memory and get offset
|
||||
let argv_offset = unsafe {
|
||||
copy_cstr_array_into_wasm(argc, argv, &instance)
|
||||
};
|
||||
|
||||
debug!("argc = {:?}", argc);
|
||||
debug!("argv = {:?}", arg_addrs);
|
||||
|
||||
return call_protected!(main(argc, argv_offset, &instance)).map_err(|err| format!("{}", err));
|
||||
// TODO: We should implement emscripten __ATEXIT__
|
||||
} else {
|
||||
let func_index =
|
||||
@ -93,7 +138,7 @@ fn execute_wasm(wasm_path: PathBuf) -> Result<(), String> {
|
||||
}
|
||||
|
||||
fn run(options: Run) {
|
||||
match execute_wasm(options.path.clone()) {
|
||||
match execute_wasm(&options) {
|
||||
Ok(()) => {}
|
||||
Err(message) => {
|
||||
// let name = options.path.as_os_str().to_string_lossy();
|
||||
@ -110,3 +155,9 @@ fn main() {
|
||||
CLIOptions::SelfUpdate => update::self_update(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn get_args() {
|
||||
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ fn get_function_addr(
|
||||
}
|
||||
|
||||
pub struct EmscriptenData {
|
||||
pub malloc: extern "C" fn(i32, &mut Instance) -> u32,
|
||||
pub malloc: extern "C" fn(i32, &Instance) -> u32,
|
||||
pub free: extern "C" fn(i32, &mut Instance),
|
||||
pub memalign: extern "C" fn (u32, u32, &mut Instance) -> u32,
|
||||
pub memset: extern "C" fn(u32, i32, u32, &mut Instance) -> u32,
|
||||
@ -551,11 +551,29 @@ impl Instance {
|
||||
let memalign_export = module.info.exports.get("_memalign");
|
||||
let memset_export = module.info.exports.get("_memset");
|
||||
|
||||
if let (Some(Export::Function(malloc_index)), Some(Export::Function(free_index)), Some(Export::Function(memalign_index)), Some(Export::Function(memset_index))) = (malloc_export, free_export, memalign_export, memset_export) {
|
||||
let malloc_addr = get_function_addr(&malloc_index, &import_functions, &functions);
|
||||
let free_addr = get_function_addr(&free_index, &import_functions, &functions);
|
||||
let memalign_addr = get_function_addr(&memalign_index, &import_functions, &functions);
|
||||
let memset_addr = get_function_addr(&memset_index, &import_functions, &functions);
|
||||
let mut malloc_addr = 0 as *const u8;
|
||||
let mut free_addr = 0 as *const u8;
|
||||
let mut memalign_addr = 0 as *const u8;
|
||||
let mut memset_addr = 0 as *const u8;
|
||||
|
||||
if malloc_export.is_none() && free_export.is_none() && memalign_export.is_none() && memset_export.is_none() {
|
||||
None
|
||||
} else {
|
||||
if let Some(Export::Function(malloc_index)) = malloc_export {
|
||||
malloc_addr = get_function_addr(&malloc_index, &import_functions, &functions);
|
||||
}
|
||||
|
||||
if let Some(Export::Function(free_index)) = free_export {
|
||||
free_addr = get_function_addr(&free_index, &import_functions, &functions);
|
||||
}
|
||||
|
||||
if let Some(Export::Function(memalign_index)) = memalign_export {
|
||||
memalign_addr = get_function_addr(&memalign_index, &import_functions, &functions);
|
||||
}
|
||||
|
||||
if let Some(Export::Function(memset_index)) = memset_export {
|
||||
memset_addr = get_function_addr(&memset_index, &import_functions, &functions);
|
||||
}
|
||||
|
||||
Some(EmscriptenData {
|
||||
malloc: mem::transmute(malloc_addr),
|
||||
@ -563,8 +581,6 @@ impl Instance {
|
||||
memalign: mem::transmute(memalign_addr),
|
||||
memset: mem::transmute(memset_addr),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user