WIP: command line utility and start of Wasm-parsing frontend.
This commit is contained in:
parent
8a2e3e5eed
commit
1cca77ec37
|
@ -2,10 +2,14 @@
|
||||||
name = "waffle"
|
name = "waffle"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
description = "Wasm Analysis Framework For Lightweight Experiments"
|
description = "Wasm Analysis Framework For Lightweight Experiments"
|
||||||
author = ["Chris Fallin <chris@cfallin.org>"]
|
authors = ["Chris Fallin <chris@cfallin.org>"]
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmparser = "0.81"
|
wasmparser = "0.81"
|
||||||
wasm-encoder = "0.3"
|
wasm-encoder = "0.3"
|
||||||
|
anyhow = "1.0"
|
||||||
|
structopt = "0.3"
|
||||||
|
log = "0.4"
|
||||||
|
env_logger = "0.9"
|
47
src/bin/waffle-util.rs
Normal file
47
src/bin/waffle-util.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
//! WAFFLE command-line tool.
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use log::debug;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use structopt::StructOpt;
|
||||||
|
use waffle::frontend;
|
||||||
|
|
||||||
|
#[derive(Debug, StructOpt)]
|
||||||
|
#[structopt(name = "waffle-util", about = "WAFFLE utility.")]
|
||||||
|
struct Options {
|
||||||
|
#[structopt(short, long)]
|
||||||
|
debug: bool,
|
||||||
|
|
||||||
|
#[structopt(subcommand)]
|
||||||
|
command: Command,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, StructOpt)]
|
||||||
|
enum Command {
|
||||||
|
#[structopt(name = "print-ir", about = "Parse Wasm and print resulting IR")]
|
||||||
|
PrintIR {
|
||||||
|
#[structopt(help = "Wasm file to parse")]
|
||||||
|
wasm: PathBuf,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let opts = Options::from_args();
|
||||||
|
|
||||||
|
let mut logger = env_logger::Builder::from_default_env();
|
||||||
|
if opts.debug {
|
||||||
|
logger.filter_level(log::LevelFilter::Debug);
|
||||||
|
}
|
||||||
|
let _ = logger.try_init();
|
||||||
|
|
||||||
|
match opts.command {
|
||||||
|
Command::PrintIR { wasm } => {
|
||||||
|
let bytes = std::fs::read(wasm)?;
|
||||||
|
debug!("Loaded {} bytes of Wasm data", bytes.len());
|
||||||
|
let module = frontend::wasm_to_ir(&bytes[..])?;
|
||||||
|
println!("{:?}", module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
39
src/frontend.rs
Normal file
39
src/frontend.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
//! Frontend: convert Wasm to IR.
|
||||||
|
|
||||||
|
use crate::ir::*;
|
||||||
|
use anyhow::{bail, Result};
|
||||||
|
use log::debug;
|
||||||
|
use wasmparser::{Chunk, Parser, Payload, TypeDef};
|
||||||
|
|
||||||
|
pub fn wasm_to_ir(bytes: &[u8]) -> Result<Module> {
|
||||||
|
let mut module = Module::default();
|
||||||
|
let mut parser = Parser::new(0);
|
||||||
|
for chunk in parser.parse(bytes, /* eof = */ true) {
|
||||||
|
match chunk {
|
||||||
|
Chunk::NeedMoreData(_) => bail!("Unexpected EOF in Wasm"),
|
||||||
|
Chunk::Parsed { payload, .. } => handle_payload(&mut module, payload)?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(module)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_payload<'a>(module: &mut Module, payload: Payload<'a>) -> Result<()> {
|
||||||
|
debug!("Wasm parser item: {:?}", payload);
|
||||||
|
match payload {
|
||||||
|
Payload::TypeSection(mut reader) => {
|
||||||
|
for _ in 0..reader.get_count() {
|
||||||
|
let ty = reader.read()?;
|
||||||
|
match ty {
|
||||||
|
TypeDef::Func(fty) => {
|
||||||
|
module.signatures.push(fty);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
39
src/ir.rs
39
src/ir.rs
|
@ -1,13 +1,14 @@
|
||||||
//! Intermediate representation for Wasm.
|
//! Intermediate representation for Wasm.
|
||||||
|
|
||||||
use wasmparser::{FuncType, Type};
|
use wasmparser::{FuncType, Operator, Type};
|
||||||
|
|
||||||
pub type SignatureId = usize;
|
pub type SignatureId = usize;
|
||||||
pub type FuncId = usize;
|
pub type FuncId = usize;
|
||||||
pub type BlockId = usize;
|
pub type BlockId = usize;
|
||||||
pub type InstId = usize;
|
pub type InstId = usize;
|
||||||
|
pub type ValueId = usize;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct Module {
|
pub struct Module {
|
||||||
pub funcs: Vec<FuncDecl>,
|
pub funcs: Vec<FuncDecl>,
|
||||||
pub signatures: Vec<FuncType>,
|
pub signatures: Vec<FuncType>,
|
||||||
|
@ -19,8 +20,40 @@ pub enum FuncDecl {
|
||||||
Body(SignatureId, FunctionBody),
|
Body(SignatureId, FunctionBody),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct FunctionBody {
|
pub struct FunctionBody {
|
||||||
pub locals: Vec<Type>,
|
pub locals: Vec<Type>,
|
||||||
pub blocks: Vec<Block>,
|
pub blocks: Vec<Block>,
|
||||||
|
pub values: Vec<ValueDef>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ValueDef {
|
||||||
|
pub kind: ValueKind,
|
||||||
|
pub ty: Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum ValueKind {
|
||||||
|
BlockParam(Block),
|
||||||
|
Inst(Block, Inst),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
pub struct Block {
|
||||||
|
pub params: Vec<Type>,
|
||||||
|
pub insts: Vec<Inst>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Inst {
|
||||||
|
pub operator: Operator<'static>,
|
||||||
|
pub outputs: Vec<ValueId>,
|
||||||
|
pub inputs: Vec<Operand>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Operand {
|
||||||
|
Value(ValueId),
|
||||||
|
Sub(Box<Inst>),
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
// Re-export wasmparser and wasmencoder for easier use of the right
|
// Re-export wasmparser and wasmencoder for easier use of the right
|
||||||
// version by our embedders.
|
// version by our embedders.
|
||||||
pub use wasmparser;
|
|
||||||
pub use wasm_encoder;
|
pub use wasm_encoder;
|
||||||
|
pub use wasmparser;
|
||||||
|
|
||||||
|
pub mod frontend;
|
||||||
pub mod ir;
|
pub mod ir;
|
||||||
|
|
Loading…
Reference in a new issue