Line data Source code
1 : /* -----------------------------------------------------------------------
2 : ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc.
3 : Copyright (c) 2002 Ranjit Mathew
4 : Copyright (c) 2002 Bo Thorsen
5 : Copyright (c) 2002 Roger Sayle
6 : Copyright (C) 2008, 2010 Free Software Foundation, Inc.
7 :
8 : x86 Foreign Function Interface
9 :
10 : Permission is hereby granted, free of charge, to any person obtaining
11 : a copy of this software and associated documentation files (the
12 : ``Software''), to deal in the Software without restriction, including
13 : without limitation the rights to use, copy, modify, merge, publish,
14 : distribute, sublicense, and/or sell copies of the Software, and to
15 : permit persons to whom the Software is furnished to do so, subject to
16 : the following conditions:
17 :
18 : The above copyright notice and this permission notice shall be included
19 : in all copies or substantial portions of the Software.
20 :
21 : THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
22 : EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 : MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 : NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 : HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 : WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : DEALINGS IN THE SOFTWARE.
29 : ----------------------------------------------------------------------- */
30 :
31 : #if !defined(__x86_64__) || defined(_WIN64)
32 :
33 : #ifdef _WIN64
34 : #include <windows.h>
35 : #endif
36 :
37 : #include <ffi.h>
38 : #include <ffi_common.h>
39 :
40 : #include <stdlib.h>
41 :
42 : /* ffi_prep_args is called by the assembly routine once stack space
43 : has been allocated for the function's arguments */
44 :
45 0 : void ffi_prep_args(char *stack, extended_cif *ecif)
46 : {
47 : register unsigned int i;
48 : register void **p_argv;
49 : register char *argp;
50 : register ffi_type **p_arg;
51 : #ifdef X86_WIN32
52 : size_t p_stack_args[2];
53 : void *p_stack_data[2];
54 : char *argp2 = stack;
55 : int stack_args_count = 0;
56 : int cabi = ecif->cif->abi;
57 : #endif
58 :
59 0 : argp = stack;
60 :
61 0 : if ((ecif->cif->flags == FFI_TYPE_STRUCT
62 0 : || ecif->cif->flags == FFI_TYPE_MS_STRUCT)
63 : #ifdef X86_WIN64
64 : && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
65 : && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
66 : #endif
67 : )
68 : {
69 0 : *(void **) argp = ecif->rvalue;
70 : #ifdef X86_WIN32
71 : /* For fastcall/thiscall this is first register-passed
72 : argument. */
73 : if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
74 : {
75 : p_stack_args[stack_args_count] = sizeof (void*);
76 : p_stack_data[stack_args_count] = argp;
77 : ++stack_args_count;
78 : }
79 : #endif
80 0 : argp += sizeof(void*);
81 : }
82 :
83 0 : p_argv = ecif->avalue;
84 :
85 0 : for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
86 : i != 0;
87 0 : i--, p_arg++)
88 : {
89 : size_t z;
90 :
91 : /* Align if necessary */
92 0 : if ((sizeof(void*) - 1) & (size_t) argp)
93 0 : argp = (char *) ALIGN(argp, sizeof(void*));
94 :
95 0 : z = (*p_arg)->size;
96 : #ifdef X86_WIN64
97 : if (z > sizeof(ffi_arg)
98 : || ((*p_arg)->type == FFI_TYPE_STRUCT
99 : && (z != 1 && z != 2 && z != 4 && z != 8))
100 : #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
101 : || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
102 : #endif
103 : )
104 : {
105 : z = sizeof(ffi_arg);
106 : *(void **)argp = *p_argv;
107 : }
108 : else if ((*p_arg)->type == FFI_TYPE_FLOAT)
109 : {
110 : memcpy(argp, *p_argv, z);
111 : }
112 : else
113 : #endif
114 0 : if (z < sizeof(ffi_arg))
115 : {
116 0 : z = sizeof(ffi_arg);
117 0 : switch ((*p_arg)->type)
118 : {
119 : case FFI_TYPE_SINT8:
120 0 : *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
121 0 : break;
122 :
123 : case FFI_TYPE_UINT8:
124 0 : *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
125 0 : break;
126 :
127 : case FFI_TYPE_SINT16:
128 0 : *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
129 0 : break;
130 :
131 : case FFI_TYPE_UINT16:
132 0 : *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
133 0 : break;
134 :
135 : case FFI_TYPE_SINT32:
136 0 : *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
137 0 : break;
138 :
139 : case FFI_TYPE_UINT32:
140 0 : *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
141 0 : break;
142 :
143 : case FFI_TYPE_STRUCT:
144 0 : *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
145 0 : break;
146 :
147 : default:
148 : FFI_ASSERT(0);
149 : }
150 : }
151 : else
152 : {
153 0 : memcpy(argp, *p_argv, z);
154 : }
155 :
156 : #ifdef X86_WIN32
157 : /* For thiscall/fastcall convention register-passed arguments
158 : are the first two none-floating-point arguments with a size
159 : smaller or equal to sizeof (void*). */
160 : if ((cabi == FFI_THISCALL && stack_args_count < 1)
161 : || (cabi == FFI_FASTCALL && stack_args_count < 2))
162 : {
163 : if (z <= 4
164 : && ((*p_arg)->type != FFI_TYPE_FLOAT
165 : && (*p_arg)->type != FFI_TYPE_STRUCT))
166 : {
167 : p_stack_args[stack_args_count] = z;
168 : p_stack_data[stack_args_count] = argp;
169 : ++stack_args_count;
170 : }
171 : }
172 : #endif
173 0 : p_argv++;
174 : #ifdef X86_WIN64
175 : argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
176 : #else
177 0 : argp += z;
178 : #endif
179 : }
180 :
181 : #ifdef X86_WIN32
182 : /* We need to move the register-passed arguments for thiscall/fastcall
183 : on top of stack, so that those can be moved to registers ecx/edx by
184 : call-handler. */
185 : if (stack_args_count > 0)
186 : {
187 : size_t zz = (p_stack_args[0] + 3) & ~3;
188 : char *h;
189 :
190 : /* Move first argument to top-stack position. */
191 : if (p_stack_data[0] != argp2)
192 : {
193 : h = alloca (zz + 1);
194 : memcpy (h, p_stack_data[0], zz);
195 : memmove (argp2 + zz, argp2,
196 : (size_t) ((char *) p_stack_data[0] - (char*)argp2));
197 : memcpy (argp2, h, zz);
198 : }
199 :
200 : argp2 += zz;
201 : --stack_args_count;
202 : if (zz > 4)
203 : stack_args_count = 0;
204 :
205 : /* If we have a second argument, then move it on top
206 : after the first one. */
207 : if (stack_args_count > 0 && p_stack_data[1] != argp2)
208 : {
209 : zz = p_stack_args[1];
210 : zz = (zz + 3) & ~3;
211 : h = alloca (zz + 1);
212 : h = alloca (zz + 1);
213 : memcpy (h, p_stack_data[1], zz);
214 : memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2));
215 : memcpy (argp2, h, zz);
216 : }
217 : }
218 : #endif
219 0 : return;
220 : }
221 :
222 : /* Perform machine dependent cif processing */
223 0 : ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
224 : {
225 : unsigned int i;
226 : ffi_type **ptr;
227 :
228 : /* Set the return type flag */
229 0 : switch (cif->rtype->type)
230 : {
231 : case FFI_TYPE_VOID:
232 : case FFI_TYPE_UINT8:
233 : case FFI_TYPE_UINT16:
234 : case FFI_TYPE_SINT8:
235 : case FFI_TYPE_SINT16:
236 : #ifdef X86_WIN64
237 : case FFI_TYPE_UINT32:
238 : case FFI_TYPE_SINT32:
239 : #endif
240 : case FFI_TYPE_SINT64:
241 : case FFI_TYPE_FLOAT:
242 : case FFI_TYPE_DOUBLE:
243 : #ifndef X86_WIN64
244 : #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
245 : case FFI_TYPE_LONGDOUBLE:
246 : #endif
247 : #endif
248 0 : cif->flags = (unsigned) cif->rtype->type;
249 0 : break;
250 :
251 : case FFI_TYPE_UINT64:
252 : #ifdef X86_WIN64
253 : case FFI_TYPE_POINTER:
254 : #endif
255 0 : cif->flags = FFI_TYPE_SINT64;
256 0 : break;
257 :
258 : case FFI_TYPE_STRUCT:
259 : #ifndef X86
260 : if (cif->rtype->size == 1)
261 : {
262 : cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
263 : }
264 : else if (cif->rtype->size == 2)
265 : {
266 : cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
267 : }
268 : else if (cif->rtype->size == 4)
269 : {
270 : #ifdef X86_WIN64
271 : cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
272 : #else
273 : cif->flags = FFI_TYPE_INT; /* same as int type */
274 : #endif
275 : }
276 : else if (cif->rtype->size == 8)
277 : {
278 : cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
279 : }
280 : else
281 : #endif
282 : {
283 : #ifdef X86_WIN32
284 : if (cif->abi == FFI_MS_CDECL)
285 : cif->flags = FFI_TYPE_MS_STRUCT;
286 : else
287 : #endif
288 0 : cif->flags = FFI_TYPE_STRUCT;
289 : /* allocate space for return value pointer */
290 0 : cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
291 : }
292 0 : break;
293 :
294 : default:
295 : #ifdef X86_WIN64
296 : cif->flags = FFI_TYPE_SINT64;
297 : break;
298 : case FFI_TYPE_INT:
299 : cif->flags = FFI_TYPE_SINT32;
300 : #else
301 0 : cif->flags = FFI_TYPE_INT;
302 : #endif
303 0 : break;
304 : }
305 :
306 0 : for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
307 : {
308 0 : if (((*ptr)->alignment - 1) & cif->bytes)
309 0 : cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
310 0 : cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
311 : }
312 :
313 : #ifdef X86_WIN64
314 : /* ensure space for storing four registers */
315 : cif->bytes += 4 * sizeof(ffi_arg);
316 : #endif
317 :
318 : #ifdef X86_DARWIN
319 : cif->bytes = (cif->bytes + 15) & ~0xF;
320 : #endif
321 :
322 0 : return FFI_OK;
323 : }
324 :
325 : #ifdef X86_WIN64
326 : extern int
327 : ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
328 : unsigned, unsigned, unsigned *, void (*fn)(void));
329 : #elif defined(X86_WIN32)
330 : extern void
331 : ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
332 : unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
333 : #else
334 : extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
335 : unsigned, unsigned, unsigned *, void (*fn)(void));
336 : #endif
337 :
338 0 : void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
339 : {
340 : extended_cif ecif;
341 :
342 0 : ecif.cif = cif;
343 0 : ecif.avalue = avalue;
344 :
345 : /* If the return value is a struct and we don't have a return */
346 : /* value address then we need to make one */
347 :
348 : #ifdef X86_WIN64
349 : if (rvalue == NULL
350 : && cif->flags == FFI_TYPE_STRUCT
351 : && cif->rtype->size != 1 && cif->rtype->size != 2
352 : && cif->rtype->size != 4 && cif->rtype->size != 8)
353 : {
354 : ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
355 : }
356 : #else
357 0 : if (rvalue == NULL
358 0 : && (cif->flags == FFI_TYPE_STRUCT
359 0 : || cif->flags == FFI_TYPE_MS_STRUCT))
360 : {
361 0 : ecif.rvalue = alloca(cif->rtype->size);
362 : }
363 : #endif
364 : else
365 0 : ecif.rvalue = rvalue;
366 :
367 :
368 0 : switch (cif->abi)
369 : {
370 : #ifdef X86_WIN64
371 : case FFI_WIN64:
372 : ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
373 : cif->flags, ecif.rvalue, fn);
374 : break;
375 : #elif defined(X86_WIN32)
376 : case FFI_SYSV:
377 : case FFI_STDCALL:
378 : case FFI_MS_CDECL:
379 : ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
380 : ecif.rvalue, fn);
381 : break;
382 : case FFI_THISCALL:
383 : case FFI_FASTCALL:
384 : {
385 : unsigned int abi = cif->abi;
386 : unsigned int i, passed_regs = 0;
387 :
388 : if (cif->flags == FFI_TYPE_STRUCT)
389 : ++passed_regs;
390 :
391 : for (i=0; i < cif->nargs && passed_regs < 2;i++)
392 : {
393 : size_t sz;
394 :
395 : if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
396 : || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
397 : continue;
398 : sz = (cif->arg_types[i]->size + 3) & ~3;
399 : if (sz == 0 || sz > 4)
400 : continue;
401 : ++passed_regs;
402 : }
403 : if (passed_regs < 2 && abi == FFI_FASTCALL)
404 : abi = FFI_THISCALL;
405 : if (passed_regs < 1 && abi == FFI_THISCALL)
406 : abi = FFI_STDCALL;
407 : ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
408 : ecif.rvalue, fn);
409 : }
410 : break;
411 : #else
412 : case FFI_SYSV:
413 0 : ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
414 : fn);
415 0 : break;
416 : #endif
417 : default:
418 : FFI_ASSERT(0);
419 0 : break;
420 : }
421 0 : }
422 :
423 :
424 : /** private members **/
425 :
426 : /* The following __attribute__((regparm(1))) decorations will have no effect
427 : on MSVC - standard cdecl convention applies. */
428 : static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
429 : void** args, ffi_cif* cif);
430 : void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
431 : __attribute__ ((regparm(1)));
432 : unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
433 : __attribute__ ((regparm(1)));
434 : void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
435 : __attribute__ ((regparm(1)));
436 : #ifdef X86_WIN32
437 : void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
438 : __attribute__ ((regparm(1)));
439 : void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
440 : __attribute__ ((regparm(1)));
441 : void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
442 : __attribute__ ((regparm(1)));
443 : #endif
444 : #ifdef X86_WIN64
445 : void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
446 : #endif
447 :
448 : /* This function is jumped to by the trampoline */
449 :
450 : #ifdef X86_WIN64
451 : void * FFI_HIDDEN
452 : ffi_closure_win64_inner (ffi_closure *closure, void *args) {
453 : ffi_cif *cif;
454 : void **arg_area;
455 : void *result;
456 : void *resp = &result;
457 :
458 : cif = closure->cif;
459 : arg_area = (void**) alloca (cif->nargs * sizeof (void*));
460 :
461 : /* this call will initialize ARG_AREA, such that each
462 : * element in that array points to the corresponding
463 : * value on the stack; and if the function returns
464 : * a structure, it will change RESP to point to the
465 : * structure return address. */
466 :
467 : ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
468 :
469 : (closure->fun) (cif, resp, arg_area, closure->user_data);
470 :
471 : /* The result is returned in rax. This does the right thing for
472 : result types except for floats; we have to 'mov xmm0, rax' in the
473 : caller to correct this.
474 : TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
475 : */
476 : return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
477 : }
478 :
479 : #else
480 : unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
481 0 : ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
482 : {
483 : /* our various things... */
484 : ffi_cif *cif;
485 : void **arg_area;
486 :
487 0 : cif = closure->cif;
488 0 : arg_area = (void**) alloca (cif->nargs * sizeof (void*));
489 :
490 : /* this call will initialize ARG_AREA, such that each
491 : * element in that array points to the corresponding
492 : * value on the stack; and if the function returns
493 : * a structure, it will change RESP to point to the
494 : * structure return address. */
495 :
496 0 : ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
497 :
498 0 : (closure->fun) (cif, *respp, arg_area, closure->user_data);
499 :
500 0 : return cif->flags;
501 : }
502 : #endif /* !X86_WIN64 */
503 :
504 : static void
505 0 : ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
506 : ffi_cif *cif)
507 : {
508 : register unsigned int i;
509 : register void **p_argv;
510 : register char *argp;
511 : register ffi_type **p_arg;
512 :
513 0 : argp = stack;
514 :
515 : #ifdef X86_WIN64
516 : if (cif->rtype->size > sizeof(ffi_arg)
517 : || (cif->flags == FFI_TYPE_STRUCT
518 : && (cif->rtype->size != 1 && cif->rtype->size != 2
519 : && cif->rtype->size != 4 && cif->rtype->size != 8))) {
520 : *rvalue = *(void **) argp;
521 : argp += sizeof(void *);
522 : }
523 : #else
524 0 : if ( cif->flags == FFI_TYPE_STRUCT
525 0 : || cif->flags == FFI_TYPE_MS_STRUCT ) {
526 0 : *rvalue = *(void **) argp;
527 0 : argp += sizeof(void *);
528 : }
529 : #endif
530 :
531 0 : p_argv = avalue;
532 :
533 0 : for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
534 : {
535 : size_t z;
536 :
537 : /* Align if necessary */
538 0 : if ((sizeof(void*) - 1) & (size_t) argp) {
539 0 : argp = (char *) ALIGN(argp, sizeof(void*));
540 : }
541 :
542 : #ifdef X86_WIN64
543 : if ((*p_arg)->size > sizeof(ffi_arg)
544 : || ((*p_arg)->type == FFI_TYPE_STRUCT
545 : && ((*p_arg)->size != 1 && (*p_arg)->size != 2
546 : && (*p_arg)->size != 4 && (*p_arg)->size != 8)))
547 : {
548 : z = sizeof(void *);
549 : *p_argv = *(void **)argp;
550 : }
551 : else
552 : #endif
553 : {
554 0 : z = (*p_arg)->size;
555 :
556 : /* because we're little endian, this is what it turns into. */
557 :
558 0 : *p_argv = (void*) argp;
559 : }
560 :
561 0 : p_argv++;
562 : #ifdef X86_WIN64
563 : argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
564 : #else
565 0 : argp += z;
566 : #endif
567 : }
568 :
569 0 : return;
570 : }
571 :
572 : #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
573 : { unsigned char *__tramp = (unsigned char*)(TRAMP); \
574 : void* __fun = (void*)(FUN); \
575 : void* __ctx = (void*)(CTX); \
576 : *(unsigned char*) &__tramp[0] = 0x41; \
577 : *(unsigned char*) &__tramp[1] = 0xbb; \
578 : *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
579 : *(unsigned char*) &__tramp[6] = 0x48; \
580 : *(unsigned char*) &__tramp[7] = 0xb8; \
581 : *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
582 : *(unsigned char *) &__tramp[16] = 0x49; \
583 : *(unsigned char *) &__tramp[17] = 0xba; \
584 : *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
585 : *(unsigned char *) &__tramp[26] = 0x41; \
586 : *(unsigned char *) &__tramp[27] = 0xff; \
587 : *(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \
588 : }
589 :
590 : /* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
591 :
592 : #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
593 : { unsigned char *__tramp = (unsigned char*)(TRAMP); \
594 : unsigned int __fun = (unsigned int)(FUN); \
595 : unsigned int __ctx = (unsigned int)(CTX); \
596 : unsigned int __dis = __fun - (__ctx + 10); \
597 : *(unsigned char*) &__tramp[0] = 0xb8; \
598 : *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
599 : *(unsigned char *) &__tramp[5] = 0xe9; \
600 : *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
601 : }
602 :
603 : #define FFI_INIT_TRAMPOLINE_THISCALL(TRAMP,FUN,CTX,SIZE) \
604 : { unsigned char *__tramp = (unsigned char*)(TRAMP); \
605 : unsigned int __fun = (unsigned int)(FUN); \
606 : unsigned int __ctx = (unsigned int)(CTX); \
607 : unsigned int __dis = __fun - (__ctx + 49); \
608 : unsigned short __size = (unsigned short)(SIZE); \
609 : *(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \
610 : *(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \
611 : *(unsigned int *) &__tramp[8] = 0x04890424; /* mov %ecx, 4(%esp) */ \
612 : *(unsigned char*) &__tramp[12] = 0x24; /* mov %eax, (%esp) */ \
613 : *(unsigned char*) &__tramp[13] = 0xb8; \
614 : *(unsigned int *) &__tramp[14] = __size; /* mov __size, %eax */ \
615 : *(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \
616 : *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
617 : *(unsigned short*) &__tramp[26] = 0x0b74; /* jz 1f */ \
618 : *(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \
619 : *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
620 : *(unsigned char*) &__tramp[36] = 0x48; /* dec %eax */ \
621 : *(unsigned short*) &__tramp[37] = 0xf575; /* jnz 2b ; 1f: */ \
622 : *(unsigned char*) &__tramp[39] = 0xb8; \
623 : *(unsigned int*) &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
624 : *(unsigned char *) &__tramp[44] = 0xe8; \
625 : *(unsigned int*) &__tramp[45] = __dis; /* call __fun */ \
626 : *(unsigned char*) &__tramp[49] = 0xc2; /* ret */ \
627 : *(unsigned short*) &__tramp[50] = (__size + 8); /* ret (__size + 8) */ \
628 : }
629 :
630 : #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) \
631 : { unsigned char *__tramp = (unsigned char*)(TRAMP); \
632 : unsigned int __fun = (unsigned int)(FUN); \
633 : unsigned int __ctx = (unsigned int)(CTX); \
634 : unsigned int __dis = __fun - (__ctx + 10); \
635 : unsigned short __size = (unsigned short)(SIZE); \
636 : *(unsigned char*) &__tramp[0] = 0xb8; \
637 : *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
638 : *(unsigned char *) &__tramp[5] = 0xe8; \
639 : *(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \
640 : *(unsigned char *) &__tramp[10] = 0xc2; \
641 : *(unsigned short*) &__tramp[11] = __size; /* ret __size */ \
642 : }
643 :
644 : /* the cif must already be prep'ed */
645 :
646 : ffi_status
647 0 : ffi_prep_closure_loc (ffi_closure* closure,
648 : ffi_cif* cif,
649 : void (*fun)(ffi_cif*,void*,void**,void*),
650 : void *user_data,
651 : void *codeloc)
652 : {
653 : #ifdef X86_WIN64
654 : #define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
655 : #define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
656 : if (cif->abi == FFI_WIN64)
657 : {
658 : int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
659 : FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
660 : &ffi_closure_win64,
661 : codeloc, mask);
662 : /* make sure we can execute here */
663 : }
664 : #else
665 0 : if (cif->abi == FFI_SYSV)
666 : {
667 0 : FFI_INIT_TRAMPOLINE (&closure->tramp[0],
668 : &ffi_closure_SYSV,
669 : (void*)codeloc);
670 : }
671 : #ifdef X86_WIN32
672 : else if (cif->abi == FFI_THISCALL)
673 : {
674 : FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0],
675 : &ffi_closure_THISCALL,
676 : (void*)codeloc,
677 : cif->bytes);
678 : }
679 : else if (cif->abi == FFI_STDCALL)
680 : {
681 : FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
682 : &ffi_closure_STDCALL,
683 : (void*)codeloc, cif->bytes);
684 : }
685 : else if (cif->abi == FFI_MS_CDECL)
686 : {
687 : FFI_INIT_TRAMPOLINE (&closure->tramp[0],
688 : &ffi_closure_SYSV,
689 : (void*)codeloc);
690 : }
691 : #endif /* X86_WIN32 */
692 : #endif /* !X86_WIN64 */
693 : else
694 : {
695 0 : return FFI_BAD_ABI;
696 : }
697 :
698 0 : closure->cif = cif;
699 0 : closure->user_data = user_data;
700 0 : closure->fun = fun;
701 :
702 0 : return FFI_OK;
703 : }
704 :
705 : /* ------- Native raw API support -------------------------------- */
706 :
707 : #if !FFI_NO_RAW_API
708 :
709 : ffi_status
710 0 : ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
711 : ffi_cif* cif,
712 : void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
713 : void *user_data,
714 : void *codeloc)
715 : {
716 : int i;
717 :
718 0 : if (cif->abi != FFI_SYSV) {
719 : #ifdef X86_WIN32
720 : if (cif->abi != FFI_THISCALL)
721 : #endif
722 0 : return FFI_BAD_ABI;
723 : }
724 :
725 : /* we currently don't support certain kinds of arguments for raw
726 : closures. This should be implemented by a separate assembly
727 : language routine, since it would require argument processing,
728 : something we don't do now for performance. */
729 :
730 0 : for (i = cif->nargs-1; i >= 0; i--)
731 : {
732 : FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
733 : FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
734 : }
735 :
736 : #ifdef X86_WIN32
737 : if (cif->abi == FFI_SYSV)
738 : {
739 : #endif
740 0 : FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
741 : codeloc);
742 : #ifdef X86_WIN32
743 : }
744 : else if (cif->abi == FFI_THISCALL)
745 : {
746 : FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL,
747 : codeloc, cif->bytes);
748 : }
749 : #endif
750 0 : closure->cif = cif;
751 0 : closure->user_data = user_data;
752 0 : closure->fun = fun;
753 :
754 0 : return FFI_OK;
755 : }
756 :
757 : static void
758 0 : ffi_prep_args_raw(char *stack, extended_cif *ecif)
759 : {
760 0 : memcpy (stack, ecif->avalue, ecif->cif->bytes);
761 0 : }
762 :
763 : /* we borrow this routine from libffi (it must be changed, though, to
764 : * actually call the function passed in the first argument. as of
765 : * libffi-1.20, this is not the case.)
766 : */
767 :
768 : void
769 0 : ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
770 : {
771 : extended_cif ecif;
772 0 : void **avalue = (void **)fake_avalue;
773 :
774 0 : ecif.cif = cif;
775 0 : ecif.avalue = avalue;
776 :
777 : /* If the return value is a struct and we don't have a return */
778 : /* value address then we need to make one */
779 :
780 0 : if (rvalue == NULL
781 0 : && (cif->flags == FFI_TYPE_STRUCT
782 0 : || cif->flags == FFI_TYPE_MS_STRUCT))
783 : {
784 0 : ecif.rvalue = alloca(cif->rtype->size);
785 : }
786 : else
787 0 : ecif.rvalue = rvalue;
788 :
789 :
790 0 : switch (cif->abi)
791 : {
792 : #ifdef X86_WIN32
793 : case FFI_SYSV:
794 : case FFI_STDCALL:
795 : case FFI_MS_CDECL:
796 : ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
797 : ecif.rvalue, fn);
798 : break;
799 : case FFI_THISCALL:
800 : case FFI_FASTCALL:
801 : {
802 : unsigned int abi = cif->abi;
803 : unsigned int i, passed_regs = 0;
804 :
805 : if (cif->flags == FFI_TYPE_STRUCT)
806 : ++passed_regs;
807 :
808 : for (i=0; i < cif->nargs && passed_regs < 2;i++)
809 : {
810 : size_t sz;
811 :
812 : if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
813 : || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
814 : continue;
815 : sz = (cif->arg_types[i]->size + 3) & ~3;
816 : if (sz == 0 || sz > 4)
817 : continue;
818 : ++passed_regs;
819 : }
820 : if (passed_regs < 2 && abi == FFI_FASTCALL)
821 : cif->abi = abi = FFI_THISCALL;
822 : if (passed_regs < 1 && abi == FFI_THISCALL)
823 : cif->abi = abi = FFI_STDCALL;
824 : ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
825 : ecif.rvalue, fn);
826 : }
827 : break;
828 : #else
829 : case FFI_SYSV:
830 0 : ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
831 0 : ecif.rvalue, fn);
832 0 : break;
833 : #endif
834 : default:
835 : FFI_ASSERT(0);
836 0 : break;
837 : }
838 0 : }
839 :
840 : #endif
841 :
842 : #endif /* !__x86_64__ || X86_WIN64 */
843 :
|