1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
// This examples allow to query all function exports of the
// provided wasm module
extern crate parity_wasm;
use std::env::args;
use parity_wasm::elements::{Internal, External, Type, FunctionType, Module};
// Auxillary function to resolve function type (signature) given it's callable index
fn type_by_index(module: &Module, index: usize) -> FunctionType {
// Demand that function and type section exist. Otherwise, fail with a
// corresponding error.
let function_section = module.function_section().expect("No function section found");
let type_section = module.type_section().expect("No type section found");
// This counts the number of _function_ imports listed by the module, excluding
// the globals, since indexing for actual functions for `call` and `export` purposes
// includes both imported and own functions. So we actualy need the imported function count
// to resolve actual index of the given function in own functions list.
let import_section_len: usize = match module.import_section() {
Some(import) =>
import.entries().iter().filter(|entry| match entry.external() {
&External::Function(_) => true,
_ => false,
}).count(),
None => 0,
};
// Substract the value queried in the previous step from the provided index
// to get own function index from which we can query type next.
let function_index_in_section = index - import_section_len;
// Query the own function given we have it's index
let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize;
// Finally, return function type (signature)
match type_section.types()[func_type_ref] {
Type::Function(ref func_type) => func_type.clone(),
}
}
fn main() {
// Example executable takes one argument which must
// refernce the existing file with a valid wasm module
let args: Vec<_> = args().collect();
if args.len() < 2 {
println!("Prints export function names with and their types");
println!("Usage: {} <wasm file>", args[0]);
return;
}
// Here we load module using dedicated for this purpose
// `deserialize_file` function (which works only with modules)
let module = parity_wasm::deserialize_file(&args[1]).expect("File to be deserialized");
// Query the export section from the loaded module. Note that not every
// wasm module obliged to contain export section. So in case there is no
// any export section, we panic with the corresponding error.
let export_section = module.export_section().expect("No export section found");
// Process all exports, leaving only those which reference the internal function
// of the wasm module
let exports: Vec<String> = export_section.entries().iter()
.filter_map(|entry|
// This is match on export variant, which can be function, global,table or memory
// We are interested only in functions for an example
match *entry.internal() {
// Return function export name (return by field() function and it's index)
Internal::Function(index) => Some((entry.field(), index as usize)),
_ => None
})
// Another map to resolve function signature index given it's internal index and return
// the printable string of the export
.map(|(field, index)| format!("{:}: {:?}", field, type_by_index(&module, index).params())).collect();
// Print the result
for export in exports {
println!("{:}", export);
}
}
|