wasmtime/runtime/
instantiate.rs1use crate::code::EngineCode;
7use crate::prelude::*;
8use crate::profiling_agent::ProfilingAgent;
9use crate::runtime::vm::CompiledModuleId;
10use alloc::sync::Arc;
11use core::ops::Range;
12use core::str;
13use wasmtime_environ::{
14 CompiledFunctionsTable, CompiledModuleInfo, DefinedFuncIndex, EntityRef, FilePos, FuncIndex,
15 FuncKey, FunctionLoc, FunctionName, Metadata, Module, ModuleInternedTypeIndex,
16 StaticModuleIndex,
17};
18
19pub struct CompiledModule {
21 unique_id: CompiledModuleId,
23 engine_code: Arc<EngineCode>,
24 module: Arc<Module>,
25 meta: Metadata,
26 index: Arc<CompiledFunctionsTable>,
27 func_names: Vec<FunctionName>,
29}
30
31impl CompiledModule {
32 pub fn from_artifacts(
50 engine_code: Arc<EngineCode>,
51 info: CompiledModuleInfo,
52 index: Arc<CompiledFunctionsTable>,
53 profiler: &dyn ProfilingAgent,
54 ) -> Result<Self> {
55 let mut ret = Self {
56 unique_id: CompiledModuleId::new(),
57 engine_code,
58 module: Arc::new(info.module),
59 meta: info.meta,
60 index,
61 func_names: info.func_names,
62 };
63 ret.register_profiling(profiler)?;
64
65 Ok(ret)
66 }
67
68 fn register_profiling(&mut self, profiler: &dyn ProfilingAgent) -> Result<()> {
69 profiler.register_module(self.engine_code.image(), &|addr| {
73 let idx = self.func_by_text_offset(addr)?;
74 let idx = self.module.func_index(idx);
75 let name = self.func_name(idx)?;
76 let mut demangled = String::new();
77 wasmtime_environ::demangle_function_name(&mut demangled, name).unwrap();
78 Some(demangled)
79 });
80 Ok(())
81 }
82
83 pub fn unique_id(&self) -> CompiledModuleId {
86 self.unique_id
87 }
88
89 pub fn module(&self) -> &Arc<Module> {
91 &self.module
92 }
93
94 fn module_index(&self) -> StaticModuleIndex {
95 self.module.module_index
96 }
97
98 pub fn func_name(&self, idx: FuncIndex) -> Option<&str> {
101 let i = self.func_names.binary_search_by_key(&idx, |n| n.idx).ok()?;
103 let name = &self.func_names[i];
104
105 let data = self.engine_code.func_name_data();
110 Some(str::from_utf8(&data[name.offset as usize..][..name.len as usize]).unwrap())
111 }
112
113 #[inline]
116 pub fn finished_function_ranges(
117 &self,
118 ) -> impl ExactSizeIterator<Item = (DefinedFuncIndex, Range<usize>)> + '_ {
119 self.module
120 .defined_func_indices()
121 .map(|i| (i, self.finished_function_range(i)))
122 }
123
124 #[inline]
126 pub fn finished_function_range(&self, def_func_index: DefinedFuncIndex) -> Range<usize> {
127 let loc = self.func_loc(def_func_index);
128 let start = usize::try_from(loc.start).unwrap();
129 let end = usize::try_from(loc.start + loc.length).unwrap();
130 start..end
131 }
132
133 pub fn array_to_wasm_trampoline_range(
142 &self,
143 def_func_index: DefinedFuncIndex,
144 ) -> Option<Range<usize>> {
145 assert!(def_func_index.index() < self.module.num_defined_funcs());
146 let key = FuncKey::ArrayToWasmTrampoline(self.module_index(), def_func_index);
147 let loc = self.index.func_loc(key)?;
148 let start = usize::try_from(loc.start).unwrap();
149 let end = usize::try_from(loc.start + loc.length).unwrap();
150 Some(start..end)
151 }
152
153 pub fn wasm_to_array_trampoline(&self, signature: ModuleInternedTypeIndex) -> Option<&[u8]> {
160 let key = FuncKey::WasmToArrayTrampoline(signature);
161 let loc = self.index.func_loc(key)?;
162 let start = usize::try_from(loc.start).unwrap();
163 let end = usize::try_from(loc.start + loc.length).unwrap();
164 Some(
165 self.engine_code
166 .raw_wasm_to_array_trampoline_data(start..end),
167 )
168 }
169
170 pub fn func_by_text_offset(&self, text_offset: usize) -> Option<DefinedFuncIndex> {
175 let text_offset = u32::try_from(text_offset).unwrap();
176 let key = self.index.func_by_text_offset(text_offset)?;
177 match key {
178 FuncKey::DefinedWasmFunction(module, def_func_index) => {
179 debug_assert_eq!(module, self.module_index());
180 Some(def_func_index)
181 }
182 _ => None,
183 }
184 }
185
186 pub fn func_loc(&self, def_func_index: DefinedFuncIndex) -> &FunctionLoc {
188 assert!(def_func_index.index() < self.module.num_defined_funcs());
189 let key = FuncKey::DefinedWasmFunction(self.module_index(), def_func_index);
190 self.index
191 .func_loc(key)
192 .expect("defined function should be present")
193 }
194
195 pub fn func_start_srcloc(&self, def_func_index: DefinedFuncIndex) -> FilePos {
198 assert!(def_func_index.index() < self.module.num_defined_funcs());
199 let key = FuncKey::DefinedWasmFunction(self.module_index(), def_func_index);
200 self.index
201 .src_loc(key)
202 .expect("defined function should be present")
203 }
204
205 #[cfg(feature = "addr2line")]
211 pub fn symbolize_context(&self) -> Result<Option<SymbolizeContext<'_>>> {
212 use gimli::EndianSlice;
213 if !self.meta.has_wasm_debuginfo {
214 return Ok(None);
215 }
216 let dwarf = gimli::Dwarf::load(|id| -> Result<_> {
217 let data = self
223 .meta
224 .dwarf
225 .binary_search_by_key(&(id as u8), |(id, _)| *id)
226 .ok()
227 .and_then(|i| {
228 let (_, range) = &self.meta.dwarf[i];
229 let start = range.start.try_into().ok()?;
230 let end = range.end.try_into().ok()?;
231 self.engine_code.wasm_dwarf().get(start..end)
232 })
233 .unwrap_or(&[]);
234 Ok(EndianSlice::new(data, gimli::LittleEndian))
235 })?;
236 let cx = addr2line::Context::from_dwarf(dwarf)
237 .context("failed to create addr2line dwarf mapping context")?;
238 Ok(Some(SymbolizeContext {
239 inner: cx,
240 code_section_offset: self.meta.code_section_offset,
241 }))
242 }
243
244 pub fn has_unparsed_debuginfo(&self) -> bool {
247 self.meta.has_unparsed_debuginfo
248 }
249
250 pub fn has_address_map(&self) -> bool {
256 !self.engine_code.address_map_data().is_empty()
257 }
258}
259
260#[cfg(feature = "addr2line")]
261type Addr2LineContext<'a> = addr2line::Context<gimli::EndianSlice<'a, gimli::LittleEndian>>;
262
263#[cfg(feature = "addr2line")]
266pub struct SymbolizeContext<'a> {
267 inner: Addr2LineContext<'a>,
268 code_section_offset: u64,
269}
270
271#[cfg(feature = "addr2line")]
272impl<'a> SymbolizeContext<'a> {
273 pub fn addr2line(&self) -> &Addr2LineContext<'a> {
276 &self.inner
277 }
278
279 pub fn code_section_offset(&self) -> u64 {
282 self.code_section_offset
283 }
284}