Package: libffcall1
Version: 1.10+cvs20100619-2
Severity: important
Tags: sid upstream

libffcall uses cpu regiter r10 to pass callback data. when libffcall is linked
as shared library, ld.so breaks this register.
As long as clisp is linked this way, I've made a patch.



-- System Information:
Debian Release: unstable
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 3.0.0-1-amd64 (SMP w/2 CPU cores)
Locale: LANG=ru_UA.utf8, LC_CTYPE=ru_UA.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages libffcall1 depends on:
ii  libc6                         2.13-14    Embedded GNU C Library: Shared lib

libffcall1 recommends no packages.

libffcall1 suggests no packages.

-- no debconf information
>From 6a2bdfe7800ff0e78acff9d8115594b37a5ea455 Mon Sep 17 00:00:00 2001
From: Andrey Kutejko <andy1...@gmail.com>
Date: Mon, 14 Feb 2011 00:45:15 +0200
Subject: [PATCH] fix callback on x86_64

---
 callback/trampoline_r/trampoline.c |   20 ++++++++++++--------
 callback/vacall_r/vacall-x86_64.c  |    5 ++---
 callback/vacall_r/vacall-x86_64.s  |    3 +++
 3 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/callback/trampoline_r/trampoline.c b/callback/trampoline_r/trampoline.c
index ef2c248..035d643 100644
--- a/callback/trampoline_r/trampoline.c
+++ b/callback/trampoline_r/trampoline.c
@@ -299,7 +299,7 @@ extern void __TR_clear_cache();
 #define TRAMP_ALIGN 16
 #endif
 #ifdef __x86_64__
-#define TRAMP_LENGTH 22
+#define TRAMP_LENGTH 26
 #define TRAMP_ALIGN 16
 #endif
 #ifdef __s390__
@@ -945,6 +945,9 @@ __TR_function alloc_trampoline_r (__TR_function address, void* data0, void* data
 #ifdef __x86_64__
   /* function:
    *    movabsq $<data>,%r10		49 BA <data>
+   *    popq %rcx                   59
+   *    pushq %r10		            41 52
+   *    pushq %rcx                  51
    *    movabsq $<address>,%rax		48 B8 <address>
    *    jmp *%rax			FF E0
    */
@@ -952,21 +955,22 @@ __TR_function alloc_trampoline_r (__TR_function address, void* data0, void* data
   *(short *) (function + 2) = (unsigned long) data & 0xffff;
   *(int *)   (function + 4) = ((unsigned long) data >> 16) & 0xffffffff;
   *(short *) (function + 8) = ((unsigned long) data >> 48) & 0xffff;
-  *(short *) (function +10) = 0xB848;
-  *(int *)   (function +12) = (unsigned long) address & 0xffffffff;
-  *(int *)   (function +16) = ((unsigned long) address >> 32) & 0xffffffff;
-  *(short *) (function +20) = 0xE0FF;
+  *(int *)   (function +10) = 0x51524159;
+  *(short *) (function +14) = 0xB848;
+  *(int *)   (function +16) = (unsigned long) address & 0xffffffff;
+  *(int *)   (function +20) = ((unsigned long) address >> 32) & 0xffffffff;
+  *(short *) (function +24) = 0xE0FF;
 #define is_tramp(function)  \
   *(unsigned short *) (function + 0) == 0xBA49 && \
-  *(unsigned short *) (function +10) == 0xB848 && \
-  *(unsigned short *) (function +20) == 0xE0FF
+  *(unsigned short *) (function +14) == 0xB848 && \
+  *(unsigned short *) (function +24) == 0xE0FF
 #define hilo(hiword,loword)  \
   (((unsigned long) (hiword) << 32) | (unsigned long) (loword))
 #define himidlo(hishort,midword,loshort)  \
   (((unsigned long) (hishort) << 48) | (unsigned long) (midword) << 16 \
    | (unsigned long) (loshort))
 #define tramp_address(function)  \
-  hilo(*(unsigned int *) (function +16), *(unsigned int *) (function +12))
+  hilo(*(unsigned int *) (function +20), *(unsigned int *) (function +16))
 #define tramp_data(function)  \
   himidlo(*(unsigned short *) (function + 8), \
           *(unsigned int *)   (function + 4), \
diff --git a/callback/vacall_r/vacall-x86_64.c b/callback/vacall_r/vacall-x86_64.c
index 9ae2d16..2268bc0 100644
--- a/callback/vacall_r/vacall-x86_64.c
+++ b/callback/vacall_r/vacall-x86_64.c
@@ -17,8 +17,7 @@
 
 #ifdef REENTRANT
 #define __vacall __vacall_r
-register struct { void (*vacall_function) (void*,va_alist); void* arg; }
-         *		env	__asm__("r10");
+typedef struct { void (*vacall_function) (void*,va_alist); void* arg; } env_t;
 #endif
 
 register __vaword iarg1 __asm__("rdi");
@@ -51,7 +50,7 @@ register void*	dummy1	__asm__("%rbx");
 register void*	dummy2	__asm__("%rbp");
 
 void /* the return type is variable, not void! */
-__vacall (__vaword word1, __vaword word2, __vaword word3, __vaword word4,
+__vacall (env_t *env, __vaword word1, __vaword word2, __vaword word3, __vaword word4,
           __vaword word5, __vaword word6,
           __vaword firstword)
 {
diff --git a/callback/vacall_r/vacall-x86_64.s b/callback/vacall_r/vacall-x86_64.s
index 3e59347..30df874 100644
--- a/callback/vacall_r/vacall-x86_64.s
+++ b/callback/vacall_r/vacall-x86_64.s
@@ -4,6 +4,9 @@
 .globl __vacall_r
 	.type	__vacall_r,@function
 __vacall_r:
+    popq    %rcx
+    popq    %r10
+    pushq   %rcx
 .LFB1:
 	pushq	%r13
 .LCFI0:
-- 
1.7.2.3

#include <stdio.h>
#include <callback.h>

static void add(void* data, va_alist alist)
{
  int a, b, r;
  va_start_int(alist);
  a = va_arg_int(alist);
  b = va_arg_int(alist);
  r = a + b;

  printf("data = %p: %d + %d = %d\n", data, a, b, r);

  va_return_int(alist, r);
}

int main()
{
  __TR_function callback;
  int r;

  callback = alloc_callback(add, (void*)0xBEBEBE);
  r = ((int (*) (int,int)) callback) (2,3);

  printf("%d\n", r);

  return 0;
}

Reply via email to