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