aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYifan Lu2016-10-08 14:03:00 -0700
committerYifan Lu2016-10-08 14:03:00 -0700
commit750b4eb89e8504ef7ec88528538e0c92fc06678a (patch)
tree72dda33aa6d51e29b0494ed3f6025d5be9b07ffd
parentSupport using a different VMA for the hook dest (diff)
downloadsubstitute-750b4eb89e8504ef7ec88528538e0c92fc06678a.tar.gz
Added support for platform specific aux data to execmem
-rw-r--r--lib/darwin/execmem.c7
-rw-r--r--lib/execmem.h7
-rw-r--r--lib/hook-functions.c22
-rw-r--r--lib/substitute.h2
-rw-r--r--lib/vita/execmem.c9
5 files changed, 28 insertions, 19 deletions
diff --git a/lib/darwin/execmem.c b/lib/darwin/execmem.c
index 540cb8e..44b26ae 100644
--- a/lib/darwin/execmem.c
+++ b/lib/darwin/execmem.c
@@ -63,7 +63,8 @@ static execmem_pc_patch_callback g_pc_patch_callback;
static void *g_pc_patch_callback_ctx;
static mach_port_t g_suspending_thread;
-int execmem_alloc_unsealed(uintptr_t hint, void **page_p, uintptr_t *vma_p, size_t *size_p) {
+int execmem_alloc_unsealed(uintptr_t hint, void **page_p, uintptr_t *vma_p,
+ size_t *size_p, UNUSED void *opt) {
*size_p = PAGE_SIZE;
*page_p = mmap((void *) hint, *size_p, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_SHARED, -1, 0);
@@ -73,13 +74,13 @@ int execmem_alloc_unsealed(uintptr_t hint, void **page_p, uintptr_t *vma_p, size
return SUBSTITUTE_OK;
}
-int execmem_seal(void *page) {
+int execmem_seal(void *page, UNUSED void *opt) {
if (mprotect(page, PAGE_SIZE, PROT_READ | PROT_EXEC))
return SUBSTITUTE_ERR_VM;
return SUBSTITUTE_OK;
}
-void execmem_free(void *page) {
+void execmem_free(void *page, UNUSED void *opt) {
munmap(page, PAGE_SIZE);
}
diff --git a/lib/execmem.h b/lib/execmem.h
index 8817f38..07e9fa4 100644
--- a/lib/execmem.h
+++ b/lib/execmem.h
@@ -1,9 +1,9 @@
#pragma once
#include <sys/types.h>
/* For allocating trampolines - this is just a mmap wrapper. */
-int execmem_alloc_unsealed(uintptr_t hint, void **page_p, uintptr_t *vma_p, size_t *size_p);
-int execmem_seal(void *page);
-void execmem_free(void *page);
+int execmem_alloc_unsealed(uintptr_t hint, void **page_p, uintptr_t *vma_p, size_t *size_p, void *opt);
+int execmem_seal(void *page, void *opt);
+void execmem_free(void *page, void *opt);
/* Write to "foreign" (i.e. owned by another library, not out-of-process) pages
* which are already RX or have unknown permissions.
@@ -15,6 +15,7 @@ struct execmem_foreign_write {
void *dst;
const void *src;
size_t len;
+ void *opt;
};
typedef uintptr_t (*execmem_pc_patch_callback)(void *ctx, uintptr_t pc);
int execmem_foreign_write_with_pc_patch(struct execmem_foreign_write *writes,
diff --git a/lib/hook-functions.c b/lib/hook-functions.c
index 4fc61e0..996e781 100644
--- a/lib/hook-functions.c
+++ b/lib/hook-functions.c
@@ -72,7 +72,8 @@ static int check_intro_trampoline(void **trampoline_ptr_p,
int *patch_size_p,
bool *need_intro_trampoline_p,
void **trampoline_page_p,
- struct arch_dis_ctx arch) {
+ struct arch_dis_ctx arch,
+ void *opt) {
void *trampoline_ptr = *trampoline_ptr_p;
uintptr_t trampoline_addr = *trampoline_addr_p;
size_t trampoline_size_left = *trampoline_size_left_p;
@@ -98,7 +99,7 @@ static int check_intro_trampoline(void **trampoline_ptr_p,
/* Allocate new trampoline - try after pc. If this fails, we can try
* before pc before giving up. */
int ret = execmem_alloc_unsealed(pc, &trampoline_ptr, &trampoline_addr,
- &trampoline_size_left);
+ &trampoline_size_left, opt);
if (!ret) {
*patch_size_p = jump_patch_size(pc, trampoline_addr, arch, false);
if (*patch_size_p != -1) {
@@ -106,13 +107,13 @@ static int check_intro_trampoline(void **trampoline_ptr_p,
goto end;
}
- execmem_free(trampoline_ptr);
+ execmem_free(trampoline_ptr, opt);
}
/* Allocate new trampoline - try before pc (xxx only meaningful on arm64) */
uintptr_t start_address = pc - 0x80000000;
ret = execmem_alloc_unsealed(start_address, &trampoline_ptr, &trampoline_addr,
- &trampoline_size_left);
+ &trampoline_size_left, opt);
if (!ret) {
*patch_size_p = jump_patch_size(pc, trampoline_addr, arch, false);
if (*patch_size_p != -1) {
@@ -120,7 +121,7 @@ static int check_intro_trampoline(void **trampoline_ptr_p,
goto end;
}
- execmem_free(trampoline_ptr);
+ execmem_free(trampoline_ptr, opt);
ret = SUBSTITUTE_ERR_OUT_OF_RANGE;
}
@@ -190,7 +191,8 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks,
&trampoline_size_left, pc_patch_start,
(uintptr_t) hook->replacement,
&patch_size, &need_intro_trampoline,
- &hi->trampoline_page, arch)))
+ &hi->trampoline_page, arch,
+ hook->opt)))
goto end;
uint_tptr pc_patch_end = pc_patch_start + patch_size;
@@ -217,7 +219,8 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks,
/* Not enough space left in our existing block... */
if ((ret = execmem_alloc_unsealed(0, &trampoline_ptr,
&trampoline_addr,
- &trampoline_size_left)))
+ &trampoline_size_left,
+ hook->opt)))
goto end;
/* NOTE: We assume that each page is large enough (min 0x1000)
* so we don't lose a reference by having one hook allocate two
@@ -273,10 +276,11 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks,
struct hook_internal *hi = &his[i];
void *page = hi->trampoline_page;
if (page)
- execmem_seal(page);
+ execmem_seal(page, hooks[i].opt);
fws[i].dst = hi->code;
fws[i].src = hi->jump_patch;
fws[i].len = hi->jump_patch_size;
+ fws[i].opt = hooks[i].opt;
}
struct pc_callback_info info = {his, nhooks, false};
@@ -296,7 +300,7 @@ end:
for (size_t i = 0; i < nhooks; i++) {
void *page = his[i].trampoline_page;
if (page)
- execmem_free(page);
+ execmem_free(page, hooks[i].opt);
}
end_dont_free:
return ret;
diff --git a/lib/substitute.h b/lib/substitute.h
index 9a8d9ba..4e4f7f9 100644
--- a/lib/substitute.h
+++ b/lib/substitute.h
@@ -100,6 +100,8 @@ struct substitute_function_hook {
int options;
/* If not zero, then assume the actual address of function is func_addr */
uintptr_t func_addr;
+ /* Any platform specific auxiliary data */
+ void *opt;
};
/* substitute_hook_functions options */
diff --git a/lib/vita/execmem.c b/lib/vita/execmem.c
index c0fba65..6bfb2ba 100644
--- a/lib/vita/execmem.c
+++ b/lib/vita/execmem.c
@@ -2,20 +2,21 @@
#include "execmem.h"
#include "substitute.h"
-int execmem_alloc_unsealed(uintptr_t hint, void **page_p, uintptr_t *vma_p, size_t *size_p) {
+int execmem_alloc_unsealed(uintptr_t hint, void **page_p, uintptr_t *vma_p,
+ size_t *size_p, void *opt) {
return 0;
}
-int execmem_seal(void *page) {
+int execmem_seal(void *page, void *opt) {
return SUBSTITUTE_OK;
}
-void execmem_free(void *page) {
+void execmem_free(void *page, void *opt) {
}
int execmem_foreign_write_with_pc_patch(struct execmem_foreign_write *writes,
size_t nwrites,
execmem_pc_patch_callback callback,
- void *callback_ctx) {
+ void *callback_ctx, void *opt) {
return 0;
}