X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Flibffi.c;h=897affbd56d28dded713f8029159b7ec0fa70884;hp=c6df4276d0f70dbae707e391a8d93a93f5cbfb23;hb=9c71742e3aa27507196cf34daa9eeecde8545a40;hpb=7eb47ef2fc5655e7196e4e0fbf5104eed8274601 diff --git a/src/libffi.c b/src/libffi.c index c6df427..897affb 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -2,12 +2,51 @@ #include "php_psi.h" #include "libffi.h" +#undef PACKAGE +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION + #include #ifndef PSI_HAVE_FFI_CLOSURE_ALLOC -# include -# include +# 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); @@ -85,7 +124,7 @@ typedef struct PSI_LibffiData { static inline PSI_LibffiData *PSI_LibffiDataAlloc(PSI_LibffiContext *context, impl *impl) { ffi_status rc; - size_t i, c = impl->decl->args->count; + size_t i, c = impl->decl->args ? impl->decl->args->count : 0; PSI_LibffiData *data = malloc(sizeof(*data) + c * sizeof(ffi_type *)); data->context = context; @@ -104,8 +143,9 @@ static inline PSI_LibffiData *PSI_LibffiDataAlloc(PSI_LibffiContext *context, im data->params); ZEND_ASSERT(FFI_OK == rc); -#ifdef PSI_HAVE_FFI_CLOSURE_ALLOC - 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, @@ -113,14 +153,11 @@ static inline PSI_LibffiData *PSI_LibffiDataAlloc(PSI_LibffiContext *context, im data, data->code); ZEND_ASSERT(FFI_OK == rc); -#else - i = getpagesize(); - data->closure = malloc(sizeof(ffi_closure) + i); - data->code = (void *) (((intptr_t) data->closure + i - 1) & ~((intptr_t) i - 1)); - rc = mprotect(data->code, sizeof(ffi_closure), PROT_EXEC|PROT_WRITE); - ZEND_ASSERT(rc == 0); +#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)); @@ -130,12 +167,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); -#ifdef PSI_HAVE_FFI_CLOSURE_FREE - ffi_closure_free(data->closure); -#else - free(data->closure); -#endif free(data); } @@ -185,7 +218,7 @@ static void handler(ffi_cif *_sig, void *_result, void **_args, void *_data) return; } - if (data->impl->decl->args->count) { + if (data->impl->decl->args) { arg_ptr = malloc(data->impl->decl->args->count * sizeof(*arg_ptr)); arg_prm = malloc(data->impl->decl->args->count * sizeof(*arg_prm)); @@ -193,7 +226,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]; } @@ -206,7 +240,9 @@ static void handler(ffi_cif *_sig, void *_result, void **_args, void *_data) for (i = 0; i < data->impl->stmts->set.count; ++i) { set_stmt *set = data->impl->stmts->set.list[i]; - psi_do_set(set->arg->_zv, set->val->func, set->val->vars); + if (set->arg->_zv) { + psi_do_set(set->arg->_zv, set->val->func, set->val->vars); + } } for (i = 0; i < data->impl->stmts->fre.count; ++i) {