//! Disassembly calling function for `wasm32` targets. use crate::Function; use std::collections::HashSet; pub(crate) fn disassemble_myself() -> HashSet { // Use `std::env::args` to find the path to our executable. Assume the // environment is configured such that we can read that file. Read it and // use the `wasmprinter` crate to transform the binary to text, then search // the text for appropriately named functions. let me = std::env::args() .next() .expect("failed to find current wasm file"); let output = wasmprinter::print_file(&me).unwrap(); let mut ret: HashSet = HashSet::new(); let mut lines = output.lines().map(|s| s.trim()); while let Some(line) = lines.next() { // If this isn't a function, we don't care about it. if !line.starts_with("(func ") { continue; } let mut function = Function { name: String::new(), instrs: Vec::new(), }; // Empty functions will end in `))` so there's nothing to do, otherwise // we'll have a bunch of following lines which are instructions. // // Lines that have an imbalanced `)` mark the end of a function. if !line.ends_with("))") { while let Some(line) = lines.next() { function.instrs.push(line.to_string()); if !line.starts_with("(") && line.ends_with(")") { break; } } } // The second element here split on whitespace should be the name of // the function, skipping the type/params/results function.name = line.split_whitespace().nth(1).unwrap().to_string(); if function.name.starts_with("$") { function.name = function.name[1..].to_string() } if !function.name.contains("stdarch_test_shim") { continue; } assert!(ret.insert(function)); } return ret; }