@@ -1,9 +1,9 @@ /* Trampoline construction */ /* - * Copyright 1995-1999, 2001-2006 Bruno Haible, + * Copyright 1995-1999, 2001-2004 Bruno Haible, * * This is free software distributed under the GNU General Public Licence * described in the file COPYING. Contact the author if you don't have this * or can't live with it. There is ABSOLUTELY NO WARRANTY, explicit or implied, * on this software. @@ -18,20 +18,20 @@ #define __hppaold__ /* Old trampoline, real machine code. */ #else #define __hppanew__ /* New trampoline, just a closure. */ #endif #endif -#if defined(__powerpc__) && !defined(__powerpc64__) +#if defined(__rs6000__) +#if defined(__NetBSD__) +#define __rs6000netbsd__ +#else #if !defined(_AIX) -#define __powerpcsysv4__ /* SysV.4 ABI, real machine code. */ +#define __rs6000sysv4__ /* SysV.4 ABI, real machine code. */ #else -#define __powerpcaix__ /* AIX ABI, just a closure. */ +#define __rs6000aix__ /* AIX ABI, just a closure. */ #endif #endif -#if defined(__powerpc64__) -/* The only ABI on powerpc64 known so far is the AIX ABI. */ -#define __powerpc64aix__ /* AIX ABI, just a closure. */ #endif #if defined(__hppanew__) /* * A function pointer is a biased pointer to a data area whose first word * contains the actual address of the function. @@ -42,11 +42,11 @@ */ #ifndef CODE_EXECUTABLE #define CODE_EXECUTABLE #endif #endif -#if defined(__powerpcaix__) || defined(__powerpc64aix__) || defined(__ia64__) +#if defined(__rs6000aix__) || defined(__ia64__) /* * A function pointer is a pointer to a data area whose first word contains * the actual address of the function. */ extern void (*tramp_r) (); /* trampoline prototype */ @@ -102,12 +102,14 @@ /* Declare getpagesize(). */ #ifdef HAVE_GETPAGESIZE #ifdef __cplusplus extern "C" RETGETPAGESIZETYPE getpagesize (void); -#else +#elif defined(__STDC__) extern RETGETPAGESIZETYPE getpagesize (void); +#else +extern RETGETPAGESIZETYPE getpagesize (); #endif #else #ifdef HAVE_SYS_PARAM_H #include #else @@ -152,10 +154,13 @@ /* Declare open(). */ #ifdef EXECUTABLE_VIA_MMAP_DEVZERO #include #include #include +#ifdef OPEN_NEEDS_SYS_FILE_H +#include +#endif #endif /* Declare shmget(), shmat(), shmctl(). */ #ifdef EXECUTABLE_VIA_SHM #include @@ -199,11 +204,11 @@ #endif #ifdef __m88k__ #include #endif /* Inline assembly function for instruction cache flush. */ -#if defined(__sparc__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppaold__) || defined(__powerpcsysv4__) || defined(__convex__) +#if defined(__sparc__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppaold__) || defined(__rs6000sysv4__) || defined(__rs6000netbsd__) || defined(__convex__) #ifdef __GNUC__ extern inline #if defined(__sparc__) || defined(__sparc64__) #include "cache-sparc.c" #endif @@ -211,12 +216,12 @@ #include "cache-alpha.c" #endif #ifdef __hppa__ #include "cache-hppa.c" #endif -#if defined(__powerpc__) && !defined(__powerpc64__) -#include "cache-powerpc.c" +#ifdef __rs6000__ +#include "cache-rs6000.c" #endif #ifdef __convex__ #include "cache-convex.c" #endif #else @@ -235,11 +240,15 @@ #endif #ifdef __m68k__ #define TRAMP_LENGTH 14 #define TRAMP_ALIGN 16 #endif -#if defined(__mips__) || defined(__mipsn32__) && !defined(__mips64__) +#if defined(__mips__) && !defined(__mipsn32__) +#define TRAMP_LENGTH 24 +#define TRAMP_ALIGN 4 +#endif +#ifdef __mipsn32__ #define TRAMP_LENGTH 24 #define TRAMP_ALIGN 4 #endif #ifdef __mips64old__ #define TRAMP_LENGTH 56 @@ -269,25 +278,25 @@ #define TRAMP_LENGTH 16 #define TRAMP_ALIGN 16 #define TRAMP_BIAS 2 #endif #ifdef __arm__ -#define TRAMP_LENGTH 16 +#define TRAMP_LENGTH 32 +#define TRAMP_ALIGN 4 +#endif +#ifdef __rs6000sysv4__ +#define TRAMP_LENGTH 24 #define TRAMP_ALIGN 4 #endif -#ifdef __powerpcsysv4__ +#ifdef __rs6000netbsd__ #define TRAMP_LENGTH 24 #define TRAMP_ALIGN 4 #endif -#ifdef __powerpcaix__ +#ifdef __rs6000aix__ #define TRAMP_LENGTH 20 #define TRAMP_ALIGN 4 #endif -#ifdef __powerpc64aix__ -#define TRAMP_LENGTH 40 -#define TRAMP_ALIGN 8 -#endif #ifdef __m88k__ #define TRAMP_LENGTH 20 #define TRAMP_ALIGN 8 #endif #ifdef __convex__ @@ -319,11 +328,18 @@ * free trampolines. */ static char* freelist = NULL; #endif +#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) __TR_function alloc_trampoline_r (__TR_function address, void* data0, void* data1) +#else +__TR_function alloc_trampoline_r (address, data0, data1) + __TR_function address; + void* data0; + void* data1; +#endif { char* function; char* data; #if !defined(CODE_EXECUTABLE) @@ -351,11 +367,11 @@ #if !defined(CODE_EXECUTABLE) && !defined(EXECUTABLE_VIA_MPROTECT) /* Note: This memory allocation is not multithread-safe. We might need * to add special (platform dependent) code for locking. * Fortunately, most modern systems where multithread-safety matters - * have EXECUTABLE_VIA_MPROTECT, and those which don't (AIX on powerpc and + * have EXECUTABLE_VIA_MPROTECT, and those which don't (AIX on rs6000 and * HP-UX on hppa) have CODE_EXECUTABLE. Thus no locking code is needed * for the moment. */ if (freelist == NULL) { /* Get a new page. */ @@ -422,26 +438,10 @@ *(long *) (function + 8) + (long) (function + 12) #define tramp_data(function) \ *(long *) (function + 2) #endif #ifdef __m68k__ -#ifdef __NetBSD__ - /* function: - * movel #,a1 22 7C - * jmp
4E F9
- * nop 4E 71 - */ - *(short *) (function + 0) = 0x227C; - *(long *) (function + 2) = (long) data; - *(short *) (function + 6) = 0x4EF9; - *(long *) (function + 8) = (long) address; - *(short *) (function +12) = 0x4E71; -#define is_tramp(function) \ - *(unsigned short *) (function + 0) == 0x227C && \ - *(unsigned short *) (function + 6) == 0x4EF9 && \ - *(unsigned short *) (function +12) == 0x4E71 -#else /* function: * movel #,a0 20 7C * jmp
4E F9
* nop 4E 71 */ @@ -452,36 +452,70 @@ *(short *) (function +12) = 0x4E71; #define is_tramp(function) \ *(unsigned short *) (function + 0) == 0x207C && \ *(unsigned short *) (function + 6) == 0x4EF9 && \ *(unsigned short *) (function +12) == 0x4E71 -#endif #define tramp_address(function) \ *(long *) (function + 8) #define tramp_data(function) \ *(long *) (function + 2) #endif -#if defined(__mips__) || defined(__mipsn32__) && !defined(__mips64__) +#if defined(__mips__) && !defined(__mipsn32__) + /* function: + * li $2,&0xffff0000 3C 02 hi16() + * ori $2,$2,&0xffff 34 42 lo16() + * li $25,
&0xffff0000 3C 19 hi16(
) + * ori $25,$25,
&0xffff 37 39 lo16(
) + * j $25 03 20 00 08 + * nop 00 00 00 00 + */ + /* What about big endian / little endian ?? */ + *(short *) (function + 0) = 0x3C02; + *(short *) (function + 2) = (unsigned long) data >> 16; + *(short *) (function + 4) = 0x3442; + *(short *) (function + 6) = (unsigned long) data & 0xffff; + *(short *) (function + 8) = 0x3C19; + *(short *) (function +10) = (unsigned long) address >> 16; + *(short *) (function +12) = 0x3739; + *(short *) (function +14) = (unsigned long) address & 0xffff; + *(long *) (function +16) = 0x03200008; + *(long *) (function +20) = 0x00000000; +#define is_tramp(function) \ + *(unsigned short *) (function + 0) == 0x3C02 && \ + *(unsigned short *) (function + 4) == 0x3442 && \ + *(unsigned short *) (function + 8) == 0x3C19 && \ + *(unsigned short *) (function +12) == 0x3739 && \ + *(unsigned long *) (function +16) == 0x03200008 && \ + *(unsigned long *) (function +20) == 0x00000000 +#define hilo(hiword,loword) \ + (((unsigned long) (hiword) << 16) | (unsigned long) (loword)) +#define tramp_address(function) \ + hilo(*(unsigned short *) (function +10), *(unsigned short *) (function +14)) +#define tramp_data(function) \ + hilo(*(unsigned short *) (function + 2), *(unsigned short *) (function + 6)) +#endif +#ifdef __mipsn32__ /* function: * lw $2,16($25) 8F 22 00 10 * lw $25,20($25) 8F 39 00 14 * j $25 03 20 00 08 * nop 00 00 00 00 * .word * .word
*/ + /* What about big endian / little endian ?? */ *(unsigned int *) (function + 0) = 0x8F220010; *(unsigned int *) (function + 4) = 0x8F390014; *(unsigned int *) (function + 8) = 0x03200008; *(unsigned int *) (function +12) = 0x00000000; *(unsigned int *) (function +16) = (unsigned int) data; *(unsigned int *) (function +20) = (unsigned int) address; #define is_tramp(function) \ - *(unsigned int *) (function + 0) == 0x8F220010 && \ - *(unsigned int *) (function + 4) == 0x8F390014 && \ - *(unsigned int *) (function + 8) == 0x03200008 && \ - *(unsigned int *) (function +12) == 0x00000000 + *(int *) (function + 0) == 0x8F220010 && \ + *(int *) (function + 4) == 0x8F390014 && \ + *(int *) (function + 8) == 0x03200008 && \ + *(int *) (function +12) == 0x00000000 #define tramp_address(function) \ *(unsigned int *) (function +20) #define tramp_data(function) \ *(unsigned int *) (function +16) #endif @@ -561,21 +595,18 @@ * j $25 03 20 00 08 * nop 00 00 00 00 * .dword * .dword
*/ - *(unsigned int *) (function + 0) = 0xDF220010; - *(unsigned int *) (function + 4) = 0xDF390018; - *(unsigned int *) (function + 8) = 0x03200008; - *(unsigned int *) (function +12) = 0x00000000; + /* What about big endian / little endian ?? */ + *(long *) (function + 0) = 0xDF220010DF390018L; + *(long *) (function + 8) = 0x0320000800000000L; *(unsigned long *) (function +16) = (unsigned long) data; *(unsigned long *) (function +24) = (unsigned long) address; #define is_tramp(function) \ - *(unsigned int *) (function + 0) == 0xDF220010 && \ - *(unsigned int *) (function + 4) == 0xDF390018 && \ - *(unsigned int *) (function + 8) == 0x03200008 && \ - *(unsigned int *) (function +12) == 0x00000000 + *(long *) (function + 0) == 0xDF220010DF390018L && \ + *(long *) (function + 8) == 0x0320000800000000L #define tramp_address(function) \ *(unsigned long *) (function +24) #define tramp_data(function) \ *(unsigned long *) (function +16) #endif @@ -747,59 +778,43 @@ #define tramp_data(function) \ ((long *) function)[2] #endif #ifdef __arm__ /* function: - * add r12,pc,#8 E28FC008 - * ldr pc,[pc] E59FF000 - * _data: - * .word - * _function: - * .word
- */ - { - ((long *) function)[0] = 0xE28FC008; - ((long *) function)[1] = 0xE59FF000; - ((long *) function)[2] = (long) data; - ((long *) function)[3] = (long) address; - } -#define is_tramp(function) \ - ((long *) function)[0] == 0xE28FC008 && \ - ((long *) function)[1] == 0xE59FF000 -#define tramp_address(function) \ - ((long *) function)[3] -#define tramp_data(function) \ - ((long *) function)[2] -#endif -#ifdef __powerpcsysv4__ -#ifdef __NetBSD__ - /* function: - * {liu|lis} 13,hi16() 3D A0 hi16() - * {oril|ori} 13,13,lo16() 61 AD lo16() - * {liu|lis} 0,hi16(
) 3C 00 hi16(
) - * {oril|ori} 0,0,lo16(
) 60 00 lo16(
) - * mtctr 0 7C 09 03 A6 - * bctr 4E 80 04 20 - */ - *(short *) (function + 0) = 0x3DA0; - *(short *) (function + 2) = (unsigned long) data >> 16; - *(short *) (function + 4) = 0x61AD; - *(short *) (function + 6) = (unsigned long) data & 0xffff; - *(short *) (function + 8) = 0x3C00; - *(short *) (function +10) = (unsigned long) address >> 16; - *(short *) (function +12) = 0x6000; - *(short *) (function +14) = (unsigned long) address & 0xffff; - *(long *) (function +16) = 0x7C0903A6; - *(long *) (function +20) = 0x4E800420; -#define is_tramp(function) \ - *(unsigned short *) (function + 0) == 0x3DA0 && \ - *(unsigned short *) (function + 4) == 0x61AD && \ - *(unsigned short *) (function + 8) == 0x3C00 && \ - *(unsigned short *) (function +12) == 0x6000 && \ - *(unsigned long *) (function +16) == 0x7C0903A6 && \ - *(unsigned long *) (function +20) == 0x4E800420 -#else + * ldr ip,[pc,#_function-.-8] E59FC014 + * ldr ip,[ip,#0] E59CC000 ??Is this correct?? + * stmfd sp!,{ip} E92D1000 + * ldr ip,[pc,#_data-.-8] E59FC004 + * ldr ip,[ip,#0] E59CC000 ??Is this correct?? + * ldmfd sp!,{pc}^ E8FD8000 + * _data: + * .word + * _function: + * .word
+ */ + { static long code [6] = + { 0xE59FC014, 0xE59CC000, 0xE92D1000, 0xE59FC004, + 0xE59CC000, 0xE8FD8000 + }; + int i; + for (i=0; i<6; i++) { ((long *) function)[i] = code[i]; } + ((long *) function)[6] = (long) data; + ((long *) function)[7] = (long) address; + } +#define is_tramp(function) \ + ((long *) function)[0] == 0xE59FC014 && \ + ((long *) function)[1] == 0xE59CC000 && \ + ((long *) function)[2] == 0xE92D1000 && \ + ((long *) function)[3] == 0xE59FC004 && \ + ((long *) function)[4] == 0xE59CC000 && \ + ((long *) function)[5] == 0xE8FD8000 +#define tramp_address(function) \ + ((long *) function)[7] +#define tramp_data(function) \ + ((long *) function)[6] +#endif +#ifdef __rs6000sysv4__ /* function: * {liu|lis} 11,hi16() 3D 60 hi16() * {oril|ori} 11,11,lo16() 61 6B lo16() * {liu|lis} 0,hi16(
) 3C 00 hi16(
) * {oril|ori} 0,0,lo16(
) 60 00 lo16(
) @@ -821,19 +836,51 @@ *(unsigned short *) (function + 4) == 0x616B && \ *(unsigned short *) (function + 8) == 0x3C00 && \ *(unsigned short *) (function +12) == 0x6000 && \ *(unsigned long *) (function +16) == 0x7C0903A6 && \ *(unsigned long *) (function +20) == 0x4E800420 +#define hilo(hiword,loword) \ + (((unsigned long) (hiword) << 16) | (unsigned long) (loword)) +#define tramp_address(function) \ + hilo(*(unsigned short *) (function +10), *(unsigned short *) (function +14)) +#define tramp_data(function) \ + hilo(*(unsigned short *) (function + 2), *(unsigned short *) (function + 6)) #endif +#ifdef __rs6000netbsd__ + /* function: + * {liu|lis} 13,hi16() 3D A0 hi16() + * {oril|ori} 13,13,lo16() 61 AD lo16() + * {liu|lis} 0,hi16(
) 3C 00 hi16(
) + * {oril|ori} 0,0,lo16(
) 60 00 lo16(
) + * mtctr 0 7C 09 03 A6 + * bctr 4E 80 04 20 + */ + *(short *) (function + 0) = 0x3DA0; + *(short *) (function + 2) = (unsigned long) data >> 16; + *(short *) (function + 4) = 0x61AD; + *(short *) (function + 6) = (unsigned long) data & 0xffff; + *(short *) (function + 8) = 0x3C00; + *(short *) (function +10) = (unsigned long) address >> 16; + *(short *) (function +12) = 0x6000; + *(short *) (function +14) = (unsigned long) address & 0xffff; + *(long *) (function +16) = 0x7C0903A6; + *(long *) (function +20) = 0x4E800420; +#define is_tramp(function) \ + *(unsigned short *) (function + 0) == 0x3DA0 && \ + *(unsigned short *) (function + 4) == 0x61AD && \ + *(unsigned short *) (function + 8) == 0x3C00 && \ + *(unsigned short *) (function +12) == 0x6000 && \ + *(unsigned long *) (function +16) == 0x7C0903A6 && \ + *(unsigned long *) (function +20) == 0x4E800420 #define hilo(hiword,loword) \ (((unsigned long) (hiword) << 16) | (unsigned long) (loword)) #define tramp_address(function) \ hilo(*(unsigned short *) (function +10), *(unsigned short *) (function +14)) #define tramp_data(function) \ hilo(*(unsigned short *) (function + 2), *(unsigned short *) (function + 6)) #endif -#ifdef __powerpcaix__ +#ifdef __rs6000aix__ /* function: * .long .tramp_r * .long .mytoc * .long 0 * .mytoc: @@ -844,31 +891,10 @@ *(long *) (function + 4) = (long) (function + 12); *(long *) (function + 8) = 0; *(long *) (function +12) = (long) data; *(long *) (function +16) = (long) address; #define is_tramp(function) \ - ((long *) function)[0] == ((long *) &tramp_r)[0] -#define tramp_address(function) \ - ((long *) function)[4] -#define tramp_data(function) \ - ((long *) function)[3] -#endif -#ifdef __powerpc64aix__ - /* function: - * .quad .tramp_r - * .quad .mytoc - * .quad 0 - * .mytoc: - * .quad - * .quad
- */ - *(long *) (function + 0) = ((long *) &tramp_r)[0]; - *(long *) (function + 8) = (long) (function + 24); - *(long *) (function +16) = 0; - *(long *) (function +24) = (long) data; - *(long *) (function +32) = (long) address; -#define is_tramp(function) \ ((long *) function)[0] == ((long *) &tramp_r)[0] #define tramp_address(function) \ ((long *) function)[4] #define tramp_data(function) \ ((long *) function)[3] @@ -1042,11 +1068,11 @@ /* 4. Flush instruction cache */ /* We need this because some CPUs have separate data cache and instruction * cache. The freshly built trampoline is visible to the data cache, but not * maybe not to the instruction cache. This is hairy. */ -#if !(defined(__hppanew__) || defined(__powerpcaix__) || defined(__powerpc64aix__) || defined(__ia64__)) +#if !(defined(__hppanew__) || defined(__rs6000aix__) || defined(__ia64__)) /* Only needed if we really set up machine instructions. */ #ifdef __i386__ #if defined(_WIN32) while (!FlushInstructionCache(GetCurrentProcess(),function,TRAMP_LENGTH)) continue; @@ -1123,13 +1149,13 @@ #ifdef __hppa__ /* This assumes that the trampoline fits in at most two cache lines. */ __TR_clear_cache(function,function+TRAMP_LENGTH-1); #endif #ifdef __arm__ - __TR_clear_cache(function,function+TRAMP_LENGTH); + /* This CPU does not have a separate instruction cache. (I think.) */ #endif -#if defined(__powerpc__) && !defined(__powerpc64__) +#ifdef __rs6000__ __TR_clear_cache(function); #endif #ifdef __m88k__ sysmot(S88CACHEFLUSHPAGE, (unsigned long)function & -pagesize); #endif @@ -1140,11 +1166,16 @@ /* 5. Return. */ return (__TR_function) (function + TRAMP_BIAS); } +#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) void free_trampoline_r (__TR_function function) +#else +void free_trampoline_r (function) + __TR_function function; +#endif { #if TRAMP_BIAS function = (__TR_function)((char*)function - TRAMP_BIAS); #endif #if !defined(CODE_EXECUTABLE) && !defined(EXECUTABLE_VIA_MPROTECT) @@ -1153,11 +1184,16 @@ #else free(((char**)function)[-1]); #endif } +#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) int is_trampoline_r (void* function) +#else +int is_trampoline_r (function) + void* function; +#endif { #if defined(is_tramp) && defined(tramp_data) #ifdef __hppanew__ void* tramp_r_address = &tramp_r; if (!(((long)function & 3) == (TRAMP_BIAS & 3))) return 0; @@ -1170,31 +1206,46 @@ #else abort(); #endif } +#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) __TR_function trampoline_r_address (void* function) +#else +__TR_function trampoline_r_address (function) + void* function; +#endif { #ifdef tramp_address return (__TR_function)(tramp_address(((char*)function - TRAMP_BIAS))); #else abort(); #endif } +#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) void* trampoline_r_data0 (void* function) +#else +void* trampoline_r_data0 (function) + void* function; +#endif { #ifdef tramp_data return ((void**)((char*)function-TRAMP_BIAS+TRAMP_LENGTH))[0]; #else abort(); #endif } +#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) void* trampoline_r_data1 (void* function) +#else +void* trampoline_r_data1 (function) + void* function; +#endif { #ifdef tramp_data return ((void**)((char*)function-TRAMP_BIAS+TRAMP_LENGTH))[1]; #else abort(); #endif }