Skip to content

Commit

Permalink
Add frame select command
Browse files Browse the repository at this point in the history
  • Loading branch information
kateinoigakukun committed Nov 22, 2023
1 parent b1d7c09 commit f12accd
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 28 deletions.
5 changes: 3 additions & 2 deletions crates/debugger/src/commands/debugger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ pub trait Debugger {
fn store(&self) -> Result<&Store>;
fn set_breakpoint(&mut self, breakpoint: Breakpoint);
fn stack_values(&self) -> Vec<WasmValue>;
fn instructions(&self) -> Result<(&[Instruction], usize)>;
fn selected_instructions(&self) -> Result<(&[Instruction], usize)>;
fn step(&self, style: StepStyle) -> Result<Signal>;
fn process(&self) -> Result<RunResult>;
fn process(&mut self) -> Result<RunResult>;
fn select_frame(&mut self, frame_index: Option<usize>) -> Result<()>;
}
2 changes: 1 addition & 1 deletion crates/debugger/src/commands/disassemble.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub fn display_asm<D: Debugger>(
count: Option<usize>,
pc_rel: bool,
) -> Result<()> {
let (insts, inst_index) = debugger.instructions()?;
let (insts, inst_index) = debugger.selected_instructions()?;
let begin = if pc_rel { inst_index } else { 0 };
let end = if let Some(count) = count {
begin + count
Expand Down
2 changes: 1 addition & 1 deletion crates/debugger/src/commands/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl<D: Debugger> Command<D> for ExpressionCommand {
args: Vec<&str>,
) -> Result<Option<CommandResult>> {
let opts = Opts::from_iter_safe(args)?;
let (insts, next_index) = debugger.instructions()?;
let (insts, next_index) = debugger.selected_instructions()?;
let current_index = if next_index == 0 { 0 } else { next_index - 1 };
let current_inst = insts[current_index].clone();
let locals = debugger.locals();
Expand Down
11 changes: 10 additions & 1 deletion crates/debugger/src/commands/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ impl FrameCommand {
enum Opts {
#[structopt(name = "variable")]
Variable,
#[structopt(name = "select")]
Select {
#[structopt(name = "index")]
frame_index: usize,
},
}

impl<D: Debugger> Command<D> for FrameCommand {
Expand All @@ -36,7 +41,7 @@ impl<D: Debugger> Command<D> for FrameCommand {
let opts = Opts::from_iter_safe(args)?;
match opts {
Opts::Variable => {
let (insts, next_index) = debugger.instructions()?;
let (insts, next_index) = debugger.selected_instructions()?;
let current_index = if next_index == 0 { 0 } else { next_index - 1 };
let current_inst = insts[current_index].clone();
let variable_names = context.subroutine.variable_name_list(current_inst.offset)?;
Expand All @@ -46,6 +51,10 @@ impl<D: Debugger> Command<D> for FrameCommand {
}
Ok(None)
}
Opts::Select { frame_index } => {
debugger.select_frame(Some(frame_index))?;
Ok(None)
}
}
}
}
2 changes: 1 addition & 1 deletion crates/debugger/src/commands/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl<D: Debugger> Command<D> for ListCommand {
}

pub fn next_line_info<D: Debugger>(debugger: &D, sourcemap: &dyn SourceMap) -> Result<LineInfo> {
let (insts, next_index) = debugger.instructions()?;
let (insts, next_index) = debugger.selected_instructions()?;
match sourcemap.find_line_info(insts[next_index].offset) {
Some(info) => Ok(info),
None => Err(anyhow!("Source info not found")),
Expand Down
6 changes: 5 additions & 1 deletion crates/debugger/src/commands/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ impl<D: Debugger> Command<D> for LocalCommand {
}
}
Opts::Read { index: Some(index) } => {
let output = format!("{:?}", debugger.locals()[index]);
let locals = debugger.locals();
if index >= locals.len() {
return Err(anyhow::anyhow!("{:?} is out of range, locals length is {:?}", index, locals.len()));
}
let output = format!("{:?}", locals[index]);
context.printer.println(&output);
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/debugger/src/commands/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl<D: Debugger> Command<D> for ThreadCommand {
Opts::Info => {
let frames = debugger.frame();
let frame_name = frames.last().unwrap();
let (insts, next_index) = debugger.instructions()?;
let (insts, next_index) = debugger.selected_instructions()?;
let current_index = if next_index == 0 { 0 } else { next_index - 1 };
let current_inst = insts[current_index].clone();
let code_offset = current_inst.offset;
Expand Down
61 changes: 43 additions & 18 deletions crates/debugger/src/debugger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub struct MainDebugger {
config: wasminspect_vm::Config,
breakpoints: Breakpoints,
is_interrupted: Arc<AtomicBool>,
selected_frame: Option<usize>,
}

#[derive(Default)]
Expand Down Expand Up @@ -89,6 +90,7 @@ impl MainDebugger {
is_interrupted,
preopen_dirs,
envs,
selected_frame: None,
})
}

Expand Down Expand Up @@ -182,6 +184,25 @@ impl MainDebugger {
}
}
}

fn selected_frame(&self) -> Result<ProgramCounter> {
let executor = self.executor()?;
let executor = executor.borrow();
if let Some(frame_index) = self.selected_frame {
if frame_index != 0 {
let frame = executor.stack.frame_at(frame_index - 1).map_err(|_| {
anyhow!("Frame index {} is out of range", frame_index - 1)
})?;
match frame.ret_pc {
Some(pc) => return Ok(pc),
None => {
return Err(anyhow!("No return address, maybe main or host function?"));
}
};
}
}
Ok(executor.pc)
}
}

impl debugger::Debugger for MainDebugger {
Expand All @@ -191,11 +212,18 @@ impl debugger::Debugger for MainDebugger {
fn set_opts(&mut self, opts: DebuggerOpts) {
self.opts = opts
}
fn instructions(&self) -> Result<(&[Instruction], usize)> {
let executor = self.executor()?;
let executor = executor.borrow();
let insts = executor.current_func_insts(self.store()?)?;
Ok((insts, executor.pc.inst_index().0 as usize))

fn select_frame(&mut self, frame_index: Option<usize>) -> Result<()> {
self.selected_frame = frame_index;
Ok(())
}

fn selected_instructions(&self) -> Result<(&[Instruction], usize)> {
let pc = self.selected_frame()?;
let func = self.store()?.func_global(pc.exec_addr());
let func = func.defined().ok_or(anyhow!("Function not found"))?;
let insts = func.instructions();
Ok((insts, pc.inst_index().0 as usize))
}

fn set_breakpoint(&mut self, breakpoint: debugger::Breakpoint) {
Expand Down Expand Up @@ -224,26 +252,22 @@ impl debugger::Debugger for MainDebugger {
fn locals(&self) -> Vec<WasmValue> {
if let Ok(ref executor) = self.executor() {
let executor = executor.borrow();
executor.stack.current_frame().unwrap().locals.clone()
} else {
Vec::new()
let frame_index = self.selected_frame.unwrap_or(0);
if let Ok(frame) = executor.stack.frame_at(frame_index) {
return frame.locals.clone()
}
}
vec![]
}
fn current_frame(&self) -> Option<debugger::FunctionFrame> {
let executor = if let Ok(executor) = self.executor() {
executor
} else {
return None;
};
let executor = executor.borrow();
let frame = executor.stack.current_frame().unwrap();
let frame = self.selected_frame().ok()?;
let func = match self.store() {
Ok(store) => store.func_global(frame.exec_addr),
Ok(store) => store.func_global(frame.exec_addr()),
Err(_) => return None,
};

Some(debugger::FunctionFrame {
module_index: frame.module_index,
module_index: frame.module_index(),
argument_count: func.ty().params().len(),
})
}
Expand Down Expand Up @@ -328,7 +352,8 @@ impl debugger::Debugger for MainDebugger {
}
}

fn process(&self) -> Result<RunResult> {
fn process(&mut self) -> Result<RunResult> {
self.selected_frame = None;
let store = self.store()?;
let executor = self.executor()?;
loop {
Expand Down
2 changes: 1 addition & 1 deletion crates/vm/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ impl Executor {
Ok(results.into_iter().rev().collect())
}

pub fn current_func_insts<'a>(&self, store: &'a Store) -> ExecResult<&'a [Instruction]> {
fn current_func_insts<'a>(&self, store: &'a Store) -> ExecResult<&'a [Instruction]> {
let func = store.func_global(self.pc.exec_addr());
Ok(func.defined().unwrap().instructions())
}
Expand Down
2 changes: 1 addition & 1 deletion crates/vm/src/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl DefinedFunctionInstance {
self.module_index
}

pub(crate) fn instructions(&self) -> &[Instruction] {
pub fn instructions(&self) -> &[Instruction] {
&self.instructions
}

Expand Down
11 changes: 11 additions & 0 deletions crates/vm/src/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,17 @@ impl Stack {
.collect()
}

pub fn frame_at(&self, index: usize) -> Result<&CallFrame> {
let mut frames = self.stack
.iter()
.rev()
.filter_map(|v| match v {
StackValue::Activation(frame) => Some(frame),
_ => None,
});
frames.nth(index).ok_or(Error::NotEnoughFrames)
}

pub fn peek_values(&self) -> Vec<&Value> {
self.stack
.iter()
Expand Down

0 comments on commit f12accd

Please sign in to comment.