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