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