Moved FrameInfo into wasmer types

This commit is contained in:
Syrus Akbary
2023-04-21 12:46:35 -07:00
parent 74fe894c07
commit a19ffa2769
16 changed files with 143 additions and 125 deletions

View File

@ -3,6 +3,7 @@ use std::fmt;
use std::sync::Arc; use std::sync::Arc;
use wasm_bindgen::{prelude::*, JsValue}; use wasm_bindgen::{prelude::*, JsValue};
use wasm_bindgen_downcast::DowncastJS; use wasm_bindgen_downcast::DowncastJS;
use wasmer_types::FrameInfo;
pub trait CoreError: fmt::Debug + fmt::Display { pub trait CoreError: fmt::Debug + fmt::Display {
fn source(&self) -> Option<&(dyn CoreError + 'static)> { fn source(&self) -> Option<&(dyn CoreError + 'static)> {
@ -169,6 +170,13 @@ impl RuntimeError {
wasm_bindgen::throw_val(js_error) wasm_bindgen::throw_val(js_error)
} }
/// Returns a list of function frames in WebAssembly code that led to this
/// trap happening.
pub fn trace(&self) -> &[FrameInfo] {
// unimplemented!();
return &[];
}
/// Creates a custom user Error. /// Creates a custom user Error.
/// ///
/// This error object can be passed through Wasm frames and later retrieved /// This error object can be passed through Wasm frames and later retrieved

View File

@ -470,10 +470,10 @@ pub use wasmer_derive::ValueType;
// TODO: OnCalledAction is needed for asyncify. It will be refactored with https://github.com/wasmerio/wasmer/issues/3451 // TODO: OnCalledAction is needed for asyncify. It will be refactored with https://github.com/wasmerio/wasmer/issues/3451
pub use wasmer_types::{ pub use wasmer_types::{
is_wasm, Bytes, CompileError, CpuFeature, DeserializeError, ExportIndex, ExportType, is_wasm, Bytes, CompileError, CpuFeature, DeserializeError, ExportIndex, ExportType,
ExternType, FunctionType, GlobalInit, GlobalType, ImportType, LocalFunctionIndex, MemoryError, ExternType, FrameInfo, FunctionType, GlobalInit, GlobalType, ImportType, LocalFunctionIndex,
MemoryType, MiddlewareError, Mutability, OnCalledAction, Pages, ParseCpuFeatureError, MemoryError, MemoryType, MiddlewareError, Mutability, OnCalledAction, Pages,
SerializeError, TableType, Target, Type, ValueType, WasmError, WasmResult, WASM_MAX_PAGES, ParseCpuFeatureError, SerializeError, TableType, Target, Type, ValueType, WasmError,
WASM_MIN_PAGES, WASM_PAGE_SIZE, WasmResult, WASM_MAX_PAGES, WASM_MIN_PAGES, WASM_PAGE_SIZE,
}; };
#[cfg(feature = "wat")] #[cfg(feature = "wat")]
pub use wat::parse_bytes as wat2wasm; pub use wat::parse_bytes as wat2wasm;

View File

@ -14,7 +14,7 @@ pub use target_lexicon::{Architecture, CallingConvention, OperatingSystem, Tripl
pub use wasmer_compiler::{ pub use wasmer_compiler::{
wasmparser, CompilerConfig, FunctionMiddleware, MiddlewareReaderState, ModuleMiddleware, wasmparser, CompilerConfig, FunctionMiddleware, MiddlewareReaderState, ModuleMiddleware,
}; };
pub use wasmer_compiler::{Artifact, EngineBuilder, Features, FrameInfo, Tunables}; pub use wasmer_compiler::{Artifact, EngineBuilder, Features, Tunables};
#[cfg(feature = "cranelift")] #[cfg(feature = "cranelift")]
pub use wasmer_compiler_cranelift::{Cranelift, CraneliftOptLevel}; pub use wasmer_compiler_cranelift::{Cranelift, CraneliftOptLevel};
#[cfg(feature = "llvm")] #[cfg(feature = "llvm")]

View File

@ -254,7 +254,7 @@ fn test_run() {
println!("outputting batch to {}", path.display()); println!("outputting batch to {}", path.display());
std::fs::write(&path, vcvars_modified).unwrap(); std::fs::write(&path, vcvars_modified).unwrap();
print_wasmer_root_to_stdout(&config); // print_wasmer_root_to_stdout(&config);
let mut vcvars = std::process::Command::new("cmd"); let mut vcvars = std::process::Command::new("cmd");
vcvars.arg("/C"); vcvars.arg("/C");
@ -270,7 +270,7 @@ fn test_run() {
if !output.status.success() { if !output.status.success() {
println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
println!("stdout: {}", String::from_utf8_lossy(&output.stderr)); println!("stdout: {}", String::from_utf8_lossy(&output.stderr));
print_wasmer_root_to_stdout(&config); // print_wasmer_root_to_stdout(&config);
panic!("failed to compile {test}"); panic!("failed to compile {test}");
} }
@ -296,7 +296,7 @@ fn test_run() {
println!("{output:#?}"); println!("{output:#?}");
println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
print_wasmer_root_to_stdout(&config); // print_wasmer_root_to_stdout(&config);
panic!("failed to execute {test}"); panic!("failed to execute {test}");
} }
} else { } else {
@ -353,7 +353,7 @@ fn test_run() {
if !output.status.success() { if !output.status.success() {
println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
print_wasmer_root_to_stdout(&config); // print_wasmer_root_to_stdout(&config);
panic!("failed to compile {test}: {command:#?}"); panic!("failed to compile {test}: {command:#?}");
} }
@ -368,7 +368,7 @@ fn test_run() {
if !output.status.success() { if !output.status.success() {
println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
println!("stdout: {}", String::from_utf8_lossy(&output.stderr)); println!("stdout: {}", String::from_utf8_lossy(&output.stderr));
print_wasmer_root_to_stdout(&config); // print_wasmer_root_to_stdout(&config);
panic!("failed to execute {test} executable"); panic!("failed to execute {test} executable");
} }
} }

View File

@ -161,7 +161,7 @@ fn test_ok() {
println!(); println!();
println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
print_wasmer_root_to_stdout(&config); // print_wasmer_root_to_stdout(&config);
panic!("failed to invoke vcvars64.bat {test}"); panic!("failed to invoke vcvars64.bat {test}");
} }
@ -203,7 +203,7 @@ fn test_ok() {
println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
println!("output: {:#?}", output); println!("output: {:#?}", output);
print_wasmer_root_to_stdout(&config); // print_wasmer_root_to_stdout(&config);
panic!("failed to compile {test}"); panic!("failed to compile {test}");
} }
@ -225,7 +225,7 @@ fn test_ok() {
println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
println!("output: {:#?}", output); println!("output: {:#?}", output);
print_wasmer_root_to_stdout(&config); // print_wasmer_root_to_stdout(&config);
panic!("failed to execute {test}"); panic!("failed to execute {test}");
} }
@ -275,7 +275,7 @@ fn test_ok() {
command.arg("-o"); command.arg("-o");
command.arg(&format!("{manifest_dir}/../{test}")); command.arg(&format!("{manifest_dir}/../{test}"));
print_wasmer_root_to_stdout(&config); // print_wasmer_root_to_stdout(&config);
println!("compile: {command:#?}"); println!("compile: {command:#?}");
// compile // compile
@ -288,7 +288,7 @@ fn test_ok() {
if !output.status.success() { if !output.status.success() {
println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
print_wasmer_root_to_stdout(&config); // print_wasmer_root_to_stdout(&config);
panic!("failed to compile {test}: {command:#?}"); panic!("failed to compile {test}: {command:#?}");
} }
@ -303,7 +303,7 @@ fn test_ok() {
if !output.status.success() { if !output.status.success() {
println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
print_wasmer_root_to_stdout(&config); // print_wasmer_root_to_stdout(&config);
panic!("failed to execute {test}: {command:#?}"); panic!("failed to execute {test}: {command:#?}");
} }
} }

View File

@ -1,8 +1,9 @@
use super::frame_info::{FrameInfo, GlobalFrameInfo, FRAME_INFO}; use super::frame_info::{GlobalFrameInfo, FRAME_INFO};
use backtrace::Backtrace; use backtrace::Backtrace;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::sync::Arc; use std::sync::Arc;
use wasmer_types::FrameInfo;
use wasmer_vm::{Trap, TrapCode}; use wasmer_vm::{Trap, TrapCode};
/// A struct representing an aborted instruction execution, with a message /// A struct representing an aborted instruction execution, with a message
@ -44,8 +45,6 @@ struct RuntimeErrorInner {
source: RuntimeErrorSource, source: RuntimeErrorSource,
/// The reconstructed Wasm trace (from the native trace and the `GlobalFrameInfo`). /// The reconstructed Wasm trace (from the native trace and the `GlobalFrameInfo`).
wasm_trace: Vec<FrameInfo>, wasm_trace: Vec<FrameInfo>,
/// The native backtrace
native_trace: Option<Backtrace>,
} }
fn _assert_trap_is_sync_and_send(t: &Trap) -> (&dyn Sync, &dyn Send) { fn _assert_trap_is_sync_and_send(t: &Trap) -> (&dyn Sync, &dyn Send) {
@ -191,7 +190,6 @@ impl RuntimeError {
inner: Arc::new(RuntimeErrorInner { inner: Arc::new(RuntimeErrorInner {
source, source,
wasm_trace, wasm_trace,
native_trace: Some(native_trace),
}), }),
} }
} }
@ -257,7 +255,6 @@ impl fmt::Debug for RuntimeError {
f.debug_struct("RuntimeError") f.debug_struct("RuntimeError")
.field("source", &self.inner.source) .field("source", &self.inner.source)
.field("wasm_trace", &self.inner.wasm_trace) .field("wasm_trace", &self.inner.wasm_trace)
.field("native_trace", &self.inner.native_trace)
.finish() .finish()
} }
} }

View File

@ -15,8 +15,9 @@ use std::cmp;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use wasmer_types::entity::{BoxedSlice, EntityRef, PrimaryMap}; use wasmer_types::entity::{BoxedSlice, EntityRef, PrimaryMap};
use wasmer_types::{CompiledFunctionFrameInfo, SourceLoc, TrapInformation}; use wasmer_types::{
use wasmer_types::{LocalFunctionIndex, ModuleInfo}; CompiledFunctionFrameInfo, FrameInfo, LocalFunctionIndex, ModuleInfo, TrapInformation,
};
use wasmer_vm::FunctionBodyPtr; use wasmer_vm::FunctionBodyPtr;
lazy_static::lazy_static! { lazy_static::lazy_static! {
@ -240,97 +241,3 @@ pub fn register(
assert!(prev.is_none()); assert!(prev.is_none());
Some(GlobalFrameInfoRegistration { key: max }) Some(GlobalFrameInfoRegistration { key: max })
} }
/// Description of a frame in a backtrace for a [`RuntimeError::trace`](crate::RuntimeError::trace).
///
/// Whenever a WebAssembly trap occurs an instance of [`RuntimeError`]
/// is created. Each [`RuntimeError`] has a backtrace of the
/// WebAssembly frames that led to the trap, and each frame is
/// described by this structure.
///
/// [`RuntimeError`]: crate::RuntimeError
#[derive(Debug, Clone)]
pub struct FrameInfo {
module_name: String,
func_index: u32,
function_name: Option<String>,
func_start: SourceLoc,
instr: SourceLoc,
}
impl FrameInfo {
/// Creates a new [FrameInfo], useful for testing.
pub fn new(
module_name: String,
func_index: u32,
function_name: Option<String>,
func_start: SourceLoc,
instr: SourceLoc,
) -> Self {
Self {
module_name,
func_index,
function_name,
func_start,
instr,
}
}
/// Returns the WebAssembly function index for this frame.
///
/// This function index is the index in the function index space of the
/// WebAssembly module that this frame comes from.
pub fn func_index(&self) -> u32 {
self.func_index
}
/// Returns the identifer of the module that this frame is for.
///
/// ModuleInfo identifiers are present in the `name` section of a WebAssembly
/// binary, but this may not return the exact item in the `name` section.
/// ModuleInfo names can be overwritten at construction time or perhaps inferred
/// from file names. The primary purpose of this function is to assist in
/// debugging and therefore may be tweaked over time.
///
/// This function returns `None` when no name can be found or inferred.
pub fn module_name(&self) -> &str {
&self.module_name
}
/// Returns a descriptive name of the function for this frame, if one is
/// available.
///
/// The name of this function may come from the `name` section of the
/// WebAssembly binary, or wasmer may try to infer a better name for it if
/// not available, for example the name of the export if it's exported.
///
/// This return value is primarily used for debugging and human-readable
/// purposes for things like traps. Note that the exact return value may be
/// tweaked over time here and isn't guaranteed to be something in
/// particular about a wasm module due to its primary purpose of assisting
/// in debugging.
///
/// This function returns `None` when no name could be inferred.
pub fn function_name(&self) -> Option<&str> {
self.function_name.as_deref()
}
/// Returns the offset within the original wasm module this frame's program
/// counter was at.
///
/// The offset here is the offset from the beginning of the original wasm
/// module to the instruction that this frame points to.
pub fn module_offset(&self) -> usize {
self.instr.bits() as usize
}
/// Returns the offset from the original wasm module's function to this
/// frame's program counter.
///
/// The offset here is the offset from the beginning of the defining
/// function of this frame (within the wasm module) to the instruction this
/// frame points to.
pub fn func_offset(&self) -> usize {
(self.instr.bits() - self.func_start.bits()) as usize
}
}

View File

@ -2,6 +2,5 @@ mod error;
mod frame_info; mod frame_info;
pub use error::RuntimeError; pub use error::RuntimeError;
pub use frame_info::{ pub use frame_info::{
register as register_frame_info, FrameInfo, FunctionExtent, GlobalFrameInfoRegistration, register as register_frame_info, FunctionExtent, GlobalFrameInfoRegistration, FRAME_INFO,
FRAME_INFO,
}; };

View File

@ -1,8 +1,8 @@
//! Data structures to provide transformation of the source //! Data structures to provide transformation of the source
// addresses of a WebAssembly module into the native code. // addresses of a WebAssembly module into the native code.
use super::sourceloc::SourceLoc;
use crate::lib::std::vec::Vec; use crate::lib::std::vec::Vec;
use crate::SourceLoc;
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
#[cfg(feature = "enable-serde")] #[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View File

@ -4,9 +4,9 @@
//! A `Compilation` contains the compiled function bodies for a WebAssembly //! A `Compilation` contains the compiled function bodies for a WebAssembly
//! module (`CompiledFunction`). //! module (`CompiledFunction`).
use super::trap::TrapInformation;
use crate::entity::PrimaryMap; use crate::entity::PrimaryMap;
use crate::lib::std::vec::Vec; use crate::lib::std::vec::Vec;
use crate::TrapInformation;
use crate::{CompiledFunctionUnwindInfo, FunctionAddressMap}; use crate::{CompiledFunctionUnwindInfo, FunctionAddressMap};
use crate::{ use crate::{
CustomSection, FunctionIndex, LocalFunctionIndex, Relocation, SectionIndex, SignatureIndex, CustomSection, FunctionIndex, LocalFunctionIndex, Relocation, SectionIndex, SignatureIndex,

View File

@ -5,8 +5,6 @@ pub mod function;
pub mod module; pub mod module;
pub mod relocation; pub mod relocation;
pub mod section; pub mod section;
pub mod sourceloc;
pub mod symbols; pub mod symbols;
pub mod target; pub mod target;
pub mod trap;
pub mod unwind; pub mod unwind;

View File

@ -62,6 +62,7 @@ mod libcalls;
mod memory; mod memory;
mod module; mod module;
mod serialize; mod serialize;
mod stack;
mod store_id; mod store_id;
mod table; mod table;
mod trapcode; mod trapcode;
@ -125,11 +126,10 @@ pub use crate::compilation::function::{
Functions, Functions,
}; };
pub use crate::compilation::module::CompileModuleInfo; pub use crate::compilation::module::CompileModuleInfo;
pub use crate::compilation::sourceloc::SourceLoc;
pub use crate::compilation::symbols::{Symbol, SymbolRegistry}; pub use crate::compilation::symbols::{Symbol, SymbolRegistry};
pub use crate::compilation::trap::TrapInformation;
pub use crate::compilation::unwind::CompiledFunctionUnwindInfo; pub use crate::compilation::unwind::CompiledFunctionUnwindInfo;
pub use crate::stack::{FrameInfo, SourceLoc, TrapInformation};
pub use crate::store_id::StoreId; pub use crate::store_id::StoreId;
/// Offset in bytes from the beginning of the function. /// Offset in bytes from the beginning of the function.

View File

@ -0,0 +1,100 @@
use crate::SourceLoc;
/// Description of a frame in a backtrace for a [`RuntimeError::trace`](crate::RuntimeError::trace).
///
/// Whenever a WebAssembly trap occurs an instance of [`RuntimeError`]
/// is created. Each [`RuntimeError`] has a backtrace of the
/// WebAssembly frames that led to the trap, and each frame is
/// described by this structure.
///
/// [`RuntimeError`]: crate::RuntimeError
#[derive(Debug, Clone)]
pub struct FrameInfo {
/// The name of the module
pub module_name: String,
/// The index of the function in the module
pub func_index: u32,
/// The function name, if one is available.
pub function_name: Option<String>,
/// The source location of the function
pub func_start: SourceLoc,
/// The source location of the instruction
pub instr: SourceLoc,
}
impl FrameInfo {
/// Creates a new [FrameInfo], useful for testing.
pub fn new(
module_name: String,
func_index: u32,
function_name: Option<String>,
func_start: SourceLoc,
instr: SourceLoc,
) -> Self {
Self {
module_name,
func_index,
function_name,
func_start,
instr,
}
}
/// Returns the WebAssembly function index for this frame.
///
/// This function index is the index in the function index space of the
/// WebAssembly module that this frame comes from.
pub fn func_index(&self) -> u32 {
self.func_index
}
/// Returns the identifer of the module that this frame is for.
///
/// ModuleInfo identifiers are present in the `name` section of a WebAssembly
/// binary, but this may not return the exact item in the `name` section.
/// ModuleInfo names can be overwritten at construction time or perhaps inferred
/// from file names. The primary purpose of this function is to assist in
/// debugging and therefore may be tweaked over time.
///
/// This function returns `None` when no name can be found or inferred.
pub fn module_name(&self) -> &str {
&self.module_name
}
/// Returns a descriptive name of the function for this frame, if one is
/// available.
///
/// The name of this function may come from the `name` section of the
/// WebAssembly binary, or wasmer may try to infer a better name for it if
/// not available, for example the name of the export if it's exported.
///
/// This return value is primarily used for debugging and human-readable
/// purposes for things like traps. Note that the exact return value may be
/// tweaked over time here and isn't guaranteed to be something in
/// particular about a wasm module due to its primary purpose of assisting
/// in debugging.
///
/// This function returns `None` when no name could be inferred.
pub fn function_name(&self) -> Option<&str> {
self.function_name.as_deref()
}
/// Returns the offset within the original wasm module this frame's program
/// counter was at.
///
/// The offset here is the offset from the beginning of the original wasm
/// module to the instruction that this frame points to.
pub fn module_offset(&self) -> usize {
self.instr.bits() as usize
}
/// Returns the offset from the original wasm module's function to this
/// frame's program counter.
///
/// The offset here is the offset from the beginning of the defining
/// function of this frame (within the wasm module) to the instruction this
/// frame points to.
pub fn func_offset(&self) -> usize {
(self.instr.bits() - self.func_start.bits()) as usize
}
}

View File

@ -0,0 +1,9 @@
//! Types for the stack tracing / frames.
mod frame;
mod sourceloc;
mod trap;
pub use frame::FrameInfo;
pub use sourceloc::SourceLoc;
pub use trap::TrapInformation;