Differences From Artifact [44289e1896]:

To Artifact [e0267b9acf]:


1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25

26
27

28
29




30
31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
1
2
3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24

25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54



-
+


















-
+

-
+

-
+


+
+
+
+













-
+







/* Trampoline construction */

/*
 * Copyright 1995-1999, 2001-2004 Bruno Haible, <bruno@clisp.org>
 * Copyright 1995-1999, 2001-2006 Bruno Haible, <bruno@clisp.org>
 *
 * 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.
 */


#include "config.h"
#include "trampoline.h"

#if defined(__hppa__)
#if 0
#define __hppaold__  /* Old trampoline, real machine code. */
#else
#define __hppanew__  /* New trampoline, just a closure. */
#endif
#endif
#if defined(__rs6000__)
#if defined(__powerpc__) && !defined(__powerpc64__)
#if !defined(_AIX)
#define __rs6000sysv4__  /* SysV.4 ABI, real machine code. */
#define __powerpcsysv4__  /* SysV.4 ABI, real machine code. */
#else
#define __rs6000aix__  /* AIX ABI, just a closure. */
#define __powerpcaix__  /* 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.
 */
extern void tramp (); /* trampoline prototype */
/* We don't need to take any special measures to make the code executable
 * since the actual instructions are in the text segment.
 */
#ifndef CODE_EXECUTABLE
#define CODE_EXECUTABLE
#endif
#endif
#if defined(__rs6000aix__) || defined(__ia64__)
#if defined(__powerpcaix__) || defined(__powerpc64aix__) || 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) (); /* trampoline prototype */
/* We don't need to take any special measures to make the code executable
 * since the actual instructions are in the text segment.
96
97
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
100
101
102
103
104
105
106


107

108
109
110
111
112
113
114
115







-
-

-
+







#include <unistd.h>
#endif

/* Declare getpagesize(). */
#ifdef HAVE_GETPAGESIZE
#ifdef __cplusplus
extern "C" RETGETPAGESIZETYPE getpagesize (void);
#elif defined(__STDC__)
extern RETGETPAGESIZETYPE getpagesize (void);
#else
extern RETGETPAGESIZETYPE getpagesize ();
extern RETGETPAGESIZETYPE getpagesize (void);
#endif
#else
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#else
/* Not Unix, e.g. mingw32 */
#define PAGESIZE 4096
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
150
151
152
153
154
155
156



157
158
159
160
161
162
163







-
-
-







#endif

/* Declare open(). */
#ifdef EXECUTABLE_VIA_MMAP_DEVZERO
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef OPEN_NEEDS_SYS_FILE_H
#include <sys/file.h>
#endif
#endif

/* Declare shmget(), shmat(), shmctl(). */
#ifdef EXECUTABLE_VIA_SHM
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216
217
218


219
220
221
222
223
224
225
197
198
199
200
201
202
203

204
205
206
207
208
209
210
211
212
213
214
215


216
217
218
219
220
221
222
223
224







-
+











-
-
+
+







#endif
#endif
#endif
#ifdef __m88k__
#include <sys/syslocal.h>
#endif
/* Inline assembly function for instruction cache flush. */
#if defined(__sparc__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppaold__) || defined(__rs6000sysv4__) || defined(__convex__)
#if defined(__sparc__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppaold__) || defined(__powerpcsysv4__) || defined(__convex__)
#ifdef __GNUC__
extern inline
#if defined(__sparc__) || defined(__sparc64__)
#include "cache-sparc.c"
#endif
#ifdef __alpha__
#include "cache-alpha.c"
#endif
#ifdef __hppa__
#include "cache-hppa.c"
#endif
#ifdef __rs6000__
#include "cache-rs6000.c"
#if defined(__powerpc__) && !defined(__powerpc64__)
#include "cache-powerpc.c"
#endif
#ifdef __convex__
#include "cache-convex.c"
#endif
#else
#if defined(__sparc__) || defined(__sparc64__)
extern void __TR_clear_cache_4();
272
273
274
275
276
277
278
279

280
281
282

283
284
285
286

287
288




289
290
291
292
293
294
295
271
272
273
274
275
276
277

278
279
280

281
282
283
284

285
286
287
288
289
290
291
292
293
294
295
296
297
298







-
+


-
+



-
+


+
+
+
+







#endif
#ifdef __hppanew__
#define TRAMP_LENGTH 20
#define TRAMP_ALIGN 16
#define TRAMP_BIAS 2
#endif
#ifdef __arm__
#define TRAMP_LENGTH 44
#define TRAMP_LENGTH 36
#define TRAMP_ALIGN 4
#endif
#ifdef __rs6000sysv4__
#ifdef __powerpcsysv4__
#define TRAMP_LENGTH 36
#define TRAMP_ALIGN 4
#endif
#ifdef __rs6000aix__
#ifdef __powerpcaix__
#define TRAMP_LENGTH 24
#define TRAMP_ALIGN 4
#endif
#ifdef __powerpc64aix__
#define TRAMP_LENGTH 48
#define TRAMP_ALIGN 8
#endif
#ifdef __m88k__
#define TRAMP_LENGTH 32
#define TRAMP_ALIGN 8
#endif
#ifdef __convex__
#define TRAMP_LENGTH 20
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
319
320
321
322
323
324
325

326






327
328
329
330
331
332
333







-

-
-
-
-
-
-







/* AIX doesn't support mprotect() in malloc'ed memory. Must get pages of
 * memory with execute permission via mmap(). Then keep a free list of
 * free trampolines.
 */
static char* freelist = NULL;
#endif

#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus)
__TR_function alloc_trampoline (__TR_function address, void* variable, void* data)
#else
__TR_function alloc_trampoline (address, variable, data)
  __TR_function address;
  void* variable;
  void* data;
#endif
{
  char* function;

#if !defined(CODE_EXECUTABLE)
  static long pagesize = 0;
#if defined(EXECUTABLE_VIA_MMAP_DEVZERO)
  static int zero_fd;
852
853
854
855
856
857
858
859
860


861
862
863
864
865




866
867
868

869
870

871
872

873

874
875
876



877
878
879
880
881
882






883
884
885
886
887
888
889
890






891
892
893
894

895
896

897
898

899
900

901
902
903
904
905
906
907
848
849
850
851
852
853
854


855
856





857
858
859
860

861

862
863

864
865

866
867
868



869
870
871






872
873
874
875
876
877
878
879






880
881
882
883
884
885


886

887
888

889
890

891
892

893
894
895
896
897
898
899
900







-
-
+
+
-
-
-
-
-
+
+
+
+
-

-
+

-
+

-
+

+
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+


-
-
-
-
-
-
+
+
+
+
+
+
-
-

-
+

-
+

-
+

-
+







#define tramp_variable(function)  \
  ((long *) function)[2]
#define tramp_data(function)  \
  ((long *) function)[3]
#endif
#ifdef __arm__
  /* function:
   *    stmfd   sp!,{r0}			E92D0001
   *    ldr     r0,[pc,#_data-.-8]		E59F0014
   *	stmfd	sp!,{r0}		E92D0001
   * 	ldr	r0,[pc,#16]		E59F000C
   *    ldr     ip,[r0,#0]			E590C000
   *    ldr     r0,[pc,#_variable-.-8]		E59F0010
   *    str     ip,[r0,#0]			E580C000
   *    ldmfd   sp!,{r0}^			E8FD0001
   *    ldr     ip,[pc,#_function-.-8]		E59FC008
   *	ldr	ip,[pc,#16]		E59FC00C
   *	str	r0,[ip]			E58C0000
   *	ldmfd	sp!,{r0}		E8BD0001
   *	ldr	pc,[pc,#4]		E59FF004
   *    ldr     pc,[ip,#0]			E59CF000
   * _data:
   *    .word   <data>				<data>
   *	.word	<data>
   * _variable:
   *    .word   <variable>			<variable>
   *	.word	<variable>
   * _function:
   *    .word   <address>			<address>
   *	.word	<address>
   */
  {
  { static long code [8] =
      { 0xE92D0001, 0xE59F0014, 0xE590C000, 0xE59F0010,
        0xE580C000, 0xE8FD0001, 0xE59FC008, 0xE59CF000
    ((long *) function)[0] = 0xE92D0001;
    ((long *) function)[1] = 0xE59F000C;
    ((long *) function)[2] = 0xE59FC00C;
      };
    int i;
    for (i=0; i<8; i++) { ((long *) function)[i] = code[i]; }
    ((long *) function)[8] = (long) data;
    ((long *) function)[9] = (long) variable;
    ((long *) function)[10] = (long) address;
    ((long *) function)[3] = 0xE58C0000;
    ((long *) function)[4] = 0xE8BD0001;
    ((long *) function)[5] = 0xE59FF004;
    ((long *) function)[6] = (long)data;
    ((long *) function)[7] = (long)variable;
    ((long *) function)[8] = (long)address;
  }
#define is_tramp(function)  \
  ((long *) function)[0] == 0xE92D0001 && \
  ((long *) function)[1] == 0xE59F0014 && \
  ((long *) function)[2] == 0xE590C000 && \
  ((long *) function)[3] == 0xE59F0010 && \
  ((long *) function)[4] == 0xE580C000 && \
  ((long *) function)[5] == 0xE8FD0001 && \
    ((long *) function)[0] == 0xE92D0001 && \
    ((long *) function)[1] == 0xE59F000C && \
    ((long *) function)[2] == 0xE59FC00C && \
    ((long *) function)[3] == 0xE58C0000 && \
    ((long *) function)[4] == 0xE8BD0001 && \
    ((long *) function)[5] == 0xE59FF004
  ((long *) function)[6] == 0xE59FC008 && \
  ((long *) function)[7] == 0xE59CF000
#define tramp_address(function)  \
  ((long *) function)[10]
  ((long *) function)[8]
#define tramp_variable(function)  \
  ((long *) function)[9]
  ((long *) function)[7]
#define tramp_data(function)  \
  ((long *) function)[8]
  ((long *) function)[6]
#endif
#ifdef __rs6000sysv4__
#ifdef __powerpcsysv4__
  /* function:
   *    {liu|lis} 11,hi16(<variable>)		3D 60 hi16(<variable>)
   *    {oril|ori} 11,11,lo16(<variable>)	61 6B lo16(<variable>)
   *    {liu|lis} 12,hi16(<data>)		3D 80 hi16(<data>)
   *    {oril|ori} 12,12,lo16(<data>)		61 8C lo16(<data>)
   *    {st|stw} 12,0(11)			91 8B 00 00
   *    {liu|lis} 0,hi16(<address>)		3C 00 hi16(<address>)
939
940
941
942
943
944
945
946

947
948
949
950
951
952
953
954
955
956
957
958
959
960
961

























962
963
964
965
966
967
968
932
933
934
935
936
937
938

939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986







-
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#define tramp_address(function)  \
  hilo(*(unsigned short *) (function +22), *(unsigned short *) (function +26))
#define tramp_variable(function)  \
  hilo(*(unsigned short *) (function + 2), *(unsigned short *) (function + 6))
#define tramp_data(function)  \
  hilo(*(unsigned short *) (function +10), *(unsigned short *) (function +14))
#endif
#ifdef __rs6000aix__
#ifdef __powerpcaix__
  /* function:
   *    .long .tramp
   *    .long .mytoc
   *    .long 0
   * .mytoc:
   *    .long <variable>
   *    .long <data>
   *    .long <address>
   */
  *(long *)  (function + 0) = ((long *) &tramp)[0];
  *(long *)  (function + 4) = (long) (function + 12);
  *(long *)  (function + 8) = 0;
  *(long *)  (function +12) = (long) variable;
  *(long *)  (function +16) = (long) data;
  *(long *)  (function +20) = (long) address;
#define is_tramp(function)  \
  ((long *) function)[0] == ((long *) &tramp)[0]
#define tramp_address(function)  \
  ((long *) function)[5]
#define tramp_variable(function)  \
  ((long *) function)[3]
#define tramp_data(function)  \
  ((long *) function)[4]
#endif
#ifdef __powerpc64aix__
  /* function:
   *    .quad .tramp
   *    .quad .mytoc
   *    .quad 0
   * .mytoc:
   *    .quad <variable>
   *    .quad <data>
   *    .quad <address>
   */
  *(long *)  (function + 0) = ((long *) &tramp)[0];
  *(long *)  (function + 8) = (long) (function + 24);
  *(long *)  (function +16) = 0;
  *(long *)  (function +24) = (long) variable;
  *(long *)  (function +32) = (long) data;
  *(long *)  (function +40) = (long) address;
#define is_tramp(function)  \
  ((long *) function)[0] == ((long *) &tramp)[0]
#define tramp_address(function)  \
  ((long *) function)[5]
#define tramp_variable(function)  \
  ((long *) function)[3]
#define tramp_data(function)  \
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191
1195
1196
1197
1198
1199
1200
1201

1202
1203
1204
1205
1206
1207
1208
1209







-
+







#endif

  /* 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(__rs6000aix__) || defined(__ia64__))
#if !(defined(__hppanew__) || defined(__powerpcaix__) || defined(__powerpc64aix__) || defined(__ia64__))
  /* Only needed if we really set up machine instructions. */
#ifdef __i386__
#if defined(_WIN32)
  while (!FlushInstructionCache(GetCurrentProcess(),function,TRAMP_LENGTH))
    continue;
#endif
#endif
1258
1259
1260
1261
1262
1263
1264
1265

1266
1267

1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1276
1277
1278
1279
1280
1281
1282

1283
1284

1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299

1300




1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312

1313




1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325

1326




1327
1328
1329
1330
1331
1332
1333
1334

1335




1336
1337
1338
1339
1340
1341
1342
1343

1344




1345
1346
1347
1348
1349
1350
1351







-
+

-
+














-

-
-
-
-












-

-
-
-
-












-

-
-
-
-








-

-
-
-
-








-

-
-
-
-







  __TR_clear_cache();
#endif
#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__
  /* This CPU does not have a separate instruction cache. (I think.) */
  __TR_clear_cache(function,function+TRAMP_LENGTH);
#endif
#ifdef __rs6000__
#if defined(__powerpc__) && !defined(__powerpc64__)
  __TR_clear_cache(function);
#endif
#ifdef __m88k__
  sysmot(S88CACHEFLUSHPAGE, (unsigned long)function & -pagesize);
#endif
#ifdef __convex__
  __TR_clear_cache();
#endif
#endif

  /* 5. Return. */
  return (__TR_function) (function + TRAMP_BIAS);
}

#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus)
void free_trampoline (__TR_function function)
#else
void free_trampoline (function)
  __TR_function function;
#endif
{
#if TRAMP_BIAS
  function = (__TR_function)((char*)function - TRAMP_BIAS);
#endif
#if !defined(CODE_EXECUTABLE) && !defined(EXECUTABLE_VIA_MPROTECT)
  *(char**)function = freelist; freelist = (char*)function;
  /* It is probably not worth calling munmap() for entirely freed pages. */
#else
  free(((char**)function)[-1]);
#endif
}

#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus)
int is_trampoline (void* function)
#else
int is_trampoline (function)
  void* function;
#endif
{
#ifdef is_tramp
#ifdef __hppanew__
  void* tramp_address = &tramp;
  if (!(((long)function & 3) == (TRAMP_BIAS & 3))) return 0;
#endif
  return ((is_tramp(((char*)function - TRAMP_BIAS))) ? 1 : 0);
#else
  abort();
#endif
}

#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus)
__TR_function trampoline_address (void* function)
#else
__TR_function trampoline_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_variable (void* function)
#else
void* trampoline_variable (function)
  void* function;
#endif
{
#ifdef tramp_variable
  return (void*)(tramp_variable(((char*)function - TRAMP_BIAS)));
#else
  abort();
#endif
}

#if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus)
void* trampoline_data (void* function)
#else
void* trampoline_data (function)
  void* function;
#endif
{
#ifdef tramp_data
  return (void*)(tramp_data(((char*)function - TRAMP_BIAS)));
#else
  abort();
#endif
}