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
use yaxpeax_x86::long_mode::Opcode;
use yaxpeax_x86::long_mode::{Arch as x86_64};
use yaxpeax_arch::Arch;
use analyses::control_flow;
use analyses::Value;
use data::ValueLocations;
use analyses::control_flow::ControlFlowAnalysis;
use analyses::OpaqueIndirection;
use arch::x86_64::analyses::data_flow::Location;
use analyses::DFG;
impl DFG<control_flow::Effect<<x86_64 as Arch>::Address>, x86_64, ()> for ControlFlowAnalysis<<x86_64 as Arch>::Address> {
type Indirect = OpaqueIndirection<control_flow::Effect<<x86_64 as Arch>::Address>>;
fn indirect_loc(&self, _when: (), _loc: <x86_64 as ValueLocations>::Location) -> OpaqueIndirection<control_flow::Effect<<x86_64 as Arch>::Address>> {
OpaqueIndirection::inst()
}
fn read_loc(&self, _when: (), loc: <x86_64 as ValueLocations>::Location) -> control_flow::Effect<<x86_64 as Arch>::Address> {
if loc == Location::RIP {
self.effect.clone()
} else if let Location::Memory(_) = loc {
control_flow::Effect::unknown()
} else {
control_flow::Effect::unknown()
}
}
fn write_loc(&mut self, _when: (), loc: <x86_64 as ValueLocations>::Location, value: control_flow::Effect<<x86_64 as Arch>::Address>) {
if loc == Location::RIP {
self.effect = value;
} else {
}
}
}
impl_control_flow!(
crate::arch::x86_64::semantic::evaluate,
yaxpeax_x86::long_mode::Arch,
yaxpeax_x86::long_mode::Instruction,
|inst| {
let assume_calls_return = true;
match inst.opcode() {
Opcode::CALL |
Opcode::SYSCALL => {
if assume_calls_return {
return Some(control_flow::Effect::cont());
}
}
Opcode::UD2 => { return Some(control_flow::Effect::stop()); }
_ => {}
}
None
},
);
#[test]
fn test_x86_determinant() {
use yaxpeax_arch::Decoder;
use memory::MemoryRange;
use memory::repr::ReadCursor;
use analyses::control_flow::Determinant;
fn decode(data: &[u8]) -> <x86_64 as Arch>::Instruction {
let decoder = <x86_64 as Arch>::Decoder::default();
let cursor: ReadCursor<x86_64, [u8]> = data.range(0..(data.len() as u64)).unwrap();
decoder.decode(&mut cursor.to_reader()).unwrap()
}
let call = decode(&[0xe8, 0x78, 0x56, 0x34, 0x12][..]);
assert_eq!(call.control_flow(Option::<&()>::None), control_flow::Effect::cont());
let jmp = decode(&[0xe9, 0x78, 0x56, 0x34, 0x12][..]);
assert_eq!(jmp.control_flow(Option::<&()>::None), control_flow::Effect::stop_and(
control_flow::Target::Relative(AddressDiff::from_const(0x12345678))
));
let ret = decode(&[0xc3][..]);
assert_eq!(ret.control_flow(Option::<&()>::None), control_flow::Effect::stop());
let jl = decode(&[0x7c, 0x14][..]);
assert_eq!(jl.control_flow(Option::<&()>::None), control_flow::Effect::cont_and(
control_flow::Target::Relative(AddressDiff::from_const(0x14))
));
}