From 7eaaa4f36e91fb8ff16fd11ae30b7a03972dd5bb Mon Sep 17 00:00:00 2001
From: Kedar Sovani <kedars@marvell.com>
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 <buytenh@marvell.com>
Signed-off-by: Kedar Sovani <kedars@marvell.com>
---
 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

