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.
8 x86 Foreign Function Interface
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:
18 The above copyright notice and this permission notice shall be included
19 in all copies or substantial portions of the Software.
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 ----------------------------------------------------------------------- */
31 #if !defined(__x86_64__) || defined(_WIN64)
38 #include <ffi_common.h>
42 /* ffi_prep_args is called by the assembly routine once stack space
43 has been allocated for the function's arguments */
45 void ffi_prep_args(char *stack
, extended_cif
*ecif
)
47 register unsigned int i
;
48 register void **p_argv
;
50 register ffi_type
**p_arg
;
54 if (ecif
->cif
->flags
== FFI_TYPE_STRUCT
56 && (ecif
->cif
->rtype
->size
!= 1 && ecif
->cif
->rtype
->size
!= 2
57 && ecif
->cif
->rtype
->size
!= 4 && ecif
->cif
->rtype
->size
!= 8)
61 *(void **) argp
= ecif
->rvalue
;
62 argp
+= sizeof(void*);
65 p_argv
= ecif
->avalue
;
67 for (i
= ecif
->cif
->nargs
, p_arg
= ecif
->cif
->arg_types
;
73 /* Align if necessary */
74 if ((sizeof(void*) - 1) & (size_t) argp
)
75 argp
= (char *) ALIGN(argp
, sizeof(void*));
79 if (z
> sizeof(ffi_arg
)
80 || ((*p_arg
)->type
== FFI_TYPE_STRUCT
81 && (z
!= 1 && z
!= 2 && z
!= 4 && z
!= 8))
82 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
83 || ((*p_arg
)->type
== FFI_TYPE_LONGDOUBLE
)
88 *(void **)argp
= *p_argv
;
90 else if ((*p_arg
)->type
== FFI_TYPE_FLOAT
)
92 memcpy(argp
, *p_argv
, z
);
96 if (z
< sizeof(ffi_arg
))
99 switch ((*p_arg
)->type
)
102 *(ffi_sarg
*) argp
= (ffi_sarg
)*(SINT8
*)(* p_argv
);
106 *(ffi_arg
*) argp
= (ffi_arg
)*(UINT8
*)(* p_argv
);
109 case FFI_TYPE_SINT16
:
110 *(ffi_sarg
*) argp
= (ffi_sarg
)*(SINT16
*)(* p_argv
);
113 case FFI_TYPE_UINT16
:
114 *(ffi_arg
*) argp
= (ffi_arg
)*(UINT16
*)(* p_argv
);
117 case FFI_TYPE_SINT32
:
118 *(ffi_sarg
*) argp
= (ffi_sarg
)*(SINT32
*)(* p_argv
);
121 case FFI_TYPE_UINT32
:
122 *(ffi_arg
*) argp
= (ffi_arg
)*(UINT32
*)(* p_argv
);
125 case FFI_TYPE_STRUCT
:
126 *(ffi_arg
*) argp
= *(ffi_arg
*)(* p_argv
);
135 memcpy(argp
, *p_argv
, z
);
139 argp
+= (z
+ sizeof(void*) - 1) & ~(sizeof(void*) - 1);
148 /* Perform machine dependent cif processing */
149 ffi_status
ffi_prep_cif_machdep(ffi_cif
*cif
)
154 /* Set the return type flag */
155 switch (cif
->rtype
->type
)
158 #if defined(X86) || defined (X86_WIN32) || defined(X86_FREEBSD) || defined(X86_DARWIN) || defined(X86_WIN64)
160 case FFI_TYPE_UINT16
:
162 case FFI_TYPE_SINT16
:
165 case FFI_TYPE_UINT32
:
166 case FFI_TYPE_SINT32
:
168 case FFI_TYPE_SINT64
:
170 case FFI_TYPE_DOUBLE
:
172 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
173 case FFI_TYPE_LONGDOUBLE
:
176 cif
->flags
= (unsigned) cif
->rtype
->type
;
179 case FFI_TYPE_UINT64
:
181 case FFI_TYPE_POINTER
:
183 cif
->flags
= FFI_TYPE_SINT64
;
186 case FFI_TYPE_STRUCT
:
188 if (cif
->rtype
->size
== 1)
190 cif
->flags
= FFI_TYPE_SMALL_STRUCT_1B
; /* same as char size */
192 else if (cif
->rtype
->size
== 2)
194 cif
->flags
= FFI_TYPE_SMALL_STRUCT_2B
; /* same as short size */
196 else if (cif
->rtype
->size
== 4)
199 cif
->flags
= FFI_TYPE_SMALL_STRUCT_4B
;
201 cif
->flags
= FFI_TYPE_INT
; /* same as int type */
204 else if (cif
->rtype
->size
== 8)
206 cif
->flags
= FFI_TYPE_SINT64
; /* same as int64 type */
211 cif
->flags
= FFI_TYPE_STRUCT
;
212 /* allocate space for return value pointer */
213 cif
->bytes
+= ALIGN(sizeof(void*), FFI_SIZEOF_ARG
);
219 cif
->flags
= FFI_TYPE_SINT64
;
222 cif
->flags
= FFI_TYPE_SINT32
;
224 cif
->flags
= FFI_TYPE_INT
;
229 for (ptr
= cif
->arg_types
, i
= cif
->nargs
; i
> 0; i
--, ptr
++)
231 if (((*ptr
)->alignment
- 1) & cif
->bytes
)
232 cif
->bytes
= ALIGN(cif
->bytes
, (*ptr
)->alignment
);
233 cif
->bytes
+= ALIGN((*ptr
)->size
, FFI_SIZEOF_ARG
);
237 /* ensure space for storing four registers */
238 cif
->bytes
+= 4 * sizeof(ffi_arg
);
242 cif
->bytes
= (cif
->bytes
+ 15) & ~0xF;
250 ffi_call_win64(void (*)(char *, extended_cif
*), extended_cif
*,
251 unsigned, unsigned, unsigned *, void (*fn
)(void));
252 #elif defined(X86_WIN32)
254 ffi_call_win32(void (*)(char *, extended_cif
*), extended_cif
*,
255 unsigned, unsigned, unsigned *, void (*fn
)(void));
257 extern void ffi_call_SYSV(void (*)(char *, extended_cif
*), extended_cif
*,
258 unsigned, unsigned, unsigned *, void (*fn
)(void));
261 void ffi_call(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
)
266 ecif
.avalue
= avalue
;
268 /* If the return value is a struct and we don't have a return */
269 /* value address then we need to make one */
273 && cif
->flags
== FFI_TYPE_STRUCT
274 && cif
->rtype
->size
!= 1 && cif
->rtype
->size
!= 2
275 && cif
->rtype
->size
!= 4 && cif
->rtype
->size
!= 8)
277 ecif
.rvalue
= alloca((cif
->rtype
->size
+ 0xF) & ~0xF);
281 && cif
->flags
== FFI_TYPE_STRUCT
)
283 ecif
.rvalue
= alloca(cif
->rtype
->size
);
287 ecif
.rvalue
= rvalue
;
295 /* Make copies of all struct arguments
296 NOTE: not sure if responsibility should be here or in caller */
298 for (i
=0; i
< cif
->nargs
;i
++) {
299 size_t size
= cif
->arg_types
[i
]->size
;
300 if ((cif
->arg_types
[i
]->type
== FFI_TYPE_STRUCT
301 && (size
!= 1 && size
!= 2 && size
!= 4 && size
!= 8))
302 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
303 || cif
->arg_types
[i
]->type
== FFI_TYPE_LONGDOUBLE
307 void *local
= alloca(size
);
308 memcpy(local
, avalue
[i
], size
);
312 ffi_call_win64(ffi_prep_args
, &ecif
, cif
->bytes
,
313 cif
->flags
, ecif
.rvalue
, fn
);
316 #elif defined(X86_WIN32)
319 ffi_call_win32(ffi_prep_args
, &ecif
, cif
->bytes
, cif
->flags
,
324 ffi_call_SYSV(ffi_prep_args
, &ecif
, cif
->bytes
, cif
->flags
, ecif
.rvalue
,
335 /** private members **/
337 /* The following __attribute__((regparm(1))) decorations will have no effect
338 on MSVC - standard cdecl convention applies. */
339 static void ffi_prep_incoming_args_SYSV (char *stack
, void **ret
,
340 void** args
, ffi_cif
* cif
);
341 void FFI_HIDDEN
ffi_closure_SYSV (ffi_closure
*)
342 __attribute__ ((regparm(1)));
343 unsigned int FFI_HIDDEN
ffi_closure_SYSV_inner (ffi_closure
*, void **, void *)
344 __attribute__ ((regparm(1)));
345 void FFI_HIDDEN
ffi_closure_raw_SYSV (ffi_raw_closure
*)
346 __attribute__ ((regparm(1)));
348 void FFI_HIDDEN
ffi_closure_STDCALL (ffi_closure
*)
349 __attribute__ ((regparm(1)));
352 void FFI_HIDDEN
ffi_closure_win64 (ffi_closure
*);
355 /* This function is jumped to by the trampoline */
359 ffi_closure_win64_inner (ffi_closure
*closure
, void *args
) {
363 void *resp
= &result
;
366 arg_area
= (void**) alloca (cif
->nargs
* sizeof (void*));
368 /* this call will initialize ARG_AREA, such that each
369 * element in that array points to the corresponding
370 * value on the stack; and if the function returns
371 * a structure, it will change RESP to point to the
372 * structure return address. */
374 ffi_prep_incoming_args_SYSV(args
, &resp
, arg_area
, cif
);
376 (closure
->fun
) (cif
, resp
, arg_area
, closure
->user_data
);
378 /* The result is returned in rax. This does the right thing for
379 result types except for floats; we have to 'mov xmm0, rax' in the
380 caller to correct this.
381 TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
383 return cif
->rtype
->size
> sizeof(void *) ? resp
: *(void **)resp
;
387 unsigned int FFI_HIDDEN
__attribute__ ((regparm(1)))
388 ffi_closure_SYSV_inner (ffi_closure
*closure
, void **respp
, void *args
)
390 /* our various things... */
395 arg_area
= (void**) alloca (cif
->nargs
* sizeof (void*));
397 /* this call will initialize ARG_AREA, such that each
398 * element in that array points to the corresponding
399 * value on the stack; and if the function returns
400 * a structure, it will change RESP to point to the
401 * structure return address. */
403 ffi_prep_incoming_args_SYSV(args
, respp
, arg_area
, cif
);
405 (closure
->fun
) (cif
, *respp
, arg_area
, closure
->user_data
);
409 #endif /* !X86_WIN64 */
412 ffi_prep_incoming_args_SYSV(char *stack
, void **rvalue
, void **avalue
,
415 register unsigned int i
;
416 register void **p_argv
;
418 register ffi_type
**p_arg
;
423 if (cif
->rtype
->size
> sizeof(ffi_arg
)
424 || (cif
->flags
== FFI_TYPE_STRUCT
425 && (cif
->rtype
->size
!= 1 && cif
->rtype
->size
!= 2
426 && cif
->rtype
->size
!= 4 && cif
->rtype
->size
!= 8))) {
427 *rvalue
= *(void **) argp
;
428 argp
+= sizeof(void *);
431 if ( cif
->flags
== FFI_TYPE_STRUCT
) {
432 *rvalue
= *(void **) argp
;
433 argp
+= sizeof(void *);
439 for (i
= cif
->nargs
, p_arg
= cif
->arg_types
; (i
!= 0); i
--, p_arg
++)
443 /* Align if necessary */
444 if ((sizeof(void*) - 1) & (size_t) argp
) {
445 argp
= (char *) ALIGN(argp
, sizeof(void*));
449 if ((*p_arg
)->size
> sizeof(ffi_arg
)
450 || ((*p_arg
)->type
== FFI_TYPE_STRUCT
451 && ((*p_arg
)->size
!= 1 && (*p_arg
)->size
!= 2
452 && (*p_arg
)->size
!= 4 && (*p_arg
)->size
!= 8)))
455 *p_argv
= *(void **)argp
;
462 /* because we're little endian, this is what it turns into. */
464 *p_argv
= (void*) argp
;
469 argp
+= (z
+ sizeof(void*) - 1) & ~(sizeof(void*) - 1);
478 #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
479 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
480 void* __fun = (void*)(FUN); \
481 void* __ctx = (void*)(CTX); \
482 *(unsigned char*) &__tramp[0] = 0x41; \
483 *(unsigned char*) &__tramp[1] = 0xbb; \
484 *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
485 *(unsigned char*) &__tramp[6] = 0x48; \
486 *(unsigned char*) &__tramp[7] = 0xb8; \
487 *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
488 *(unsigned char *) &__tramp[16] = 0x49; \
489 *(unsigned char *) &__tramp[17] = 0xba; \
490 *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
491 *(unsigned char *) &__tramp[26] = 0x41; \
492 *(unsigned char *) &__tramp[27] = 0xff; \
493 *(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \
496 /* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
498 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
499 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
500 unsigned int __fun = (unsigned int)(FUN); \
501 unsigned int __ctx = (unsigned int)(CTX); \
502 unsigned int __dis = __fun - (__ctx + 10); \
503 *(unsigned char*) &__tramp[0] = 0xb8; \
504 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
505 *(unsigned char *) &__tramp[5] = 0xe9; \
506 *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
509 #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) \
510 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
511 unsigned int __fun = (unsigned int)(FUN); \
512 unsigned int __ctx = (unsigned int)(CTX); \
513 unsigned int __dis = __fun - (__ctx + 10); \
514 unsigned short __size = (unsigned short)(SIZE); \
515 *(unsigned char*) &__tramp[0] = 0xb8; \
516 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
517 *(unsigned char *) &__tramp[5] = 0xe8; \
518 *(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \
519 *(unsigned char *) &__tramp[10] = 0xc2; \
520 *(unsigned short*) &__tramp[11] = __size; /* ret __size */ \
523 /* the cif must already be prep'ed */
526 ffi_prep_closure_loc (ffi_closure
* closure
,
528 void (*fun
)(ffi_cif
*,void*,void**,void*),
533 #define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
534 #define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
535 if (cif
->abi
== FFI_WIN64
)
537 int mask
= FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
538 FFI_INIT_TRAMPOLINE_WIN64 (&closure
->tramp
[0],
541 /* make sure we can execute here */
544 if (cif
->abi
== FFI_SYSV
)
546 FFI_INIT_TRAMPOLINE (&closure
->tramp
[0],
551 else if (cif
->abi
== FFI_STDCALL
)
553 FFI_INIT_TRAMPOLINE_STDCALL (&closure
->tramp
[0],
554 &ffi_closure_STDCALL
,
555 (void*)codeloc
, cif
->bytes
);
557 #endif /* X86_WIN32 */
558 #endif /* !X86_WIN64 */
565 closure
->user_data
= user_data
;
571 /* ------- Native raw API support -------------------------------- */
576 ffi_prep_raw_closure_loc (ffi_raw_closure
* closure
,
578 void (*fun
)(ffi_cif
*,void*,ffi_raw
*,void*),
584 if (cif
->abi
!= FFI_SYSV
) {
588 /* we currently don't support certain kinds of arguments for raw
589 closures. This should be implemented by a separate assembly
590 language routine, since it would require argument processing,
591 something we don't do now for performance. */
593 for (i
= cif
->nargs
-1; i
>= 0; i
--)
595 FFI_ASSERT (cif
->arg_types
[i
]->type
!= FFI_TYPE_STRUCT
);
596 FFI_ASSERT (cif
->arg_types
[i
]->type
!= FFI_TYPE_LONGDOUBLE
);
600 FFI_INIT_TRAMPOLINE (&closure
->tramp
[0], &ffi_closure_raw_SYSV
,
604 closure
->user_data
= user_data
;
611 ffi_prep_args_raw(char *stack
, extended_cif
*ecif
)
613 memcpy (stack
, ecif
->avalue
, ecif
->cif
->bytes
);
616 /* we borrow this routine from libffi (it must be changed, though, to
617 * actually call the function passed in the first argument. as of
618 * libffi-1.20, this is not the case.)
622 ffi_raw_call(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, ffi_raw
*fake_avalue
)
625 void **avalue
= (void **)fake_avalue
;
628 ecif
.avalue
= avalue
;
630 /* If the return value is a struct and we don't have a return */
631 /* value address then we need to make one */
633 if ((rvalue
== NULL
) &&
634 (cif
->rtype
->type
== FFI_TYPE_STRUCT
))
636 ecif
.rvalue
= alloca(cif
->rtype
->size
);
639 ecif
.rvalue
= rvalue
;
647 ffi_call_win32(ffi_prep_args_raw
, &ecif
, cif
->bytes
, cif
->flags
,
652 ffi_call_SYSV(ffi_prep_args_raw
, &ecif
, cif
->bytes
, cif
->flags
,
664 #endif /* !__x86_64__ || X86_WIN64 */