Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# shellcheck shell=bash
if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
fi

dotenv_if_exists

# watch_file "$(find ./nix -name "*.nix" -type f)"

OS_AND_SYSTEM=$(uname -a)

if [[ "${NO_NIX:-}" == "1" || $OS_AND_SYSTEM == "Darwin"* ]]; then
source non-nix-build/env.sh
else
use flake
fi
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ spec/target
**/fuzz/artifacts/
**/fuzz/crash-inputs/
**/fuzz/Cargo.lock

*.wasm
.direnv/
79 changes: 79 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ members = [
"crates/ir",
"crates/fuzz",
"crates/wast",
"fuzz",
"fuzz", "crates/tracer",
# "wasm-test",
]
exclude = []
resolver = "2"
Expand Down Expand Up @@ -39,6 +40,7 @@ wasmi_c_api_impl = { version = "0.44.0", path = "crates/c_api" }
wasmi_c_api_macros = { version = "0.44.0", path = "crates/c_api/macro" }
wasmi_fuzz = { version = "0.44.0", path = "crates/fuzz" }
wasmi_wast = { version = "0.44.0", path = "crates/wast" }
wasmi_tracer = { version = "0.1.0", path = "crates/tracer" }

# wasm-tools dependencies
wat = { version = "1.227.1", default-features = false }
Expand Down
15 changes: 15 additions & 0 deletions crates/tracer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "wasmi_tracer"
version = "0.1.0"
authors.workspace = true
repository.workspace = true
# version.workspace = true
rust-version.workspace = true
edition.workspace = true
readme.workspace = true
license.workspace = true
keywords.workspace = true
categories.workspace = true
exclude.workspace = true

[dependencies]
74 changes: 74 additions & 0 deletions crates/tracer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use std::path::{Path, PathBuf};
use std::println;

pub fn add(left: u64, right: u64) -> u64 {
left + right
}

// TODO
#[derive(Debug, Clone)]
struct DebugInfo {
// for now minimal info here
wasm_exe_path: std::path::PathBuf,
// TODO eventually dwarf/gimli stuff, not sure
// TODO: eventually the tracer from runtime_tracer but maybe DebugInfo is just PDO for debug info?A
// maybe there are several kinds, e.g. frame-based, maybe others
// so maybe our fn-s will know how to deal with them
// TODO: local_variables: HashMap<VariableId, DebugLocation>,
}

impl DebugInfo {
fn new(wasm_exe_path: &Path) -> Self {
DebugInfo { wasm_exe_path: PathBuf::from(wasm_exe_path) }
}
}

#[derive(Debug, Clone)]
pub struct WasmTracer {
debug_info: DebugInfo,
// TODO: tracer: runtime_tracing.Tracer,
// etc
}

// just to make it build so we can branch-out

impl WasmTracer {
pub fn new(wasm_exe_path: &Path) -> Self {
WasmTracer {
debug_info: DebugInfo::new(wasm_exe_path),
}
}

pub fn load_local_variables(&mut self, address: usize) { // -> ???
println!("load_local_variables {address}");
// e.g. here we might call something like
// some kind of check if we already have the info for the current context
// let cached = TODO;
let cached = false;

if !cached {
// TODO etc
// load debuginfo etc
}
}
}

// load wasm file
// find out its subprogram and scope for a certain address and somehow
//
// print mapping with expr => relevant location
// x <- 0x000A7321
// ip; (debuginfo address of some code(?))
//
//

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}
7 changes: 7 additions & 0 deletions crates/wasmi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,16 @@ exclude = [
]

[dependencies]

# Dwarf utilities
gimli = "0.31.1"
object = { "version" = "0.36.7", "features" = ["elf", "wasm"] }
memmap2 = "0.9.5"

wasmi_core = { workspace = true }
wasmi_collections = { workspace = true }
wasmi_ir = { workspace = true }
wasmi_tracer = { workspace = true }
wasmparser = { workspace = true, features = ["validate", "features"] }
wat = { workspace = true, optional = true }
spin = { version = "0.9", default-features = false, features = [
Expand Down
22 changes: 22 additions & 0 deletions crates/wasmi/src/engine/executor/instrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

pub use self::call::{dispatch_host_func, ResumableHostError};
use super::{cache::CachedInstance, InstructionPtr, Stack};
use wasmi_tracer::WasmTracer;
use crate::{
core::{hint, wasm, ReadAs, TrapCode, UntypedVal, WriteAs},
engine::{
Expand Down Expand Up @@ -91,6 +92,9 @@ struct Executor<'engine> {
///
/// [`Engine`]: crate::Engine
code_map: &'engine CodeMap,

// debug:
// TODO tracer: &'engine mut WasmTracer,
}

impl<'engine> Executor<'engine> {
Expand All @@ -110,12 +114,14 @@ impl<'engine> Executor<'engine> {
// valid for all register indices used by the associated function body.
let sp = unsafe { stack.values.stack_ptr_at(frame.base_offset()) };
let ip = frame.instr_ptr();

Self {
sp,
ip,
cache,
stack,
code_map,
// TODO tracer: &mut tracer, // probably were not gonna make it
}
}

Expand All @@ -124,6 +130,22 @@ impl<'engine> Executor<'engine> {
fn execute<T>(mut self, store: &mut Store<T>) -> Result<(), Error> {
use Instruction as Instr;
loop {
// TODO: change that, just startting from somewehre
// Args: path : Path, instruction address(?) , step?
// TODO: good way to take address
//let address = usize::from(self.ip.get());
let address = 0x000000010; // should be in the main subprogram >= low_pc
//std::println!("address of {:?}: {:?}", *self.ip.get(), address);
// TODO: make this be a field with correct lifetime
let mut tracer = WasmTracer::new(std::path::Path::new("/home/pesho/code/codetracer-wasmi-recorder/wasm_test.wasm")); // "<path to test.wasm>: for now hardcoded TODO pass");
tracer.load_local_variables(address);

// load debuginfo from gimli <- for this ip;
// -> find out current scope and vars in it:
// some kind of mapping between them and locations
// -> load them with some general(for us) mechanism from wasmi's memory(?)
// e.g. load_expression(expr, location, ..) -> ValueRecord
// (to be iterated on, just an idea)
match *self.ip.get() {
Instr::Trap { trap_code } => self.execute_trap(trap_code)?,
Instr::ConsumeFuel { block_fuel } => {
Expand Down
Loading