Skip to content

Commit f4b1a26

Browse files
committed
feat(WasmTracer): Define initial structs for wasm tracing
1 parent a640a92 commit f4b1a26

File tree

6 files changed

+203
-1
lines changed

6 files changed

+203
-1
lines changed

Cargo.lock

Lines changed: 83 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ members = [
1010
"crates/ir",
1111
"crates/fuzz",
1212
"crates/wast",
13-
"fuzz",
13+
"fuzz", "wasm-test", "crates/tracer",
1414
]
1515
exclude = []
1616
resolver = "2"
@@ -39,6 +39,7 @@ wasmi_c_api_impl = { version = "0.44.0", path = "crates/c_api" }
3939
wasmi_c_api_macros = { version = "0.44.0", path = "crates/c_api/macro" }
4040
wasmi_fuzz = { version = "0.44.0", path = "crates/fuzz" }
4141
wasmi_wast = { version = "0.44.0", path = "crates/wast" }
42+
wasmi_tracer = { version = "0.1.0", path = "crates/tracer" }
4243

4344
# wasm-tools dependencies
4445
wat = { version = "1.227.1", default-features = false }

crates/tracer/Cargo.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[package]
2+
name = "wasmi_tracer"
3+
version = "0.1.0"
4+
authors.workspace = true
5+
repository.workspace = true
6+
# version.workspace = true
7+
rust-version.workspace = true
8+
edition.workspace = true
9+
readme.workspace = true
10+
license.workspace = true
11+
keywords.workspace = true
12+
categories.workspace = true
13+
exclude.workspace = true
14+
15+
[dependencies]

crates/tracer/src/lib.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use std::path::{Path, PathBuf};
2+
use std::println;
3+
4+
pub fn add(left: u64, right: u64) -> u64 {
5+
left + right
6+
}
7+
8+
// TODO
9+
#[derive(Debug, Clone)]
10+
struct DebugInfo {
11+
// for now minimal info here
12+
wasm_exe_path: std::path::PathBuf,
13+
// TODO eventually dwarf/gimli stuff, not sure
14+
// TODO: eventually the tracer from runtime_tracer but maybe DebugInfo is just PDO for debug info?A
15+
// maybe there are several kinds, e.g. frame-based, maybe others
16+
// so maybe our fn-s will know how to deal with them
17+
// TODO: local_variables: HashMap<VariableId, DebugLocation>,
18+
}
19+
20+
impl DebugInfo {
21+
fn new(wasm_exe_path: &Path) -> Self {
22+
DebugInfo { wasm_exe_path: PathBuf::from(wasm_exe_path) }
23+
}
24+
}
25+
26+
#[derive(Debug, Clone)]
27+
pub struct WasmTracer {
28+
debug_info: DebugInfo,
29+
// TODO: tracer: runtime_tracing.Tracer,
30+
// etc
31+
}
32+
33+
// just to make it build so we can branch-out
34+
35+
impl WasmTracer {
36+
pub fn new(wasm_exe_path: &Path) -> Self {
37+
WasmTracer {
38+
debug_info: DebugInfo::new(wasm_exe_path),
39+
}
40+
}
41+
42+
pub fn load_local_variables(&mut self, address: usize) { // -> ???
43+
println!("load_local_variables {address}");
44+
// e.g. here we might call something like
45+
// some kind of check if we already have the info for the current context
46+
// let cached = TODO;
47+
let cached = false;
48+
49+
if !cached {
50+
// TODO etc
51+
// load debuginfo etc
52+
}
53+
}
54+
}
55+
56+
// load wasm file
57+
// find out its subprogram and scope for a certain address and somehow
58+
//
59+
// print mapping with expr => relevant location
60+
// x <- 0x000A7321
61+
// ip; (debuginfo address of some code(?))
62+
//
63+
//
64+
65+
#[cfg(test)]
66+
mod tests {
67+
use super::*;
68+
69+
#[test]
70+
fn it_works() {
71+
let result = add(2, 2);
72+
assert_eq!(result, 4);
73+
}
74+
}

crates/wasmi/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,16 @@ exclude = [
1919
]
2020

2121
[dependencies]
22+
23+
# Dwarf utilities
24+
gimli = "0.31.1"
25+
object = { "version" = "0.36.7", "features" = ["elf", "wasm"] }
26+
memmap2 = "0.9.5"
27+
2228
wasmi_core = { workspace = true }
2329
wasmi_collections = { workspace = true }
2430
wasmi_ir = { workspace = true }
31+
wasmi_tracer = { workspace = true }
2532
wasmparser = { workspace = true, features = ["validate", "features"] }
2633
wat = { workspace = true, optional = true }
2734
spin = { version = "0.9", default-features = false, features = [

crates/wasmi/src/engine/executor/instrs.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
pub use self::call::{dispatch_host_func, ResumableHostError};
44
use super::{cache::CachedInstance, InstructionPtr, Stack};
5+
use wasmi_tracer::WasmTracer;
56
use crate::{
67
core::{hint, wasm, ReadAs, TrapCode, UntypedVal, WriteAs},
78
engine::{
@@ -91,6 +92,9 @@ struct Executor<'engine> {
9192
///
9293
/// [`Engine`]: crate::Engine
9394
code_map: &'engine CodeMap,
95+
96+
// debug:
97+
// TODO tracer: &'engine mut WasmTracer,
9498
}
9599

96100
impl<'engine> Executor<'engine> {
@@ -110,12 +114,14 @@ impl<'engine> Executor<'engine> {
110114
// valid for all register indices used by the associated function body.
111115
let sp = unsafe { stack.values.stack_ptr_at(frame.base_offset()) };
112116
let ip = frame.instr_ptr();
117+
113118
Self {
114119
sp,
115120
ip,
116121
cache,
117122
stack,
118123
code_map,
124+
// TODO tracer: &mut tracer, // probably were not gonna make it
119125
}
120126
}
121127

@@ -124,6 +130,22 @@ impl<'engine> Executor<'engine> {
124130
fn execute<T>(mut self, store: &mut Store<T>) -> Result<(), Error> {
125131
use Instruction as Instr;
126132
loop {
133+
// TODO: change that, just startting from somewehre
134+
// Args: path : Path, instruction address(?) , step?
135+
// TODO: good way to take address
136+
//let address = usize::from(self.ip.get());
137+
let address = 0x000000010; // should be in the main subprogram >= low_pc
138+
//std::println!("address of {:?}: {:?}", *self.ip.get(), address);
139+
// TODO: make this be a field with correct lifetime
140+
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");
141+
tracer.load_local_variables(address);
142+
143+
// load debuginfo from gimli <- for this ip;
144+
// -> find out current scope and vars in it:
145+
// some kind of mapping between them and locations
146+
// -> load them with some general(for us) mechanism from wasmi's memory(?)
147+
// e.g. load_expression(expr, location, ..) -> ValueRecord
148+
// (to be iterated on, just an idea)
127149
match *self.ip.get() {
128150
Instr::Trap { trap_code } => self.execute_trap(trap_code)?,
129151
Instr::ConsumeFuel { block_fuel } => {

0 commit comments

Comments
 (0)