Flush CPU cache in YAHFA

This commit is contained in:
LoveSy 2020-12-13 14:25:18 +08:00 committed by kotori0
parent 87f9ab1f61
commit 6dd10b1fb7
3 changed files with 26 additions and 48 deletions

View File

@ -115,17 +115,6 @@ void *getEntryPoint(void* method) {
} }
static int replaceMethod(void *fromMethod, void *toMethod, int isBackup) { static int replaceMethod(void *fromMethod, void *toMethod, int isBackup) {
if (hookCount >= hookCap) {
LOGI("not enough capacity. Allocating...");
if (doInitHookCap(DEFAULT_CAP)) {
LOGE("cannot hook method");
return 1;
}
LOGI("Allocating done");
}
LOGI("replace method from %p to %p", fromMethod, toMethod);
// replace entry point // replace entry point
void *newEntrypoint = NULL; void *newEntrypoint = NULL;
if(isBackup) { if(isBackup) {
@ -157,7 +146,6 @@ static int replaceMethod(void *fromMethod, void *toMethod, int isBackup) {
pointer_size); pointer_size);
} }
hookCount += 1;
return 0; return 0;
} }

View File

@ -16,11 +16,6 @@
#define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b))
static unsigned char *trampolineCode; // place where trampolines are saved
static unsigned int trampolineSize; // trampoline size required for each hook
unsigned int hookCap = 0;
unsigned int hookCount = 0;
// trampoline: // trampoline:
// 1. set eax/rdi/r0/x0 to the hook ArtMethod addr // 1. set eax/rdi/r0/x0 to the hook ArtMethod addr
@ -127,17 +122,23 @@ unsigned char trampolineForBackup[] = {
}; };
#endif #endif
static unsigned int trampolineSize = roundUpToPtrSize(MAX(sizeof(trampoline), sizeof(trampolineForBackup)));
static inline void FlushCache(void *addr, size_t size) {
__builtin___clear_cache((char *) addr, (char *) ((uintptr_t) addr + size));
}
void *genTrampoline(void *toMethod, void *entrypoint) { void *genTrampoline(void *toMethod, void *entrypoint) {
unsigned char *targetAddr = trampolineCode + trampolineSize * hookCount; size_t size = entrypoint == NULL ? sizeof(trampoline) : sizeof(trampolineForBackup);
// TODO: make use of thread_local to avoid frequent memory allocate
void *targetAddr = doInitHookCap(size);
if (targetAddr == NULL) return NULL;
if (entrypoint != NULL) { if (entrypoint != NULL) {
memcpy(targetAddr, trampolineForBackup, sizeof(trampolineForBackup)); memcpy(targetAddr, trampolineForBackup, size);
} } else {
else { memcpy(targetAddr, trampoline, size);
memcpy(targetAddr, trampoline,
sizeof(trampoline)); // do not use trampolineSize since it's a rounded size
} }
// replace with the actual ArtMethod addr // replace with the actual ArtMethod addr
@ -172,14 +173,14 @@ void *genTrampoline(void *toMethod, void *entrypoint) {
if (entrypoint) { if (entrypoint) {
memcpy(targetAddr + 20, &entrypoint, pointer_size); memcpy(targetAddr + 20, &entrypoint, pointer_size);
memcpy(targetAddr + 12, &toMethod, pointer_size); memcpy(targetAddr + 12, &toMethod, pointer_size);
} } else {
else {
memcpy(targetAddr + 12, &toMethod, pointer_size); memcpy(targetAddr + 12, &toMethod, pointer_size);
} }
#else #else
#error Unsupported architecture #error Unsupported architecture
#endif #endif
FlushCache(targetAddr, size);
return targetAddr; return targetAddr;
} }
@ -199,23 +200,17 @@ void setupTrampoline(uint8_t offset) {
#endif #endif
} }
int doInitHookCap(unsigned int cap) { void *doInitHookCap(size_t size) {
if (cap == 0) { if (size == 0) {
LOGE("invalid capacity: %d", cap); LOGE("invalid capacity: %zx", size);
return 1; return NULL;
} }
if (hookCap) { unsigned char *buf = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
LOGI("allocating new space for trampoline code");
}
unsigned int allSize = trampolineSize * cap;
unsigned char *buf = mmap(NULL, allSize, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (buf == MAP_FAILED) { if (buf == MAP_FAILED) {
LOGE("mmap failed, errno = %s", strerror(errno)); LOGE("mmap failed, errno = %s", strerror(errno));
return 1; return NULL;
} }
hookCap = cap; return buf;
hookCount = 0;
trampolineCode = buf;
return 0;
} }

View File

@ -7,15 +7,10 @@
extern int SDKVersion; extern int SDKVersion;
extern unsigned int hookCap; // capacity for trampolines
extern unsigned int hookCount; // current count of used trampolines
extern unsigned char trampoline[]; extern unsigned char trampoline[];
int doInitHookCap(unsigned int cap); void* doInitHookCap(size_t cap);
void setupTrampoline(uint8_t offset); void setupTrampoline(uint8_t offset);
void *genTrampoline(void *toMethod, void *entrypoint); void *genTrampoline(void *toMethod, void *entrypoint);
#define DEFAULT_CAP 1 //size of each trampoline area would be no more than 4k Bytes(one page)
#endif //YAHFA_TAMPOLINE_H #endif //YAHFA_TAMPOLINE_H