xref: /wasmtime-44.0.1/crates/wizer/src/parse.rs (revision bedbcd85)
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