1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
use std::fmt::{self, Write};
use yaxpeax_arch::{Decoder, LengthedInstruction};
use yaxpeax_arch::display::{ArchDisplayRules, DisplaySink};
use yaxpeax_power::Power;
use yaxpeax_power::InstDecoder;
use yaxpeax_power::DisplayRules;
fn test_display_rule<Rules: for<'f, 'g> DisplayRules<yaxpeax_arch::display::FmtSink<'f, fmt::Formatter<'g>>>>(
decoder: &InstDecoder, testcase: &'static TestCase, rules: &Rules
) {
let mut reader = yaxpeax_arch::U8Reader::new(testcase.bytes);
let instr = decoder.decode(&mut reader).expect("display rule tests only run on instructions that decode");
assert_eq!(instr.len().to_const(), testcase.bytes.len() as u64, "instruction length is incorrect");
let actual = instr.display_rules(rules).to_string();
if testcase.expected != actual {
let mut hex = String::new();
for b in testcase.bytes {
write!(hex, "{:02x}", b).unwrap();
}
eprintln!("rule-based formatting test failed. \n \
instr: {}\n \
hex: {}", instr, hex);
eprintln!(" [-] got: {}, wanted {}", testcase.expected, actual);
panic!("issues in display rule formatting");
}
}
struct TestCase {
bytes: &'static [u8],
expected: &'static str,
}
#[test]
fn test_absolute_addr() {
let rules = yaxpeax_power::AbsoluteAddressFormatter::new(0x82113e04);
let decoder = InstDecoder::default();
static CASES: &'static [TestCase] = &[
TestCase {
bytes: &[0x48, 0x5c, 0x53, 0xcd],
expected: "bl 0x826d91d0",
}
];
for case in CASES.iter() {
test_display_rule(&decoder, case, &rules);
}
}
/// a simple DisplayRules impl to test that addresses directly at symbols are printed reasonably.
/// if a symbol is not directly at an address, the address is printed instead.
#[derive(Copy, Clone)]
struct SimpleSymbolicator<'syms> {
pc: u64,
symbols: &'syms [(u64, &'static str)],
}
impl<'syms> SimpleSymbolicator<'syms> {
pub fn new(pc: u64, symbols: &'syms [(u64, &'static str)]) -> Self {
SimpleSymbolicator {
pc,
symbols,
}
}
}
impl<'syms, S: DisplaySink> ArchDisplayRules<Power, S> for SimpleSymbolicator<'syms> {
fn instr_addr(&self) -> Option<u64> {
Some(self.pc)
}
fn emit_address(&self, addr: u64, s: &mut S) -> Result<bool, fmt::Error> {
for (sym_addr, sym) in self.symbols {
eprintln!("does symbol {} at {:04x} match {:04x}?", sym, sym_addr, addr);
if *sym_addr == addr {
s.write_str(sym)?;
return Ok(true);
}
}
Ok(false)
}
}
impl<'syms, S: DisplaySink> DisplayRules<S> for SimpleSymbolicator<'syms> {}
#[test]
fn test_symbolication() {
let syms = &[
(0x0002_0000, "memcpy"),
(0x0020_0000, "global"),
(0x0021_0006, "global_riprel"),
(0x0001_0002, "branch_target"),
(0x0001_0005, "wide_target"),
];
let rules = SimpleSymbolicator::new(0x0001_0000, syms);
let decoder = InstDecoder::default();
static CASES: &'static [TestCase] = &[
];
for case in CASES.iter() {
test_display_rule(&decoder, case, &rules);
}
}
|