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