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