mirror of
https://github.com/pezkuwichain/wasm-instrument.git
synced 2026-06-09 20:11:06 +00:00
allocator replacement
This commit is contained in:
@@ -0,0 +1 @@
|
||||
target
|
||||
Generated
+23
@@ -0,0 +1,23 @@
|
||||
[root]
|
||||
name = "wasm-ext"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"parity-wasm 0.3.2 (git+https://github.com/nikvolf/parity-wasm)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "parity-wasm"
|
||||
version = "0.3.2"
|
||||
source = "git+https://github.com/nikvolf/parity-wasm#b11f34f2e5410d0773dcf32699d767d7359e4ca9"
|
||||
dependencies = [
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
|
||||
"checksum parity-wasm 0.3.2 (git+https://github.com/nikvolf/parity-wasm)" = "<none>"
|
||||
@@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "wasm-ext"
|
||||
version = "0.1.0"
|
||||
authors = ["NikVolf <nikvolf@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
parity-wasm = { git="https://github.com/nikvolf/parity-wasm" }
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
extern crate parity_wasm;
|
||||
|
||||
use std::env;
|
||||
use parity_wasm::{builder, elements};
|
||||
|
||||
type Insertion = (u32, u32, String);
|
||||
|
||||
pub fn update_call_index(opcodes: &mut elements::Opcodes, original_imports: usize, inserts: &[Insertion]) {
|
||||
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) | &mut Loop(_, ref mut block) => {
|
||||
update_call_index(block, original_imports, inserts)
|
||||
},
|
||||
&mut Call(ref mut call_index) => {
|
||||
if let Some(pos) = inserts.iter().position(|x| x.0 == *call_index) {
|
||||
*call_index = (original_imports + pos) as u32;
|
||||
} else if *call_index as usize > original_imports {
|
||||
*call_index += inserts.len() as u32;
|
||||
}
|
||||
},
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
let args = env::args().collect::<Vec<_>>();
|
||||
if args.len() != 3 {
|
||||
println!("Usage: {} input_file.wasm output_file.wasm", args[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Loading module
|
||||
let module = parity_wasm::deserialize_file(&args[1]).unwrap();
|
||||
|
||||
let replaced_funcs = vec!["_free", "_malloc"];
|
||||
|
||||
// Save import functions number for later
|
||||
let import_funcs_total = module
|
||||
.import_section().expect("Import section to exist")
|
||||
.entries()
|
||||
.iter()
|
||||
.filter(|e| if let &elements::External::Function(_) = e.external() { true } else { false })
|
||||
.count();
|
||||
|
||||
// First, we find functions indices that are to be rewired to externals
|
||||
// Triple is (function_index (callable), type_index, function_name)
|
||||
let replaces: Vec<Insertion> = replaced_funcs
|
||||
.into_iter()
|
||||
.filter_map(|f| {
|
||||
let export = module
|
||||
.export_section().expect("Export section to exist")
|
||||
.entries().iter()
|
||||
.find(|e| e.field() == f)
|
||||
.expect("All functions of interest to exist");
|
||||
|
||||
if let &elements::Internal::Function(func_idx) = export.internal() {
|
||||
let type_ref = module
|
||||
.functions_section().expect("Functions section to exist")
|
||||
.entries()[func_idx as usize - import_funcs_total]
|
||||
.type_ref();
|
||||
|
||||
Some((func_idx, type_ref, export.field().to_owned()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Second, we duplicate them as import definitions
|
||||
let mut mbuilder = builder::from_module(module);
|
||||
for &(_, type_ref, ref field) in replaces.iter() {
|
||||
mbuilder.push_import(
|
||||
builder::import()
|
||||
.module("env")
|
||||
.field(field)
|
||||
.external().func(type_ref)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
// Back to mutable access
|
||||
let mut module = mbuilder.build();
|
||||
|
||||
// Third, rewire all calls to imported functions and update all other calls indices
|
||||
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() {
|
||||
update_call_index(func_body.code_mut(), import_funcs_total, &replaces);
|
||||
}
|
||||
},
|
||||
&mut elements::Section::Export(ref mut export_section) => {
|
||||
for ref mut export in export_section.entries_mut() {
|
||||
match export.internal_mut() {
|
||||
&mut elements::Internal::Function(ref mut func_index) => {
|
||||
if *func_index >= import_funcs_total as u32 { *func_index += replaces.len() as u32; }
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
|
||||
// Forth step could be to eliminate now dead code in actual functions
|
||||
// but it is managed by `wasm-opt`
|
||||
|
||||
parity_wasm::serialize_to_file(&args[2], module).unwrap();
|
||||
}
|
||||
+1
-1
@@ -240,7 +240,7 @@ fn main() {
|
||||
// which in turn compile in unused imports and leaves unused functions
|
||||
|
||||
// List of exports that are actually used in the managed code
|
||||
let used_exports = vec!["_call", "_malloc", "_free"];
|
||||
let used_exports = vec!["_call"];
|
||||
|
||||
// Algo starts from the top, listing all items that should stay
|
||||
let mut stay = HashSet::new();
|
||||
|
||||
Reference in New Issue
Block a user