2018-09-12 11:46:27 +02:00
|
|
|
//! Disassembly calling function for `wasm32` targets.
|
|
|
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
|
|
2019-07-08 14:30:51 +02:00
|
|
|
use crate::Function;
|
|
|
|
|
use std::collections::HashSet;
|
2018-09-12 11:46:27 +02:00
|
|
|
|
|
|
|
|
#[wasm_bindgen(module = "child_process")]
|
|
|
|
|
extern "C" {
|
2019-04-10 16:17:39 -07:00
|
|
|
#[wasm_bindgen(js_name = execFileSync)]
|
|
|
|
|
fn exec_file_sync(cmd: &str, args: &js_sys::Array, opts: &js_sys::Object) -> Buffer;
|
2018-09-12 11:46:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[wasm_bindgen(module = "buffer")]
|
|
|
|
|
extern "C" {
|
|
|
|
|
type Buffer;
|
|
|
|
|
#[wasm_bindgen(method, js_name = toString)]
|
|
|
|
|
fn to_string(this: &Buffer) -> String;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
|
extern "C" {
|
|
|
|
|
#[wasm_bindgen(js_namespace = require)]
|
|
|
|
|
fn resolve(module: &str) -> String;
|
|
|
|
|
#[wasm_bindgen(js_namespace = console, js_name = log)]
|
2018-12-13 20:17:30 -06:00
|
|
|
pub fn js_console_log(s: &str);
|
2018-09-12 11:46:27 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-08 14:30:51 +02:00
|
|
|
pub(crate) fn disassemble_myself() -> HashSet<Function> {
|
2018-09-12 11:46:27 +02:00
|
|
|
use std::path::Path;
|
2018-10-23 09:10:54 -07:00
|
|
|
::console_error_panic_hook::set_once();
|
2018-09-12 11:46:27 +02:00
|
|
|
// Our wasm module in the wasm-bindgen test harness is called
|
|
|
|
|
// "wasm-bindgen-test_bg". When running in node this is actually a shim JS
|
|
|
|
|
// file. Ask node where that JS file is, and then we use that with a wasm
|
|
|
|
|
// extension to find the wasm file itself.
|
2020-03-29 15:15:59 +01:00
|
|
|
let js_shim = resolve("wasm-bindgen-test");
|
|
|
|
|
let js_shim = Path::new(&js_shim).with_file_name("wasm-bindgen-test_bg.wasm");
|
2018-09-12 11:46:27 +02:00
|
|
|
|
|
|
|
|
// Execute `wasm2wat` synchronously, waiting for and capturing all of its
|
2019-04-10 16:17:39 -07:00
|
|
|
// output. Note that we pass in a custom `maxBuffer` parameter because we're
|
|
|
|
|
// generating a ton of output that needs to be buffered.
|
|
|
|
|
let args = js_sys::Array::new();
|
|
|
|
|
args.push(&js_shim.display().to_string().into());
|
|
|
|
|
args.push(&"--enable-simd".into());
|
|
|
|
|
let opts = js_sys::Object::new();
|
2019-09-16 17:42:00 +02:00
|
|
|
js_sys::Reflect::set(&opts, &"maxBuffer".into(), &(200 * 1024 * 1024).into()).unwrap();
|
2019-04-10 16:17:39 -07:00
|
|
|
let output = exec_file_sync("wasm2wat", &args, &opts).to_string();
|
2018-09-12 11:46:27 +02:00
|
|
|
|
2019-07-08 14:30:51 +02:00
|
|
|
let mut ret: HashSet<Function> = HashSet::new();
|
2018-09-12 11:46:27 +02:00
|
|
|
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 {
|
2019-07-08 14:30:51 +02:00
|
|
|
name: String::new(),
|
2018-09-12 11:46:27 +02:00
|
|
|
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() {
|
2019-07-08 14:30:51 +02:00
|
|
|
function.instrs.push(line.to_string());
|
2018-09-12 11:46:27 +02:00
|
|
|
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
|
2019-07-08 14:30:51 +02:00
|
|
|
function.name = line.split_whitespace().nth(1).unwrap().to_string();
|
|
|
|
|
if function.name.starts_with("$") {
|
|
|
|
|
function.name = function.name[1..].to_string()
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-08 23:21:37 +02:00
|
|
|
if !function.name.contains("stdarch_test_shim") {
|
2019-07-08 14:30:51 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert!(ret.insert(function));
|
2018-09-12 11:46:27 +02:00
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|