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; }