diff --git a/examples/inject.rs b/examples/inject.rs new file mode 100644 index 0000000..c03d8d4 --- /dev/null +++ b/examples/inject.rs @@ -0,0 +1,42 @@ +extern crate parity_wasm; + +use std::env; + +use parity_wasm::elements; + +pub fn inject_nop(opcodes: &mut elements::Opcodes) { + use parity_wasm::elements::Opcode::*; + for opcode in opcodes.elements_mut().iter_mut() { + match opcode { + &mut Block(_, ref mut block) | &mut If(_, ref mut block) => { + inject_nop(block) + }, + _ => { } + } + } + + opcodes.elements_mut().insert(0, Nop); +} + +fn main() { + let args = env::args().collect::>(); + if args.len() != 3 { + println!("Usage: {} input_file.wasm output_file.wasm", args[0]); + return; + } + + let mut module = parity_wasm::deserialize_file(&args[1]).unwrap(); + + for section in module.sections_mut() { + match section { + &mut elements::Section::Code(ref mut code_section) => { + for ref mut func_body in code_section.bodies_mut() { + inject_nop(func_body.code_mut()); + } + }, + _ => { } + } + } + + parity_wasm::serialize_to_file(&args[2], module).unwrap(); +} \ No newline at end of file diff --git a/src/builder/code.rs b/src/builder/code.rs index 760c63a..d919f97 100644 --- a/src/builder/code.rs +++ b/src/builder/code.rs @@ -179,34 +179,37 @@ impl SignaturesBuilder where F: Invoke { pub struct FuncBodyBuilder { callback: F, - locals: Vec, - opcodes: elements::Opcodes, + body: elements::FuncBody, } impl FuncBodyBuilder { pub fn with_callback(callback: F) -> Self { FuncBodyBuilder { callback: callback, - locals: Vec::new(), - opcodes: elements::Opcodes::empty(), + body: elements::FuncBody::new(Vec::new(), elements::Opcodes::empty()), } } } impl FuncBodyBuilder where F: Invoke { + pub fn with_func(mut self, func: elements::FuncBody) -> Self { + self.body = func; + self + } + pub fn with_locals(mut self, locals: Vec) -> Self { - self.locals.extend(locals); + self.body.locals_mut().extend(locals); self } pub fn with_opcodes(mut self, opcodes: elements::Opcodes) -> Self { - self.opcodes = opcodes; + *self.body.code_mut() = opcodes; self } pub fn build(self) -> F::Result { - self.callback.invoke(elements::FuncBody::new(self.locals, self.opcodes)) + self.callback.invoke(self.body) } } diff --git a/src/builder/mod.rs b/src/builder/mod.rs index 034114d..6a2436e 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -6,6 +6,6 @@ mod code; mod misc; mod import; -pub use self::module::{module, ModuleBuilder}; +pub use self::module::{module, from_module, ModuleBuilder}; pub use self::code::{signatures, function}; pub use self::import::import; \ No newline at end of file diff --git a/src/builder/module.rs b/src/builder/module.rs index 4f192bc..0eacbd7 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -1,5 +1,6 @@ use super::invoke::{Invoke, Identity}; use super::code::{self, SignaturesBuilder}; +use super::import; use elements; /// Module builder @@ -90,6 +91,12 @@ impl ModuleBuilder where F: Invoke { } } + /// Builder from raw module + pub fn with_module(mut self, module: elements::Module) -> Self { + self.module = module.into(); + self + } + /// Fill module with sections from iterator pub fn with_sections(mut self, sections: I) -> Self where I: IntoIterator @@ -170,6 +177,17 @@ impl ModuleBuilder where F: Invoke { SignaturesBuilder::with_callback(self) } + /// With inserted import entry + pub fn with_import(mut self, entry: elements::ImportEntry) -> Self { + self.module.import.entries_mut().push(entry); + self + } + + /// Import entry builder + pub fn import(self) -> import::ImportBuilder { + import::ImportBuilder::with_callback(self) + } + /// Build module (final step) pub fn build(self) -> F::Result { self.callback.invoke(self.module.into()) @@ -196,11 +214,26 @@ impl Invoke for ModuleBuilder } } +impl Invoke for ModuleBuilder + where F: Invoke +{ + type Result = Self; + + fn invoke(self, entry: elements::ImportEntry) -> Self::Result { + self.with_import(entry) + } +} + /// Start new module builder pub fn module() -> ModuleBuilder { ModuleBuilder::new() } +/// Start builder to extend existing module +pub fn from_module(module: elements::Module) -> ModuleBuilder { + ModuleBuilder::new().with_module(module) +} + #[cfg(test)] mod tests { diff --git a/src/elements/func.rs b/src/elements/func.rs index f022e72..fcef2ad 100644 --- a/src/elements/func.rs +++ b/src/elements/func.rs @@ -79,6 +79,12 @@ impl FuncBody { /// Opcode sequence of the function body. Minimal opcode sequence /// is just `&[Opcode::End]` pub fn code(&self) -> &Opcodes { &self.opcodes } + + /// Locals declared in function body (mutable). + pub fn locals_mut(&mut self) -> &mut Vec { &mut self.locals } + + /// Opcode sequence of the function body (mutable). + pub fn code_mut(&mut self) -> &mut Opcodes { &mut self.opcodes } } impl Deserialize for FuncBody { diff --git a/src/elements/ops.rs b/src/elements/ops.rs index 68710d1..a96c603 100644 --- a/src/elements/ops.rs +++ b/src/elements/ops.rs @@ -10,18 +10,21 @@ use super::{ pub struct Opcodes(Vec); impl Opcodes { - /// New list of opcodes from vector of opcodes + /// New list of opcodes from vector of opcodes. pub fn new(elements: Vec) -> Self { Opcodes(elements) } - /// Empty expression with only `Opcode::End` opcode + /// Empty expression with only `Opcode::End` opcode. pub fn empty() -> Self { Opcodes(vec![Opcode::End]) } - /// List of individual opcodes + /// List of individual opcodes. pub fn elements(&self) -> &[Opcode] { &self.0 } + + /// Individual opcodes, mutable. + pub fn elements_mut(&mut self) -> &mut Vec { &mut self.0 } } impl Deserialize for Opcodes { diff --git a/src/elements/section.rs b/src/elements/section.rs index 947eadc..e9e4614 100644 --- a/src/elements/section.rs +++ b/src/elements/section.rs @@ -228,6 +228,11 @@ impl ImportSection { pub fn entries(&self) -> &[ImportEntry] { &self.0 } + + /// List of import entries (mutable). + pub fn entries_mut(&mut self) -> &mut Vec { + &mut self.0 + } } impl Deserialize for ImportSection { @@ -903,9 +908,9 @@ mod tests { 9, // function #1 total code size 1, // 1 local variable declaration 1, // amount of variables - 0xff, // type of variable (-0x01), negative + 0x7f, // type of variable (7-bit, -0x01), negative 0x02, // block - 0xff, // block return type (-0x01), negative + 0x7f, // block return type (7-bit, -0x01), negative 0x23, 0x00, // get_global(0) 0x0b, // block end 0x0b, // function end