Skip to content

Commit

Permalink
Include globals and memories in core dumps
Browse files Browse the repository at this point in the history
Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com>
  • Loading branch information
itsrainy and fitzgen committed Aug 25, 2023
1 parent 1d4766f commit 04df873
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 19 deletions.
43 changes: 43 additions & 0 deletions crates/runtime/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,13 @@ impl Instance {
unsafe { *self.vmctx_plus_offset(self.offsets().vmctx_vmmemory_pointer(index)) }
}

/// Return the memories defined in this instance
pub fn defined_memories<'a>(
&'a self,
) -> impl ExactSizeIterator<Item = (DefinedMemoryIndex, &'a Memory)> + 'a {
self.memories.iter()
}

/// Return the indexed `VMGlobalDefinition`.
fn global(&mut self, index: DefinedGlobalIndex) -> &VMGlobalDefinition {
unsafe { &*self.global_ptr(index) }
Expand All @@ -376,6 +383,25 @@ impl Instance {
}
}

/// Get the globals defined in this instance
pub fn defined_globals<'a>(
&'a mut self,
) -> impl ExactSizeIterator<Item = (DefinedGlobalIndex, ExportGlobal)> + 'a {
let module = self.module().clone();
module
.globals
.keys()
.skip(module.num_imported_globals)
.map(move |global_idx| {
let def_idx = module.defined_global_index(global_idx).unwrap();
let global = ExportGlobal {
definition: self.global_ptr(def_idx),
global: self.module().globals[global_idx],
};
(def_idx, global)
})
}

/// Return a pointer to the interrupts structure
pub fn runtime_limits(&mut self) -> *mut *const VMRuntimeLimits {
unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_runtime_limits()) }
Expand Down Expand Up @@ -1323,6 +1349,23 @@ impl InstanceHandle {
self.instance_mut().get_table_with_lazy_init(index, range)
}

/// Return the memories defined in this instance
pub fn defined_memories<'a>(&'a mut self) -> impl ExactSizeIterator<Item = ExportMemory> + 'a {
let idxs = (0..self.module().memory_plans.len())
.skip(self.module().num_imported_memories)
.map(|i| MemoryIndex::new(i))
.collect::<Vec<_>>();
idxs.into_iter()
.map(|memidx| self.get_exported_memory(memidx))
}

/// Get the globals defined in this instance
pub fn defined_globals<'a>(
&'a mut self,
) -> impl ExactSizeIterator<Item = (DefinedGlobalIndex, ExportGlobal)> + 'a {
self.instance_mut().defined_globals()
}

/// Return a reference to the contained `Instance`.
#[inline]
pub(crate) fn instance(&self) -> &Instance {
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmtime/src/coredump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub struct WasmCoreDump {
}

impl WasmCoreDump {
pub(crate) fn new(store: &StoreOpaque, backtrace: WasmBacktrace) -> WasmCoreDump {
pub(crate) fn new(store: &mut StoreOpaque, backtrace: WasmBacktrace) -> WasmCoreDump {
let modules: Vec<_> = store.modules().all_modules().cloned().collect();
let instances: Vec<Instance> = store.all_instances().collect();
let store_memories: Vec<Memory> = store.all_memories().collect();
Expand Down
9 changes: 9 additions & 0 deletions crates/wasmtime/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ pub(crate) struct InstanceData {
exports: Vec<Option<Extern>>,
}

impl InstanceData {
pub fn from_index(idx: usize) -> InstanceData {
InstanceData {
id: InstanceId::from_index(idx),
exports: vec![],
}
}
}

impl Instance {
/// Creates a new [`Instance`] from the previously compiled [`Module`] and
/// list of `imports` specified.
Expand Down
69 changes: 54 additions & 15 deletions crates/wasmtime/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ use std::sync::atomic::AtomicU64;
use std::sync::Arc;
use std::task::{Context, Poll};
use wasmtime_runtime::{
ExportGlobal, ExportMemory, InstanceAllocationRequest, InstanceAllocator, InstanceHandle,
ModuleInfo, OnDemandInstanceAllocator, SignalHandler, StoreBox, StorePtr, VMContext,
VMExternRef, VMExternRefActivationsTable, VMFuncRef, VMRuntimeLimits, WasmFault,
ExportGlobal, InstanceAllocationRequest, InstanceAllocator, InstanceHandle, ModuleInfo,
OnDemandInstanceAllocator, SignalHandler, StoreBox, StorePtr, VMContext, VMExternRef,
VMExternRefActivationsTable, VMFuncRef, VMRuntimeLimits, WasmFault,
};

mod context;
Expand Down Expand Up @@ -1263,22 +1263,61 @@ impl StoreOpaque {
&mut self.instances[id.0].handle
}

pub fn all_instances(&self) -> impl ExactSizeIterator<Item = Instance> {
self.store_data()
.iter::<InstanceData>()
.map(Instance::from_stored)
pub fn all_instances<'a>(&'a mut self) -> impl ExactSizeIterator<Item = Instance> + 'a {
let instances = self
.instances
.iter()
.enumerate()
.map(|(idx, _)| InstanceData::from_index(idx))
.collect::<Vec<_>>();
instances
.into_iter()
.map(|i| Instance::from_wasmtime(i, self))
}

pub fn all_memories(&self) -> impl ExactSizeIterator<Item = Memory> {
self.store_data()
.iter::<ExportMemory>()
.map(Memory::from_stored)
pub fn all_memories<'a>(&'a mut self) -> impl Iterator<Item = Memory> + 'a {
unsafe {
let mems = self
.instances
.iter_mut()
.flat_map(|instance| instance.handle.defined_memories())
.collect::<Vec<_>>();
mems.into_iter()
.map(|memory| Memory::from_wasmtime_memory(memory, self))
}
}

pub fn all_globals(&self) -> impl ExactSizeIterator<Item = Global> {
self.store_data()
.iter::<ExportGlobal>()
.map(Global::from_stored)
// TODO: have this (and the above methods) put these into a hashset and dedupe them
// (from_wasmtime_global inserts duplicates into the store, so dedupe here)
pub fn all_globals<'a>(&'a mut self) -> impl Iterator<Item = Global> + 'a {
unsafe {
// host globals first
let host_globals = self
.host_globals()
.iter()
.map(|global| ExportGlobal {
definition: &mut (*global.get()).global as *mut _,
global: (*global.get()).ty.to_wasm_type(),
})
.collect::<Vec<_>>();

let host_globals = host_globals
.into_iter()
.map(|g| Global::from_wasmtime_global(g, self))
.collect::<Vec<_>>();

// then go through all the instances and emit their globals
let globals = self
.instances
.iter_mut()
.flat_map(|instance| instance.handle.defined_globals())
.collect::<Vec<_>>();
host_globals.into_iter().chain(
globals
.into_iter()
.map(|(_, global)| Global::from_wasmtime_global(global, self)),
)
}
}

#[cfg_attr(not(target_os = "linux"), allow(dead_code))] // not used on all platforms
Expand Down
6 changes: 6 additions & 0 deletions crates/wasmtime/src/store/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ use std::sync::atomic::{AtomicU64, Ordering::Relaxed};
#[derive(Copy, Clone)]
pub struct InstanceId(pub(super) usize);

impl InstanceId {
pub fn from_index(idx: usize) -> InstanceId {
InstanceId(idx)
}
}

pub struct StoreData {
id: StoreId,
funcs: Vec<crate::func::FuncData>,
Expand Down
4 changes: 2 additions & 2 deletions crates/wasmtime/src/trampoline/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use wasmtime_runtime::{StoreBox, VMGlobalDefinition};

#[repr(C)]
pub struct VMHostGlobalContext {
ty: GlobalType,
global: VMGlobalDefinition,
pub(crate) ty: GlobalType,
pub(crate) global: VMGlobalDefinition,
}

impl Drop for VMHostGlobalContext {
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmtime/src/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub(crate) unsafe fn raise(error: anyhow::Error) -> ! {

#[cold] // traps are exceptional, this helps move handling off the main path
pub(crate) fn from_runtime_box(
store: &StoreOpaque,
store: &mut StoreOpaque,
runtime_trap: Box<wasmtime_runtime::Trap>,
) -> Error {
let wasmtime_runtime::Trap {
Expand Down
9 changes: 9 additions & 0 deletions crates/wasmtime/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,15 @@ impl GlobalType {
self.mutability
}

pub(crate) fn to_wasm_type(&self) -> Global {
let wasm_ty = self.content().to_wasm_type();
let mutability = matches!(self.mutability(), Mutability::Var);
Global {
wasm_ty,
mutability,
}
}

/// Returns `None` if the wasmtime global has a type that we can't
/// represent, but that should only very rarely happen and indicate a bug.
pub(crate) fn from_wasmtime_global(global: &Global) -> GlobalType {
Expand Down

0 comments on commit 04df873

Please sign in to comment.