diff --git a/crates/wasmtime/src/runtime/debug.rs b/crates/wasmtime/src/runtime/debug.rs index 52bf817970c9..4ac487e9a10f 100644 --- a/crates/wasmtime/src/runtime/debug.rs +++ b/crates/wasmtime/src/runtime/debug.rs @@ -47,6 +47,86 @@ impl Store { pub fn edit_breakpoints<'a>(&'a mut self) -> Option> { self.as_store_opaque().edit_breakpoints() } + + /// Get a vector of all Instances held in the Store, for debug + /// purposes. + /// + /// Guest debugging must be enabled for this accessor to return + /// any instances. If it is not, an empty vector is returend. + pub fn debug_all_instances(&mut self) -> Vec { + self.as_store_opaque().debug_all_instances() + } + + /// Get a vector of all Modules held in the Store, for debug + /// purposes. + /// + /// Guest debugging must be enabled for this accessor to return + /// any modules. If it is not, an empty vector is returend. + pub fn debug_all_modules(&mut self) -> Vec { + self.as_store_opaque().debug_all_modules() + } +} + +impl<'a, T> StoreContextMut<'a, T> { + /// Provide a frame handle for all activations, in order from + /// innermost (most recently called) to outermost on the stack. + /// + /// See [`Store::debug_exit_frames`] for more details. + pub fn debug_exit_frames(&mut self) -> impl Iterator { + self.0.as_store_opaque().debug_exit_frames() + } + + /// Start an edit session to update breakpoints. + pub fn edit_breakpoints(self) -> Option> { + self.0.as_store_opaque().edit_breakpoints() + } + + /// Get a vector of all Instances held in the Store, for debug + /// purposes. + /// + /// See [`Store::debug_all_instances`] for more details. + pub fn debug_all_instances(self) -> Vec { + self.0.as_store_opaque().debug_all_instances() + } + + /// Get a vector of all Modules held in the Store, for debug + /// purposes. + /// + /// See [`Store::debug_all_modules`] for more details. + pub fn debug_all_modules(self) -> Vec { + self.0.as_store_opaque().debug_all_modules() + } +} + +impl<'a, T> Caller<'a, T> { + /// Provide a frame handle for all activations, in order from + /// innermost (most recently called) to outermost on the stack. + /// + /// See [`Store::debug_exit_frames`] for more details. + pub fn debug_exit_frames(&mut self) -> impl Iterator { + self.store.0.as_store_opaque().debug_exit_frames() + } + + /// Start an edit session to update breakpoints. + pub fn edit_breakpoints<'b>(&'b mut self) -> Option> { + self.store.0.as_store_opaque().edit_breakpoints() + } + + /// Get a vector of all Instances held in the Store, for debug + /// purposes. + /// + /// See [`Store::debug_all_instances`] for more details. + pub fn debug_all_instances(&mut self) -> Vec { + self.store.0.as_store_opaque().debug_all_instances() + } + + /// Get a vector of all Modules held in the Store, for debug + /// purposes. + /// + /// See [`Store::debug_all_modules`] for more details. + pub fn debug_all_modules(&mut self) -> Vec { + self.store.0.as_store_opaque().debug_all_modules() + } } impl StoreOpaque { @@ -72,30 +152,21 @@ impl StoreOpaque { let (breakpoints, registry) = self.breakpoints_and_registry_mut(); Some(breakpoints.edit(registry)) } -} -impl<'a, T> StoreContextMut<'a, T> { - /// Provide a frame handle for all activations, in order from - /// innermost (most recently called) to outermost on the stack. - /// - /// See [`Store::debug_exit_frames`] for more details. - pub fn debug_exit_frames(&mut self) -> impl Iterator { - self.0.as_store_opaque().debug_exit_frames() - } + fn debug_all_instances(&mut self) -> Vec { + if !self.engine().tunables().debug_guest { + return vec![]; + } - /// Start an edit session to update breakpoints. - pub fn edit_breakpoints(self) -> Option> { - self.0.as_store_opaque().edit_breakpoints() + self.all_instances().collect() } -} -impl<'a, T> Caller<'a, T> { - /// Provide a frame handle for all activations, in order from - /// innermost (most recently called) to outermost on the stack. - /// - /// See [`Store::debug_exit_frames`] for more details. - pub fn debug_exit_frames(&mut self) -> impl Iterator { - self.store.0.as_store_opaque().debug_exit_frames() + fn debug_all_modules(&self) -> Vec { + if !self.engine().tunables().debug_guest { + return vec![]; + } + + self.modules().all_modules().cloned().collect() } } diff --git a/tests/all/debug.rs b/tests/all/debug.rs index 8ef5da10ca1c..10fe1148771a 100644 --- a/tests/all/debug.rs +++ b/tests/all/debug.rs @@ -499,6 +499,41 @@ fn private_entity_access_shared_memory() -> wasmtime::Result<()> { Ok(()) } +#[test] +#[cfg_attr(miri, ignore)] +fn all_instances_and_modules_in_store() -> wasmtime::Result<()> { + let mut config = Config::default(); + config.guest_debug(true); + let engine = Engine::new(&config)?; + let mut store = Store::new(&engine, ()); + let m1 = Module::new( + &engine, + r#" + (module (func (param i32) (result i32) (local.get 0))) + "#, + )?; + let m2 = Module::new( + &engine, + r#" + (module (func (param i32) (result i32) (local.get 0))) + "#, + )?; + let i1 = Instance::new(&mut store, &m1, &[])?; + let i2 = Instance::new(&mut store, &m2, &[])?; + + let instances = store.debug_all_instances(); + let modules = store.debug_all_modules(); + assert_eq!(instances.len(), 2); + assert_eq!(modules.len(), 2); + assert!( + (Module::same(&modules[0], &m1) && Module::same(&modules[1], &m2)) + || (Module::same(&modules[1], &m1) && Module::same(&modules[0], &m2)) + ); + assert!(instances[0] == i1); + assert!(instances[1] == i2); + Ok(()) +} + macro_rules! debug_event_checker { ($ty:tt, $store:tt,