#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 <ffi.h>
#ifndef PSI_HAVE_FFI_CLOSURE_ALLOC
-# include <unistd.h>
-# include <sys/mman.h>
+# if HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+# if HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+# 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 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;
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,
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));
}
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);
}
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));
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];
}
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) {