aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Kamensky <victor.kamensky@linaro.org>2013-08-08 20:37:02 -0700
committerRiku Voipio <riku.voipio@linaro.org>2013-08-20 09:50:13 +0300
commitfc8bf09a48c6e220350727814d2c49d45c80dbf2 (patch)
treec07a03ee8608465de3bd346ffcf32ad6a36d1325
parentb14a568e7e67a76fcad59f557c7564fa8bdc1538 (diff)
libffi: fix arm trampoline to work on arm v7 big endian (be8) case
cffi code creates trampoline for python callback function, which is supposed to be called from another C function and it does not take into account that in ARMv7a in big endian mode instructions are still in little endian. Since written by big endian code they have to be byteswapped. Proposed fix uses byteswap codes for instructions. Here is python code snippet that will fail when libffi is used by ctypes in python code (func1 and func2 are C functions): from ctypes import * mylib = CDLL("libmytest.so") func1 = mylib.func1 print func1(1, 2) CBFUNC = CFUNCTYPE(c_int, c_int, c_int) def myfunc2(a, b): return a * a + b * b cb_func = CBFUNC(myfunc2) func2 = mylib.func2 print func2(cb_func, 1, 2) code will produce illegal instruction when func2 will call myfunc2 through trampoline Signed-off-by: Victor Kamensky <victor.kamensky@linaro.org> Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
-rw-r--r--meta-bigendian/recipes-gnome/libffi/libffi/libffi_armeb_be8.patch37
-rw-r--r--meta-bigendian/recipes-gnome/libffi/libffi_3.0.13.bbappend3
2 files changed, 40 insertions, 0 deletions
diff --git a/meta-bigendian/recipes-gnome/libffi/libffi/libffi_armeb_be8.patch b/meta-bigendian/recipes-gnome/libffi/libffi/libffi_armeb_be8.patch
new file mode 100644
index 00000000..7efa58e8
--- /dev/null
+++ b/meta-bigendian/recipes-gnome/libffi/libffi/libffi_armeb_be8.patch
@@ -0,0 +1,37 @@
+Index: libffi-3.0.13/src/arm/ffi.c
+===================================================================
+--- libffi-3.0.13.orig/src/arm/ffi.c
++++ libffi-3.0.13/src/arm/ffi.c
+@@ -582,6 +582,7 @@ ffi_closure_free (void *ptr)
+
+ #else
+
++#if !(defined(__ARMEB__) && defined(__ARM_ARCH_7A__))
+ #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
+ ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+ unsigned int __fun = (unsigned int)(FUN); \
+@@ -595,7 +596,23 @@ ffi_closure_free (void *ptr)
+ /* Clear instruction \
+ mapping. */ \
+ })
+-
++#else /* armv7 big endian: be8 instructions are still little endian */
++#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 char *insns = (unsigned char *)(CTX); \
++ *(unsigned int*) &__tramp[0] = 0x0f002de9; /* swab(0xe92d000f, 4) - stmfd sp!, {r0-r3} */ \
++ *(unsigned int*) &__tramp[4] = 0x00009fe5; /* swab(0xe59f0000, 4) - ldr r0, [pc] */ \
++ *(unsigned int*) &__tramp[8] = 0x00f09fe5; /* swab(0xe59ff000, 4) - ldr pc, [pc] */ \
++ *(unsigned int*) &__tramp[12] = __ctx; \
++ *(unsigned int*) &__tramp[16] = __fun; \
++ __clear_cache((&__tramp[0]), (&__tramp[19])); /* Clear data mapping. */ \
++ __clear_cache(insns, insns + 3 * sizeof (unsigned int)); \
++ /* Clear instruction \
++ mapping. */ \
++ })
++#endif
+ #endif
+
+ /* the cif must already be prep'ed */
diff --git a/meta-bigendian/recipes-gnome/libffi/libffi_3.0.13.bbappend b/meta-bigendian/recipes-gnome/libffi/libffi_3.0.13.bbappend
new file mode 100644
index 00000000..1774c0c4
--- /dev/null
+++ b/meta-bigendian/recipes-gnome/libffi/libffi_3.0.13.bbappend
@@ -0,0 +1,3 @@
+FILESEXTRAPATHS := "${THISDIR}/${PN}"
+
+SRC_URI += "file://libffi_armeb_be8.patch"