Skip to content

Commit cc67940

Browse files
author
CosineMath
committed
Patch up Bionic linker for aarch64.
1 parent bbc7226 commit cc67940

File tree

2 files changed

+155
-1
lines changed

2 files changed

+155
-1
lines changed

jni/boat/loadme.c

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <dlfcn.h>
55
#include <stdlib.h>
66
#include <android/log.h>
7+
#include <sys/mman.h>
78

89
JNIEXPORT void JNICALL Java_cosine_boat_LoadMe_redirectStdio(JNIEnv* env, jclass clazz, jstring path){
910

@@ -51,7 +52,157 @@ JNIEXPORT jint JNICALL Java_cosine_boat_LoadMe_dlopen(JNIEnv* env, jclass clazz,
5152
return 0;
5253
}
5354

55+
#ifdef __aarch64__
56+
unsigned gen_ldr_pc(unsigned rt, signed long off) {
57+
// 33 222 2 22 2222111111111100000 00000
58+
// 10 987 6 54 3210987654321098765 43210
59+
// 01 011 0 00 1111111111111111011 00010
60+
// imm rt
61+
unsigned result = 0x0;
62+
63+
result |= 0x58; // 01 011 0 00;
64+
result <<= 19;
65+
66+
signed long imm = off / 4;
67+
imm &= 0x7ffff;
68+
result |= imm;
69+
result <<= 5;
70+
71+
rt &= 0x1f;
72+
result |= rt;
73+
74+
return result;
75+
76+
}
77+
unsigned gen_ret(unsigned lr) {
78+
// 3322222 2 2 22 21111 1111 1 1 00000 00000
79+
// 1098765 4 3 21 09876 5432 1 0 98765 43210
80+
// 1101011 0 0 10 11111 0000 0 0 11110 00000
81+
// lr
82+
unsigned result = 0x0;
83+
84+
result |= 0x3597c0; // 1101011 0 0 10 11111 0000 0 0
85+
result <<= 5;
86+
lr &= 0x1f;
87+
result |= lr;
88+
result <<= 5;
89+
result |= 0x0;
90+
return result;
91+
}
92+
unsigned gen_mov_reg(unsigned tr, unsigned sr) {
93+
// 3 32 22222 22 2 21111 111111 00000 00000
94+
// 1 09 87654 32 1 09876 543210 98765 43210
95+
// 1 01 01010 00 0 11110 000000 11111 00010
96+
// sr tr
97+
unsigned result = 0x0;
98+
99+
result |= 0x550; // 1 01 01010 00 0
100+
result <<= 5;
101+
102+
sr &= 0x1f;
103+
result |= sr;
104+
result <<= 11;
105+
106+
result |= 0x1f; // 000000 11111
107+
result <<= 5;
108+
109+
tr &= 0x1f;
110+
result |= tr;
111+
112+
return result;
113+
}
114+
115+
unsigned gen_mov_imm(unsigned tr, signed short imm) {
116+
// 3 32 222222 22 2111111111100000 00000
117+
// 1 09 876543 21 0987654321098765 43210
118+
// 1 10 100101 00 0000000001111111 00000
119+
// imm tr
120+
unsigned result = 0x0;
121+
122+
result |= 0x694; // 1 10 100101 00
123+
result <<= 16;
124+
125+
result |= imm;
126+
result <<= 5;
127+
128+
tr &= 0x1f;
129+
result |= tr;
130+
131+
return result;
132+
}
54133

134+
void stub() {
135+
136+
}
137+
#endif
138+
JNIEXPORT void JNICALL Java_cosine_boat_LoadMe_patchLinker(JNIEnv *env, jclass clazz) {
139+
140+
#ifdef __aarch64__
141+
#define PAGE_START(x) ((void*)((unsigned long)(x) & ~((unsigned long)getpagesize() - 1)))
142+
143+
void* libdl_handle = dlopen("libdl.so", RTLD_LAZY);
144+
145+
unsigned* dlopen_addr = (unsigned*)dlsym(libdl_handle, "dlopen");
146+
unsigned* dlsym_addr = (unsigned*)dlsym(libdl_handle, "dlsym");
147+
unsigned* dlvsym_addr = (unsigned*)dlsym(libdl_handle, "dlvsym");
148+
unsigned* buffer = (unsigned*)dlsym(libdl_handle, "android_get_LD_LIBRARY_PATH");
149+
150+
mprotect(PAGE_START(buffer), getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC );
151+
mprotect(PAGE_START(dlopen_addr), getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC );
152+
mprotect(PAGE_START(dlsym_addr), getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC );
153+
mprotect(PAGE_START(dlvsym_addr), getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC );
154+
155+
unsigned ins_ret = gen_ret(30);
156+
unsigned ins_mov_x0_0 = gen_mov_imm(0, 0);
157+
158+
buffer[0] = ins_mov_x0_0;
159+
buffer[1] = ins_ret;
160+
161+
void** tmp_addr = (void**)(buffer + 2);
162+
*tmp_addr = stub;
163+
164+
unsigned ins_mov_x2_x30 = gen_mov_reg(2, 30);
165+
unsigned ins_mov_x3_x30 = gen_mov_reg(3, 30);
166+
167+
int dlopen_hooked = 0;
168+
int dlsym_hooked = 0;
169+
int dlvsym_hooked = 0;
170+
for (int i = 0; dlopen_addr[i] != ins_ret; i++){
171+
if (dlopen_addr[i] == ins_mov_x2_x30) {
172+
dlopen_addr[i] = gen_ldr_pc(2, (unsigned long)tmp_addr - (unsigned long)&dlopen_addr[i]);
173+
dlopen_hooked = 1;
174+
break;
175+
}
176+
}
177+
for (int i = 0; dlsym_addr[i] != ins_ret; i++){
178+
if (dlsym_addr[i] == ins_mov_x2_x30) {
179+
dlsym_addr[i] = gen_ldr_pc(2, (unsigned long)tmp_addr - (unsigned long)&dlsym_addr[i]);
180+
dlsym_hooked = 1;
181+
break;
182+
}
183+
}
184+
for (int i = 0; dlvsym_addr[i] != ins_ret; i++){
185+
if (dlvsym_addr[i] == ins_mov_x3_x30) {
186+
dlvsym_addr[i] = gen_ldr_pc(3, (unsigned long)tmp_addr - (unsigned long)&dlvsym_addr[i]);
187+
dlvsym_hooked = 1;
188+
break;
189+
}
190+
}
191+
192+
if (dlopen_hooked == 0) {
193+
__android_log_print(ANDROID_LOG_ERROR, "Boat", "dlopen() not patched");
194+
}
195+
if (dlsym_hooked == 0) {
196+
__android_log_print(ANDROID_LOG_ERROR, "Boat", "dlsym() not patched");
197+
}
198+
if (dlvsym_hooked == 0) {
199+
__android_log_print(ANDROID_LOG_ERROR, "Boat", "dlvsym() not patched");
200+
}
201+
#undef PAGE_START
202+
#else // !__aarch64__
203+
__android_log_print(ANDROID_LOG_ERROR, "Boat", "Nothing to patch.");
204+
#endif // __aarch64__
205+
}
55206

56207
// copy from java.c
57208

src/cosine/boat/LoadMe.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public class LoadMe {
1212
public static native void setenv(String str, String str2);
1313
public static native void setupJLI();
1414
public static native int dlopen(String name);
15+
public static native void patchLinker();
1516

1617
static {
1718
System.loadLibrary("boat");
@@ -33,7 +34,9 @@ public static int exec(LauncherConfig config) {
3334

3435
setenv("HOME", home);
3536
setenv("JAVA_HOME" ,runtimePath + "/j2re-image");
36-
37+
38+
patchLinker();
39+
3740
// openjdk
3841
dlopen(runtimePath + "/j2re-image/lib/aarch32/libfreetype.so");
3942
dlopen(runtimePath + "/j2re-image/lib/aarch32/jli/libjli.so");

0 commit comments

Comments
 (0)