-
Notifications
You must be signed in to change notification settings - Fork 0
/
backend_demo.c
executable file
·112 lines (103 loc) · 3.5 KB
/
backend_demo.c
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
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
// Include this header to use the built-in backend functions
#include <builtin_backend.h>
typedef enum arch_t {
arm,
x86_64,
mips,
mipsel,
} arch_t;
static arch_t arch = arm;
extern bool arch_supported(const char *arch_name) {
if (!strcmp(arch_name, "arm")) {
arch = arm;
return true;
}
if (!strcmp(arch_name, "x86_64")) {
arch = x86_64;
return true;
}
if (!strcmp(arch_name, "mips")) {
arch = mips;
return true;
}
if (!strcmp(arch_name, "mipsel")) {
arch = mipsel;
return true;
}
return false;
}
extern bool is_indirect_branch(uint8_t *insn_data, size_t insn_size) {
if (arch == arm) {
// Handles blx rn
const uint32_t blx_variable_bits = 0xf000000f;
const uint32_t blx_constant_bits = 0x012fff30;
// Arbitrarily set all variable bits in the blx instruction before comparing with the input instruction
const uint32_t blx = blx_constant_bits | blx_variable_bits;
if (insn_size == 4) {
uint32_t b0 = insn_data[0];
uint32_t b1 = insn_data[1];
uint32_t b2 = insn_data[2];
uint32_t b3 = insn_data[3];
uint32_t word = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
// Set all variable bits in the instruction
word |= blx_variable_bits;
if (word == blx) {
printf("Found a `blx` instruction\n");
return true;
}
}
} else if (arch == x86_64) {
// Handles callq rax, rcx, rdx, etc.
if (insn_size == 2) {
uint8_t b0 = insn_data[0];
uint8_t b1 = insn_data[1];
if ((b0 == 0xff) && (0xd0 <= b1) && (b1 <= 0xd6)) {
printf("Found a `callq` instruction\n");
return true;
}
}
// Handles callq r8, r9, r10, etc.
if (insn_size == 3) {
uint8_t b0 = insn_data[0];
uint8_t b1 = insn_data[1];
uint8_t b2 = insn_data[2];
if ((b0 == 0x41) && (b1 == 0xff) && (0xd0 <= b2) && (b2 <= 0xd6)) {
printf("Found a `callq` instruction\n");
return true;
}
}
}else if (arch == mipsel) {
// Handles jr and jalr instructions
if (insn_size == 4) {
uint32_t instruction = (insn_data[0] << 24) | (insn_data[1] << 16) | (insn_data[2] << 8) | insn_data[3];
if (instruction == 0x0320f809) {
printf("Found a `jalr $t9` instruction\n");
return true;
}
if (instruction == 0x03020008) {
printf("Found a `jr $t9` instruction\n");
return true;
}
}
}else if (arch == mips) {
// Handles jr and jalr instructions
if (insn_size == 4) {
uint32_t instruction = (insn_data[0] << 24) | (insn_data[1] << 16) | (insn_data[2] << 8) | insn_data[3];
if (instruction == 0x09f82003) {
printf("Found a `jalr $t9` instruction\n");
return true;
}
if (instruction == 0x08002003) {
printf("Found a `jr $t9` instruction\n");
return true;
}
}
}
// If we can't tell if the instruction is an indirect branch, let's use the
// built-in backend as a fallback
return is_indirect_branch_default_impl(insn_data, insn_size);
}