diff options
author | Landon Fuller <landonf@bikemonkey.org> | 2010-09-19 14:36:45 -0700 |
---|---|---|
committer | Landon Fuller <landonf@bikemonkey.org> | 2010-09-19 14:36:45 -0700 |
commit | 83038cf24aa1a92b62b91ffee1dcc25d79243484 (patch) | |
tree | 3a97ff8e18e182320087ff4c18736aa29feec1ca /src/closures.c | |
parent | b00ff3e98fdde622cef617030e14d5356dff988f (diff) | |
download | libffi-83038cf24aa1a92b62b91ffee1dcc25d79243484.tar.gz |
Implement FFI_EXEC_TRAMPOLINE_TABLE allocator for iOS/ARM.
This provides working closure support on iOS/ARM devices where
PROT_WRITE|PROT_EXEC is not permitted. The code passes basic
smoke tests, but requires further review.
Diffstat (limited to 'src/closures.c')
-rw-r--r-- | src/closures.c | 80 |
1 files changed, 1 insertions, 79 deletions
diff --git a/src/closures.c b/src/closures.c index c214196..ac878df 100644 --- a/src/closures.c +++ b/src/closures.c @@ -65,85 +65,7 @@ # if FFI_EXEC_TRAMPOLINE_TABLE -// XXX - non-thread-safe, non-portable implementation, intended for initial testing -#include <mach/mach.h> -#include <stdio.h> -#include <stdlib.h> - -extern void *ffi_closure_trampoline_table; - -static void *tramp_table = NULL; -static void **config_table = NULL; -static int tramp_table_free = 0; - -void * -ffi_closure_alloc (size_t size, void **code) -{ - if (!code) - return NULL; - - /* Allocate our config page and remap the trampoline table */ - while (tramp_table == NULL) { - vm_address_t config_page = 0x0; - kern_return_t kt; - - /* Try to allocate two pages */ - kt = vm_allocate(mach_task_self(), &config_page, PAGE_SIZE*2, VM_FLAGS_ANYWHERE); - if (kt != KERN_SUCCESS) { - fprintf(stderr, "vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); - break; - } - - /* Now drop the second half of the allocation to make room for the trampoline table */ - kt = vm_deallocate(mach_task_self(), config_page+PAGE_SIZE, PAGE_SIZE); - if (kt != KERN_SUCCESS) { - fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); - break; - } - - /* Remap the trampoline table to directly follow the config page */ - vm_address_t table_page = config_page+PAGE_SIZE; - vm_prot_t cur_prot; - vm_prot_t max_prot; - - kt = vm_remap(mach_task_self(), &table_page, PAGE_SIZE, 0x0, FALSE, mach_task_self(), (vm_address_t) &ffi_closure_trampoline_table, FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE); - - /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */ - if (kt != KERN_SUCCESS) { - /* Log unexpected failures */ - if (kt != KERN_NO_SPACE) { - fprintf(stderr, "vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); - } - - vm_deallocate(mach_task_self(), config_page, PAGE_SIZE); - continue; - } - - tramp_table = (void *) table_page; - config_table = (void **) config_page; - config_table += 4; // XXX - there's a 16 byte offset into the config page on ARM - - fprintf(stderr, "[DEBUG] Allocated config page at %p, trampoline page at %p, configs start at %p\n", (void *) config_page, (void *) table_page, config_table); - } - - /* Check for permanent allocation failure */ - if (tramp_table == NULL) - return *code = NULL; - - *code = tramp_table + (3 * tramp_table_free); - tramp_table_free++; - - void *closure = malloc(size); - - return closure; -} - -void -ffi_closure_free (void *ptr) -{ - // TODO - //free (ptr); -} +// Per-target implementation; It's unclear what can reasonable be shared between two OS/architecture implementations. # elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */ |