From 7eaaa4f36e91fb8ff16fd11ae30b7a03972dd5bb Mon Sep 17 00:00:00 2001 From: Kedar Sovani Date: Tue, 9 Dec 2008 19:43:29 -0500 Subject: [PATCH] python: backport ARM libffi closure support This patch backports ARM libffi closure support to python 2.5's version of libffi, to enable building the ctype module. Signed-off-by: Lennert Buytenhek Signed-off-by: Kedar Sovani --- python-2.5.1-libffi-arm-closures.patch | 389 ++++++++++++++++++++++++++++++++ python.spec | 5 +- 2 files changed, 392 insertions(+), 2 deletions(-) create mode 100644 python-2.5.1-libffi-arm-closures.patch diff --git a/python-2.5.1-libffi-arm-closures.patch b/python-2.5.1-libffi-arm-closures.patch new file mode 100644 index 0000000..85bfe53 --- /dev/null +++ b/python-2.5.1-libffi-arm-closures.patch @@ -0,0 +1,389 @@ +diff -up Python-2.5.1/Modules/_ctypes/libffi/src/arm/ffitarget.h.libffi Python-2.5.1/Modules/_ctypes/libffi/src/arm/ffitarget.h +--- Python-2.5.1/Modules/_ctypes/libffi/src/arm/ffitarget.h.libffi 2006-03-08 20:35:32.000000000 -0500 ++++ Python-2.5.1/Modules/_ctypes/libffi/src/arm/ffitarget.h 2008-01-02 17:30:17.000000000 -0500 +@@ -40,7 +40,8 @@ typedef enum ffi_abi { + + /* ---- Definitions for closures ----------------------------------------- */ + +-#define FFI_CLOSURES 0 ++#define FFI_CLOSURES 1 ++#define FFI_TRAMPOLINE_SIZE 20 + #define FFI_NATIVE_RAW_API 0 + + #endif +diff -up Python-2.5.1/Modules/_ctypes/libffi/src/arm/ffi.c.libffi Python-2.5.1/Modules/_ctypes/libffi/src/arm/ffi.c +--- Python-2.5.1/Modules/_ctypes/libffi/src/arm/ffi.c.libffi 2006-03-08 20:35:32.000000000 -0500 ++++ Python-2.5.1/Modules/_ctypes/libffi/src/arm/ffi.c 2008-01-02 17:45:01.000000000 -0500 +@@ -31,9 +31,7 @@ + /* ffi_prep_args is called by the assembly routine once stack space + has been allocated for the function's arguments */ + +-/*@-exportheader@*/ + void ffi_prep_args(char *stack, extended_cif *ecif) +-/*@=exportheader@*/ + { + register unsigned int i; + register void **p_argv; +@@ -42,7 +40,7 @@ void ffi_prep_args(char *stack, extended + + argp = stack; + +- if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) { ++ if ( ecif->cif->flags == FFI_TYPE_STRUCT ) { + *(void **) argp = ecif->rvalue; + argp += 4; + } +@@ -60,6 +58,9 @@ void ffi_prep_args(char *stack, extended + argp = (char *) ALIGN(argp, (*p_arg)->alignment); + } + ++ if ((*p_arg)->type == FFI_TYPE_STRUCT) ++ argp = (char *) ALIGN(argp, 4); ++ + z = (*p_arg)->size; + if (z < sizeof(int)) + { +@@ -83,7 +84,7 @@ void ffi_prep_args(char *stack, extended + break; + + case FFI_TYPE_STRUCT: +- *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); ++ memcpy(argp, *p_argv, (*p_arg)->size); + break; + + default: +@@ -117,7 +118,6 @@ ffi_status ffi_prep_cif_machdep(ffi_cif + switch (cif->rtype->type) + { + case FFI_TYPE_VOID: +- case FFI_TYPE_STRUCT: + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + cif->flags = (unsigned) cif->rtype->type; +@@ -128,6 +128,17 @@ ffi_status ffi_prep_cif_machdep(ffi_cif + cif->flags = (unsigned) FFI_TYPE_SINT64; + break; + ++ case FFI_TYPE_STRUCT: ++ if (cif->rtype->size <= 4) ++ /* A Composite Type not larger than 4 bytes is returned in r0. */ ++ cif->flags = (unsigned)FFI_TYPE_INT; ++ else ++ /* A Composite Type larger than 4 bytes, or whose size cannot ++ be determined statically ... is stored in memory at an ++ address passed [in r0]. */ ++ cif->flags = (unsigned)FFI_TYPE_STRUCT; ++ break; ++ + default: + cif->flags = FFI_TYPE_INT; + break; +@@ -136,50 +147,161 @@ ffi_status ffi_prep_cif_machdep(ffi_cif + return FFI_OK; + } + +-/*@-declundef@*/ +-/*@-exportheader@*/ +-extern void ffi_call_SYSV(void (*)(char *, extended_cif *), +- /*@out@*/ extended_cif *, +- unsigned, unsigned, +- /*@out@*/ unsigned *, +- void (*fn)()); +-/*@=declundef@*/ +-/*@=exportheader@*/ ++extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, ++ unsigned, unsigned, unsigned *, void (*fn)()); + +-void ffi_call(/*@dependent@*/ ffi_cif *cif, +- void (*fn)(), +- /*@out@*/ void *rvalue, +- /*@dependent@*/ void **avalue) ++void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue) + { + extended_cif ecif; + ++ int small_struct = (cif->flags == FFI_TYPE_INT ++ && cif->rtype->type == FFI_TYPE_STRUCT); ++ + ecif.cif = cif; + ecif.avalue = avalue; ++ ++ unsigned int temp; + + /* If the return value is a struct and we don't have a return */ + /* value address then we need to make one */ + + if ((rvalue == NULL) && +- (cif->rtype->type == FFI_TYPE_STRUCT)) ++ (cif->flags == FFI_TYPE_STRUCT)) + { +- /*@-sysunrecog@*/ + ecif.rvalue = alloca(cif->rtype->size); +- /*@=sysunrecog@*/ + } ++ else if (small_struct) ++ ecif.rvalue = &temp; + else + ecif.rvalue = rvalue; +- +- ++ + switch (cif->abi) + { + case FFI_SYSV: +- /*@-usedef@*/ +- ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, +- cif->flags, ecif.rvalue, fn); +- /*@=usedef@*/ ++ ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, ++ fn); ++ + break; + default: + FFI_ASSERT(0); + break; + } ++ if (small_struct) ++ memcpy (rvalue, &temp, cif->rtype->size); ++} ++ ++/** private members **/ ++ ++static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, ++ void** args, ffi_cif* cif); ++ ++void ffi_closure_SYSV (ffi_closure *); ++ ++/* This function is jumped to by the trampoline */ ++ ++unsigned int ++ffi_closure_SYSV_inner (closure, respp, args) ++ ffi_closure *closure; ++ void **respp; ++ void *args; ++{ ++ // our various things... ++ ffi_cif *cif; ++ void **arg_area; ++ ++ cif = closure->cif; ++ arg_area = (void**) alloca (cif->nargs * sizeof (void*)); ++ ++ /* this call will initialize ARG_AREA, such that each ++ * element in that array points to the corresponding ++ * value on the stack; and if the function returns ++ * a structure, it will re-set RESP to point to the ++ * structure return address. */ ++ ++ ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif); ++ ++ (closure->fun) (cif, *respp, arg_area, closure->user_data); ++ ++ return cif->flags; ++} ++ ++/*@-exportheader@*/ ++static void ++ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, ++ void **avalue, ffi_cif *cif) ++/*@=exportheader@*/ ++{ ++ register unsigned int i; ++ register void **p_argv; ++ register char *argp; ++ register ffi_type **p_arg; ++ ++ argp = stack; ++ ++ if ( cif->flags == FFI_TYPE_STRUCT ) { ++ *rvalue = *(void **) argp; ++ argp += 4; ++ } ++ ++ p_argv = avalue; ++ ++ for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) ++ { ++ size_t z; ++ ++ size_t alignment = (*p_arg)->alignment; ++ if (alignment < 4) ++ alignment = 4; ++ /* Align if necessary */ ++ if ((alignment - 1) & (unsigned) argp) { ++ argp = (char *) ALIGN(argp, alignment); ++ } ++ ++ z = (*p_arg)->size; ++ ++ /* because we're little endian, this is what it turns into. */ ++ ++ *p_argv = (void*) argp; ++ ++ p_argv++; ++ argp += z; ++ } ++ ++ return; ++} ++ ++/* How to make a trampoline. */ ++ ++#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ ++({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ ++ unsigned int __fun = (unsigned int)(FUN); \ ++ unsigned int __ctx = (unsigned int)(CTX); \ ++ *(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \ ++ *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \ ++ *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \ ++ *(unsigned int*) &__tramp[12] = __ctx; \ ++ *(unsigned int*) &__tramp[16] = __fun; \ ++ __clear_cache((&__tramp[0]), (&__tramp[19])); \ ++ }) ++ ++ ++/* the cif must already be prep'ed */ ++ ++ffi_status ++ffi_prep_closure (ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,void**,void*), ++ void *user_data) ++{ ++ FFI_ASSERT (cif->abi == FFI_SYSV); ++ ++ FFI_INIT_TRAMPOLINE (&closure->tramp[0], \ ++ &ffi_closure_SYSV, \ ++ (void*)closure); ++ ++ closure->cif = cif; ++ closure->user_data = user_data; ++ closure->fun = fun; ++ ++ return FFI_OK; + } +diff -up Python-2.5.1/Modules/_ctypes/libffi/src/arm/sysv.S.libffi Python-2.5.1/Modules/_ctypes/libffi/src/arm/sysv.S +--- Python-2.5.1/Modules/_ctypes/libffi/src/arm/sysv.S.libffi 2006-03-08 20:35:32.000000000 -0500 ++++ Python-2.5.1/Modules/_ctypes/libffi/src/arm/sysv.S 2008-01-02 17:30:17.000000000 -0500 +@@ -82,6 +82,14 @@ + # define call_reg(x) mov lr, pc ; mov pc, x + #endif + ++/* Conditionally compile unwinder directives. */ ++#ifdef __ARM_EABI__ ++#define UNWIND ++#else ++#define UNWIND @ ++#endif ++ ++ + #if defined(__thumb__) && !defined(__THUMB_INTERWORK__) + .macro ARM_FUNC_START name + .text +@@ -92,6 +100,7 @@ + bx pc + nop + .arm ++ UNWIND .fnstart + /* A hook to tell gdb that we've switched to ARM mode. Also used to call + directly from other local arm routines. */ + _L__\name: +@@ -102,6 +111,7 @@ _L__\name: + .align 0 + .arm + ENTRY(\name) ++ UNWIND .fnstart + .endm + #endif + +@@ -134,8 +144,11 @@ _L__\name: + ARM_FUNC_START ffi_call_SYSV + @ Save registers + stmfd sp!, {r0-r3, fp, lr} ++ UNWIND .save {r0-r3, fp, lr} + mov fp, sp + ++ UNWIND .setfp fp, sp ++ + @ Make room for all of the new args. + sub sp, fp, r2 + +@@ -205,5 +218,78 @@ LSYM(Lepilogue): + RETLDM "r0-r3,fp" + + .ffi_call_SYSV_end: ++ UNWIND .fnend + .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) + ++/* ++ unsigned int FFI_HIDDEN ++ ffi_closure_SYSV_inner (closure, respp, args) ++ ffi_closure *closure; ++ void **respp; ++ void *args; ++*/ ++ ++ARM_FUNC_START ffi_closure_SYSV ++ UNWIND .pad #16 ++ add ip, sp, #16 ++ stmfd sp!, {ip, lr} ++ UNWIND .save {r0, lr} ++ add r2, sp, #8 ++ .pad #16 ++ sub sp, sp, #16 ++ str sp, [sp, #8] ++ add r1, sp, #8 ++ bl ffi_closure_SYSV_inner ++ cmp r0, #FFI_TYPE_INT ++ beq .Lretint ++ ++ cmp r0, #FFI_TYPE_FLOAT ++#ifdef __SOFTFP__ ++ beq .Lretint ++#else ++ beq .Lretfloat ++#endif ++ ++ cmp r0, #FFI_TYPE_DOUBLE ++#ifdef __SOFTFP__ ++ beq .Lretlonglong ++#else ++ beq .Lretdouble ++#endif ++ ++ cmp r0, #FFI_TYPE_LONGDOUBLE ++#ifdef __SOFTFP__ ++ beq .Lretlonglong ++#else ++ beq .Lretlongdouble ++#endif ++ ++ cmp r0, #FFI_TYPE_SINT64 ++ beq .Lretlonglong ++.Lclosure_epilogue: ++ add sp, sp, #16 ++ ldmfd sp, {sp, pc} ++.Lretint: ++ ldr r0, [sp] ++ b .Lclosure_epilogue ++.Lretlonglong: ++ ldr r0, [sp] ++ ldr r1, [sp, #4] ++ b .Lclosure_epilogue ++ ++#ifndef __SOFTFP__ ++.Lretfloat: ++ ldfs f0, [sp] ++ b .Lclosure_epilogue ++.Lretdouble: ++ ldfd f0, [sp] ++ b .Lclosure_epilogue ++.Lretlongdouble: ++ ldfd f0, [sp] ++ b .Lclosure_epilogue ++#endif ++ ++.ffi_closure_SYSV_end: ++ UNWIND .fnend ++ .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) ++ diff --git a/python.spec b/python.spec index a06fe67..94ac100 100644 --- a/python.spec +++ b/python.spec @@ -22,7 +22,7 @@ Summary: An interpreted, interactive, object-oriented programming language. Name: %{python} Version: 2.5.2 -Release: 1%{?dist} +Release: 1%{?dist}.fa1 License: Python Group: Development/Languages Provides: python-abi = %{pybasever} @@ -45,7 +45,6 @@ Patch12: python-2.5.1-pysqlite.patch Patch13: python-2.5.1-socketmodule-constants.patch Patch14: python-2.5.1-socketmodule-constants2.patch Patch15: python-2.5.1-listdir.patch - # upstreamed Patch50: python-2.5-disable-egginfo.patch @@ -63,6 +62,7 @@ Patch260: python-2.5.2-set_wakeup_fd4.patch Patch999: python-2.5.CVE-2007-4965-int-overflow.patch Patch998: python-2.5-CVE-2008-2316.patch +Patch1100: python-2.5.1-libffi-arm-closures.patch %if %{main_python} Obsoletes: Distutils @@ -223,6 +223,7 @@ code that uses more than just unittest and/or test_support.py. %patch999 -p1 -b .cve2007-4965 %patch998 -p0 -b .cve2008-2316 +%patch1100 -p1 -b .libffi-armclosures # This shouldn't be necesarry, but is right now (2.2a3) find -name "*~" |xargs rm -f -- 1.5.3.3