tinywasm_wasmparser/readers/core/
dylink0.rs

1use alloc::vec::Vec;
2
3use crate::std::ops::Range;
4use crate::{BinaryReader, Result, Subsection, Subsections, SymbolFlags};
5
6/// Parser for the dynamic linking `dylink.0` custom section.
7///
8/// This format is currently defined upstream at
9/// <https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md>.
10pub type Dylink0SectionReader<'a> = Subsections<'a, Dylink0Subsection<'a>>;
11
12const WASM_DYLINK_MEM_INFO: u8 = 1;
13const WASM_DYLINK_NEEDED: u8 = 2;
14const WASM_DYLINK_EXPORT_INFO: u8 = 3;
15const WASM_DYLINK_IMPORT_INFO: u8 = 4;
16
17/// Represents a `WASM_DYLINK_MEM_INFO` field
18#[derive(Debug, Copy, Clone)]
19pub struct MemInfo {
20    /// Size of the memory area the loader should reserve for the module, which
21    /// will begin at `env.__memory_base`.
22    pub memory_size: u32,
23
24    /// The required alignment of the memory area, in bytes, encoded as a power
25    /// of 2.
26    pub memory_alignment: u32,
27
28    /// Size of the table area the loader should reserve for the module, which
29    /// will begin at `env.__table_base`.
30    pub table_size: u32,
31
32    /// The required alignment of the table area, in elements, encoded as a
33    /// power of 2.
34    pub table_alignment: u32,
35}
36
37#[allow(missing_docs)]
38#[derive(Debug)]
39pub struct ExportInfo<'a> {
40    pub name: &'a str,
41    pub flags: SymbolFlags,
42}
43
44#[allow(missing_docs)]
45#[derive(Debug)]
46pub struct ImportInfo<'a> {
47    pub module: &'a str,
48    pub field: &'a str,
49    pub flags: SymbolFlags,
50}
51
52/// Possible subsections of the `dylink.0` custom section.
53#[derive(Debug)]
54#[allow(missing_docs)]
55pub enum Dylink0Subsection<'a> {
56    MemInfo(MemInfo),
57    Needed(Vec<&'a str>),
58    ExportInfo(Vec<ExportInfo<'a>>),
59    ImportInfo(Vec<ImportInfo<'a>>),
60    Unknown {
61        ty: u8,
62        data: &'a [u8],
63        range: Range<usize>,
64    },
65}
66
67impl<'a> Subsection<'a> for Dylink0Subsection<'a> {
68    fn from_reader(id: u8, mut reader: BinaryReader<'a>) -> Result<Self> {
69        let data = reader.remaining_buffer();
70        let offset = reader.original_position();
71        Ok(match id {
72            WASM_DYLINK_MEM_INFO => Self::MemInfo(MemInfo {
73                memory_size: reader.read_var_u32()?,
74                memory_alignment: reader.read_var_u32()?,
75                table_size: reader.read_var_u32()?,
76                table_alignment: reader.read_var_u32()?,
77            }),
78            WASM_DYLINK_NEEDED => Self::Needed(
79                (0..reader.read_var_u32()?)
80                    .map(|_| reader.read_string())
81                    .collect::<Result<_, _>>()?,
82            ),
83            WASM_DYLINK_EXPORT_INFO => Self::ExportInfo(
84                (0..reader.read_var_u32()?)
85                    .map(|_| {
86                        Ok(ExportInfo {
87                            name: reader.read_string()?,
88                            flags: reader.read()?,
89                        })
90                    })
91                    .collect::<Result<_, _>>()?,
92            ),
93            WASM_DYLINK_IMPORT_INFO => Self::ImportInfo(
94                (0..reader.read_var_u32()?)
95                    .map(|_| {
96                        Ok(ImportInfo {
97                            module: reader.read_string()?,
98                            field: reader.read_string()?,
99                            flags: reader.read()?,
100                        })
101                    })
102                    .collect::<Result<_, _>>()?,
103            ),
104            ty => Self::Unknown {
105                ty,
106                data,
107                range: offset..offset + data.len(),
108            },
109        })
110    }
111}