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