Skip to content

Commit

Permalink
compute available size for trampoline in trampoline.c
Browse files Browse the repository at this point in the history
  • Loading branch information
rk700 committed Dec 22, 2020
1 parent 4fe1f60 commit cd76a9d
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 39 deletions.
10 changes: 0 additions & 10 deletions library/src/main/jni/HookMain.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,6 @@ static void setNonCompilable(void *method) {
}

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
Expand Down Expand Up @@ -177,7 +168,6 @@ static int replaceMethod(void *fromMethod, void *toMethod, int isBackup) {
LOGI("change access flags from 0x%x to 0x%x", old_flags, access_flags);
}

hookCount += 1;
return 0;

}
Expand Down
56 changes: 35 additions & 21 deletions library/src/main/jni/trampoline.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

#include "common.h"
#include "trampoline.h"
Expand All @@ -13,8 +14,10 @@
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;
static unsigned char *currentTrampolineOff = 0;
static unsigned char *trampolineSpaceEnd = 0;

static void *allocTrampolineSpace();

// trampoline:
// 1. set eax/rdi/r0/x0 to the hook ArtMethod addr
Expand Down Expand Up @@ -124,10 +127,21 @@ unsigned char trampolineForBackup[] = {
0x89, 0x67, 0x45, 0x23
};
#endif
static unsigned int trampolineSize = roundUpToPtrSize(MAX(sizeof(trampoline), sizeof(trampolineForBackup)));

void *genTrampoline(void *toMethod, void *entrypoint) {
unsigned char *targetAddr = trampolineCode + trampolineSize * hookCount;
size_t trampolineSize = entrypoint != NULL ? sizeof(trampolineForBackup) : sizeof(trampoline);

// check available space for new trampoline
if(currentTrampolineOff+trampolineSize > trampolineSpaceEnd) {
currentTrampolineOff = allocTrampolineSpace();
if (currentTrampolineOff == NULL) {
return NULL;
} else {
trampolineSpaceEnd = currentTrampolineOff + TRAMPOLINE_SPACE_SIZE;
}
}

unsigned char *targetAddr = currentTrampolineOff;

if(entrypoint != NULL) {
memcpy(targetAddr, trampolineForBackup, sizeof(trampolineForBackup));
Expand Down Expand Up @@ -173,11 +187,18 @@ void *genTrampoline(void *toMethod, void *entrypoint) {
else {
memcpy(targetAddr + 16, &toMethod, pointer_size);
}

#else
#error Unsupported architecture
#endif

// skip 4 bytes of code_size_
if(entrypoint == NULL) {
targetAddr += 4;
}

// keep each trampoline aligned
currentTrampolineOff += roundUpToPtrSize(trampolineSize);

return targetAddr;
}

Expand All @@ -196,23 +217,16 @@ void setupTrampoline(uint8_t offset) {
#endif
}

int doInitHookCap(unsigned int cap) {
if (cap == 0) {
LOGE("invalid capacity: %d", cap);
return 1;
}
if (hookCap) {
LOGW("allocating new space for trampoline code");
}
unsigned int allSize = trampolineSize * cap;
unsigned char *buf = mmap(NULL, allSize, PROT_READ | PROT_WRITE | PROT_EXEC,
static void *allocTrampolineSpace() {
unsigned char *buf = mmap(NULL, TRAMPOLINE_SPACE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (buf == MAP_FAILED) {
LOGE("mmap failed, errno = %s", strerror(errno));
return 1;
return NULL;
}
hookCap = cap;
hookCount = 0;
trampolineCode = buf;
return 0;
}
else {
LOGI("allocating space for trampoline code at %p", buf);
return buf;
}

}
9 changes: 1 addition & 8 deletions library/src/main/jni/trampoline.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,10 @@

extern int SDKVersion;

extern unsigned int hookCap; // capacity for trampolines
extern unsigned int hookCount; // current count of used trampolines

extern unsigned char trampoline[];

int doInitHookCap(unsigned int cap);

void setupTrampoline(uint8_t offset);

void *genTrampoline(void *toMethod, void *entrypoint);

#define DEFAULT_CAP 100 //size of each trampoline area would be no more than 4k Bytes(one page)
#define TRAMPOLINE_SPACE_SIZE 4096 // 4k mem page size

#endif //YAHFA_TAMPOLINE_H

0 comments on commit cd76a9d

Please sign in to comment.