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