aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYifan Lu2016-10-09 10:12:46 -0700
committerYifan Lu2016-10-09 10:12:46 -0700
commit5848726e6ab91bfb685afb7f5c8f46d1526d6385 (patch)
treee8de8bad63a49db1c4d357174885c77fcd4039ce
parentAdded slab allocator for trampoline in Vita platform (diff)
downloadsubstitute-5848726e6ab91bfb685afb7f5c8f46d1526d6385.tar.gz
Slab allocation mirroring for Vita
-rw-r--r--lib/darwin/execmem.c4
-rw-r--r--lib/execmem.h4
-rw-r--r--lib/hook-functions.c17
-rw-r--r--lib/vita/execmem.c17
-rwxr-xr-xlib/vita/slab.c15
-rwxr-xr-xlib/vita/slab.h2
6 files changed, 32 insertions, 27 deletions
diff --git a/lib/darwin/execmem.c b/lib/darwin/execmem.c
index ce3bafd..44b26ae 100644
--- a/lib/darwin/execmem.c
+++ b/lib/darwin/execmem.c
@@ -74,13 +74,13 @@ int execmem_alloc_unsealed(uintptr_t hint, void **page_p, uintptr_t *vma_p,
return SUBSTITUTE_OK;
}
-int execmem_seal(void *page, UNUSED uintptr_t vma, UNUSED void *opt) {
+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, UNUSED uintptr_t vma, UNUSED void *opt) {
+void execmem_free(void *page, UNUSED void *opt) {
munmap(page, PAGE_SIZE);
}
diff --git a/lib/execmem.h b/lib/execmem.h
index dbf2dda..07e9fa4 100644
--- a/lib/execmem.h
+++ b/lib/execmem.h
@@ -2,8 +2,8 @@
#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, void *opt);
-int execmem_seal(void *page, uintptr_t vma, void *opt);
-void execmem_free(void *page, uintptr_t vma, 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.
diff --git a/lib/hook-functions.c b/lib/hook-functions.c
index 11fa9ac..ac28b69 100644
--- a/lib/hook-functions.c
+++ b/lib/hook-functions.c
@@ -19,7 +19,6 @@ struct hook_internal {
/* page allocated with execmem_alloc_unsealed - only if we had to allocate
* one when processing this hook */
void *trampoline_page;
- uintptr_t trampoline_addr;
struct arch_dis_ctx arch_dis_ctx;
};
@@ -73,7 +72,6 @@ static int check_intro_trampoline(void **trampoline_ptr_p,
int *patch_size_p,
bool *need_intro_trampoline_p,
void **trampoline_page_p,
- uintptr_t *trampoline_page_addr_p,
struct arch_dis_ctx arch,
void *opt) {
void *trampoline_ptr = *trampoline_ptr_p;
@@ -109,7 +107,7 @@ static int check_intro_trampoline(void **trampoline_ptr_p,
goto end;
}
- execmem_free(trampoline_ptr, trampoline_addr, opt);
+ execmem_free(trampoline_ptr, opt);
}
/* Allocate new trampoline - try before pc (xxx only meaningful on arm64) */
@@ -123,7 +121,7 @@ static int check_intro_trampoline(void **trampoline_ptr_p,
goto end;
}
- execmem_free(trampoline_ptr, trampoline_addr, opt);
+ execmem_free(trampoline_ptr, opt);
ret = SUBSTITUTE_ERR_OUT_OF_RANGE;
}
@@ -132,7 +130,6 @@ end:
*trampoline_addr_p = trampoline_addr;
*trampoline_size_left_p = trampoline_size_left;
*trampoline_page_p = trampoline_ptr;
- *trampoline_page_addr_p = trampoline_addr;
return ret;
}
@@ -194,8 +191,7 @@ 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,
- &hi->trampoline_addr, arch,
+ &hi->trampoline_page, arch,
hook->opt)))
goto end;
@@ -232,7 +228,6 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks,
* ensure this size is aligned to ARCH_MAX_CODE_ALIGNMENT otherwise
* MAX_JUMP_PATCH_SIZE might be wrong. */
hi->trampoline_page = trampoline_ptr;
- hi->trampoline_addr = trampoline_addr;
}
void *outro_trampoline_real = trampoline_ptr;
@@ -282,9 +277,8 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks,
for (size_t i = 0; i < nhooks; i++) {
struct hook_internal *hi = &his[i];
void *page = hi->trampoline_page;
- uintptr_t addr = hi->trampoline_addr;
if (page)
- execmem_seal(page, addr, hooks[i].opt);
+ execmem_seal(page, hooks[i].opt);
fws[i].dst = hi->code;
fws[i].src = hi->jump_patch;
fws[i].len = hi->jump_patch_size;
@@ -307,9 +301,8 @@ end:
/* if we failed, get rid of the trampolines. */
for (size_t i = 0; i < nhooks; i++) {
void *page = his[i].trampoline_page;
- uintptr_t addr = his[i].trampoline_addr;
if (page)
- execmem_free(page, addr, hooks[i].opt);
+ execmem_free(page, hooks[i].opt);
}
end_dont_free:
return ret;
diff --git a/lib/vita/execmem.c b/lib/vita/execmem.c
index 526b29b..84927d6 100644
--- a/lib/vita/execmem.c
+++ b/lib/vita/execmem.c
@@ -8,12 +8,15 @@
/** The size of each trampoline allocation. We use it for outro and optional
* intro. Realistically, we do not use an intro.
*/
-#define SLAB_SIZE (TD_MAX_REWRITTEN_SIZE + 2 * MAX_JUMP_PATCH_SIZE)
-#if (SLAB_SIZE % ARCH_MAX_CODE_ALIGNMENT != 0)
+#define SLAB_ITEM_SIZE (TD_MAX_REWRITTEN_SIZE + 2 * MAX_JUMP_PATCH_SIZE)
+#if (SLAB_ITEM_SIZE % ARCH_MAX_CODE_ALIGNMENT != 0)
// if not aligned then substitute_hook_functions breaks!
-#error SLAB_SIZE Must be aligned to ARCH_MAX_CODE_ALIGNMENT
+#error SLAB_ITEM_SIZE Must be aligned to ARCH_MAX_CODE_ALIGNMENT
#endif
+/** Allow other files to use this constant. */
+const int g_exe_slab_item_size = SLAB_ITEM_SIZE;
+
/**
* @file execmem.c
*
@@ -34,7 +37,7 @@
* @param[in] hint Unused
* @param ptr_p The writable pointer
* @param vma_p The executable pointer address
- * @param size_p The size of the allocation. Always `SLAB_SIZE`.
+ * @param size_p The size of the allocation. Always `SLAB_ITEM_SIZE`.
* @param opt A `tai_substitute_args_t` structure
* @param[in] hint Unused
*
@@ -49,12 +52,11 @@ int execmem_alloc_unsealed(UNUSED uintptr_t hint, void **ptr_p, uintptr_t *vma_p
* @brief Flushes icache
*
* @param ptr Unused
- * @param[in] vma Pointer to flush
* @param opt A `tai_substitute_args_t` structure
*
* @return `SUBSTITUTE_OK`
*/
-int execmem_seal(UNUSED void *ptr, uintptr_t vma, void *opt) {
+int execmem_seal(UNUSED void *ptr, void *opt) {
return SUBSTITUTE_OK;
}
@@ -62,10 +64,9 @@ int execmem_seal(UNUSED void *ptr, uintptr_t vma, void *opt) {
* @brief Frees executable memory from slab allocator
*
* @param ptr The writable pointer
- * @param[in] vma The executable address. Must match with ptr.
* @param opt A `tai_substitute_args_t` structure
*/
-void execmem_free(void *ptr, uintptr_t vma, void *opt) {
+void execmem_free(void *ptr, void *opt) {
}
/**
diff --git a/lib/vita/slab.c b/lib/vita/slab.c
index 0ca3529..91742a6 100755
--- a/lib/vita/slab.c
+++ b/lib/vita/slab.c
@@ -2,7 +2,6 @@
#include "slab.h"
-#include <math.h>
#include <stdint.h>
#include <stddef.h>
@@ -49,6 +48,18 @@ static int sce_exe_free(SceUID write_res, SceUID exe_res) {
return 0;
}
+static inline uint32_t next_pow_2(uint32_t v) {
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v++;
+ v += (v == 0);
+ return v;
+}
+
void slab_init(struct slab_chain *const sch, const size_t itemsize, SceUID pid)
{
assert(sch != NULL);
@@ -60,7 +71,7 @@ void slab_init(struct slab_chain *const sch, const size_t itemsize, SceUID pid)
const size_t data_offset = offsetof(struct slab_header, data);
const size_t least_slabsize = data_offset + 64 * sch->itemsize;
- sch->slabsize = (size_t) 1 << (size_t) ceil(log2(least_slabsize));
+ sch->slabsize = (size_t) next_pow_2(least_slabsize);
sch->itemcount = 64;
if (sch->slabsize - least_slabsize != 0) {
diff --git a/lib/vita/slab.h b/lib/vita/slab.h
index 942eb70..c8c5d9b 100755
--- a/lib/vita/slab.h
+++ b/lib/vita/slab.h
@@ -32,7 +32,7 @@ struct slab_chain {
SceUID pid;
};
-void slab_init(struct slab_chain *, size_t);
+void slab_init(struct slab_chain *, size_t, SceUID);
void *slab_alloc(struct slab_chain *, uintptr_t *);
void slab_free(struct slab_chain *, const void *);
void slab_traverse(const struct slab_chain *, void (*)(const void *));