From 5848726e6ab91bfb685afb7f5c8f46d1526d6385 Mon Sep 17 00:00:00 2001 From: Yifan Lu Date: Sun, 9 Oct 2016 10:12:46 -0700 Subject: Slab allocation mirroring for Vita --- lib/darwin/execmem.c | 4 ++-- lib/execmem.h | 4 ++-- lib/hook-functions.c | 17 +++++------------ lib/vita/execmem.c | 17 +++++++++-------- lib/vita/slab.c | 15 +++++++++++++-- lib/vita/slab.h | 2 +- 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 /* 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 #include #include @@ -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 *)); -- cgit v1.2.3