1 use crate::info::ModuleContext; 2 use anyhow::Context; 3 use wasmparser::Parser; 4 5 /// Parse the given Wasm bytes into a `ModuleInfo` tree. 6 pub(crate) fn parse<'a>(full_wasm: &'a [u8]) -> anyhow::Result<ModuleContext<'a>> { 7 log::debug!("Parsing the input Wasm"); 8 9 let mut module = ModuleContext::default(); 10 11 for payload in Parser::new(0).parse_all(full_wasm) { 12 use wasmparser::Payload::*; 13 14 let payload = payload.context("failed to parse Wasm")?; 15 16 if let Some((id, range)) = payload.as_section() { 17 module.add_raw_section(id, range, full_wasm); 18 } 19 20 match payload { 21 ImportSection(imports) => import_section(&mut module, imports)?, 22 FunctionSection(funcs) => function_section(&mut module, funcs)?, 23 TableSection(tables) => table_section(&mut module, tables)?, 24 MemorySection(mems) => memory_section(&mut module, mems)?, 25 GlobalSection(globals) => global_section(&mut module, globals)?, 26 ExportSection(exports) => export_section(&mut module, exports)?, 27 _ => {} 28 } 29 } 30 31 Ok(module) 32 } 33 34 fn import_section<'a>( 35 module: &mut ModuleContext<'a>, 36 imports: wasmparser::ImportSectionReader<'a>, 37 ) -> anyhow::Result<()> { 38 // Check that we can properly handle all imports. 39 for imp in imports { 40 let imp = imp?; 41 42 if imp.module.starts_with("__wizer_") || imp.name.starts_with("__wizer_") { 43 anyhow::bail!( 44 "input Wasm module already imports entities named with the `__wizer_*` prefix" 45 ); 46 } 47 48 module.push_import(imp); 49 } 50 Ok(()) 51 } 52 53 fn function_section<'a>( 54 module: &mut ModuleContext<'a>, 55 funcs: wasmparser::FunctionSectionReader<'a>, 56 ) -> anyhow::Result<()> { 57 for ty_idx in funcs { 58 module.push_function(ty_idx?); 59 } 60 Ok(()) 61 } 62 63 fn table_section<'a>( 64 module: &mut ModuleContext<'a>, 65 tables: wasmparser::TableSectionReader<'a>, 66 ) -> anyhow::Result<()> { 67 for table in tables { 68 module.push_table(table?.ty); 69 } 70 Ok(()) 71 } 72 73 fn memory_section<'a>( 74 module: &mut ModuleContext<'a>, 75 mems: wasmparser::MemorySectionReader<'a>, 76 ) -> anyhow::Result<()> { 77 for m in mems { 78 module.push_defined_memory(m?); 79 } 80 Ok(()) 81 } 82 83 fn global_section<'a>( 84 module: &mut ModuleContext<'a>, 85 globals: wasmparser::GlobalSectionReader<'a>, 86 ) -> anyhow::Result<()> { 87 for g in globals { 88 module.push_defined_global(g?.ty); 89 } 90 Ok(()) 91 } 92 93 fn export_section<'a>( 94 module: &mut ModuleContext<'a>, 95 exports: wasmparser::ExportSectionReader<'a>, 96 ) -> anyhow::Result<()> { 97 for export in exports { 98 let export = export?; 99 100 if export.name.starts_with("__wizer_") { 101 anyhow::bail!( 102 "input Wasm module already exports entities named with the `__wizer_*` prefix" 103 ); 104 } 105 106 match export.kind { 107 wasmparser::ExternalKind::Tag 108 | wasmparser::ExternalKind::Func 109 | wasmparser::ExternalKind::Table 110 | wasmparser::ExternalKind::Memory 111 | wasmparser::ExternalKind::Global => { 112 module.push_export(export); 113 } 114 } 115 } 116 Ok(()) 117 } 118