wasmer_wasix/state/linker/instance_group/
exports.rs1use tracing::trace;
2use wasmer::{AsStoreMut, Exportable, Extern, ExternType, Function, Global, Instance, Value};
3
4use super::{
5 DylinkInfo, InstanceGroupState, LinkerState, MAIN_MODULE_HANDLE, ModuleHandle,
6 PartiallyResolvedExport, ResolveError,
7};
8
9impl InstanceGroupState {
10 pub(in crate::state::linker) fn resolve_exported_symbol(
11 &self,
12 symbol: &str,
13 ) -> Option<(ModuleHandle, &Extern)> {
14 if let Some(export) = self
15 .main_instance()
16 .and_then(|instance| instance.exports.get_extern(symbol))
17 {
18 trace!(symbol, from = ?MAIN_MODULE_HANDLE, ?export, "Resolved exported symbol");
19 Some((MAIN_MODULE_HANDLE, export))
20 } else {
21 for (handle, dl_instance) in &self.side_instances {
22 if let Some(export) = dl_instance.instance.exports.get_extern(symbol) {
23 trace!(symbol, from = ?handle, ?export, "Resolved exported symbol");
24 return Some((*handle, export));
25 }
26 }
27
28 trace!(symbol, "Failed to resolve exported symbol");
29 None
30 }
31 }
32
33 pub(in crate::state::linker) fn resolve_export(
37 &self,
38 linker_state: &LinkerState,
39 store: &mut impl AsStoreMut,
40 module_handle: Option<ModuleHandle>,
41 symbol: &str,
42 allow_hidden: bool,
43 ) -> Result<(PartiallyResolvedExport, ModuleHandle), ResolveError> {
44 trace!(?module_handle, ?symbol, "Resolving export");
45 match module_handle {
46 Some(module_handle) => {
47 let instance = self
48 .try_instance(module_handle)
49 .ok_or(ResolveError::InvalidModuleHandle)?;
50 let tls_base = self.tls_base(module_handle);
51 let memory_base = linker_state.memory_base(module_handle);
52 let dylink_info = linker_state.dylink_info(module_handle);
53 Ok((
54 self.resolve_export_from(
55 store,
56 module_handle,
57 symbol,
58 instance,
59 dylink_info,
60 memory_base,
61 tls_base,
62 allow_hidden,
63 )?,
64 module_handle,
65 ))
66 }
67
68 None => {
69 if let Some(instance) = self.main_instance() {
71 match self.resolve_export_from(
72 store,
73 MAIN_MODULE_HANDLE,
74 symbol,
75 instance,
76 &linker_state.main_module_dylink_info,
77 linker_state.memory_base(MAIN_MODULE_HANDLE),
78 self.main_instance_tls_base,
79 allow_hidden,
80 ) {
81 Ok(export) => return Ok((export, MAIN_MODULE_HANDLE)),
82 Err(ResolveError::MissingExport) => (),
83 Err(e) => return Err(e),
84 }
85 }
86
87 for (handle, module) in &linker_state.side_modules {
93 let instance = &self.side_instances[handle];
94 match self.resolve_export_from(
95 store,
96 *handle,
97 symbol,
98 &instance.instance,
99 &module.dylink_info,
100 linker_state.memory_base(*handle),
101 instance.tls_base,
102 allow_hidden,
103 ) {
104 Ok(export) => return Ok((export, *handle)),
105 Err(ResolveError::MissingExport) => (),
106 Err(e) => return Err(e),
107 }
108 }
109
110 trace!(
111 ?module_handle,
112 ?symbol,
113 "Failed to locate symbol after searching all instances"
114 );
115 Err(ResolveError::MissingExport)
116 }
117 }
118 }
119
120 pub(in crate::state::linker) fn resolve_export_from(
121 &self,
122 store: &mut impl AsStoreMut,
123 module_handle: ModuleHandle,
124 symbol: &str,
125 instance: &Instance,
126 dylink_info: &DylinkInfo,
127 memory_base: u64,
128 tls_base: Option<u64>,
129 allow_hidden: bool,
130 ) -> Result<PartiallyResolvedExport, ResolveError> {
131 trace!(from = ?module_handle, symbol, "Resolving export from instance");
132 let export = instance.exports.get_extern(symbol).ok_or_else(|| {
133 trace!(from = ?module_handle, symbol, "Not found");
134 ResolveError::MissingExport
135 })?;
136
137 if !allow_hidden
138 && dylink_info
139 .export_metadata
140 .get(symbol)
141 .map(|flags| flags.contains(wasmparser::SymbolFlags::VISIBILITY_HIDDEN))
142 .unwrap_or(false)
143 {
144 return Err(ResolveError::MissingExport);
145 }
146
147 match export.ty(store) {
148 ExternType::Function(_) => {
149 trace!(from = ?module_handle, symbol, "Found function");
150 Ok(PartiallyResolvedExport::Function(
151 Function::get_self_from_extern(export).unwrap().clone(),
152 ))
153 }
154 ty @ ExternType::Global(_) => {
155 let global = Global::get_self_from_extern(export).unwrap();
156 let value = match global.get(store) {
157 Value::I32(value) => value as u64,
158 Value::I64(value) => value as u64,
159 _ => return Err(ResolveError::InvalidExportType(ty.clone())),
160 };
161
162 let is_tls = dylink_info
163 .export_metadata
164 .get(symbol)
165 .map(|flags| flags.contains(wasmparser::SymbolFlags::TLS))
166 .unwrap_or(false);
167
168 if is_tls {
169 let Some(tls_base) = tls_base else {
170 return Err(ResolveError::NoTlsBaseGlobalExport);
171 };
172 let final_value = value + tls_base;
173 trace!(
174 from = ?module_handle,
175 symbol,
176 value,
177 offset = value,
178 final_value,
179 "Found TLS global"
180 );
181 Ok(PartiallyResolvedExport::Tls {
182 offset: value,
183 final_addr: final_value,
184 })
185 } else {
186 let final_value = value + memory_base;
187 trace!(from = ?module_handle, symbol, value, final_value, "Found global");
188 Ok(PartiallyResolvedExport::Global(final_value))
189 }
190 }
191 ty => Err(ResolveError::InvalidExportType(ty.clone())),
192 }
193 }
194}