X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Flibffi.c;h=2c68fbf0ee4bb34834dd51b910bdb1ec39e3f3e5;hp=1dbc08010023f1e44d53db044ffb83f45eacf853;hb=70136a34090807976d66b361fbc8963c0c91f17e;hpb=633acd548ce5da37812bca7119e57c8f56e974e2 diff --git a/src/libffi.c b/src/libffi.c index 1dbc080..2c68fbf 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -4,6 +4,43 @@ #include +#ifndef PSI_HAVE_FFI_CLOSURE_ALLOC +# if HAVE_UNISTD_H +# include +# endif +# if HAVE_SYS_MMAN_H +# include +# ifndef MAP_ANONYMOUS +# define MAP_ANONYMOUS MAP_ANON +# endif +# endif +#endif + +static void *psi_ffi_closure_alloc(size_t s, void **code) +{ +#ifdef PSI_HAVE_FFI_CLOSURE_ALLOC + return ffi_closure_alloc(s, code); +#elif HAVE_MMAP + *code = mmap(NULL, s, PROT_EXEC|PROT_WRITE|PROT_READ, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + if (MAP_FAILED == *code) { + return NULL; + } + return *code; +#else + return NULL; +#endif +} + +static void psi_ffi_closure_free(void *c) +{ +#ifdef PSI_HAVE_FFI_CLOSURE_ALLOC + ffi_closure_free(c); +#elif HAVE_MMAP + munmap(c, sizeof(ffi_closure)); +#endif +} + static void handler(ffi_cif *signature, void *_result, void **_args, void *_data); static inline ffi_abi psi_ffi_abi(const char *convention) { @@ -98,7 +135,10 @@ static inline PSI_LibffiData *PSI_LibffiDataAlloc(PSI_LibffiContext *context, im psi_ffi_decl_arg_type(data->impl->decl->func), data->params); ZEND_ASSERT(FFI_OK == rc); - data->closure = ffi_closure_alloc(sizeof(ffi_closure), &data->code); + + data->closure = psi_ffi_closure_alloc(sizeof(ffi_closure), &data->code); + ZEND_ASSERT(data->closure != NULL); +#if PSI_HAVE_FFI_PREP_CLOSURE_LOC rc = ffi_prep_closure_loc( data->closure, &context->signature, @@ -106,6 +146,12 @@ static inline PSI_LibffiData *PSI_LibffiDataAlloc(PSI_LibffiContext *context, im data, data->code); ZEND_ASSERT(FFI_OK == rc); +#elif PSI_HAVE_FFI_PREP_CLOSURE + rc = ffi_prep_closure(data->code, &context->signature, handler, data); + ZEND_ASSERT(FFI_OK == rc); +#else +# error "Neither ffi_prep_closure() nor ffi_prep_closure_loc() available" +#endif context->data.list = realloc(context->data.list, ++context->data.count * sizeof(*context->data.list)); context->data.list[context->data.count-1] = data; @@ -114,8 +160,8 @@ static inline PSI_LibffiData *PSI_LibffiDataAlloc(PSI_LibffiContext *context, im } static inline void PSI_LibffiDataFree(PSI_LibffiData *data) { + psi_ffi_closure_free(data->closure); free(data->arginfo); - ffi_closure_free(data->closure); free(data); } @@ -173,7 +219,8 @@ static void handler(ffi_cif *_sig, void *_result, void **_args, void *_data) decl_arg *darg = data->impl->decl->args->args[i]; arg_ptr[i] = psi_do_let(darg); - arg_prm[i] = darg->let->val->is_reference ? &arg_ptr[i] : arg_ptr[i]; + arg_prm[i] = (darg->let->val && darg->let->val->is_reference) + ? &arg_ptr[i] : arg_ptr[i]; darg->let->ptr = arg_ptr[i]; }