wasmparser/readers/core/
dylink0.rs

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