diff --git a/Cargo.lock b/Cargo.lock index 294f5f430..020ce3628 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1006,14 +1006,14 @@ dependencies = [ "lucet-validate 0.4.1", "memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "minisign 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmonkey 0.1.8", + "wasmonkey 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1165,6 +1165,11 @@ name = "parity-wasm" version = "0.40.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "parity-wasm" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pbkdf2" version = "0.3.0" @@ -1935,13 +1940,14 @@ dependencies = [ [[package]] name = "wasmonkey" -version = "0.1.8" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2128,6 +2134,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum object 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a411a7fd46b7ebc9849c80513c84280f41cbc3159f489cd77fb30ecefdd1218a" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1e39faaa292a687ea15120b1ac31899b13586446521df6c149e46f1584671e0f" +"checksum parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc878dac00da22f8f61e7af3157988424567ab01d9920b962ef7dcbd7cd865" "checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" "checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea" @@ -2219,6 +2226,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum wabt-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af5d153dc96aad7dc13ab90835b892c69867948112d95299e522d370c4e13a08" "checksum wait-timeout 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" +"checksum wasmonkey 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "af7c4bc80224427965ba21d87982cfc07d12e859824f303272056fb19f571ef9" "checksum wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5083b449454f7de0b15f131eee17de54b5a71dcb9adcf11df2b2f78fad0cd82" "checksum which 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "240a31163872f7e8e49f35b42b58485e35355b07eb009d9f3686733541339a69" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/lucet-builtins/wasmonkey/.gitignore b/lucet-builtins/wasmonkey/.gitignore deleted file mode 100644 index 53eaa2196..000000000 --- a/lucet-builtins/wasmonkey/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -**/*.rs.bk diff --git a/lucet-builtins/wasmonkey/.travis.yml b/lucet-builtins/wasmonkey/.travis.yml deleted file mode 100644 index 32905a519..000000000 --- a/lucet-builtins/wasmonkey/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: rust -rust: - - nightly - - stable diff --git a/lucet-builtins/wasmonkey/Cargo.toml b/lucet-builtins/wasmonkey/Cargo.toml deleted file mode 100644 index 0c18dd000..000000000 --- a/lucet-builtins/wasmonkey/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "wasmonkey" -version = "0.1.8" -authors = ["Lucet team "] -description = "Patch a WASM object file to replace a set of exported functions with imported functions from another library" -license = "Apache-2.0 WITH LLVM-exception" -homepage = "https://github.com/fastly/lucet" -repository = "https://github.com/fastly/lucet" -categories = ["wasm"] -edition = "2018" - -[dependencies] -clap = "2.33" -failure = "0.1" -goblin = "0.0.24" -lazy_static = "1.3" -parity-wasm = "0.40.3" -serde = "1.0" -serde_derive = "1.0" -serde_json = "1.0" -siphasher = "0.3" -xfailure = "0.1" diff --git a/lucet-builtins/wasmonkey/README.md b/lucet-builtins/wasmonkey/README.md deleted file mode 100644 index ae588b3d9..000000000 --- a/lucet-builtins/wasmonkey/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# WASMonkey - -The WASMonkey patches a WASM object file to replace a set of exported -functions with imported functions from another library. - -## Usage - -```text -USAGE: - wasmonkey [FLAGS] [OPTIONS] --input --output - -FLAGS: - -n, --original-names Use the original name as a key in the builtins map - -h, --help Prints help information - -V, --version Prints version information - -OPTIONS: - -B, --builtins-additional ... Additional builtins function names to replace - -b, --builtins Path to the builtins library - -m, --builtins-map Path to the builtins map file - -i, --input Path to the input file - -o, --output Path to the output file -``` - -`builtins_file` is an object containing alternative implementations to -functions called in the wasm code. - -Symbols starting with a `builtin_` prefix will be used for substitution. - -For example, a `memmove()` function defined as an external in the WASM -object will be replaced by calls to an imported `builtin_memmove()` -function, if `builtin_memmove()` is present in the builtins file. - -A JSON-encoded map of the performed substitutions can be optionally written -into `builtins_map_file`. diff --git a/lucet-builtins/wasmonkey/src/bin/config/mod.rs b/lucet-builtins/wasmonkey/src/bin/config/mod.rs deleted file mode 100644 index ccd29b985..000000000 --- a/lucet-builtins/wasmonkey/src/bin/config/mod.rs +++ /dev/null @@ -1,96 +0,0 @@ -use crate::{PatcherConfig, WError}; -use clap::Arg; -use std::path::PathBuf; - -#[derive(Default, Clone, Debug)] -pub struct Config { - pub input_path: PathBuf, - pub output_path: PathBuf, - pub patcher_config: PatcherConfig, -} - -impl Config { - pub fn parse_cmdline() -> Result { - let _ = include_str!("../../../Cargo.toml"); - let matches = app_from_crate!() - .arg( - Arg::with_name("input_file") - .short("i") - .long("input") - .takes_value(true) - .required(true) - .help("Path to the input file"), - ) - .arg( - Arg::with_name("output_file") - .short("o") - .long("output") - .takes_value(true) - .required(true) - .help("Path to the output file"), - ) - .arg( - Arg::with_name("builtins_file") - .short("b") - .long("builtins") - .takes_value(true) - .required(false) - .help("Path to the builtins library"), - ) - .arg( - Arg::with_name("builtins_additional") - .short("B") - .long("builtins-additional") - .takes_value(true) - .required(false) - .multiple(true) - .help("Additional builtins function names to replace"), - ) - .arg( - Arg::with_name("builtins_map_file") - .short("m") - .long("builtins-map") - .takes_value(true) - .required(false) - .help("Path to the builtins map file"), - ) - .arg( - Arg::with_name("builtins_map_original_names") - .short("n") - .long("original-names") - .takes_value(false) - .required(false) - .help("Use the original name as a key in the builtins map"), - ) - .get_matches(); - let input_path = PathBuf::from( - matches - .value_of("input_file") - .ok_or(WError::UsageError("Input file required"))?, - ); - let output_path = PathBuf::from( - matches - .value_of("output_file") - .ok_or(WError::UsageError("Output file required"))?, - ); - let builtins_path = matches.value_of("builtins_file").map(PathBuf::from); - let builtins_map_path = matches.value_of("builtins_map_file").map(PathBuf::from); - let builtins_map_original_names = matches.is_present("builtins_map_original_names"); - let builtins_additional = matches - .values_of("builtins_additional") - .unwrap_or_default() - .map(|name| name.to_string()) - .collect(); - let config = Config { - input_path, - output_path, - patcher_config: PatcherConfig { - builtins_path, - builtins_map_path, - builtins_map_original_names, - builtins_additional, - }, - }; - Ok(config) - } -} diff --git a/lucet-builtins/wasmonkey/src/bin/wasmonkey.rs b/lucet-builtins/wasmonkey/src/bin/wasmonkey.rs deleted file mode 100644 index 5ed604369..000000000 --- a/lucet-builtins/wasmonkey/src/bin/wasmonkey.rs +++ /dev/null @@ -1,14 +0,0 @@ -mod config; - -#[macro_use] -extern crate clap; - -use crate::config::*; -use wasmonkey::*; - -fn main() -> Result<(), WError> { - let config = Config::parse_cmdline()?; - let patcher = Patcher::from_file(config.patcher_config, config.input_path)?; - patcher.store_to_file(config.output_path)?; - Ok(()) -} diff --git a/lucet-builtins/wasmonkey/src/errors.rs b/lucet-builtins/wasmonkey/src/errors.rs deleted file mode 100644 index 70e0998f8..000000000 --- a/lucet-builtins/wasmonkey/src/errors.rs +++ /dev/null @@ -1,31 +0,0 @@ -use parity_wasm::elements; -use std::io; - -#[allow(dead_code)] -#[derive(Debug, Fail)] -pub enum WError { - #[fail(display = "Internal error: {}", _0)] - InternalError(&'static str), - #[fail(display = "Incorrect usage: {}", _0)] - UsageError(&'static str), - #[fail(display = "{}", _0)] - Io(#[cause] io::Error), - #[fail(display = "{}", _0)] - WAsmError(#[cause] elements::Error), - #[fail(display = "Parse error")] - ParseError, - #[fail(display = "Unsupported")] - Unsupported, -} - -impl From for WError { - fn from(e: io::Error) -> WError { - WError::Io(e) - } -} - -impl From for WError { - fn from(e: elements::Error) -> WError { - WError::WAsmError(e) - } -} diff --git a/lucet-builtins/wasmonkey/src/functions_ids.rs b/lucet-builtins/wasmonkey/src/functions_ids.rs deleted file mode 100644 index 64850d85a..000000000 --- a/lucet-builtins/wasmonkey/src/functions_ids.rs +++ /dev/null @@ -1,104 +0,0 @@ -use crate::errors::*; -use parity_wasm::elements::{ - CodeSection, ElementSection, ExportSection, FuncBody, Instruction, Instructions, Internal, - Module, -}; - -fn shift_function_ids_in_code_section( - code_section: &mut CodeSection, - shift: u32, -) -> Result<(), WError> { - let code_bodies = code_section.bodies_mut(); - for code_body in code_bodies.iter_mut() { - let opcodes = code_body.code_mut().elements_mut(); - for opcode in opcodes.iter_mut() { - if let Instruction::Call(function_id) = *opcode { - *opcode = Instruction::Call(function_id + shift) - } - } - } - Ok(()) -} - -fn shift_function_ids_in_exports_section(export_section: &mut ExportSection, shift: u32) { - for entry in export_section.entries_mut() { - let internal = entry.internal_mut(); - if let Internal::Function(function_id) = *internal { - *internal = Internal::Function(function_id + shift) - } - } -} - -fn shift_function_ids_in_elements_section(elements_section: &mut ElementSection, shift: u32) { - for elements_segment in elements_section.entries_mut() { - for function_id in elements_segment.members_mut() { - *function_id += shift; - } - } -} - -pub fn shift_function_ids(module: &mut Module, shift: u32) -> Result<(), WError> { - shift_function_ids_in_code_section(module.code_section_mut().expect("No code section"), shift)?; - if let Some(export_section) = module.export_section_mut() { - shift_function_ids_in_exports_section(export_section, shift) - } - if let Some(elements_section) = module.elements_section_mut() { - shift_function_ids_in_elements_section(elements_section, shift) - } - Ok(()) -} - -fn replace_function_id_in_code_section(code_section: &mut CodeSection, before: u32, after: u32) { - let code_bodies = code_section.bodies_mut(); - for code_body in code_bodies.iter_mut() { - let opcodes = code_body.code_mut().elements_mut(); - for opcode in opcodes.iter_mut() { - match *opcode { - Instruction::Call(function_id) if function_id == before => { - *opcode = Instruction::Call(after) - } - _ => {} - } - } - } -} - -fn replace_function_id_in_elements_section( - elements_section: &mut ElementSection, - before: u32, - after: u32, -) { - for elements_segment in elements_section.entries_mut() { - for function_id in elements_segment.members_mut() { - if *function_id == before { - *function_id = after; - } - } - } -} - -pub fn replace_function_id(module: &mut Module, before: u32, after: u32) -> Result<(), WError> { - if let Some(code_section) = module.code_section_mut() { - replace_function_id_in_code_section(code_section, before, after) - } - - if let Some(elements_section) = module.elements_section_mut() { - replace_function_id_in_elements_section(elements_section, before, after) - }; - - Ok(()) -} - -#[allow(dead_code)] -pub fn disable_function_id(module: &mut Module, function_id: u32) -> Result<(), WError> { - let base_id = match module.import_section() { - None => 0, - Some(import_section) => import_section.entries().len() as u32, - }; - let code_section = module.code_section_mut().expect("No code section"); - let code_bodies = code_section.bodies_mut(); - let opcodes = Instructions::new(vec![Instruction::Unreachable, Instruction::End]); - let func_body = FuncBody::new(vec![], opcodes); - code_bodies[(function_id - base_id) as usize] = func_body; - Ok(()) -} diff --git a/lucet-builtins/wasmonkey/src/functions_names.rs b/lucet-builtins/wasmonkey/src/functions_names.rs deleted file mode 100644 index 25ba00b9c..000000000 --- a/lucet-builtins/wasmonkey/src/functions_names.rs +++ /dev/null @@ -1,15 +0,0 @@ -use crate::errors::*; -use parity_wasm::elements::{FunctionNameSubsection, IndexMap}; - -pub fn prepend_function_name( - function_names_subsection: &mut FunctionNameSubsection, - name: String, -) -> Result<(), WError> { - let mut map_new = IndexMap::with_capacity(function_names_subsection.names().len() + 1 as usize); - for (idx, name) in function_names_subsection.names() { - map_new.insert(idx + 1, name.clone()); - } - map_new.insert(0, name); - *function_names_subsection.names_mut() = map_new; - Ok(()) -} diff --git a/lucet-builtins/wasmonkey/src/lib.rs b/lucet-builtins/wasmonkey/src/lib.rs deleted file mode 100644 index fa3966bc7..000000000 --- a/lucet-builtins/wasmonkey/src/lib.rs +++ /dev/null @@ -1,27 +0,0 @@ -#[macro_use] -extern crate failure; - -#[cfg_attr(test, macro_use)] -extern crate lazy_static; - -#[macro_use] -extern crate serde_derive; - -#[cfg(test)] -extern crate siphasher; -#[macro_use] -extern crate xfailure; - -mod errors; -mod functions_ids; -mod functions_names; -mod map; -mod patcher; -mod sections; -mod symbols; - -#[cfg(test)] -mod tests; - -pub use crate::errors::*; -pub use crate::patcher::*; diff --git a/lucet-builtins/wasmonkey/src/map.rs b/lucet-builtins/wasmonkey/src/map.rs deleted file mode 100644 index ae50353ff..000000000 --- a/lucet-builtins/wasmonkey/src/map.rs +++ /dev/null @@ -1,63 +0,0 @@ -use crate::errors::*; -use serde_json; -use std::collections::HashMap; -use std::fs::File; -use std::io::prelude::*; -use std::path::Path; - -#[derive(Clone, Debug, Default, Serialize)] -pub struct PatchedBuiltinsMap { - pub env: HashMap, -} - -impl PatchedBuiltinsMap { - pub fn with_capacity(capacity: usize) -> Self { - PatchedBuiltinsMap { - env: HashMap::with_capacity(capacity), - } - } - - pub fn insert(&mut self, name: String, imported_name: String) -> Option { - self.env.insert(name, imported_name) - } - - pub fn write_to_file>( - &self, - builtins_map_path: P, - original_names: bool, - ) -> Result<(), WError> { - let mut map_with_original_names; - let map = if original_names { - self - } else { - map_with_original_names = PatchedBuiltinsMap::default(); - for imported_name in self.env.values() { - map_with_original_names - .env - .insert(imported_name.clone(), imported_name.clone()); - } - &map_with_original_names - }; - let json = serde_json::to_string_pretty(map).map_err(|_| WError::ParseError)?; - File::create(builtins_map_path)?.write_all(json.as_bytes())?; - Ok(()) - } - - pub fn builtins_map( - &self, - module: &str, - original_names: bool, - ) -> Result, WError> { - if module != "env" { - xbail!(WError::UsageError("Empty module")) - } - if original_names { - return Ok(self.env.clone()); - } - let mut env_map_with_original_names = HashMap::new(); - for imported_name in self.env.values() { - env_map_with_original_names.insert(imported_name.clone(), imported_name.clone()); - } - Ok(env_map_with_original_names) - } -} diff --git a/lucet-builtins/wasmonkey/src/patcher.rs b/lucet-builtins/wasmonkey/src/patcher.rs deleted file mode 100644 index 8e018060e..000000000 --- a/lucet-builtins/wasmonkey/src/patcher.rs +++ /dev/null @@ -1,225 +0,0 @@ -use crate::errors::*; -use crate::functions_ids::*; -use crate::functions_names::*; -use crate::map::*; -use crate::sections::*; -use crate::symbols::{self, ExtractedSymbols}; -use parity_wasm; -use parity_wasm::elements::{ - self, External, FunctionNameSubsection, ImportEntry, ImportSection, Internal, Module, - NameSection, Section, -}; -use std::collections::HashMap; -use std::path::{Path, PathBuf}; - -pub const BUILTIN_PREFIX: &str = "builtin_"; - -#[derive(Default, Clone, Debug)] -pub struct PatcherConfig { - pub builtins_path: Option, - pub builtins_map_path: Option, - pub builtins_map_original_names: bool, - pub builtins_additional: Vec, -} - -pub struct Patcher { - pub config: PatcherConfig, - patched_module: Module, - patched_builtins_map: PatchedBuiltinsMap, -} - -impl Patcher { - pub fn new(config: PatcherConfig, module: Module) -> Result { - let symbols = match &config.builtins_path { - None => ExtractedSymbols::from(vec![]), - Some(builtins_path) => symbols::extract_symbols(&builtins_path)?, - } - .merge_additional(&config.builtins_additional); - let builtins_names = symbols.builtins_names(); - let (patched_module, patched_builtins_map) = patch_module(module, &builtins_names)?; - let patcher = Patcher { - config, - patched_module, - patched_builtins_map, - }; - Ok(patcher) - } - - pub fn from_bytes(config: PatcherConfig, bytes: &[u8]) -> Result { - let module = parity_wasm::deserialize_buffer(bytes)?; - Self::new(config, module) - } - - pub fn from_file>(config: PatcherConfig, path_in: P) -> Result { - let module = parity_wasm::deserialize_file(path_in)?; - Self::new(config, module) - } - - pub fn into_bytes(self) -> Result, WError> { - let bytes = elements::serialize(self.patched_module)?; - Ok(bytes) - } - - pub fn store_to_file>(self, path_out: P) -> Result<(), WError> { - elements::serialize_to_file(path_out, self.patched_module)?; - if let Some(builtins_map_path) = self.config.builtins_map_path { - self.patched_builtins_map - .write_to_file(builtins_map_path, self.config.builtins_map_original_names)?; - } - Ok(()) - } - - pub fn patched_builtins_map(&self, module: &str) -> Result, WError> { - self.patched_builtins_map - .builtins_map(module, self.config.builtins_map_original_names) - } - - pub fn patched_module(self) -> Module { - self.patched_module - } -} - -#[derive(Debug)] -pub struct Builtin { - pub name: String, - pub original_function_id: Option, - pub function_type_id: Option, -} - -impl Builtin { - pub fn new(name: String) -> Self { - Builtin { - name, - original_function_id: None, - function_type_id: None, - } - } - - pub fn import_name(&self) -> String { - format!("{}{}", BUILTIN_PREFIX, self.name) - } -} - -fn function_type_id_for_function_id(module: &Module, function_id: u32) -> Option { - let offset = module - .import_section() - .map(|import_section| import_section.entries().len() as u32) - .unwrap_or(0); - if function_id < offset { - return None; - } - let functions_section_type_ids = module.function_section().unwrap().entries(); - Some(functions_section_type_ids[(function_id - offset) as usize].type_ref()) -} - -fn add_function_type_id_to_builtins( - module: &Module, - builtins: &mut Vec, -) -> Result<(), WError> { - for builtin in builtins.iter_mut() { - let function_type_id = - function_type_id_for_function_id(module, builtin.original_function_id.unwrap()) - .expect("Function ID not found"); - builtin.function_type_id = Some(function_type_id); - } - Ok(()) -} - -fn retain_only_used_builtins(module: &Module, builtins: &mut Vec) -> Result<(), WError> { - let export_section = module.export_section().expect("No export section"); - - for entry in export_section.entries() { - let internal = entry.internal(); - let function_id = match internal { - Internal::Function(function_id) => *function_id, - _ => continue, - }; - let field = entry.field(); - for builtin in builtins.iter_mut() { - if field == builtin.name { - assert!(builtin.original_function_id.is_none()); - builtin.original_function_id = Some(function_id); - break; - } - } - } - - builtins.retain(|builtin| builtin.original_function_id.is_some()); - Ok(()) -} - -fn add_import_section_if_missing(module: &mut Module) -> Result<(), WError> { - if module.import_section().is_some() { - return Ok(()); - } - let import_section = ImportSection::with_entries(vec![]); - let import_section_idx = find_type_section_idx(&module).unwrap() + 1; - module - .sections_mut() - .insert(import_section_idx, Section::Import(import_section)); - Ok(()) -} - -fn prepend_builtin_to_import_section(module: &mut Module, builtin: &Builtin) -> Result<(), WError> { - let import_name = builtin.import_name(); - let external = External::Function(builtin.function_type_id.unwrap()); - let import_entry = ImportEntry::new("env".to_string(), import_name, external); - module - .import_section_mut() - .unwrap() - .entries_mut() - .insert(0, import_entry); - Ok(()) -} - -fn prepend_builtin_to_names_section(module: &mut Module, builtin: &Builtin) -> Result<(), WError> { - let import_name = builtin.import_name(); - if module.names_section().is_none() { - let sections = module.sections_mut(); - let function_names_subsection = FunctionNameSubsection::default(); - let name_section = NameSection::new(None, Some(function_names_subsection), None); - sections.push(Section::Name(name_section)); - } - let names_section = module - .names_section_mut() - .expect("Names section not present"); - let function_names_subsection = match names_section.functions_mut() { - Some(function_names_subsection) => function_names_subsection, - _ => xbail!(WError::InternalError("Unexpected names section")), - }; - prepend_function_name(function_names_subsection, import_name)?; - Ok(()) -} - -fn patch_module( - module: Module, - builtins_names: &[&str], -) -> Result<(Module, PatchedBuiltinsMap), WError> { - let mut module = module - .parse_names() - .map_err(|_| WError::InternalError("Unable to parse names"))?; - - let mut builtins: Vec<_> = builtins_names - .iter() - .map(|x| Builtin::new(x.to_string())) - .collect(); - - retain_only_used_builtins(&module, &mut builtins)?; - add_function_type_id_to_builtins(&module, &mut builtins)?; - - add_import_section_if_missing(&mut module)?; - for (builtin_idx, builtin) in builtins.iter_mut().enumerate() { - prepend_builtin_to_import_section(&mut module, &builtin)?; - prepend_builtin_to_names_section(&mut module, &builtin)?; - shift_function_ids(&mut module, 1)?; - let original_function_id = builtin.original_function_id.unwrap() + builtin_idx as u32 + 1; - let new_function_id = 0; - replace_function_id(&mut module, original_function_id, new_function_id)?; - } - - let mut patched_builtins_map = PatchedBuiltinsMap::with_capacity(builtins.len()); - for builtin in builtins { - patched_builtins_map.insert(builtin.name.clone(), builtin.import_name()); - } - Ok((module, patched_builtins_map)) -} diff --git a/lucet-builtins/wasmonkey/src/sections.rs b/lucet-builtins/wasmonkey/src/sections.rs deleted file mode 100644 index 8d984463c..000000000 --- a/lucet-builtins/wasmonkey/src/sections.rs +++ /dev/null @@ -1,8 +0,0 @@ -use parity_wasm::elements::{Module, Section}; - -pub fn find_type_section_idx(module: &Module) -> Option { - module.sections().iter().position(|section| match section { - Section::Type(_) => true, - _ => false, - }) -} diff --git a/lucet-builtins/wasmonkey/src/symbols.rs b/lucet-builtins/wasmonkey/src/symbols.rs deleted file mode 100644 index 0ab7d4ce1..000000000 --- a/lucet-builtins/wasmonkey/src/symbols.rs +++ /dev/null @@ -1,133 +0,0 @@ -use crate::errors::*; -use crate::patcher::BUILTIN_PREFIX; -use goblin::elf::Elf; -use goblin::mach::{self, Mach, MachO}; -use goblin::Object; -use std::fs::File; -use std::io::Read; -use std::path::Path; - -#[derive(Clone, Debug, Default)] -pub struct ExtractedSymbol { - pub name: String, -} - -#[derive(Clone, Debug, Default)] -pub struct ExtractedSymbols { - pub symbols: Vec, -} - -impl From> for ExtractedSymbols { - fn from(symbols: Vec) -> Self { - ExtractedSymbols { symbols } - } -} - -impl ExtractedSymbols { - pub fn builtins_names(&self) -> Vec<&str> { - let builtins_names: Vec<&str> = self - .symbols - .iter() - .filter(|symbol| symbol.name.starts_with(BUILTIN_PREFIX)) - .map(|symbol| &symbol.name[BUILTIN_PREFIX.len()..]) - .collect(); - builtins_names - } - - pub fn merge_additional(mut self, additional_names: &[String]) -> Self { - let mut additional_symbols: Vec<_> = additional_names - .iter() - .map(|name| ExtractedSymbol { - name: name.to_string(), - }) - .collect(); - self.symbols.append(&mut additional_symbols); - self.symbols.dedup_by(|a, b| a.name == b.name); - self - } -} - -fn parse_elf(elf: &Elf<'_>) -> Result { - let mut symbols = vec![]; - - for symbol in elf - .dynsyms - .iter() - .filter(|symbol| symbol.st_info == 0x12 || symbol.st_info == 0x22) - { - let name = elf - .dynstrtab - .get(symbol.st_name) - .ok_or(WError::ParseError)? - .map_err(|_| WError::ParseError)? - .to_string(); - let extracted_symbol = ExtractedSymbol { name }; - symbols.push(extracted_symbol); - } - Ok(symbols.into()) -} - -fn parse_macho(macho: &MachO<'_>) -> Result { - let mut symbols = vec![]; - - // Start by finding the boundaries of the text section - let mut text_offset = None; - let mut text_size = None; - for section in macho.segments.sections() { - for segment in section { - if let Ok(( - mach::segment::Section { - sectname: [b'_', b'_', b't', b'e', b'x', b't', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - segname: [b'_', b'_', b'T', b'E', b'X', b'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - size, - offset, - .. - }, - _, - )) = segment - { - text_offset = Some(offset as usize); - text_size = Some(size as usize); - } - } - } - let text_offset = text_offset.ok_or(WError::ParseError)?; - let text_size = text_size.ok_or(WError::ParseError)?; - - // Extract the symbols we are interested in - for symbol in macho.symbols.as_ref().ok_or(WError::ParseError)?.iter() { - match symbol { - Ok(( - name, - mach::symbols::Nlist { - n_type: 0xf, - n_sect: 1, - n_value, - .. - }, - )) if name.len() > 1 && name.starts_with('_') => { - let extracted_symbol = ExtractedSymbol { - name: name[1..].to_string(), - }; - let offset = n_value as usize; - if offset < text_offset || offset >= text_offset + text_size { - continue; - } - symbols.push(extracted_symbol); - } - _ => {} - } - } - Ok(symbols.into()) -} - -pub fn extract_symbols>(path: P) -> Result { - let mut buffer = Vec::new(); - File::open(path)?.read_to_end(&mut buffer)?; - let symbols = match Object::parse(&buffer).map_err(|_| WError::ParseError)? { - Object::Mach(Mach::Binary(macho)) => parse_macho(&macho), - Object::Elf(elf) => parse_elf(&elf), - _ => xbail!(WError::Unsupported), - }?; - Ok(symbols) -} diff --git a/lucet-builtins/wasmonkey/src/tests/mod.rs b/lucet-builtins/wasmonkey/src/tests/mod.rs deleted file mode 100644 index 63ed2bae8..000000000 --- a/lucet-builtins/wasmonkey/src/tests/mod.rs +++ /dev/null @@ -1,46 +0,0 @@ -use super::*; -use siphasher::sip::SipHasher13; -use std::hash::Hasher; -use std::path::{Path, PathBuf}; - -lazy_static! { - static ref TESTS_DIR: PathBuf = Path::new(file!()).parent().unwrap().canonicalize().unwrap(); -} - -#[test] -fn patch_nothing() { - let path_in = TESTS_DIR.join("test_1.wasm"); - let config = PatcherConfig::default(); - let patcher = Patcher::from_file(config, path_in).unwrap(); - let mut hasher = SipHasher13::new(); - hasher.write(&patcher.into_bytes().unwrap()); - assert_eq!(hasher.finish(), 1401932366200566186); -} - -#[test] -fn patch_one() { - let path_in = TESTS_DIR.join("test_1.wasm"); - let mut config = PatcherConfig::default(); - config.builtins_additional = ["builtin_memmove", "builtin_nonexistent", "not_a_builtin"] - .into_iter() - .map(|s| s.to_string()) - .collect(); - let patcher = Patcher::from_file(config, path_in).unwrap(); - let mut hasher = SipHasher13::new(); - hasher.write(&patcher.into_bytes().unwrap()); - assert_eq!(hasher.finish(), 12884721342785729260); -} - -#[test] -fn patch_some() { - let path_in = TESTS_DIR.join("test_1.wasm"); - let mut config = PatcherConfig::default(); - config.builtins_additional = ["builtin_memmove", "builtin_memcpy", "builtin_strcmp"] - .into_iter() - .map(|s| s.to_string()) - .collect(); - let patcher = Patcher::from_file(config, path_in).unwrap(); - let mut hasher = SipHasher13::new(); - hasher.write(&patcher.into_bytes().unwrap()); - assert_eq!(hasher.finish(), 13205801729184435761); -} diff --git a/lucet-builtins/wasmonkey/src/tests/test_1.wasm b/lucet-builtins/wasmonkey/src/tests/test_1.wasm deleted file mode 100644 index 1bac61b0e..000000000 Binary files a/lucet-builtins/wasmonkey/src/tests/test_1.wasm and /dev/null differ diff --git a/lucetc/Cargo.toml b/lucetc/Cargo.toml index bb0e73db9..f152eccc5 100644 --- a/lucetc/Cargo.toml +++ b/lucetc/Cargo.toml @@ -33,12 +33,14 @@ faerie = "0.11.0" goblin = "0.0.24" failure = "0.1" byteorder = "1.2" -wasmonkey = { path = "../lucet-builtins/wasmonkey", version = "0.1.7" } +# precisely pin wasmonkey, because the shared dependency on parity-wasm is very sensitive +wasmonkey = "=0.1.9" wabt = "0.9.2" tempfile = "3.0" bimap = "0.2" human-size = "0.4" -parity-wasm = "0.40.3" +# must match wasmonkey's version specifier +parity-wasm = "0.41" minisign = "0.5.11" memoffset = "0.5.1" serde = "1.0"