aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2024-03-16 22:07:30 +0000
committeriximeow <me@iximeow.net>2024-03-16 22:07:30 +0000
commitba0628655fe016e9073b7b4121998a67c92346d7 (patch)
tree5085bf9933d89ecd3e5e03f1090ddc0d37cd4163
parentf551a6bed26e1c5e9938a1c45b47f1531ed64555 (diff)
differential testing: parse memory operands more precisely
to support more 0x prefix handling, since yax prints offsets with 0x even if the offset is less than 10
-rw-r--r--differential-tests/tests/capstone-differential.rs49
1 files changed, 46 insertions, 3 deletions
diff --git a/differential-tests/tests/capstone-differential.rs b/differential-tests/tests/capstone-differential.rs
index cb97fef..3db6fdd 100644
--- a/differential-tests/tests/capstone-differential.rs
+++ b/differential-tests/tests/capstone-differential.rs
@@ -12,7 +12,7 @@ use std::num::ParseIntError;
enum ParsedOperand {
Register { size: char, num: u8 },
Memory(String),
- MemoryWithOffset { base: String, offset: u32, writeback: bool },
+ MemoryWithOffset { base: String, offset: Option<i64>, writeback: bool },
SIMDRegister { size: char, num: u8 },
// SIMDRegisterElements { num: u8, elems: u8, elem_size: char },
// SIMDRegisterElement { num: u8, elem_size: char, elem: u8 },
@@ -110,6 +110,21 @@ fn test_instruction_parsing() {
None,
]
});
+
+ let inst = ParsedDisassembly::parse("stlurb w0, [x0, #0x1]");
+ assert_eq!(inst, ParsedDisassembly {
+ opcode: "stlurb".to_string(),
+ operands: [
+ Some(ParsedOperand::Register { size: 'w', num: 0 }),
+ Some(ParsedOperand::MemoryWithOffset { base: "x0".to_string(), offset: Some(1), writeback: false }),
+ None,
+ None,
+ None,
+ None,
+ ]
+ });
+ let inst2 = ParsedDisassembly::parse("stlurb w0, [x0, #1]");
+ assert_eq!(inst, inst2);
}
impl ParsedOperand {
@@ -155,12 +170,40 @@ impl ParsedOperand {
let imm = parse_hex_or_dec(imm_str);
(ParsedOperand::PCRel(imm), end)
} else if s.as_bytes()[0] == b'[' {
- let mut end = s.find(']').map(|x| x + 1).unwrap_or(s.len());
+ let brace_end = s.find(']').map(|x| x + 1).unwrap_or(s.len());
+ let mut end = brace_end;
+ let mut writeback = false;
if s.as_bytes().get(end) == Some(&b'!') {
end += 1;
+ writeback = true;
}
- (ParsedOperand::Memory(s[0..end].to_string()), end)
+ let addr = &s[1..brace_end - 1];
+
+ let offset = addr.rfind(',').map(|comma| {
+ addr[comma + 1..].trim()
+ }).and_then(|mut offset_str| {
+ if offset_str.as_bytes().get(0) == Some(&b'#') {
+ offset_str = &offset_str[1..];
+
+ Some(parse_hex_or_dec(offset_str))
+ } else {
+ None
+ }
+ });
+
+ let base_end = addr.rfind(',').unwrap_or(addr.len());
+ let base = addr[..base_end].trim();
+
+ if writeback || offset.is_some() {
+ (ParsedOperand::MemoryWithOffset {
+ base: base.to_string(),
+ offset: offset,
+ writeback,
+ }, end)
+ } else {
+ (ParsedOperand::Memory(base.to_string()), end)
+ }
} else if s.as_bytes()[0] == b'{' {
let mut brace_end = s.find('}');
if let Some(brace_end) = brace_end {