Entry point:
let module = parity_wasm::deserialize_file("./res/cases/v1/hello.wasm").unwrap();
assert!(module.code_section().is_some());
In src/elements/mod.rs, it invokes deserialize
in src/elements/module.rs. It then delegates the call to different sections in the binary under src/elements/section.rs. Module also naively checks for the number of code and function sections here.
Depending on the reader id from VarUint7::dserialize(reader)
in Section::deserialize
, different deserialize
calls are made as seen here.
0 - CustomSection::deserialize 1 - TypeSection::deserialize 2 - ImportSection::deserialize 3 - FunctionSection::deserialize 4 - TableSection::deserialize 5 - MemorySection::deserialize 6 - GlobalSection::deserialize 7 - ExportSection::deserialize 8 - Section::Start 9 - ElementSection::deserialize 10 - CodeSection::deserialize 11 - DataSection::deserialize
All of the deserialize functions above take in read_entries(reader: &mut R)
as an argument. read_entries
is defined here which uses CountedList::deserialize
which are lists for reading sequence of elements typed T as defined here.
As an example, in deserialize
above we have,
Section::Function(FunctionSection::deserialize(reader)?)
FunctionSection::deserialize
returns
Ok(FunctionSection(read_entries(reader)?))
and read_entries
returns a Result<Vec<T>>
.
We need to check on function section for function signature in WASM binary.
Function and Code sections
A single logical function definition is defined in two sections:
the function section declares the signatures of each internal function definition in the module;
the code section contains the function body of each function declared by the function section.
This split aids in streaming compilation by putting the function bodies, which constitute most of the byte size
of the module, near the end so that all metadata necessary for recursive module loading and parallel
compilation is available before compilation begins.
Reference: https://webassembly.org/docs/modules/