-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathinstruction.test.cpp
109 lines (77 loc) · 3.27 KB
/
instruction.test.cpp
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
#include <boost/ut.hpp>
#include <cmath>
#include <lime/instruction.hpp>
using namespace boost::ut;
using namespace boost::ut::literals;
std::vector<unsigned char> code = {
#if INTPTR_MAX == INT64_MAX
0x8b, 0x02, // mov eax, [rdx]
0x4c, 0x8b, 0xc1, // mov [rcx], eax
0x48, 0x8b, 0x05, 0x05, 0x00, 0x00, 0x00, // mov rax, [rip+0x5]
0xff, 0x25, 0x10, 0x00, 0x00, 0x00, // jmp [rip+0x10]
0xff, 0xe0, // jmp rax
0xe8, 0x00, 0x00, 0x00, 0x00, // call 0x0
#else
0x8b, 0x02, // mov eax, [edx]
0x89, 0x01, // mov [ecx], eax
0xa1, 0x05, 0x00, 0x00, 0x00, // mov eax, [rip+0x5]
0xff, 0x25, 0x10, 0x00, 0x00, 0x00, // jmp [rip+0x10]
0xff, 0xe0, // jmp eax
#endif
};
suite<"Instruction"> instruction_suite = []
{
static constexpr auto is64bit = sizeof(std::uintptr_t) == 8;
static constexpr auto MNEMONIC_MOV = 436;
static constexpr auto MNEMONIC_JMP = 311;
auto *data = code.data();
auto instruction = lime::instruction::at(reinterpret_cast<std::uintptr_t>(data));
expect(eq(instruction.has_value(), true));
expect(eq(instruction->size(), 2));
expect(eq(instruction->addr(), reinterpret_cast<std::uintptr_t>(data)));
expect(eq(instruction->relative(), false));
expect(eq(instruction->branching(), false));
expect(eq(instruction->mnemonic(), MNEMONIC_MOV));
auto mov = instruction->next();
expect(eq(mov.has_value(), true));
expect(eq(mov->relative(), false));
expect(eq(mov->branching(), false));
expect(eq(mov->mnemonic(), MNEMONIC_MOV));
auto prev = mov->prev();
expect(eq(prev.has_value(), true));
expect(eq(prev->mnemonic(), MNEMONIC_MOV));
expect(eq(prev->size(), 2));
expect(eq(prev->addr(), reinterpret_cast<std::uintptr_t>(data)));
auto rel_move = mov->next();
expect(eq(rel_move.has_value(), true));
expect(eq(rel_move->relative(), is64bit));
expect(eq(rel_move->branching(), false));
expect(eq(rel_move->mnemonic(), MNEMONIC_MOV));
auto jmp = rel_move->next();
auto jmp_until = instruction->next(MNEMONIC_JMP);
expect(eq(jmp.has_value(), true));
expect(eq(jmp_until.has_value(), true));
expect(eq(jmp->addr(), jmp_until->addr()));
expect(eq(jmp->relative(), is64bit));
expect(eq(jmp->branching(), true));
expect(eq(jmp->mnemonic(), MNEMONIC_JMP));
auto abs_jmp = jmp->next();
expect(eq(abs_jmp.has_value(), true));
expect(eq(abs_jmp->relative(), false));
expect(eq(abs_jmp->branching(), true));
expect(eq(abs_jmp->mnemonic(), MNEMONIC_JMP));
expect(eq(abs_jmp->addr(), jmp->addr() + jmp->size()));
expect(eq(rel_move->addr(), mov->addr() + mov->size()));
expect(eq(jmp->addr(), rel_move->addr() + rel_move->size()));
expect(eq(mov->addr(), instruction->addr() + instruction->size()));
#if INTPTR_MAX == INT64_MAX
auto call = abs_jmp->next();
expect(eq(call.has_value(), true));
expect(eq(call->relative(), true));
expect(eq(call->branching(), true));
expect(eq(mov->size(), 3));
expect(eq(rel_move->size(), 7));
expect(eq(jmp->size(), 6));
expect(eq(abs_jmp->size(), 2));
#endif
};