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