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) || defined(__CYGWIN__)
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
43 /* ffi_prep_args is called by the assembly routine once stack space
44 has been allocated for the function's arguments */
45
46 unsigned int ffi_prep_args(char *stack, extended_cif *ecif);
47 unsigned int ffi_prep_args(char *stack, extended_cif *ecif)
48 {
49 register unsigned int i;
50 register void **p_argv;
51 register char *argp;
52 register ffi_type **p_arg;
53 #ifndef X86_WIN64
54 const int cabi = ecif->cif->abi;
55 const int dir = (cabi == FFI_PASCAL || cabi == FFI_REGISTER) ? -1 : +1;
56 unsigned int stack_args_count = 0;
57 void *p_stack_data[3];
58 char *argp2 = stack;
59 #else
60 #define dir 1
61 #endif
62
63 argp = stack;
64
65 if ((ecif->cif->flags == FFI_TYPE_STRUCT
66 || ecif->cif->flags == FFI_TYPE_MS_STRUCT)
67 #ifdef X86_WIN64
68 && ((ecif->cif->rtype->size & (1 | 2 | 4 | 8)) == 0)
69 #endif
70 )
71 {
72 #ifndef X86_WIN64
73 /* For fastcall/thiscall/register this is first register-passed
74 argument. */
75 if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL || cabi == FFI_REGISTER)
76 {
77 p_stack_data[stack_args_count] = argp;
78 ++stack_args_count;
79 }
80 #endif
81
82 *(void **) argp = ecif->rvalue;
83 argp += sizeof(void*);
84 }
85
86 p_arg = ecif->cif->arg_types;
87 p_argv = ecif->avalue;
88 if (dir < 0)
89 {
90 const int nargs = ecif->cif->nargs - 1;
91 if (nargs > 0)
92 {
93 p_arg += nargs;
94 p_argv += nargs;
95 }
96 }
97
98 for (i = ecif->cif->nargs;
99 i != 0;
100 i--, p_arg += dir, p_argv += dir)
101 {
102 #ifdef GSTREAMER_LITE
103 size_t z = 0;
104 #endif // GSTREAMER_LITE
105
106 /* Align if necessary */
107 if ((sizeof(void*) - 1) & (size_t) argp)
108 argp = (char *) ALIGN(argp, sizeof(void*));
109
110 #ifdef GSTREAMER_LITE
111 z = (*p_arg)->size;
112 #else // GSTREAMER_LITE
113 size_t z = (*p_arg)->size;
114 #endif // GSTREAMER_LITE
115
116 #ifdef X86_WIN64
117 if (z > FFI_SIZEOF_ARG
118 || ((*p_arg)->type == FFI_TYPE_STRUCT
119 && (z & (1 | 2 | 4 | 8)) == 0)
120 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
121 || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
122 #endif
123 )
124 {
125 z = FFI_SIZEOF_ARG;
126 *(void **)argp = *p_argv;
127 }
128 else if ((*p_arg)->type == FFI_TYPE_FLOAT)
129 {
130 memcpy(argp, *p_argv, z);
131 }
132 else
133 #endif
134 if (z < FFI_SIZEOF_ARG)
135 {
136 z = FFI_SIZEOF_ARG;
137 switch ((*p_arg)->type)
138 {
139 case FFI_TYPE_SINT8:
140 *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
141 break;
142
143 case FFI_TYPE_UINT8:
144 *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
145 break;
146
147 case FFI_TYPE_SINT16:
148 *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
149 break;
150
151 case FFI_TYPE_UINT16:
152 *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
153 break;
154
155 case FFI_TYPE_SINT32:
156 *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
157 break;
158
159 case FFI_TYPE_UINT32:
160 *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
161 break;
162
163 case FFI_TYPE_STRUCT:
164 *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
165 break;
166
167 default:
168 FFI_ASSERT(0);
169 }
170 }
171 else
172 {
173 memcpy(argp, *p_argv, z);
174 }
175
176 #ifndef X86_WIN64
177 /* For thiscall/fastcall/register convention register-passed arguments
178 are the first two none-floating-point arguments with a size
179 smaller or equal to sizeof (void*). */
180 if ((z == FFI_SIZEOF_ARG)
181 && ((cabi == FFI_REGISTER)
182 || (cabi == FFI_THISCALL && stack_args_count < 1)
183 || (cabi == FFI_FASTCALL && stack_args_count < 2))
184 && ((*p_arg)->type != FFI_TYPE_FLOAT && (*p_arg)->type != FFI_TYPE_STRUCT)
185 )
186 {
187 if (dir < 0 && stack_args_count > 2)
188 {
189 /* Iterating arguments backwards, so first register-passed argument
190 will be passed last. Shift temporary values to make place. */
191 p_stack_data[0] = p_stack_data[1];
192 p_stack_data[1] = p_stack_data[2];
193 stack_args_count = 2;
194 }
195
196 p_stack_data[stack_args_count] = argp;
197 ++stack_args_count;
198 }
199 #endif
200
201 #ifdef X86_WIN64
202 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
203 #else
204 argp += z;
205 #endif
206 }
207
208 #ifndef X86_WIN64
209 /* We need to move the register-passed arguments for thiscall/fastcall/register
210 on top of stack, so that those can be moved to registers by call-handler. */
211 if (stack_args_count > 0)
212 {
213 #ifdef GSTREAMER_LITE
214 int i;
215 #endif // GSTREAMER_LITE
216 if (dir < 0 && stack_args_count > 1)
217 {
218 /* Reverse order if iterating arguments backwards */
219 ffi_arg tmp = *(ffi_arg*) p_stack_data[0];
220 *(ffi_arg*) p_stack_data[0] = *(ffi_arg*) p_stack_data[stack_args_count - 1];
221 *(ffi_arg*) p_stack_data[stack_args_count - 1] = tmp;
222 }
223
224 #ifndef GSTREAMER_LITE
225 int i;
226 #endif // GSTREAMER_LITE
227 for (i = 0; i < stack_args_count; i++)
228 {
229 if (p_stack_data[i] != argp2)
230 {
231 ffi_arg tmp = *(ffi_arg*) p_stack_data[i];
232 memmove (argp2 + FFI_SIZEOF_ARG, argp2, (size_t) ((char*) p_stack_data[i] - (char*)argp2));
233 *(ffi_arg *) argp2 = tmp;
234 }
235
236 argp2 += FFI_SIZEOF_ARG;
237 }
238 }
239
240 return stack_args_count;
241 #endif
242 return 0;
243 }
244
245 /* Perform machine dependent cif processing */
246 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
247 {
248 unsigned int i;
249 ffi_type **ptr;
250
251 /* Set the return type flag */
252 switch (cif->rtype->type)
253 {
254 case FFI_TYPE_VOID:
255 case FFI_TYPE_UINT8:
256 case FFI_TYPE_UINT16:
257 case FFI_TYPE_SINT8:
258 case FFI_TYPE_SINT16:
259 #ifdef X86_WIN64
260 case FFI_TYPE_UINT32:
261 case FFI_TYPE_SINT32:
262 #endif
263 case FFI_TYPE_SINT64:
264 case FFI_TYPE_FLOAT:
265 case FFI_TYPE_DOUBLE:
266 #ifndef X86_WIN64
267 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
268 case FFI_TYPE_LONGDOUBLE:
269 #endif
270 #endif
271 cif->flags = (unsigned) cif->rtype->type;
272 break;
273
274 case FFI_TYPE_UINT64:
275 #ifdef X86_WIN64
276 case FFI_TYPE_POINTER:
277 #endif
278 cif->flags = FFI_TYPE_SINT64;
279 break;
280
281 case FFI_TYPE_STRUCT:
282 #ifndef X86
283 if (cif->rtype->size == 1)
284 {
285 cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
286 }
287 else if (cif->rtype->size == 2)
288 {
289 cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
290 }
291 else if (cif->rtype->size == 4)
292 {
293 #ifdef X86_WIN64
294 cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
295 #else
296 cif->flags = FFI_TYPE_INT; /* same as int type */
297 #endif
298 }
299 else if (cif->rtype->size == 8)
300 {
301 cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
302 }
303 else
304 #endif
305 {
306 #ifdef X86_WIN32
307 if (cif->abi == FFI_MS_CDECL)
308 cif->flags = FFI_TYPE_MS_STRUCT;
309 else
310 #endif
311 cif->flags = FFI_TYPE_STRUCT;
312 /* allocate space for return value pointer */
313 cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
314 }
315 break;
316
317 default:
318 #ifdef X86_WIN64
319 cif->flags = FFI_TYPE_SINT64;
320 break;
321 case FFI_TYPE_INT:
322 cif->flags = FFI_TYPE_SINT32;
323 #else
324 cif->flags = FFI_TYPE_INT;
325 #endif
326 break;
327 }
328
329 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
330 {
331 if (((*ptr)->alignment - 1) & cif->bytes)
332 cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
333 cif->bytes += (unsigned)ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
334 }
335
336 #ifdef X86_WIN64
337 /* ensure space for storing four registers */
338 cif->bytes += 4 * FFI_SIZEOF_ARG;
339 #endif
340
341 #ifndef X86_WIN32
342 #ifndef X86_WIN64
343 if (cif->abi == FFI_SYSV || cif->abi == FFI_UNIX64)
344 #endif
345 cif->bytes = (cif->bytes + 15) & ~0xF;
346 #endif
347
348 return FFI_OK;
349 }
350
351 #ifdef X86_WIN64
352 extern int
353 ffi_call_win64(unsigned int (*)(char *, extended_cif *), extended_cif *,
354 unsigned, unsigned, unsigned *, void (*fn)(void));
355 #else
356 extern void
357 ffi_call_win32(unsigned int (*)(char *, extended_cif *), extended_cif *,
358 unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
359 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
360 unsigned, unsigned, unsigned *, void (*fn)(void));
361 #endif
362
363 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
364 {
365 extended_cif ecif;
366
367 ecif.cif = cif;
368 ecif.avalue = avalue;
369
370 /* If the return value is a struct and we don't have a return */
371 /* value address then we need to make one */
372
373 #ifdef X86_WIN64
374 if (rvalue == NULL
375 && cif->flags == FFI_TYPE_STRUCT
376 && ((cif->rtype->size & (1 | 2 | 4 | 8)) == 0))
377 {
378 ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
379 }
380 #else
381 if (rvalue == NULL
382 && (cif->flags == FFI_TYPE_STRUCT
383 || cif->flags == FFI_TYPE_MS_STRUCT))
384 {
385 ecif.rvalue = alloca(cif->rtype->size);
386 }
387 #endif
388 else
389 ecif.rvalue = rvalue;
390
391
392 switch (cif->abi)
393 {
394 #ifdef X86_WIN64
395 case FFI_WIN64:
396 ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
397 cif->flags, ecif.rvalue, fn);
398 break;
399 #else
400 #ifndef X86_WIN32
401 case FFI_SYSV:
402 ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
403 fn);
404 break;
405 #else
406 case FFI_SYSV:
407 case FFI_MS_CDECL:
408 #endif
409 case FFI_STDCALL:
410 case FFI_THISCALL:
411 case FFI_FASTCALL:
412 case FFI_PASCAL:
413 case FFI_REGISTER:
414 ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
415 ecif.rvalue, fn);
416 break;
417 #endif
418 default:
419 FFI_ASSERT(0);
420 break;
421 }
422 }
423
424
425 /** private members **/
426
427 /* The following __attribute__((regparm(1))) decorations will have no effect
428 on MSVC or SUNPRO_C -- standard conventions apply. */
429 static unsigned int ffi_prep_incoming_args (char *stack, void **ret,
430 void** args, ffi_cif* cif);
431 void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
432 __attribute__ ((regparm(1)));
433 unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
434 __attribute__ ((regparm(1)));
435 unsigned int FFI_HIDDEN ffi_closure_WIN32_inner (ffi_closure *, void **, void *)
436 __attribute__ ((regparm(1)));
437 void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
438 __attribute__ ((regparm(1)));
439 #ifdef X86_WIN32
440 void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
441 __attribute__ ((regparm(1)));
442 #endif
443 #ifndef X86_WIN64
444 void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *);
445 void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *);
446 void FFI_HIDDEN ffi_closure_FASTCALL (ffi_closure *);
447 void FFI_HIDDEN ffi_closure_REGISTER (ffi_closure *);
448 #else
449 void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
450 #endif
451
452 /* This function is jumped to by the trampoline */
453
454 #ifdef X86_WIN64
455 void * FFI_HIDDEN
456 ffi_closure_win64_inner (ffi_closure *closure, void *args) {
457 ffi_cif *cif;
458 void **arg_area;
459 void *result;
460 void *resp = &result;
461
462 cif = closure->cif;
463 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
464
465 /* this call will initialize ARG_AREA, such that each
466 * element in that array points to the corresponding
467 * value on the stack; and if the function returns
468 * a structure, it will change RESP to point to the
469 * structure return address. */
470
471 ffi_prep_incoming_args(args, &resp, arg_area, cif);
472
473 (closure->fun) (cif, resp, arg_area, closure->user_data);
474
475 /* The result is returned in rax. This does the right thing for
476 result types except for floats; we have to 'mov xmm0, rax' in the
477 caller to correct this.
478 TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
479 */
480 return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
481 }
482
483 #else
484 unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
485 ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
486 {
487 /* our various things... */
488 ffi_cif *cif;
489 void **arg_area;
490
491 cif = closure->cif;
492 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
493
494 /* this call will initialize ARG_AREA, such that each
495 * element in that array points to the corresponding
496 * value on the stack; and if the function returns
497 * a structure, it will change RESP to point to the
498 * structure return address. */
499
500 ffi_prep_incoming_args(args, respp, arg_area, cif);
501
502 (closure->fun) (cif, *respp, arg_area, closure->user_data);
503
504 return cif->flags;
505 }
506
507 unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
508 ffi_closure_WIN32_inner (ffi_closure *closure, void **respp, void *args)
509 {
510 /* our various things... */
511 ffi_cif *cif;
512 void **arg_area;
513 unsigned int ret;
514
515 cif = closure->cif;
516 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
517
518 /* this call will initialize ARG_AREA, such that each
519 * element in that array points to the corresponding
520 * value on the stack; and if the function returns
521 * a structure, it will change RESP to point to the
522 * structure return address. */
523
524 ret = ffi_prep_incoming_args(args, respp, arg_area, cif);
525
526 (closure->fun) (cif, *respp, arg_area, closure->user_data);
527
528 return ret;
529 }
530 #endif /* !X86_WIN64 */
531
532 static unsigned int
533 ffi_prep_incoming_args(char *stack, void **rvalue, void **avalue,
534 ffi_cif *cif)
535 {
536 register unsigned int i;
537 register void **p_argv;
538 register char *argp;
539 register ffi_type **p_arg;
540 #ifndef X86_WIN64
541 const int cabi = cif->abi;
542 const int dir = (cabi == FFI_PASCAL || cabi == FFI_REGISTER) ? -1 : +1;
543 const unsigned int max_stack_count = (cabi == FFI_THISCALL) ? 1
544 : (cabi == FFI_FASTCALL) ? 2
545 : (cabi == FFI_REGISTER) ? 3
546 : 0;
547 unsigned int passed_regs = 0;
548 void *p_stack_data[3] = { stack - 1 };
549 #else
550 #define dir 1
551 #endif
552
553 argp = stack;
554 #ifndef X86_WIN64
555 argp += max_stack_count * FFI_SIZEOF_ARG;
556 #endif
557
558 if ((cif->flags == FFI_TYPE_STRUCT
559 || cif->flags == FFI_TYPE_MS_STRUCT)
560 #ifdef X86_WIN64
561 && ((cif->rtype->size & (1 | 2 | 4 | 8)) == 0)
562 #endif
563 )
564 {
565 #ifndef X86_WIN64
566 if (passed_regs < max_stack_count)
567 {
568 *rvalue = *(void**) (stack + (passed_regs*FFI_SIZEOF_ARG));
569 ++passed_regs;
570 }
571 else
572 #endif
573 {
574 *rvalue = *(void **) argp;
575 argp += sizeof(void *);
576 }
577 }
578
579 #ifndef X86_WIN64
580 /* Do register arguments first */
581 for (i = 0, p_arg = cif->arg_types;
582 i < cif->nargs && passed_regs < max_stack_count;
583 i++, p_arg++)
584 {
585 #ifdef GSTREAMER_LITE
586 size_t sz = 0;
587 #endif // GSTREAMER_LITE
588 if ((*p_arg)->type == FFI_TYPE_FLOAT
589 || (*p_arg)->type == FFI_TYPE_STRUCT)
590 continue;
591
592 #ifdef GSTREAMER_LITE
593 sz = (*p_arg)->size;
594 #else // GSTREAMER_LITE
595 size_t sz = (*p_arg)->size;
596 #endif // GSTREAMER_LITE
597 if(sz == 0 || sz > FFI_SIZEOF_ARG)
598 continue;
599
600 p_stack_data[passed_regs] = avalue + i;
601 avalue[i] = stack + (passed_regs*FFI_SIZEOF_ARG);
602 ++passed_regs;
603 }
604 #endif
605
606 p_arg = cif->arg_types;
607 p_argv = avalue;
608 if (dir < 0)
609 {
610 const int nargs = cif->nargs - 1;
611 if (nargs > 0)
612 {
613 p_arg += nargs;
614 p_argv += nargs;
615 }
616 }
617
618 for (i = cif->nargs;
619 i != 0;
620 i--, p_arg += dir, p_argv += dir)
621 {
622 #ifdef GSTREAMER_LITE
623 size_t z = 0;
624 #endif // GSTREAMER_LITE
625 /* Align if necessary */
626 if ((sizeof(void*) - 1) & (size_t) argp)
627 argp = (char *) ALIGN(argp, sizeof(void*));
628
629 #ifdef GSTREAMER_LITE
630 z = (*p_arg)->size;
631 #else // GSTREAMER_LITE
632 size_t z = (*p_arg)->size;
633 #endif // GSTREAMER_LITE
634
635 #ifdef X86_WIN64
636 if (z > FFI_SIZEOF_ARG
637 || ((*p_arg)->type == FFI_TYPE_STRUCT
638 && (z & (1 | 2 | 4 | 8)) == 0)
639 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
640 || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
641 #endif
642 )
643 {
644 z = FFI_SIZEOF_ARG;
645 *p_argv = *(void **)argp;
646 }
647 else
648 #else
649 if (passed_regs > 0
650 && z <= FFI_SIZEOF_ARG
651 && (p_argv == p_stack_data[0]
652 || p_argv == p_stack_data[1]
653 || p_argv == p_stack_data[2]))
654 {
655 /* Already assigned a register value */
656 continue;
657 }
658 else
659 #endif
660 {
661 /* because we're little endian, this is what it turns into. */
662 *p_argv = (void*) argp;
663 }
664
665 #ifdef X86_WIN64
666 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
667 #else
668 argp += z;
669 #endif
670 }
671
672 return (size_t)argp - (size_t)stack;
673 }
674
675 #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
676 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
677 void* __fun = (void*)(FUN); \
678 void* __ctx = (void*)(CTX); \
679 *(unsigned char*) &__tramp[0] = 0x41; \
680 *(unsigned char*) &__tramp[1] = 0xbb; \
681 *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
682 *(unsigned char*) &__tramp[6] = 0x48; \
683 *(unsigned char*) &__tramp[7] = 0xb8; \
684 *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
685 *(unsigned char *) &__tramp[16] = 0x49; \
686 *(unsigned char *) &__tramp[17] = 0xba; \
687 *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
688 *(unsigned char *) &__tramp[26] = 0x41; \
689 *(unsigned char *) &__tramp[27] = 0xff; \
690 *(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \
691 }
692
693 /* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
694
695 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
696 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
697 unsigned int __fun = (unsigned int)(FUN); \
698 unsigned int __ctx = (unsigned int)(CTX); \
699 unsigned int __dis = __fun - (__ctx + 10); \
700 *(unsigned char*) &__tramp[0] = 0xb8; \
701 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
702 *(unsigned char*) &__tramp[5] = 0xe9; \
703 *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
704 }
705
706 #define FFI_INIT_TRAMPOLINE_RAW_THISCALL(TRAMP,FUN,CTX,SIZE) \
707 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
708 unsigned int __fun = (unsigned int)(FUN); \
709 unsigned int __ctx = (unsigned int)(CTX); \
710 unsigned int __dis = __fun - (__ctx + 49); \
711 unsigned short __size = (unsigned short)(SIZE); \
712 *(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \
713 *(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \
714 *(unsigned int *) &__tramp[8] = 0x04890424; /* mov %ecx, 4(%esp) */ \
715 *(unsigned char*) &__tramp[12] = 0x24; /* mov %eax, (%esp) */ \
716 *(unsigned char*) &__tramp[13] = 0xb8; \
717 *(unsigned int *) &__tramp[14] = __size; /* mov __size, %eax */ \
718 *(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \
719 *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
720 *(unsigned short*) &__tramp[26] = 0x0b74; /* jz 1f */ \
721 *(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \
722 *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
723 *(unsigned char*) &__tramp[36] = 0x48; /* dec %eax */ \
724 *(unsigned short*) &__tramp[37] = 0xf575; /* jnz 2b ; 1f: */ \
725 *(unsigned char*) &__tramp[39] = 0xb8; \
726 *(unsigned int*) &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
727 *(unsigned char *) &__tramp[44] = 0xe8; \
728 *(unsigned int*) &__tramp[45] = __dis; /* call __fun */ \
729 *(unsigned char*) &__tramp[49] = 0xc2; /* ret */ \
730 *(unsigned short*) &__tramp[50] = (__size + 8); /* ret (__size + 8) */ \
731 }
732
733 #define FFI_INIT_TRAMPOLINE_WIN32(TRAMP,FUN,CTX) \
734 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
735 unsigned int __fun = (unsigned int)(FUN); \
736 unsigned int __ctx = (unsigned int)(CTX); \
737 unsigned int __dis = __fun - (__ctx + 10); \
738 *(unsigned char*) &__tramp[0] = 0x68; \
739 *(unsigned int*) &__tramp[1] = __ctx; /* push __ctx */ \
740 *(unsigned char*) &__tramp[5] = 0xe9; \
741 *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
742 }
743
744 /* the cif must already be prep'ed */
745
746 ffi_status
747 ffi_prep_closure_loc (ffi_closure* closure,
748 ffi_cif* cif,
749 void (*fun)(ffi_cif*,void*,void**,void*),
750 void *user_data,
751 void *codeloc)
752 {
753 #ifdef X86_WIN64
754 #define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
755 #define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
756 if (cif->abi == FFI_WIN64)
757 {
758 int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
759 FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
760 &ffi_closure_win64,
761 codeloc, mask);
762 /* make sure we can execute here */
763 }
764 #else
765 if (cif->abi == FFI_SYSV)
766 {
767 FFI_INIT_TRAMPOLINE (&closure->tramp[0],
768 &ffi_closure_SYSV,
769 (void*)codeloc);
770 }
771 else if (cif->abi == FFI_REGISTER)
772 {
773 FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
774 &ffi_closure_REGISTER,
775 (void*)codeloc);
776 }
777 else if (cif->abi == FFI_FASTCALL)
778 {
779 FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
780 &ffi_closure_FASTCALL,
781 (void*)codeloc);
782 }
783 else if (cif->abi == FFI_THISCALL)
784 {
785 FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
786 &ffi_closure_THISCALL,
787 (void*)codeloc);
788 }
789 else if (cif->abi == FFI_STDCALL || cif->abi == FFI_PASCAL)
790 {
791 FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
792 &ffi_closure_STDCALL,
793 (void*)codeloc);
794 }
795 #ifdef X86_WIN32
796 else if (cif->abi == FFI_MS_CDECL)
797 {
798 FFI_INIT_TRAMPOLINE (&closure->tramp[0],
799 &ffi_closure_SYSV,
800 (void*)codeloc);
801 }
802 #endif /* X86_WIN32 */
803 #endif /* !X86_WIN64 */
804 else
805 {
806 return FFI_BAD_ABI;
807 }
808
809 closure->cif = cif;
810 closure->user_data = user_data;
811 closure->fun = fun;
812
813 return FFI_OK;
814 }
815
816 /* ------- Native raw API support -------------------------------- */
817
818 #if !FFI_NO_RAW_API
819
820 ffi_status
821 ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
822 ffi_cif* cif,
823 void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
824 void *user_data,
825 void *codeloc)
826 {
827 int i;
828
829 if (cif->abi != FFI_SYSV
830 #ifdef X86_WIN32
831 && cif->abi != FFI_THISCALL
832 #endif
833 )
834 return FFI_BAD_ABI;
835
836 /* we currently don't support certain kinds of arguments for raw
837 closures. This should be implemented by a separate assembly
838 language routine, since it would require argument processing,
839 something we don't do now for performance. */
840
841 for (i = cif->nargs-1; i >= 0; i--)
842 {
843 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
844 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
845 }
846
847 #ifdef X86_WIN32
848 if (cif->abi == FFI_SYSV)
849 {
850 #endif
851 FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
852 codeloc);
853 #ifdef X86_WIN32
854 }
855 else if (cif->abi == FFI_THISCALL)
856 {
857 FFI_INIT_TRAMPOLINE_RAW_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL, codeloc, cif->bytes);
858 }
859 #endif
860 closure->cif = cif;
861 closure->user_data = user_data;
862 closure->fun = fun;
863
864 return FFI_OK;
865 }
866
867 static unsigned int
868 ffi_prep_args_raw(char *stack, extended_cif *ecif)
869 {
870 const ffi_cif *cif = ecif->cif;
871 unsigned int i, passed_regs = 0;
872
873 #ifndef X86_WIN64
874 const unsigned int abi = cif->abi;
875 const unsigned int max_regs = (abi == FFI_THISCALL) ? 1
876 : (abi == FFI_FASTCALL) ? 2
877 : (abi == FFI_REGISTER) ? 3
878 : 0;
879
880 if (cif->flags == FFI_TYPE_STRUCT)
881 ++passed_regs;
882
883 for (i = 0; i < cif->nargs && passed_regs <= max_regs; i++)
884 {
885 #ifdef GSTREAMER_LITE
886 size_t sz = 0;
887 #endif // GSTREAMER_LITE
888 if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
889 || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
890 continue;
891
892 #ifdef GSTREAMER_LITE
893 sz = cif->arg_types[i]->size;
894 #else // GSTREAMER_LITE
895 size_t sz = cif->arg_types[i]->size;
896 #endif // GSTREAMER_LITE
897 if (sz == 0 || sz > FFI_SIZEOF_ARG)
898 continue;
899
900 ++passed_regs;
901 }
902 #endif
903
904 memcpy (stack, ecif->avalue, cif->bytes);
905 return passed_regs;
906 }
907
908 /* we borrow this routine from libffi (it must be changed, though, to
909 * actually call the function passed in the first argument. as of
910 * libffi-1.20, this is not the case.)
911 */
912
913 void
914 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
915 {
916 extended_cif ecif;
917 void **avalue = (void **)fake_avalue;
918
919 ecif.cif = cif;
920 ecif.avalue = avalue;
921
922 /* If the return value is a struct and we don't have a return */
923 /* value address then we need to make one */
924
925 if (rvalue == NULL
926 && (cif->flags == FFI_TYPE_STRUCT
927 || cif->flags == FFI_TYPE_MS_STRUCT))
928 {
929 ecif.rvalue = alloca(cif->rtype->size);
930 }
931 else
932 ecif.rvalue = rvalue;
933
934
935 switch (cif->abi)
936 {
937 #ifndef X86_WIN32
938 case FFI_SYSV:
939 ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
940 ecif.rvalue, fn);
941 break;
942 #else
943 case FFI_SYSV:
944 case FFI_MS_CDECL:
945 #endif
946 #ifndef X86_WIN64
947 case FFI_STDCALL:
948 case FFI_THISCALL:
949 case FFI_FASTCALL:
950 case FFI_PASCAL:
951 case FFI_REGISTER:
952 ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
953 ecif.rvalue, fn);
954 break;
955 #endif
956 default:
957 FFI_ASSERT(0);
958 break;
959 }
960 }
961
962 #endif
963
964 #endif /* !__x86_64__ || X86_WIN64 */
965