From 1ed9ebdea558a7ae265dcc460cedd2cbbaa48efc Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 26 Jul 2019 14:37:34 +0200 Subject: [PATCH] Support calling convention specific function name mangling On Windows certain calling conventions cause C function names to be mangled, so to import them we have to use the properly mangled names. --- ext/ffi/ffi.c | 42 +++++++++++++++++++++++++++++++-- ext/ffi/tests/callconv.phpt | 41 ++++++++++++++++++++++++++++++++ ext/ffi/tests/callconv_x86.dll | Bin 0 -> 8704 bytes 3 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 ext/ffi/tests/callconv.phpt create mode 100644 ext/ffi/tests/callconv_x86.dll diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index c665ad151e..552d168fd6 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -765,6 +765,38 @@ again: } /* }}} */ +#if defined(ZEND_WIN32) && (defined(HAVE_FFI_FASTCALL) || defined(HAVE_FFI_STDCALL)) +static size_t zend_ffi_arg_size(zend_ffi_type *type) /* {{{ */ +{ + zend_ffi_type *arg_type; + size_t arg_size = 0; + + ZEND_HASH_FOREACH_PTR(type->func.args, arg_type) { + arg_size += ZEND_FFI_TYPE(arg_type)->size; + } ZEND_HASH_FOREACH_END(); + return arg_size; +} +/* }}} */ +#endif + +static zend_always_inline zend_string *zend_ffi_mangled_func_name(zend_string *name, zend_ffi_type *type) /* {{{ */ +{ +#ifdef ZEND_WIN32 + switch (type->func.abi) { +# ifdef HAVE_FFI_FASTCALL + case FFI_FASTCALL: + return strpprintf(0, "@%s@%zu", ZSTR_VAL(name), zend_ffi_arg_size(type)); +# endif +# ifdef HAVE_FFI_STDCALL + case FFI_STDCALL: + return strpprintf(0, "_%s@%zu", ZSTR_VAL(name), zend_ffi_arg_size(type)); +# endif + } +#endif + return zend_string_copy(name); +} +/* }}} */ + #if FFI_CLOSURES typedef struct _zend_ffi_callback_data { zend_fcall_info_cache fcc; @@ -2842,7 +2874,10 @@ ZEND_METHOD(FFI, cdef) /* {{{ */ } sym->addr = addr; } else if (sym->kind == ZEND_FFI_SYM_FUNC) { - addr = DL_FETCH_SYMBOL(handle, ZSTR_VAL(name)); + zend_string *mangled_name = zend_ffi_mangled_func_name(name, ZEND_FFI_TYPE(sym->type)); + + addr = DL_FETCH_SYMBOL(handle, ZSTR_VAL(mangled_name)); + zend_string_release(mangled_name); if (!addr) { zend_throw_error(zend_ffi_exception_ce, "Failed resolving C function '%s'", ZSTR_VAL(name)); } @@ -3172,7 +3207,10 @@ ZEND_METHOD(FFI, load) /* {{{ */ } sym->addr = addr; } else if (sym->kind == ZEND_FFI_SYM_FUNC) { - addr = DL_FETCH_SYMBOL(handle, ZSTR_VAL(name)); + zend_string *mangled_name = zend_ffi_mangled_func_name(name, ZEND_FFI_TYPE(sym->type)); + + addr = DL_FETCH_SYMBOL(handle, ZSTR_VAL(mangled_name)); + zend_string_release(mangled_name); if (!addr) { if (preload) { zend_error(E_WARNING, "failed pre-loading '%s', cannot resolve C function '%s'", filename, ZSTR_VAL(name)); diff --git a/ext/ffi/tests/callconv.phpt b/ext/ffi/tests/callconv.phpt new file mode 100644 index 0000000000..aa481de224 --- /dev/null +++ b/ext/ffi/tests/callconv.phpt @@ -0,0 +1,41 @@ +--TEST-- +Different calling conventions +--SKIPIF-- + +--FILE-- +cdecl_func(1, 2.3); +$ffi1->stdcall_func(4, 5.6); +$ffi1->fastcall_func(7, 8.9); + +file_put_contents($headername, "#define FFI_LIB \"$dllname\"\n$header"); + +$ffi2 = FFI::load($headername); +$ffi2->cdecl_func(2, 3.4); +$ffi2->stdcall_func(5, 6.7); +$ffi2->fastcall_func(8, 9.1); +?> +--EXPECT-- +cdecl: 1, 2.300000 +stdcall: 4, 5.600000 +fastcall: 7, 8.900000 +cdecl: 2, 3.400000 +stdcall: 5, 6.700000 +fastcall: 8, 9.100000 +--CLEAN-- + diff --git a/ext/ffi/tests/callconv_x86.dll b/ext/ffi/tests/callconv_x86.dll new file mode 100644 index 0000000000000000000000000000000000000000..f4818d10916842c21a0663df68cbc6608fab8865 GIT binary patch literal 8704 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 J