1 use crate::Engine;
2 use crate::Module;
3 use crate::Result;
4 use crate::module::ModuleRegistry;
5 use crate::vm::ModuleMemoryImageSource;
6 use crate::{code_memory::CodeMemory, type_registry::TypeCollection};
7 #[cfg(feature = "debug")]
8 use alloc::boxed::Box;
9 use alloc::sync::Arc;
10 use core::ops::{Add, Range, Sub};
11 use wasmtime_core::error::OutOfMemory;
12 use wasmtime_environ::DefinedFuncIndex;
13 use wasmtime_environ::ModuleTypes;
14 use wasmtime_environ::StaticModuleIndex;
15 #[cfg(feature = "component-model")]
16 use wasmtime_environ::component::ComponentTypes;
17 
18 macro_rules! define_pc_kind {
19     ($ty:ident) => {
20         #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
21         pub struct $ty(usize);
22 
23         impl Add<usize> for $ty {
24             type Output = $ty;
25             fn add(self, other: usize) -> $ty {
26                 $ty(self.0.wrapping_add(other))
27             }
28         }
29         impl Sub<usize> for $ty {
30             type Output = $ty;
31             fn sub(self, other: usize) -> $ty {
32                 $ty(self.0.wrapping_sub(other))
33             }
34         }
35 
36         impl $ty {
37             /// Is the given PC within this range? Give the relative
38             /// offset if so.
39             pub fn offset_of(range: Range<$ty>, pc: usize) -> Option<usize> {
40                 if pc >= range.start.0 && pc < range.end.0 {
41                     Some(pc.wrapping_sub(range.start.0))
42                 } else {
43                     None
44                 }
45             }
46 
47             /// Get the raw PC value.
48             pub fn raw(&self) -> usize {
49                 self.0
50             }
51         }
52     };
53 }
54 
55 // An address in "engine code": the original (canonical) copy of code
56 // for a compiled module.
57 //
58 // See [`EngineCode`] for more details.
59 define_pc_kind!(EngineCodePC);
60 
61 // An address in "store code": the copy of code used when executing
62 // instances of a module in a given store.
63 //
64 // May or may not be the same as the engine code address -- a store
65 // is allowed to make a private copy of engine code as its store
66 // code.
67 //
68 // See [`StoreCode`] for more details.
69 define_pc_kind!(StoreCodePC);
70 
71 impl StoreCodePC {
72     /// Construct a StoreCodePC for search purposes from a raw PC
73     /// observed during execution.
74     pub fn from_raw(pc: usize) -> StoreCodePC {
75         StoreCodePC(pc)
76     }
77 }
78 
79 /// Metadata about, and original machine code for, a loaded compiled
80 /// artifact in memory which is ready for Wasmtime to execute.
81 ///
82 /// This structure is used in both `Module` and `Component`. For components it's
83 /// notably shared amongst the core wasm modules within a component and the
84 /// component itself. For core wasm modules this is uniquely owned within a
85 /// `Module`.
86 ///
87 /// The `EngineCode` is "static", like a module: there is one copy per
88 /// unit of code. Instantiation of a module containing an `EngineCode`
89 /// into a `Store` produces a `StoreCode`. The latter is the owner of
90 /// the actual machine code that runs. This machine code *may* be a
91 /// read-only-shared copy of the original, or may be a private copy
92 /// that we have patched. The latter is useful for some kinds of
93 /// debugging/instrumentation, which is always scoped per-Store.
94 ///
95 /// The `EngineCode` does *not* expose its underlying `CodeMemory`, to
96 /// guard against the original-copy being used in an inappropriate
97 /// (store-specific) context. Instead, it has accessors that provide
98 /// the instance-agnostic metadata from the `CodeMemory`, and
99 /// instance-specific data and code pointers can be obtained from the
100 /// `StoreCode`.
101 pub struct EngineCode {
102     /// Actual underlying code which is executable and contains other
103     /// compiled information.
104     ///
105     /// Note the `Arc` here is used to share this with `CompiledModule` and the
106     /// global module registry of traps. While probably not strictly necessary
107     /// and could be avoided with some refactorings is a hopefully a relatively
108     /// minor `Arc` for now.
109     ///
110     /// As noted above, this is the *original* copy of the code, and
111     /// may be used directly, but may also be deep-cloned to a private
112     /// copy in a `StoreCode`.
113     original_code: Arc<CodeMemory>,
114 
115     /// Registered shared signature for the loaded object.
116     ///
117     /// Note that this type has a significant destructor which unregisters
118     /// signatures within the `Engine` it was originally tied to, and this ends
119     /// up corresponding to the lifetime of a `Component` or `Module`.
120     signatures: TypeCollection,
121 
122     /// Type information for the loaded object.
123     ///
124     /// This is either a `ModuleTypes` or a `ComponentTypes` depending on the
125     /// top-level creator of this code.
126     types: Types,
127 }
128 
129 impl EngineCode {
130     pub fn new(
131         mmap: Arc<CodeMemory>,
132         signatures: TypeCollection,
133         types: Types,
134     ) -> Result<EngineCode, OutOfMemory> {
135         // The corresponding unregister for this is below in `Drop for
136         // EngineCode`.
137         crate::module::register_code(&mmap, mmap.raw_addr_range())?;
138 
139         Ok(EngineCode {
140             original_code: mmap,
141             signatures,
142             types,
143         })
144     }
145 
146     #[cfg(feature = "component-model")]
147     pub fn types(&self) -> &Types {
148         &self.types
149     }
150 
151     pub fn module_types(&self) -> &ModuleTypes {
152         self.types.module_types()
153     }
154 
155     pub fn signatures(&self) -> &TypeCollection {
156         &self.signatures
157     }
158 
159     pub fn text_size(&self) -> usize {
160         self.original_code.text().len()
161     }
162 
163     /// Give the range of engine-code PCs in this code.
164     pub fn text_range(&self) -> Range<EngineCodePC> {
165         let raw = self.original_code.raw_addr_range();
166         EngineCodePC(raw.start)..EngineCodePC(raw.end)
167     }
168 
169     // For all accessors to code object sections below: we can use the
170     // original (uncloned) code image for these: they are just slices
171     // of bytes that we interpret independent of location.
172     //
173     // We hide the raw `CodeMemory` in `original_code` (*not* a public
174     // field) because we do not want the EngineCode copy used
175     // inadvertently for execution of Wasm functions.
176     //
177     // We thus *cannot* add an accessor below for anything that
178     // actually interprets the location of the bytes as a code
179     // pointer to a Wasm function.
180     //
181     // Note that Wasm-to-array trampolines, in contrast, are fair game
182     // to execute directly from the EngineCode: these are not specific
183     // to Wasm functions, but instead call builtins, and we never
184     // patch trampolines in StoreCode, so we can freely mix in
185     // EngineCode variants.
186 
187     /// Get the Wasm-to-array trampoline for the given raw range in
188     /// the text segment.
189     pub(crate) fn raw_wasm_to_array_trampoline_data(&self, range: Range<usize>) -> &[u8] {
190         &self.original_code.text()[range]
191     }
192 
193     /// Provide the address-map data for this EngineCode.
194     pub fn address_map_data(&self) -> &[u8] {
195         // We can use the original (uncloned) code image for this: it
196         // is just a slice of bytes that we interpret independent of
197         // location.
198         self.original_code.address_map_data()
199     }
200 
201     /// Provide the stack-map data for this EngineCode.
202     pub fn stack_map_data(&self) -> &[u8] {
203         // We can use the original (uncloned) code image for this: it
204         // is just a slice of bytes that we interpret independent of
205         // location.
206         self.original_code.stack_map_data()
207     }
208 
209     /// Returns the encoded exception-tables section to pass to
210     /// `wasmtime_unwinder::ExceptionTable::parse`.
211     pub fn exception_tables(&self) -> &[u8] {
212         // We can use the original (uncloned) code image for this: it
213         // is just a slice of bytes that we interpret independent of
214         // location.
215         self.original_code.exception_tables()
216     }
217 
218     /// Returns the encoded frame-tables section to pass to
219     /// `wasmtime_environ::FrameTable::parse`.
220     pub fn frame_tables(&self) -> &[u8] {
221         self.original_code.frame_tables()
222     }
223 
224     /// Returns the data in the `ELF_NAME_DATA` section.
225     #[inline]
226     pub fn func_name_data(&self) -> &[u8] {
227         self.original_code.func_name_data()
228     }
229 
230     /// Returns the contents of the `ELF_WASMTIME_DWARF` section.
231     #[inline]
232     pub fn wasm_dwarf(&self) -> &[u8] {
233         self.original_code.wasm_dwarf()
234     }
235 
236     /// Returns the original Wasm bytecode section if preserved in the
237     /// compiled artifact.
238     #[inline]
239     pub fn wasm_bytecode_for_module(&self, module: StaticModuleIndex) -> Option<&[u8]> {
240         self.original_code.wasm_bytecode_for_module(module)
241     }
242 
243     /// Returns the raw image as bytes (in our internal image format).
244     pub fn image(&self) -> &[u8] {
245         &self.original_code.mmap()[..]
246     }
247 
248     pub fn text(&self) -> &[u8] {
249         &self.original_code.text()
250     }
251 
252     /// Returns the concatenated list of all data associated with this wasm
253     /// module.
254     ///
255     /// This is used for initialization of memories and all data ranges stored
256     /// in a `Module` are relative to the slice returned here.
257     #[inline]
258     pub fn wasm_data(&self) -> &[u8] {
259         self.original_code.wasm_data()
260     }
261 
262     pub(crate) fn module_memory_image_source(&self) -> &Arc<impl ModuleMemoryImageSource> {
263         &self.original_code
264     }
265 }
266 
267 impl Drop for EngineCode {
268     fn drop(&mut self) {
269         crate::module::unregister_code(self.original_code.raw_addr_range());
270     }
271 }
272 
273 pub enum Types {
274     Module(ModuleTypes),
275     #[cfg(feature = "component-model")]
276     Component(Arc<ComponentTypes>),
277 }
278 
279 impl Types {
280     fn module_types(&self) -> &ModuleTypes {
281         match self {
282             Types::Module(m) => m,
283             #[cfg(feature = "component-model")]
284             Types::Component(c) => c.module_types(),
285         }
286     }
287 }
288 
289 impl From<ModuleTypes> for Types {
290     fn from(types: ModuleTypes) -> Types {
291         Types::Module(types)
292     }
293 }
294 
295 #[cfg(feature = "component-model")]
296 impl From<Arc<ComponentTypes>> for Types {
297     fn from(types: Arc<ComponentTypes>) -> Types {
298         Types::Component(types)
299     }
300 }
301 
302 /// A `Store`-local instance of code.
303 ///
304 /// This type encapsulates executable code within the context of
305 /// instantiation in a single store. It may be an unmodified pointer
306 /// to the read-only original code, or it may be locally patched for
307 /// this store due to debugging or instrumentation settings.
308 ///
309 /// Most things that the runtime will want to do with a module's image
310 /// will require the `EngineCode` -- all metadata lives there. The
311 /// `StoreCode` is solely responsible for the executable machine code.
312 ///
313 /// This type is designed to be uniquely owned, unlike `EngineCode`
314 /// above. The runtime data structures will have scattered `Arc`s to
315 /// the `EngineCode` but only one
316 pub struct StoreCode(StoreCodeStorage);
317 
318 enum StoreCodeStorage {
319     Shared(Arc<CodeMemory>),
320     /// Private copy of the given code memory.
321     ///
322     /// This is the only reference to this CodeMemory. The StoreCode
323     /// is owned directly by the Store's ModuleRegistry.
324     #[cfg(feature = "debug")]
325     Private(Box<CodeMemory>),
326 }
327 
328 impl StoreCode {
329     /// Create a new StoreCode for a given Store from a given
330     /// EngineCode, given the engine's settings (tunables).
331     pub fn new(engine: &Engine, engine_code: &Arc<EngineCode>) -> Result<Self> {
332         // Enabled guest-debugging causes us to allocate private
333         // copies of code in every store, to allow individual enabling
334         // of breakpoints (by code patching) independently in each
335         // one.
336         #[cfg(feature = "debug")]
337         let code = if engine.tunables().debug_guest {
338             // TODO(#12104): we should be able to clone only `.text`;
339             // this clones the whole image.
340             let mut private_copy = engine_code.original_code.deep_clone(engine)?;
341             private_copy.publish()?;
342             crate::module::register_code(
343                 &engine_code.original_code,
344                 private_copy.raw_addr_range(),
345             )?;
346             StoreCodeStorage::Private(Box::new(private_copy))
347         } else {
348             StoreCodeStorage::Shared(engine_code.original_code.clone())
349         };
350 
351         #[cfg(not(feature = "debug"))]
352         let code = StoreCodeStorage::Shared(engine_code.original_code.clone());
353         // Avoid unused-variable warning in build without debugging
354         // support.
355         let _ = engine;
356 
357         Ok(StoreCode(code))
358     }
359 
360     /// Provide the underlying CodeMemory.
361     pub fn code_memory(&self) -> &CodeMemory {
362         match &self.0 {
363             StoreCodeStorage::Shared(m) => m,
364             #[cfg(feature = "debug")]
365             StoreCodeStorage::Private(m) => m,
366         }
367     }
368 
369     /// Provide a mutable reference to a CodeMemory that is privately
370     /// owned only by this StoreCode.
371     #[cfg(feature = "debug")]
372     pub fn code_memory_mut(&mut self) -> Option<&mut CodeMemory> {
373         match &mut self.0 {
374             StoreCodeStorage::Shared(_) => None,
375             StoreCodeStorage::Private(m) => Some(m),
376         }
377     }
378 
379     /// Provide the address range for this StoreCode.
380     pub fn text_range(&self) -> Range<StoreCodePC> {
381         let raw = self.code_memory().raw_addr_range();
382         StoreCodePC(raw.start)..StoreCodePC(raw.end)
383     }
384 
385     /// Provide the actual text segment for this StoreCode.
386     pub fn text(&self) -> &[u8] {
387         self.code_memory().text()
388     }
389 }
390 
391 impl Drop for StoreCode {
392     fn drop(&mut self) {
393         match &self.0 {
394             StoreCodeStorage::Shared(_) => {
395                 // Drop impl for EngineCode will de-register (see
396                 // above).
397             }
398             #[cfg(feature = "debug")]
399             StoreCodeStorage::Private(mem) => {
400                 crate::module::unregister_code(mem.raw_addr_range());
401             }
402         }
403     }
404 }
405 
406 /// A wrapper for a Module together with a StoreCode. Allows fetching
407 /// code pointers, ready to call.
408 pub struct ModuleWithCode<'a> {
409     module: &'a Module,
410     store_code: &'a StoreCode,
411 }
412 
413 impl<'a> ModuleWithCode<'a> {
414     /// Find the StoreCode in a given store for a module and wrap it
415     /// up with that module, ready to compute code pointers.
416     pub fn in_store(
417         registry: &'a ModuleRegistry,
418         module: &'a Module,
419     ) -> Option<ModuleWithCode<'a>> {
420         let store_code = registry.store_code(module.engine_code())?;
421         Some(ModuleWithCode { module, store_code })
422     }
423 
424     pub(crate) fn from_raw(module: &'a Module, store_code: &'a StoreCode) -> ModuleWithCode<'a> {
425         ModuleWithCode { module, store_code }
426     }
427 
428     /// Provide the Module wrapped in this tuple.
429     pub fn module(&self) -> &'a Module {
430         self.module
431     }
432 
433     /// Provide the StoreCode wrapped in this tuple.
434     pub fn store_code(&self) -> &'a StoreCode {
435         self.store_code
436     }
437 
438     /// Returns an iterator over all functions defined within this module with
439     /// their index and their raw pointer.
440     #[inline]
441     pub fn finished_functions(
442         &self,
443     ) -> impl ExactSizeIterator<Item = (DefinedFuncIndex, &[u8])> + '_ {
444         self.module
445             .env_module()
446             .defined_func_indices()
447             .map(|i| (i, self.finished_function(i)))
448     }
449 
450     /// Returns the slice in the text section of the function that
451     /// `index` points to.
452     #[inline]
453     pub fn finished_function(&self, def_func_index: DefinedFuncIndex) -> &[u8] {
454         let range = self
455             .module
456             .compiled_module()
457             .finished_function_range(def_func_index);
458         &self.store_code.text()[range]
459     }
460 
461     /// Get the array-to-Wasm trampoline for the function `index`
462     /// points to, as a slice of raw code that can be converted to a
463     /// callable function pointer.
464     ///
465     /// If the function `index` points to does not escape, then `None` is
466     /// returned.
467     ///
468     /// These trampolines are used for array callers (e.g. `Func::new`)
469     /// calling Wasm callees.
470     pub fn array_to_wasm_trampoline(&self, def_func_index: DefinedFuncIndex) -> Option<&[u8]> {
471         let range = self
472             .module
473             .compiled_module()
474             .array_to_wasm_trampoline_range(def_func_index)?;
475         Some(&self.store_code.text()[range])
476     }
477 
478     /// Get the text offset (relative PC) for a given absolute PC in
479     /// this module.
480     #[cfg(feature = "gc")]
481     pub(crate) fn text_offset(&self, pc: usize) -> Option<u32> {
482         StoreCodePC::offset_of(self.store_code.text_range(), pc)
483             .map(|offset| u32::try_from(offset).expect("Module larger than 4GiB"))
484     }
485 
486     /// Lookup the stack map at a program counter value.
487     #[cfg(feature = "gc")]
488     pub(crate) fn lookup_stack_map(&self, pc: usize) -> Option<wasmtime_environ::StackMap<'_>> {
489         let text_offset = self.text_offset(pc)?;
490         let info = self.module.engine_code().stack_map_data();
491         wasmtime_environ::StackMap::lookup(text_offset, info)
492     }
493 }
494