wasmer_wasix/state/linker/
dylink.rs

1use std::collections::HashMap;
2
3use tracing::warn;
4use wasmer::Module;
5
6use super::LinkError;
7
8#[derive(Debug, Clone)]
9pub struct DylinkInfo {
10    pub mem_info: wasmparser::MemInfo,
11    pub needed: Vec<String>,
12    pub import_metadata: HashMap<(String, String), wasmparser::SymbolFlags>,
13    pub export_metadata: HashMap<String, wasmparser::SymbolFlags>,
14    pub runtime_path: Vec<String>,
15}
16
17pub fn is_dynamically_linked(module: &Module) -> bool {
18    module.custom_sections("dylink.0").next().is_some()
19}
20
21pub fn parse_dylink0_section(module: &Module) -> Result<DylinkInfo, LinkError> {
22    let mut sections = module.custom_sections("dylink.0");
23
24    let Some(section) = sections.next() else {
25        return Err(LinkError::NotDynamicLibrary);
26    };
27
28    // Verify the module contains exactly one dylink.0 section
29    let None = sections.next() else {
30        return Err(LinkError::NotDynamicLibrary);
31    };
32
33    let reader = wasmparser::Dylink0SectionReader::new(wasmparser::BinaryReader::new(&section, 0));
34
35    let mut mem_info = None;
36    let mut needed = None;
37    let mut import_metadata = HashMap::new();
38    let mut export_metadata = HashMap::new();
39    let mut runtime_path = Vec::new();
40
41    for subsection in reader {
42        let subsection = subsection?;
43        match subsection {
44            wasmparser::Dylink0Subsection::MemInfo(m) => {
45                mem_info = Some(m);
46            }
47            wasmparser::Dylink0Subsection::Needed(n) => {
48                needed = Some(n.iter().map(|s| s.to_string()).collect::<Vec<_>>());
49            }
50            wasmparser::Dylink0Subsection::ImportInfo(i) => {
51                for i in i {
52                    import_metadata.insert((i.module.to_owned(), i.field.to_owned()), i.flags);
53                }
54            }
55            wasmparser::Dylink0Subsection::ExportInfo(e) => {
56                for e in e {
57                    export_metadata.insert(e.name.to_owned(), e.flags);
58                }
59            }
60            wasmparser::Dylink0Subsection::Unknown { ty, .. } => {
61                warn!("Skipping unknown dylink.0 subsection {ty}");
62            }
63            wasmparser::Dylink0Subsection::RuntimePath(path) => {
64                runtime_path.extend(path.into_iter().map(|path| path.to_string()));
65            }
66        }
67    }
68
69    Ok(DylinkInfo {
70        mem_info: mem_info.unwrap_or(wasmparser::MemInfo {
71            memory_size: 0,
72            memory_alignment: 0,
73            table_size: 0,
74            table_alignment: 0,
75        }),
76        needed: needed.unwrap_or_default(),
77        import_metadata,
78        export_metadata,
79        runtime_path,
80    })
81}