Make debuginfo parsing optional.

This commit is contained in:
Chris Fallin 2023-02-16 16:20:54 -08:00
parent d7c5dc934b
commit 0e2e5bf098
7 changed files with 59 additions and 34 deletions

View file

@ -2,7 +2,7 @@
use libfuzzer_sys::{arbitrary, fuzz_target};
use std::sync::atomic::{AtomicU64, Ordering};
use waffle::Module;
use waffle::{FrontendOptions, Module};
fn reject(bytes: &[u8]) -> bool {
let parser = wasmparser::Parser::new(0);
@ -134,8 +134,9 @@ fuzz_target!(|module: wasm_smith::ConfiguredModule<Config>| {
}
};
let mut parsed_module = Module::from_wasm_bytes(&orig_bytes[..]).unwrap();
parsed_module.optimize();
let mut parsed_module =
Module::from_wasm_bytes(&orig_bytes[..], &FrontendOptions::default()).unwrap();
parsed_module.per_func_body(|body| body.optimize());
let roundtrip_bytes = parsed_module.to_wasm_bytes().unwrap();
if let Ok(filename) = std::env::var("FUZZ_DUMP_WASM") {

View file

@ -1,9 +1,10 @@
#![no_main]
use libfuzzer_sys::fuzz_target;
use waffle::Module;
use waffle::{FrontendOptions, Module};
fuzz_target!(|module: wasm_smith::Module| {
let _ = env_logger::try_init();
let _parsed_module = Module::from_wasm_bytes(&module.to_bytes()[..]).unwrap();
let _parsed_module =
Module::from_wasm_bytes(&module.to_bytes()[..], &FrontendOptions::default()).unwrap();
});

View file

@ -1,30 +1,31 @@
#![no_main]
use libfuzzer_sys::fuzz_target;
use waffle::{FrontendError, Module};
use waffle::{FrontendError, FrontendOptions, Module};
fuzz_target!(|module: wasm_smith::Module| {
let _ = env_logger::try_init();
log::debug!("original module: {:?}", module);
let orig_bytes = module.to_bytes();
let mut parsed_module = match Module::from_wasm_bytes(&orig_bytes[..]) {
Ok(m) => m,
Err(e) => {
match e.downcast::<FrontendError>() {
Ok(FrontendError::UnsupportedFeature(_)) | Ok(FrontendError::TooLarge(_)) => {
// Just skip this case.
return;
}
Ok(e) => {
panic!("Frontend error: {:?}", e);
}
Err(e) => {
panic!("Other error when parsing module: {:?}", e);
let mut parsed_module =
match Module::from_wasm_bytes(&orig_bytes[..], &FrontendOptions::default()) {
Ok(m) => m,
Err(e) => {
match e.downcast::<FrontendError>() {
Ok(FrontendError::UnsupportedFeature(_)) | Ok(FrontendError::TooLarge(_)) => {
// Just skip this case.
return;
}
Ok(e) => {
panic!("Frontend error: {:?}", e);
}
Err(e) => {
panic!("Other error when parsing module: {:?}", e);
}
}
}
}
};
};
parsed_module.expand_all_funcs().unwrap();
parsed_module.optimize();
parsed_module.per_func_body(|body| body.optimize());
let _ = parsed_module.to_wasm_bytes();
});

View file

@ -1,17 +1,19 @@
#![no_main]
use libfuzzer_sys::fuzz_target;
use waffle::Module;
use waffle::{FrontendOptions, Module};
fuzz_target!(|module: wasm_smith::Module| {
let _ = env_logger::try_init();
log::debug!("original module: {:?}", module);
let orig_bytes = module.to_bytes();
let parsed_module = Module::from_wasm_bytes(&orig_bytes[..]).unwrap();
let roundtrip_bytes = parsed_module.to_wasm_bytes();
let parsed_module =
Module::from_wasm_bytes(&orig_bytes[..], &FrontendOptions::default()).unwrap();
let roundtrip_bytes = parsed_module.to_wasm_bytes().unwrap();
if let Ok(filename) = std::env::var("ROUNDTRIP_WASM_SAVE") {
std::fs::write(filename, &roundtrip_bytes[..]).unwrap();
}
let parsed_roundtrip_module = Module::from_wasm_bytes(&roundtrip_bytes[..]).unwrap();
let parsed_roundtrip_module =
Module::from_wasm_bytes(&roundtrip_bytes[..], &FrontendOptions::default()).unwrap();
let _ = parsed_roundtrip_module.to_wasm_bytes();
});

View file

@ -4,7 +4,7 @@ use anyhow::Result;
use log::debug;
use std::path::PathBuf;
use structopt::StructOpt;
use waffle::Module;
use waffle::{FrontendOptions, Module};
#[derive(Debug, StructOpt)]
#[structopt(name = "waffle-util", about = "WAFFLE utility.")]
@ -18,6 +18,13 @@ struct Options {
)]
basic_opts: bool,
#[structopt(
help = "Enable parsing of debug-info from input",
short = "g",
long = "debug-info"
)]
debug_info: bool,
#[structopt(help = "Transform to maximal SSA", long = "max-ssa")]
max_ssa: bool,
@ -61,18 +68,21 @@ fn main() -> Result<()> {
}
let _ = logger.try_init();
let mut options = FrontendOptions::default();
options.debug = opts.debug_info;
match &opts.command {
Command::PrintIR { wasm } => {
let bytes = std::fs::read(wasm)?;
debug!("Loaded {} bytes of Wasm data", bytes.len());
let mut module = Module::from_wasm_bytes(&bytes[..])?;
let mut module = Module::from_wasm_bytes(&bytes[..], &options)?;
apply_options(&opts, &mut module)?;
println!("{}", module.display());
}
Command::RoundTrip { input, output } => {
let bytes = std::fs::read(input)?;
debug!("Loaded {} bytes of Wasm data", bytes.len());
let mut module = Module::from_wasm_bytes(&bytes[..])?;
let mut module = Module::from_wasm_bytes(&bytes[..], &options)?;
apply_options(&opts, &mut module)?;
let produced = module.to_wasm_bytes()?;
std::fs::write(output, &produced[..])?;

View file

@ -16,7 +16,12 @@ use wasmparser::{
BlockType, DataKind, ExternalKind, Name, NameSectionReader, Parser, Payload, TypeRef,
};
pub fn wasm_to_ir(bytes: &[u8]) -> Result<Module<'_>> {
#[derive(Clone, Copy, Debug, Default)]
pub struct FrontendOptions {
pub debug: bool,
}
pub fn wasm_to_ir<'a>(bytes: &'a [u8], options: &FrontendOptions) -> Result<Module<'a>> {
let mut module = Module::with_orig_bytes(bytes);
let parser = Parser::new(0);
let mut next_func = 0;
@ -36,8 +41,11 @@ pub fn wasm_to_ir(bytes: &[u8]) -> Result<Module<'_>> {
gimli::LocationLists::new(extra_sections.debug_loc, extra_sections.debug_loclists);
dwarf.ranges =
gimli::RangeLists::new(extra_sections.debug_ranges, extra_sections.debug_rnglists);
let debug_map = DebugMap::from_dwarf(dwarf, &mut module.debug, extra_sections.code_offset)?;
module.debug_map = debug_map;
if options.debug {
let debug_map = DebugMap::from_dwarf(dwarf, &mut module.debug, extra_sections.code_offset)?;
module.debug_map = debug_map;
}
Ok(module)
}

View file

@ -4,6 +4,8 @@ use crate::ir::{Debug, DebugMap, FunctionBody};
use crate::{backend, frontend};
use anyhow::Result;
pub use crate::frontend::FrontendOptions;
#[derive(Clone, Debug)]
pub struct Module<'a> {
pub orig_bytes: &'a [u8],
@ -159,8 +161,8 @@ impl<'a> Module<'a> {
})
}
pub fn from_wasm_bytes(bytes: &'a [u8]) -> Result<Self> {
frontend::wasm_to_ir(bytes)
pub fn from_wasm_bytes(bytes: &'a [u8], options: &FrontendOptions) -> Result<Self> {
frontend::wasm_to_ir(bytes, options)
}
pub fn to_wasm_bytes(&self) -> Result<Vec<u8>> {