From 9bc7a5ec5f184695766ba2e74a73d92d9f81c9f7 Mon Sep 17 00:00:00 2001 From: Jan Ferdinand Sauer Date: Thu, 5 Oct 2023 09:16:31 +0200 Subject: [PATCH] feat: add support for `break` debug command --- triton-vm/src/instruction.rs | 4 ++++ triton-vm/src/parser.rs | 24 +++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/triton-vm/src/instruction.rs b/triton-vm/src/instruction.rs index c4a06f70..b41d98e7 100644 --- a/triton-vm/src/instruction.rs +++ b/triton-vm/src/instruction.rs @@ -49,6 +49,8 @@ pub enum LabelledInstruction { /// Labels look like "`:`" and are translated into absolute addresses. Label(String), + + Breakpoint, } impl LabelledInstruction { @@ -77,6 +79,7 @@ impl Display for LabelledInstruction { match self { LabelledInstruction::Instruction(instr) => write!(f, "{instr}"), LabelledInstruction::Label(label_name) => write!(f, "{label_name}:"), + LabelledInstruction::Breakpoint => write!(f, "break"), } } } @@ -469,6 +472,7 @@ pub(crate) fn build_label_to_address_map(program: &[LabelledInstruction]) -> Has } }, Instruction(instruction) => instruction_pointer += instruction.size() as u64, + Breakpoint => (), } } label_map diff --git a/triton-vm/src/parser.rs b/triton-vm/src/parser.rs index bb2368dd..7f28eac7 100644 --- a/triton-vm/src/parser.rs +++ b/triton-vm/src/parser.rs @@ -36,6 +36,7 @@ pub struct ParseError<'a> { pub enum InstructionToken<'a> { Instruction(AnInstruction, &'a str), Label(String, &'a str), + Breakpoint(&'a str), } impl<'a> Display for InstructionToken<'a> { @@ -43,6 +44,7 @@ impl<'a> Display for InstructionToken<'a> { match self { InstructionToken::Instruction(instr, _) => write!(f, "{instr}"), InstructionToken::Label(label_name, _) => write!(f, "{label_name}:"), + InstructionToken::Breakpoint(_) => write!(f, "break"), } } } @@ -60,6 +62,7 @@ impl<'a> InstructionToken<'a> { match self { InstructionToken::Instruction(_, token_str) => token_str, InstructionToken::Label(_, token_str) => token_str, + InstructionToken::Breakpoint(token_str) => token_str, } } @@ -68,6 +71,7 @@ impl<'a> InstructionToken<'a> { match self { Instruction(instr, _) => LabelledInstruction::Instruction(instr.to_owned()), Label(label, _) => LabelledInstruction::Label(label.to_owned()), + Breakpoint(_) => LabelledInstruction::Breakpoint, } } } @@ -187,7 +191,7 @@ type ParseResult<'input, Out> = IResult<&'input str, Out, VerboseError<&'input s /// pub fn tokenize(s: &str) -> ParseResult> { let (s, _) = comment_or_whitespace0(s)?; - let (s, instructions) = many0(alt((label, labelled_instruction)))(s)?; + let (s, instructions) = many0(alt((label, labelled_instruction, breakpoint)))(s)?; let (s, _) = context("expecting label, instruction or eof", eof)(s)?; Ok((s, instructions)) @@ -213,6 +217,11 @@ fn label(label_s: &str) -> ParseResult { Ok((s, InstructionToken::Label(addr, label_s))) } +fn breakpoint(breakpoint_s: &str) -> ParseResult { + let (s, _) = token1("break")(breakpoint_s)?; + Ok((s, InstructionToken::Breakpoint(breakpoint_s))) +} + fn an_instruction(s: &str) -> ParseResult> { // OpStack manipulation let pop = instruction("pop", Pop); @@ -1063,4 +1072,17 @@ pub(crate) mod tests { let expected_instructions = vec![Instruction(Divine); DIGEST_LENGTH]; assert_eq!(expected_instructions, instructions); } + + #[test] + fn break_gets_turned_into_labelled_instruction() { + let instructions = triton_asm![break]; + let expected_instructions = vec![Breakpoint]; + assert_eq!(expected_instructions, instructions); + } + + #[test] + fn break_does_not_propagate_to_full_program() { + let program = triton_program! { break halt break }; + assert_eq!(1, program.instructions.len()); + } }