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