/
utils.m
138 lines (111 loc) · 3.5 KB
/
utils.m
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#import "utils.h"
void __assert_rtn(const char* func, const char* file, int line, const char* failedexpr) {
[NSException raise:NSInternalInconsistencyException format:@"Assertion failed: (%s), file %s, line %d.\n", failedexpr, file, line];
abort(); // silent compiler warning
}
uint64_t aarch64_get_tbnz_jump_address(uint32_t instruction, uint64_t pc) {
// Check that this is a tbnz instruction
if ((instruction & 0xFF000000) != 0x37000000) {
return 0;
}
uint32_t imm = ((instruction >> 5) & 0xFFFF) * 4;
return imm + pc;
}
const char *LCHomePath() {
static const char *path;
if (path) return path;
const char *pathEnv = getenv("HOME");
path = calloc(1, strlen(pathEnv)+1);
strncpy((char *)path, pathEnv, strlen(pathEnv));
return path;
}
// https://github.com/pinauten/PatchfinderUtils/blob/master/Sources/CFastFind/CFastFind.c
//
// CFastFind.c
// CFastFind
//
// Created by Linus Henze on 2021-10-16.
// Copyright © 2021 Linus Henze. All rights reserved.
//
/**
* Emulate an adrp instruction at the given pc value
* Returns adrp destination
*/
uint64_t aarch64_emulate_adrp(uint32_t instruction, uint64_t pc) {
// Check that this is an adrp instruction
if ((instruction & 0x9F000000) != 0x90000000) {
return 0;
}
// Calculate imm from hi and lo
int32_t imm_hi_lo = (instruction & 0xFFFFE0) >> 3;
imm_hi_lo |= (instruction & 0x60000000) >> 29;
if (instruction & 0x800000) {
// Sign extend
imm_hi_lo |= 0xFFE00000;
}
// Build real imm
int64_t imm = ((int64_t) imm_hi_lo << 12);
// Emulate
return (pc & ~(0xFFFULL)) + imm;
}
bool aarch64_emulate_add_imm(uint32_t instruction, uint32_t *dst, uint32_t *src, uint32_t *imm) {
// Check that this is an add instruction with immediate
if ((instruction & 0xFF000000) != 0x91000000) {
return 0;
}
int32_t imm12 = (instruction & 0x3FFC00) >> 10;
uint8_t shift = (instruction & 0xC00000) >> 22;
switch (shift) {
case 0:
*imm = imm12;
break;
case 1:
*imm = imm12 << 12;
break;
default:
return false;
}
*dst = instruction & 0x1F;
*src = (instruction >> 5) & 0x1F;
return true;
}
/**
* Emulate an adrp and add instruction at the given pc value
* Returns destination
*/
uint64_t aarch64_emulate_adrp_add(uint32_t instruction, uint32_t addInstruction, uint64_t pc) {
uint64_t adrp_target = aarch64_emulate_adrp(instruction, pc);
if (!adrp_target) {
return 0;
}
uint32_t addDst;
uint32_t addSrc;
uint32_t addImm;
if (!aarch64_emulate_add_imm(addInstruction, &addDst, &addSrc, &addImm)) {
return 0;
}
if ((instruction & 0x1F) != addSrc) {
return 0;
}
// Emulate
return adrp_target + (uint64_t) addImm;
}
/**
* Emulate an adrp and ldr instruction at the given pc value
* Returns destination
*/
uint64_t aarch64_emulate_adrp_ldr(uint32_t instruction, uint32_t ldrInstruction, uint64_t pc) {
uint64_t adrp_target = aarch64_emulate_adrp(instruction, pc);
if (!adrp_target) {
return 0;
}
if ((instruction & 0x1F) != ((ldrInstruction >> 5) & 0x1F)) {
return 0;
}
if ((ldrInstruction & 0xFFC00000) != 0xF9400000) {
return 0;
}
uint32_t imm12 = ((ldrInstruction >> 10) & 0xFFF) << 3;
// Emulate
return adrp_target + (uint64_t) imm12;
}