Commit 32119e10 authored by Paul Monson's avatar Paul Monson Committed by Steve Dower

bpo-35947: Update Windows to the current version of libffi (GH-11797)

We now use a pre-built libffi binary from our binaries repository, and no longer vendor the full implementation.
parent 3396d1e0
......@@ -6,35 +6,6 @@ from test import support
import _ctypes_test
# Only windows 32-bit has different calling conventions.
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
@unittest.skipUnless(sizeof(c_void_p) == sizeof(c_int),
"sizeof c_void_p and c_int differ")
class WindowsTestCase(unittest.TestCase):
def test_callconv_1(self):
# Testing stdcall function
IsWindow = windll.user32.IsWindow
# ValueError: Procedure probably called with not enough arguments
# (4 bytes missing)
self.assertRaises(ValueError, IsWindow)
# This one should succeed...
self.assertEqual(0, IsWindow(0))
# ValueError: Procedure probably called with too many arguments
# (8 bytes in excess)
self.assertRaises(ValueError, IsWindow, 0, 0, 0)
def test_callconv_2(self):
# Calling stdcall function as cdecl
IsWindow = cdll.user32.IsWindow
# ValueError: Procedure called with not enough arguments
# (4 bytes missing) or wrong calling convention
self.assertRaises(ValueError, IsWindow, None)
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
class FunctionCallTestCase(unittest.TestCase):
@unittest.skipUnless('MSC' in sys.version, "SEH only supported by MSC")
......
Added current version of libffi to cpython-source-deps.
Change _ctypes to use current version of libffi on Windows.
......@@ -403,24 +403,35 @@ static PyCArgObject *
StructUnionType_paramfunc(CDataObject *self)
{
PyCArgObject *parg;
CDataObject *copied_self;
StgDictObject *stgdict;
if (self->b_size > sizeof(void*)) {
void *new_ptr = PyMem_Malloc(self->b_size);
if (new_ptr == NULL)
return NULL;
memcpy(new_ptr, self->b_ptr, self->b_size);
copied_self = (CDataObject *)PyCData_AtAddress(
(PyObject *)Py_TYPE(self), new_ptr);
copied_self->b_needsfree = 1;
} else {
copied_self = self;
Py_INCREF(copied_self);
}
parg = PyCArgObject_new();
if (parg == NULL)
if (parg == NULL) {
Py_DECREF(copied_self);
return NULL;
}
parg->tag = 'V';
stgdict = PyObject_stgdict((PyObject *)self);
stgdict = PyObject_stgdict((PyObject *)copied_self);
assert(stgdict); /* Cannot be NULL for structure/union instances */
parg->pffi_type = &stgdict->ffi_type_pointer;
/* For structure parameters (by value), parg->value doesn't contain the structure
data itself, instead parg->value.p *points* to the structure's data
See also _ctypes.c, function _call_function_pointer().
*/
parg->value.p = self->b_ptr;
parg->size = self->b_size;
Py_INCREF(self);
parg->obj = (PyObject *)self;
parg->value.p = copied_self->b_ptr;
parg->size = copied_self->b_size;
parg->obj = (PyObject *)copied_self;
return parg;
}
......
......@@ -729,6 +729,23 @@ static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa)
}
}
#if defined(MS_WIN32) && !defined(_WIN32_WCE)
/*
Per: https://msdn.microsoft.com/en-us/library/7572ztz4.aspx
To be returned by value in RAX, user-defined types must have a length
of 1, 2, 4, 8, 16, 32, or 64 bits
*/
int can_return_struct_as_int(size_t s)
{
return s == 1 || s == 2 || s == 4;
}
int can_return_struct_as_sint64(size_t s)
{
return s == 8;
}
#endif
ffi_type *_ctypes_get_ffi_type(PyObject *obj)
{
......@@ -778,12 +795,9 @@ static int _call_function_pointer(int flags,
int *space;
ffi_cif cif;
int cc;
#ifdef MS_WIN32
int delta;
#ifndef DONT_USE_SEH
#if defined(MS_WIN32) && !defined(DONT_USE_SEH)
DWORD dwExceptionCode = 0;
EXCEPTION_RECORD record;
#endif
#endif
/* XXX check before here */
if (restype == NULL) {
......@@ -828,7 +842,6 @@ static int _call_function_pointer(int flags,
#ifndef DONT_USE_SEH
__try {
#endif
delta =
#endif
ffi_call(&cif, (void *)pProc, resmem, avalues);
#ifdef MS_WIN32
......@@ -860,35 +873,6 @@ static int _call_function_pointer(int flags,
return -1;
}
#endif
#ifdef MS_WIN64
if (delta != 0) {
PyErr_Format(PyExc_RuntimeError,
"ffi_call failed with code %d",
delta);
return -1;
}
#else
if (delta < 0) {
if (flags & FUNCFLAG_CDECL)
PyErr_Format(PyExc_ValueError,
"Procedure called with not enough "
"arguments (%d bytes missing) "
"or wrong calling convention",
-delta);
else
PyErr_Format(PyExc_ValueError,
"Procedure probably called with not enough "
"arguments (%d bytes missing)",
-delta);
return -1;
} else if (delta > 0) {
PyErr_Format(PyExc_ValueError,
"Procedure probably called with too many "
"arguments (%d bytes in excess)",
delta);
return -1;
}
#endif
#endif
if ((flags & FUNCFLAG_PYTHONAPI) && PyErr_Occurred())
return -1;
......
libffi - Copyright (c) 1996-2003 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
This diff is collapsed.
The purpose is to hack the libffi sources so that they can be compiled
with MSVC, and to extend them so that they have the features I need
for ctypes.
I retrieved the libffi sources from the gcc cvs repository on
2004-01-27. Then I did 'configure' in a 'build' subdirectory on a x86
linux system, and copied the files I found useful.
This diff is collapsed.
/* -----------------------------------------------------------------*-C-*-
libffi 2.00-beta - Copyright (c) 1996-2003 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
/* -------------------------------------------------------------------
The basic API is described in the README file.
The raw API is designed to bypass some of the argument packing
and unpacking on architectures for which it can be avoided.
The closure API allows interpreted functions to be packaged up
inside a C function pointer, so that they can be called as C functions,
with no understanding on the client side that they are interpreted.
It can also be used in other cases in which it is necessary to package
up a user specified parameter and a function pointer as a single
function pointer.
The closure API must be implemented in order to get its functionality,
e.g. for use by gij. Routines are provided to emulate the raw API
if the underlying platform doesn't allow faster implementation.
More details on the raw and cloure API can be found in:
http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
and
http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
-------------------------------------------------------------------- */
#ifndef LIBFFI_H
#define LIBFFI_H
#ifdef __cplusplus
extern "C" {
#endif
/* Specify which architecture libffi is configured for. */
//XXX #define X86
/* ---- System configuration information --------------------------------- */
#include <ffitarget.h>
#ifndef LIBFFI_ASM
#include <stddef.h>
#include <limits.h>
/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
But we can find it either under the correct ANSI name, or under GNU
C's internal name. */
#ifdef LONG_LONG_MAX
# define FFI_LONG_LONG_MAX LONG_LONG_MAX
#else
# ifdef LLONG_MAX
# define FFI_LONG_LONG_MAX LLONG_MAX
# else
# ifdef __GNUC__
# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
# endif
# ifdef _MSC_VER
# define FFI_LONG_LONG_MAX _I64_MAX
# endif
# endif
#endif
#if SCHAR_MAX == 127
# define ffi_type_uchar ffi_type_uint8
# define ffi_type_schar ffi_type_sint8
#else
#error "char size not supported"
#endif
#if SHRT_MAX == 32767
# define ffi_type_ushort ffi_type_uint16
# define ffi_type_sshort ffi_type_sint16
#elif SHRT_MAX == 2147483647
# define ffi_type_ushort ffi_type_uint32
# define ffi_type_sshort ffi_type_sint32
#else
#error "short size not supported"
#endif
#if INT_MAX == 32767
# define ffi_type_uint ffi_type_uint16
# define ffi_type_sint ffi_type_sint16
#elif INT_MAX == 2147483647
# define ffi_type_uint ffi_type_uint32
# define ffi_type_sint ffi_type_sint32
#elif INT_MAX == 9223372036854775807
# define ffi_type_uint ffi_type_uint64
# define ffi_type_sint ffi_type_sint64
#else
#error "int size not supported"
#endif
#define ffi_type_ulong ffi_type_uint64
#define ffi_type_slong ffi_type_sint64
#if LONG_MAX == 2147483647
# if FFI_LONG_LONG_MAX != 9223372036854775807
#error "no 64-bit data type supported"
# endif
#elif LONG_MAX != 9223372036854775807
#error "long size not supported"
#endif
/* The closure code assumes that this works on pointers, i.e. a size_t */
/* can hold a pointer. */
typedef struct _ffi_type
{
size_t size;
unsigned short alignment;
unsigned short type;
/*@null@*/ struct _ffi_type **elements;
} ffi_type;
int can_return_struct_as_int(size_t);
int can_return_struct_as_sint64(size_t);
/* These are defined in types.c */
extern ffi_type ffi_type_void;
extern ffi_type ffi_type_uint8;
extern ffi_type ffi_type_sint8;
extern ffi_type ffi_type_uint16;
extern ffi_type ffi_type_sint16;
extern ffi_type ffi_type_uint32;
extern ffi_type ffi_type_sint32;
extern ffi_type ffi_type_uint64;
extern ffi_type ffi_type_sint64;
extern ffi_type ffi_type_float;
extern ffi_type ffi_type_double;
extern ffi_type ffi_type_longdouble;
extern ffi_type ffi_type_pointer;
typedef enum {
FFI_OK = 0,
FFI_BAD_TYPEDEF,
FFI_BAD_ABI
} ffi_status;
typedef unsigned FFI_TYPE;
typedef struct {
ffi_abi abi;
unsigned nargs;
/*@dependent@*/ ffi_type **arg_types;
/*@dependent@*/ ffi_type *rtype;
unsigned bytes;
unsigned flags;
#ifdef FFI_EXTRA_CIF_FIELDS
FFI_EXTRA_CIF_FIELDS;
#endif
} ffi_cif;
/* ---- Definitions for the raw API -------------------------------------- */
#ifdef _WIN64
#define FFI_SIZEOF_ARG 8
#else
#define FFI_SIZEOF_ARG 4
#endif
typedef union {
ffi_sarg sint;
ffi_arg uint;
float flt;
char data[FFI_SIZEOF_ARG];
void* ptr;
} ffi_raw;
void ffi_raw_call (/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ ffi_raw *avalue);
void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
size_t ffi_raw_size (ffi_cif *cif);
/* This is analogous to the raw API, except it uses Java parameter */
/* packing, even on 64-bit machines. I.e. on 64-bit machines */
/* longs and doubles are followed by an empty 64-bit word. */
void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ ffi_raw *avalue);
void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
size_t ffi_java_raw_size (ffi_cif *cif);
/* ---- Definitions for closures ----------------------------------------- */
#if FFI_CLOSURES
typedef struct {
char tramp[FFI_TRAMPOLINE_SIZE];
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
void *user_data;
} ffi_closure;
void ffi_closure_free(void *);
void *ffi_closure_alloc (size_t size, void **code);
ffi_status
ffi_prep_closure_loc (ffi_closure*,
ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void *codeloc);
typedef struct {
char tramp[FFI_TRAMPOLINE_SIZE];
ffi_cif *cif;
#if !FFI_NATIVE_RAW_API
/* if this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the transaltion, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
void *this_closure;
#endif
void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
void *user_data;
} ffi_raw_closure;
ffi_status
ffi_prep_raw_closure (ffi_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data);
ffi_status
ffi_prep_java_raw_closure (ffi_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data);
#endif /* FFI_CLOSURES */
/* ---- Public interface definition -------------------------------------- */
ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
ffi_abi abi,
unsigned int nargs,
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
/*@dependent@*/ ffi_type **atypes);
int
ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ void **avalue);
/* Useful for eliminating compiler warnings */
#define FFI_FN(f) ((void (*)())f)
/* ---- Definitions shared with assembly code ---------------------------- */
#endif
/* If these change, update src/mips/ffitarget.h. */
#define FFI_TYPE_VOID 0
#define FFI_TYPE_INT 1
#define FFI_TYPE_FLOAT 2
#define FFI_TYPE_DOUBLE 3
#if 1
#define FFI_TYPE_LONGDOUBLE 4
#else
#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
#endif
#define FFI_TYPE_UINT8 5
#define FFI_TYPE_SINT8 6
#define FFI_TYPE_UINT16 7
#define FFI_TYPE_SINT16 8
#define FFI_TYPE_UINT32 9
#define FFI_TYPE_SINT32 10
#define FFI_TYPE_UINT64 11
#define FFI_TYPE_SINT64 12
#define FFI_TYPE_STRUCT 13
#define FFI_TYPE_POINTER 14
/* This should always refer to the last type code (for sanity checks) */
#define FFI_TYPE_LAST FFI_TYPE_POINTER
#ifdef __cplusplus
}
#endif
#endif
/* -----------------------------------------------------------------------
ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
Common internal definitions and macros. Only necessary for building
libffi.
----------------------------------------------------------------------- */
#ifndef FFI_COMMON_H
#define FFI_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
#include <fficonfig.h>
#include <malloc.h>
/* Check for the existence of memcpy. */
#if STDC_HEADERS
# include <string.h>
#else
# ifndef HAVE_MEMCPY
# define memcpy(d, s, n) bcopy ((s), (d), (n))
# endif
#endif
#if defined(FFI_DEBUG)
#include <stdio.h>
#endif
#ifdef FFI_DEBUG
/*@exits@*/ void ffi_assert(/*@temp@*/ char *expr, /*@temp@*/ char *file, int line);
void ffi_stop_here(void);
void ffi_type_test(/*@temp@*/ /*@out@*/ ffi_type *a, /*@temp@*/ char *file, int line);
#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
#else
#define FFI_ASSERT(x)
#define FFI_ASSERT_AT(x, f, l)
#define FFI_ASSERT_VALID_TYPE(x)
#endif
#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
/* Extended cif, used in callback from assembly routine */
typedef struct
{
/*@dependent@*/ ffi_cif *cif;
/*@dependent@*/ void *rvalue;
/*@dependent@*/ void **avalue;
} extended_cif;
/* Terse sized type definitions. */
typedef unsigned int UINT8 __attribute__((__mode__(__QI__)));
typedef signed int SINT8 __attribute__((__mode__(__QI__)));
typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
typedef signed int SINT16 __attribute__((__mode__(__HI__)));
typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
typedef signed int SINT32 __attribute__((__mode__(__SI__)));
typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
typedef signed int SINT64 __attribute__((__mode__(__DI__)));
typedef float FLOAT32;
#ifdef __cplusplus
}
#endif
#endif
/* fficonfig.h. Originally created by configure, now hand_maintained for MSVC. */
/* fficonfig.h. Generated automatically by configure. */
/* fficonfig.h.in. Generated automatically from configure.in by autoheader. */
/* Define this for MSVC, but not for mingw32! */
#ifdef _MSC_VER
#define __attribute__(x) /* */
#endif
#define alloca _alloca
/*----------------------------------------------------------------*/
/* Define if using alloca.c. */
/* #undef C_ALLOCA */
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
/* #undef CRAY_STACKSEG_END */
/* Define if you have alloca, as a function or macro. */
#define HAVE_ALLOCA 1
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
/* #define HAVE_ALLOCA_H 1 */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
/* #undef STACK_DIRECTION */
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define if you have the memcpy function. */
#define HAVE_MEMCPY 1
/* Define if read-only mmap of a plain file works. */
//#define HAVE_MMAP_FILE 1
/* Define if mmap of /dev/zero works. */
//#define HAVE_MMAP_DEV_ZERO 1
/* Define if mmap with MAP_ANON(YMOUS) works. */
//#define HAVE_MMAP_ANON 1
/* The number of bytes in type double */
#define SIZEOF_DOUBLE 8
/* The number of bytes in type long double */
#define SIZEOF_LONG_DOUBLE 12
/* Define if you have the long double type and it is bigger than a double */
#define HAVE_LONG_DOUBLE 1
/* whether byteorder is bigendian */
/* #undef WORDS_BIGENDIAN */
/* Define if the host machine stores words of multi-word integers in
big-endian order. */
/* #undef HOST_WORDS_BIG_ENDIAN */
/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */
#define BYTEORDER 1234
/* Define if your assembler and linker support unaligned PC relative relocs. */
/* #undef HAVE_AS_SPARC_UA_PCREL */
/* Define if your assembler supports .register. */
/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
/* Define if .eh_frame sections should be read-only. */
/* #undef HAVE_RO_EH_FRAME */
/* Define to the flags needed for the .section .eh_frame directive. */
/* #define EH_FRAME_FLAGS "aw" */
/* Define to the flags needed for the .section .eh_frame directive. */
/* #define EH_FRAME_FLAGS "aw" */
/* Define this if you want extra debugging. */
/* #undef FFI_DEBUG */
/* Define this is you do not want support for aggregate types. */
/* #undef FFI_NO_STRUCTS */
/* Define this is you do not want support for the raw API. */
/* #undef FFI_NO_RAW_API */
/* Define this if you are using Purify and want to suppress spurious messages. */
/* #undef USING_PURIFY */
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for x86 and x86-64.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
/* ---- System specific configurations ----------------------------------- */
#if defined (X86_64) && defined (__i386__)
#undef X86_64
#define X86
#endif
/* ---- Generic type definitions ----------------------------------------- */
#ifndef LIBFFI_ASM
#ifndef _WIN64
typedef unsigned long ffi_arg;
#else
typedef unsigned __int64 ffi_arg;
#endif
typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
/* ---- Intel x86 Win32 ---------- */
FFI_SYSV,
#ifndef _WIN64
FFI_STDCALL,
#endif
/* TODO: Add fastcall support for the sake of completeness */
FFI_DEFAULT_ABI = FFI_SYSV,
/* ---- Intel x86 and AMD x86-64 - */
/* #if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) */
/* FFI_SYSV, */
/* FFI_UNIX64,*/ /* Unix variants all use the same ABI for x86-64 */
/* #ifdef __i386__ */
/* FFI_DEFAULT_ABI = FFI_SYSV, */
/* #else */
/* FFI_DEFAULT_ABI = FFI_UNIX64, */
/* #endif */
/* #endif */
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#ifdef _WIN64
#define FFI_TRAMPOLINE_SIZE 29
#define FFI_NATIVE_RAW_API 0
#else
#define FFI_TRAMPOLINE_SIZE 15
#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
#endif
#endif
/* -----------------------------------------------------------------------
prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
/* Round up to FFI_SIZEOF_ARG. */
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
/* Perform machine independent initialization of aggregate type
specifications. */
static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
{
ffi_type **ptr;
FFI_ASSERT(arg != NULL);
/*@-usedef@*/
FFI_ASSERT(arg->elements != NULL);
FFI_ASSERT(arg->size == 0);
FFI_ASSERT(arg->alignment == 0);
ptr = &(arg->elements[0]);
while ((*ptr) != NULL)
{
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type */
FFI_ASSERT_VALID_TYPE(*ptr);
arg->size = ALIGN(arg->size, (*ptr)->alignment);
arg->size += (*ptr)->size;
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
arg->alignment : (*ptr)->alignment;
ptr++;
}
/* Structure size includes tail padding. This is important for
structures that fit in one register on ABIs like the PowerPC64
Linux ABI that right justify small structs in a register.
It's also needed for nested structure layout, for example
struct A { long a; char b; }; struct B { struct A x; char y; };
should find y at an offset of 2*sizeof(long) and result in a
total size of 3*sizeof(long). */
arg->size = ALIGN (arg->size, arg->alignment);
if (arg->size == 0)
return FFI_BAD_TYPEDEF;
else
return FFI_OK;
/*@=usedef@*/
}
/* Perform machine independent ffi_cif preparation, then call
machine dependent routine. */
ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
ffi_abi abi, unsigned int nargs,
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
/*@dependent@*/ ffi_type **atypes)
{
unsigned bytes = 0;
unsigned int i;
ffi_type **ptr;
FFI_ASSERT(cif != NULL);
FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
cif->abi = abi;
cif->arg_types = atypes;
cif->nargs = nargs;
cif->rtype = rtype;
cif->flags = 0;
/* Initialize the return type if necessary */
/*@-usedef@*/
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
return FFI_BAD_TYPEDEF;
/*@=usedef@*/
/* Perform a sanity check on the return type */
FFI_ASSERT_VALID_TYPE(cif->rtype);
/* x86-64 and s390 stack space allocation is handled in prep_machdep. */
#if !defined M68K && !defined __x86_64__ && !defined S390
/* Make space for the return structure pointer */
if (cif->rtype->type == FFI_TYPE_STRUCT
#ifdef _WIN32
&& !can_return_struct_as_int(cif->rtype->size) /* MSVC returns small structs in registers */
&& !can_return_struct_as_sint64(cif->rtype->size)
#endif
#ifdef SPARC
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
#endif
)
bytes = STACK_ARG_SIZE(sizeof(void*));
#endif
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
{
/* Initialize any uninitialized aggregate type definitions */
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type, do this
check after the initialization. */
FFI_ASSERT_VALID_TYPE(*ptr);
#if !defined __x86_64__ && !defined S390
#ifdef SPARC
if (((*ptr)->type == FFI_TYPE_STRUCT
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|| ((*ptr)->type == FFI_TYPE_LONGDOUBLE
&& cif->abi != FFI_V9))
bytes += sizeof(void*);
else
#elif defined (_WIN64)
if ((*ptr)->type == FFI_TYPE_STRUCT &&
!can_return_struct_as_int((*ptr)->size) &&
!can_return_struct_as_sint64((*ptr)->size))
bytes += sizeof(void*);
else
#endif
{
#if !defined(_MSC_VER) && !defined(__MINGW32__)
/* Don't know if this is a libffi bug or not. At least on
Windows with MSVC, function call parameters are *not*
aligned in the same way as structure fields are, they are
only aligned in integer boundaries.
This doesn't do any harm for cdecl functions and closures,
since the caller cleans up the stack, but it is wrong for
stdcall functions where the callee cleans.
*/
/* Add any padding if necessary */
if (((*ptr)->alignment - 1) & bytes)
bytes = ALIGN(bytes, (*ptr)->alignment);
#endif
bytes += STACK_ARG_SIZE((*ptr)->size);
}
#endif
}
#ifdef _WIN64
/* Function call needs at least 40 bytes stack size, on win64 AMD64 */
if (bytes < 40)
bytes = 40;
#endif
cif->bytes = bytes;
/* Perform machine dependent cif processing */
return ffi_prep_cif_machdep(cif);
}
/* -----------------------------------------------------------------------
types.c - Copyright (c) 1996, 1998 Red Hat, Inc.
Predefined ffi_types needed by libffi.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
/* Type definitions */
#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) ffi_type ffi_type_##n = { s, a, t, NULL }
#define FFI_AGGREGATE_TYPEDEF(n, e) ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e }
/* Size and alignment are fake here. They must not be 0. */
FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID);
FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8);
FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8);
FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
#if defined ALPHA || defined SPARC64 || defined X86_64 || defined S390X \
|| defined IA64 || defined _WIN64
FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
#else
FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
#endif
#if defined X86 || defined X86_WIN32 || defined ARM || defined M68K
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
#elif defined SH
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
#else
FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
#endif
#if defined X86 || defined X86_WIN32 || defined M68K
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
#elif defined ARM || defined SH || defined POWERPC_AIX || defined POWERPC_DARWIN
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
#elif defined SPARC
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
#ifdef SPARC64
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
#else
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
#endif
#elif defined X86_64
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
#else
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
#endif
/* -----------------------------------------------------------------------
win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc.
Copyright (c) 2001 John Beniton
Copyright (c) 2002 Ranjit Mathew
X86 Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
/* theller: almost verbatim translation from gas syntax to MSVC inline
assembler code. */
/* theller: ffi_call_x86 now returns an integer - the difference of the stack
pointer before and after the function call. If everything is ok, zero is
returned. If stdcall functions are passed the wrong number of arguments,
the difference will be nonzero. */
#include <ffi.h>
#include <ffi_common.h>
__declspec(naked) int
ffi_call_x86(void (* prepfunc)(char *, extended_cif *), /* 8 */
extended_cif *ecif, /* 12 */
unsigned bytes, /* 16 */
unsigned flags, /* 20 */
unsigned *rvalue, /* 24 */
void (*fn)()) /* 28 */
{
_asm {
push ebp
mov ebp, esp
push esi // NEW: this register must be preserved across function calls
// XXX SAVE ESP NOW!
mov esi, esp // save stack pointer before the call
// Make room for all of the new args.
mov ecx, [ebp+16]
sub esp, ecx // sub esp, bytes
mov eax, esp
// Place all of the ffi_prep_args in position
push [ebp + 12] // ecif
push eax
call [ebp + 8] // prepfunc
// Return stack to previous state and call the function
add esp, 8
// FIXME: Align the stack to a 128-bit boundary to avoid
// potential performance hits.
call [ebp + 28]
// Load ecif->cif->abi
mov ecx, [ebp + 12]
mov ecx, [ecx]ecif.cif
mov ecx, [ecx]ecif.cif.abi
cmp ecx, FFI_STDCALL
je noclean
// STDCALL: Remove the space we pushed for the args
mov ecx, [ebp + 16]
add esp, ecx
// CDECL: Caller has already cleaned the stack
noclean:
// Check that esp has the same value as before!
sub esi, esp
// Load %ecx with the return type code
mov ecx, [ebp + 20]
// If the return value pointer is NULL, assume no return value.
/*
Intel asm is weird. We have to explicitly specify 'DWORD PTR' in the next instruction,
otherwise only one BYTE will be compared (instead of a DWORD)!
*/
cmp DWORD PTR [ebp + 24], 0
jne sc_retint
// Even if there is no space for the return value, we are
// obliged to handle floating-point values.
cmp ecx, FFI_TYPE_FLOAT
jne sc_noretval
// fstp %st(0)
fstp st(0)
jmp sc_epilogue
sc_retint:
cmp ecx, FFI_TYPE_INT
jne sc_retfloat
// # Load %ecx with the pointer to storage for the return value
mov ecx, [ebp + 24]
mov [ecx + 0], eax
jmp sc_epilogue
sc_retfloat:
cmp ecx, FFI_TYPE_FLOAT
jne sc_retdouble
// Load %ecx with the pointer to storage for the return value
mov ecx, [ebp+24]
// fstps (%ecx)
fstp DWORD PTR [ecx]
jmp sc_epilogue
sc_retdouble:
cmp ecx, FFI_TYPE_DOUBLE
jne sc_retlongdouble
// movl 24(%ebp),%ecx
mov ecx, [ebp+24]
fstp QWORD PTR [ecx]
jmp sc_epilogue
jmp sc_retlongdouble // avoid warning about unused label
sc_retlongdouble:
cmp ecx, FFI_TYPE_LONGDOUBLE
jne sc_retint64
// Load %ecx with the pointer to storage for the return value
mov ecx, [ebp+24]
// fstpt (%ecx)
fstp QWORD PTR [ecx] /* XXX ??? */
jmp sc_epilogue
sc_retint64:
cmp ecx, FFI_TYPE_SINT64
jne sc_retstruct
// Load %ecx with the pointer to storage for the return value
mov ecx, [ebp+24]
mov [ecx+0], eax
mov [ecx+4], edx
sc_retstruct:
// Nothing to do!
sc_noretval:
sc_epilogue:
mov eax, esi
pop esi // NEW restore: must be preserved across function calls
mov esp, ebp
pop ebp
ret
}
}
PUBLIC ffi_call_AMD64
EXTRN __chkstk:NEAR
EXTRN ffi_closure_SYSV:NEAR
_TEXT SEGMENT
;;; ffi_closure_OUTER will be called with these registers set:
;;; rax points to 'closure'
;;; r11 contains a bit mask that specifies which of the
;;; first four parameters are float or double
;;;
;;; It must move the parameters passed in registers to their stack location,
;;; call ffi_closure_SYSV for the actual work, then return the result.
;;;
ffi_closure_OUTER PROC FRAME
;; save actual arguments to their stack space.
test r11, 1
jne first_is_float
mov QWORD PTR [rsp+8], rcx
jmp second
first_is_float:
movlpd QWORD PTR [rsp+8], xmm0
second:
test r11, 2
jne second_is_float
mov QWORD PTR [rsp+16], rdx
jmp third
second_is_float:
movlpd QWORD PTR [rsp+16], xmm1
third:
test r11, 4
jne third_is_float
mov QWORD PTR [rsp+24], r8
jmp forth
third_is_float:
movlpd QWORD PTR [rsp+24], xmm2
forth:
test r11, 8
jne forth_is_float
mov QWORD PTR [rsp+32], r9
jmp done
forth_is_float:
movlpd QWORD PTR [rsp+32], xmm3
done:
.ALLOCSTACK 40
sub rsp, 40
.ENDPROLOG
mov rcx, rax ; context is first parameter
mov rdx, rsp ; stack is second parameter
add rdx, 40 ; correct our own area
mov rax, ffi_closure_SYSV
call rax ; call the real closure function
;; Here, code is missing that handles float return values
add rsp, 40
movd xmm0, rax ; In case the closure returned a float.
ret 0
ffi_closure_OUTER ENDP
;;; ffi_call_AMD64
stack$ = 0
prepfunc$ = 32
ecif$ = 40
bytes$ = 48
flags$ = 56
rvalue$ = 64
fn$ = 72
ffi_call_AMD64 PROC FRAME
mov QWORD PTR [rsp+32], r9
mov QWORD PTR [rsp+24], r8
mov QWORD PTR [rsp+16], rdx
mov QWORD PTR [rsp+8], rcx
.PUSHREG rbp
push rbp
.ALLOCSTACK 48
sub rsp, 48 ; 00000030H
.SETFRAME rbp, 32
lea rbp, QWORD PTR [rsp+32]
.ENDPROLOG
mov eax, DWORD PTR bytes$[rbp]
add rax, 15
and rax, -16
call __chkstk
sub rsp, rax
lea rax, QWORD PTR [rsp+32]
mov QWORD PTR stack$[rbp], rax
mov rdx, QWORD PTR ecif$[rbp]
mov rcx, QWORD PTR stack$[rbp]
call QWORD PTR prepfunc$[rbp]
mov rsp, QWORD PTR stack$[rbp]
movlpd xmm3, QWORD PTR [rsp+24]
movd r9, xmm3
movlpd xmm2, QWORD PTR [rsp+16]
movd r8, xmm2
movlpd xmm1, QWORD PTR [rsp+8]
movd rdx, xmm1
movlpd xmm0, QWORD PTR [rsp]
movd rcx, xmm0
call QWORD PTR fn$[rbp]
ret_int$:
cmp DWORD PTR flags$[rbp], 1 ; FFI_TYPE_INT
jne ret_float$
mov rcx, QWORD PTR rvalue$[rbp]
mov DWORD PTR [rcx], eax
jmp SHORT ret_nothing$
ret_float$:
cmp DWORD PTR flags$[rbp], 2 ; FFI_TYPE_FLOAT
jne SHORT ret_double$
mov rax, QWORD PTR rvalue$[rbp]
movlpd QWORD PTR [rax], xmm0
jmp SHORT ret_nothing$
ret_double$:
cmp DWORD PTR flags$[rbp], 3 ; FFI_TYPE_DOUBLE
jne SHORT ret_int64$
mov rax, QWORD PTR rvalue$[rbp]
movlpd QWORD PTR [rax], xmm0
jmp SHORT ret_nothing$
ret_int64$:
cmp DWORD PTR flags$[rbp], 12 ; FFI_TYPE_SINT64
jne ret_nothing$
mov rcx, QWORD PTR rvalue$[rbp]
mov QWORD PTR [rcx], rax
jmp SHORT ret_nothing$
ret_nothing$:
xor eax, eax
lea rsp, QWORD PTR [rbp+16]
pop rbp
ret 0
ffi_call_AMD64 ENDP
_TEXT ENDS
END
......@@ -52,7 +52,7 @@ EXCLUDE_FROM_PACKAGED_LIB = FileNameSet("readme.txt")
EXCLUDE_FROM_COMPILE = FileNameSet("badsyntax_*", "bad_*")
EXCLUDE_FROM_CATALOG = FileSuffixSet(".exe", ".pyd", ".dll")
REQUIRED_DLLS = FileStemSet("libcrypto*", "libssl*")
REQUIRED_DLLS = FileStemSet("libcrypto*", "libssl*", "libffi*")
LIB2TO3_GRAMMAR_FILES = FileNameSet("Grammar.txt", "PatternGrammar.txt")
......
......@@ -70,6 +70,7 @@
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="pyproject.props" />
<Import Project="libffi.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
......@@ -77,7 +78,7 @@
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>..\Modules\_ctypes\libffi_msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>FFI_BUILDING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalOptions>/EXPORT:DllGetClassObject,PRIVATE /EXPORT:DllCanUnloadNow,PRIVATE %(AdditionalOptions)</AdditionalOptions>
......@@ -86,32 +87,14 @@
<ItemGroup>
<ClInclude Include="..\Modules\_ctypes\ctypes.h" />
<ClInclude Include="..\Modules\_ctypes\ctypes_dlfcn.h" />
<ClInclude Include="..\Modules\_ctypes\libffi_msvc\ffi.h" />
<ClInclude Include="..\Modules\_ctypes\libffi_msvc\ffi_common.h" />
<ClInclude Include="..\Modules\_ctypes\libffi_msvc\fficonfig.h" />
<ClInclude Include="..\Modules\_ctypes\libffi_msvc\ffitarget.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\Modules\_ctypes\_ctypes.c" />
<ClCompile Include="..\Modules\_ctypes\callbacks.c" />
<ClCompile Include="..\Modules\_ctypes\callproc.c" />
<ClCompile Include="..\Modules\_ctypes\cfield.c" />
<ClCompile Include="..\Modules\_ctypes\libffi_msvc\ffi.c" />
<ClCompile Include="..\Modules\_ctypes\malloc_closure.c" />
<ClCompile Include="..\Modules\_ctypes\libffi_msvc\prep_cif.c">
<DisableSpecificWarnings Condition="'$(Platform)'=='x64'">4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ClCompile Include="..\Modules\_ctypes\stgdict.c" />
<ClCompile Include="..\Modules\_ctypes\libffi_msvc\win32.c">
<ExcludedFromBuild Condition="'$(Platform)'=='x64'">true</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\Modules\_ctypes\libffi_msvc\win64.asm">
<ExcludedFromBuild Condition="'$(Platform)'=='Win32'">true</ExcludedFromBuild>
<Command>ml64 /nologo /c /Zi /Fo "$(IntDir)win64.obj" "%(FullPath)"</Command>
<Outputs>$(IntDir)win64.obj;%(Outputs)</Outputs>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\PC\python_nt.rc" />
......@@ -122,4 +105,4 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
\ No newline at end of file
</Project>
......@@ -15,18 +15,6 @@
<ClInclude Include="..\Modules\_ctypes\ctypes_dlfcn.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Modules\_ctypes\libffi_msvc\ffi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Modules\_ctypes\libffi_msvc\ffi_common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Modules\_ctypes\libffi_msvc\fficonfig.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Modules\_ctypes\libffi_msvc\ffitarget.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\Modules\_ctypes\_ctypes.c">
......@@ -41,25 +29,14 @@
<ClCompile Include="..\Modules\_ctypes\cfield.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Modules\_ctypes\libffi_msvc\ffi.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Modules\_ctypes\malloc_closure.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Modules\_ctypes\libffi_msvc\prep_cif.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Modules\_ctypes\stgdict.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Modules\_ctypes\libffi_msvc\win32.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\Modules\_ctypes\libffi_msvc\win64.asm">
<Filter>Source Files</Filter>
</CustomBuild>
<ResourceCompile Include="..\PC\python_nt.rc" />
</ItemGroup>
</Project>
\ No newline at end of file
......@@ -7,14 +7,17 @@ if NOT DEFINED EXTERNALS_DIR (set EXTERNALS_DIR=%PCBUILD%\..\externals)
set DO_FETCH=true
set DO_CLEAN=false
set IncludeLibffiSrc=false
set IncludeTkinterSrc=false
set IncludeSSLSrc=false
:CheckOpts
if "%~1"=="--no-tkinter" (set IncludeTkinter=false) & shift & goto CheckOpts
if "%~1"=="--no-openssl" (set IncludeSSL=false) & shift & goto CheckOpts
if "%~1"=="--no-libffi" (set IncludeLibffi=false) & shift & goto CheckOpts
if "%~1"=="--tkinter-src" (set IncludeTkinterSrc=true) & shift & goto CheckOpts
if "%~1"=="--openssl-src" (set IncludeSSLSrc=true) & shift & goto CheckOpts
if "%~1"=="--libffi-src" (set IncludeLibffiSrc=true) & shift & goto CheckOpts
if "%~1"=="--python" (set PYTHON=%2) & shift & shift & goto CheckOpts
if "%~1"=="--organization" (set ORG=%2) & shift & shift & goto CheckOpts
if "%~1"=="-c" (set DO_CLEAN=true) & shift & goto CheckOpts
......@@ -49,6 +52,7 @@ echo.Fetching external libraries...
set libraries=
set libraries=%libraries% bzip2-1.0.6
if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0-rc0-r1
if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.0j
set libraries=%libraries% sqlite-3.21.0.0
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.9.0
......@@ -72,6 +76,7 @@ for %%e in (%libraries%) do (
echo.Fetching external binaries...
set binaries=
if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi
if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.0j
if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.9.0
if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06
......
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(libffiIncludeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(libffiOutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>libffi-7.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<_LIBFFIDLL Include="$(libffiOutDir)\libffi-7.dll" />
</ItemGroup>
<Target Name="_CopyLIBFFIDLL" Inputs="@(_LIBFFIDLL)" Outputs="@(_LIBFFIDLL->'$(OutDir)%(Filename)%(Extension)')" AfterTargets="Build">
<Copy SourceFiles="@(_LIBFFIDLL)" DestinationFolder="$(OutDir)" />
</Target>
<Target Name="_CleanLIBFFIDLL" BeforeTargets="Clean">
<Delete Files="@(_LIBFFIDLL->'$(OutDir)%(Filename)%(Extension)')" TreatErrorsAsWarnings="true" />
</Target>
</Project>
\ No newline at end of file
@echo off
goto :Run
:Usage
echo.
echo Before running prepare_libffi.bat
echo LIBFFI_SOURCE environment variable must be set to the location of
echo of python-source-deps clone of libffi branch
echo VCVARSALL must be set to location of vcvarsall.bat
echo cygwin must be installed (see below)
echo SH environment variable must be set to the location of sh.exe
echo.
echo Tested with cygwin-x86 from https://www.cygwin.com/install.html
echo Select http://mirrors.kernel.org as the download site
echo Include the following cygwin packages in cygwin configuration:
echo make, autoconf, automake, libtool, dejagnu
echo.
echo NOTE: dejagnu is only required for running tests.
echo set LIBFFI_TEST=1 to run tests (optional)
echo.
echo Based on https://github.com/libffi/libffi/blob/master/.appveyor.yml
echo.
echo.
echo.Available flags:
echo. -x64 build for x64
echo. -x86 build for x86
echo. -? this help
echo. --install-cygwin install cygwin to c:\cygwin
exit /b 127
:Run
set BUILD_X64=
set BUILD_X86=
set INSTALL_CYGWIN=
:CheckOpts
if "%1"=="" goto :CheckOptsDone
if /I "%1"=="-x64" (set BUILD_X64=1) & shift & goto :CheckOpts
if /I "%1"=="-x86" (set BUILD_X86=1) & shift & goto :CheckOpts
if /I "%1"=="-?" goto :Usage
if /I "%1"=="--install-cygwin" (set INSTALL_CYGWIN=1) & shift & goto :CheckOpts
goto :Usage
:CheckOptsDone
if NOT DEFINED BUILD_X64 if NOT DEFINED BUILD_X86 if NOT DEFINED BUILD_ARM32 (
set BUILD_X64=1
set BUILD_X86=1
)
if "%INSTALL_CYGWIN%"=="1" call :InstallCygwin
setlocal
if NOT DEFINED SH if exist c:\cygwin\bin\sh.exe set SH=c:\cygwin\bin\sh.exe
if NOT DEFINED VCVARSALL (
if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" (
set VCVARSALL="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat"
)
)
if ^%VCVARSALL:~0,1% NEQ ^" SET VCVARSALL="%VCVARSALL%"
if NOT DEFINED LIBFFI_SOURCE echo.&&echo ERROR LIBFFI_SOURCE environment variable not set && goto :Usage
if NOT DEFINED SH echo ERROR SH environment variable not set && goto :Usage
if not exist %SH% echo ERROR %SH% does not exist && goto :Usage
if not exist %LIBFFI_SOURCE% echo ERROR %LIBFFI_SOURCE% does not exist && goto :Usage
set OLDPWD=%LIBFFI_SOURCE%
pushd %LIBFFI_SOURCE%
%SH% --login -lc "cygcheck -dc cygwin"
set GET_MSVCC=%SH% -lc "cd $OLDPWD; export MSVCC=`/usr/bin/find $PWD -name msvcc.sh`; echo ${MSVCC};"
FOR /F "usebackq delims==" %%i IN (`%GET_MSVCC%`) do @set MSVCC=%%i
echo.
echo VCVARSALL : %VCVARSALL%
echo SH : %SH%
echo LIBFFI_SOURCE: %LIBFFI_SOURCE%
echo MSVCC : %MSVCC%
echo.
if not exist Makefile.in (%SH% -lc "(cd $LIBFFI_SOURCE; ./autogen.sh;)")
call :BuildOne x86 i686-pc-cygwin i686-pc-cygwin
call :BuildOne x64 x86_64-w64-cygwin x86_64-w64-cygwin
popd
endlocal
exit /b 0
REM all done
REM this subroutine is called once for each architecture
:BuildOne
setlocal
REM Initialize variables
set VCVARS_PLATFORM=%1
set BUILD=%2
set HOST=%3
set ASSEMBLER=
set SRC_ARCHITECTURE=x86
if NOT DEFINED VCVARS_PLATFORM echo ERROR bad VCVARS_PLATFORM&&exit /b 123
if /I "%VCVARS_PLATFORM%" EQU "x64" (
set ARCH=amd64
set ARTIFACTS=%LIBFFI_SOURCE%\x86_64-w64-cygwin
set ASSEMBLER=-m64
set SRC_ARCHITECTURE=x86
)
if /I "%VCVARS_PLATFORM%" EQU "x86" (
set ARCH=win32
set ARTIFACTS=%LIBFFI_SOURCE%\i686-pc-cygwin
set ASSEMBLER=
set SRC_ARCHITECTURE=x86
)
if NOT DEFINED LIBFFI_OUT set LIBFFI_OUT=%~dp0\..\externals\libffi
set _LIBFFI_OUT=%LIBFFI_OUT%\%ARCH%
echo get VS build environment
call %VCVARSALL% %VCVARS_PLATFORM%
echo clean %_LIBFFI_OUT%
if exist %_LIBFFI_OUT% (rd %_LIBFFI_OUT% /s/q)
echo Configure the build to generate fficonfig.h and ffi.h
%SH% -lc "(cd $OLDPWD; ./configure CC='%MSVCC% %ASSEMBLER%' CXX='%MSVCC% %ASSEMBLER%' LD='link' CPP='cl -nologo -EP' CXXCPP='cl -nologo -EP' CPPFLAGS='-DFFI_BUILDING_DLL' NM='dumpbin -symbols' STRIP=':' --build=$BUILD --host=$HOST;)"
echo Building libffi
%SH% -lc "(cd $OLDPWD; export PATH=/usr/bin:$PATH; cp src/%SRC_ARCHITECTURE%/ffitarget.h include; make; find .;)"
REM Tests are not needed to produce artifacts
if "%LIBFFI_TEST%" EQU "1" (
echo "Running tests..."
%SH% -lc "(cd $OLDPWD; export PATH=/usr/bin:$PATH; cp `find $PWD -name 'libffi-?.dll'` $HOST/testsuite/; make check; cat `find ./ -name libffi.log`)"
) else (
echo "Not running tests"
)
echo copying files to %_LIBFFI_OUT%
if not exist %_LIBFFI_OUT%\include (md %_LIBFFI_OUT%\include)
copy %ARTIFACTS%\.libs\libffi-7.dll %_LIBFFI_OUT%
copy %ARTIFACTS%\.libs\libffi-7.lib %_LIBFFI_OUT%
copy %ARTIFACTS%\fficonfig.h %_LIBFFI_OUT%\include
copy %ARTIFACTS%\include\*.h %_LIBFFI_OUT%\include
endlocal
exit /b
:InstallCygwin
setlocal
if NOT DEFINED CYG_ROOT (set CYG_ROOT=c:/cygwin)
if NOT DEFINED CYG_CACHE (set CYG_CACHE=C:/cygwin/var/cache/setup)
if NOT DEFINED CYG_MIRROR (set CYG_MIRROR=http://mirrors.kernel.org/sourceware/cygwin/)
powershell -c "md $env:CYG_ROOT -ErrorAction SilentlyContinue"
powershell -c "$setup = $env:CYG_ROOT+'/setup.exe'; if (!(Test-Path $setup)){invoke-webrequest https://cygwin.com/setup-x86.exe -outfile $setup}
%CYG_ROOT%/setup.exe -qnNdO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P make -P autoconf -P automake -P libtool -P dejagnu
endlocal
exit /b
......@@ -53,6 +53,9 @@
<sqlite3Dir>$(ExternalsDir)sqlite-3.21.0.0\</sqlite3Dir>
<bz2Dir>$(ExternalsDir)bzip2-1.0.6\</bz2Dir>
<lzmaDir>$(ExternalsDir)xz-5.2.2\</lzmaDir>
<libffiDir>$(ExternalsDir)libffi\</libffiDir>
<libffiOutDir>$(ExternalsDir)libffi\$(ArchName)\</libffiOutDir>
<libffiIncludeDir>$(libffiOutDir)include</libffiIncludeDir>
<opensslDir>$(ExternalsDir)openssl-1.1.0j\</opensslDir>
<opensslOutDir>$(ExternalsDir)openssl-bin-1.1.0j\$(ArchName)\</opensslOutDir>
<opensslIncludeDir>$(opensslOutDir)include</opensslIncludeDir>
......
......@@ -22,6 +22,9 @@
<Component Id="libssl.dll" Directory="DLLs" Guid="*">
<File Name="libssl$(var.ssltag).dll" KeyPath="yes" />
</Component>
<Component Id="libffi.dll" Directory="DLLs" Guid="*">
<File Name="libffi-7.dll" KeyPath="yes" />
</Component>
<Component Id="venvlauncher.exe" Directory="Lib_venv_scripts_nt" Guid="*">
<File Name="python.exe" Source="venvlauncher.exe" KeyPath="yes" />
</Component>
......@@ -59,6 +62,9 @@
<Component Id="libssl.pdb" Directory="DLLs" Guid="*">
<File Name="libssl$(var.ssltag).pdb" KeyPath="yes" />
</Component>
<Component Id="libffi.pdb" Directory="DLLs" Guid="*">
<File Name="libffi-7.pdb" KeyPath="yes" />
</Component>
<Component Id="venvlauncher.pdb" Directory="Lib_venv_scripts_nt__pdbs" Guid="*">
<File Name="python.pdb" Source="venvlauncher.pdb" KeyPath="yes" />
</Component>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment