summaryrefslogtreecommitdiff
path: root/src/closures.c
diff options
context:
space:
mode:
authorLandon Fuller <landonf@bikemonkey.org>2010-09-19 14:36:45 -0700
committerLandon Fuller <landonf@bikemonkey.org>2010-09-19 14:36:45 -0700
commit83038cf24aa1a92b62b91ffee1dcc25d79243484 (patch)
tree3a97ff8e18e182320087ff4c18736aa29feec1ca /src/closures.c
parentb00ff3e98fdde622cef617030e14d5356dff988f (diff)
downloadlibffi-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.c80
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 */