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