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