Home | History | Annotate | Download | only in x86
      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  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 #ifndef __x86_64__
     32 
     33 #include <ffi.h>
     34 #include <ffi_common.h>
     35 
     36 #include <stdlib.h>
     37 
     38 /* ffi_prep_args is called by the assembly routine once stack space
     39    has been allocated for the function's arguments */
     40 
     41 void ffi_prep_args(char *stack, extended_cif *ecif)
     42 {
     43   register unsigned int i;
     44   register void **p_argv;
     45   register char *argp;
     46   register ffi_type **p_arg;
     47 
     48   argp = stack;
     49 
     50   if (ecif->cif->flags == FFI_TYPE_STRUCT)
     51     {
     52       *(void **) argp = ecif->rvalue;
     53       argp += 4;
     54     }
     55 
     56   p_argv = ecif->avalue;
     57 
     58   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
     59        i != 0;
     60        i--, p_arg++)
     61     {
     62       size_t z;
     63 
     64       /* Align if necessary */
     65       if ((sizeof(int) - 1) & (unsigned) argp)
     66 	argp = (char *) ALIGN(argp, sizeof(int));
     67 
     68       z = (*p_arg)->size;
     69       if (z < sizeof(int))
     70 	{
     71 	  z = sizeof(int);
     72 	  switch ((*p_arg)->type)
     73 	    {
     74 	    case FFI_TYPE_SINT8:
     75 	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
     76 	      break;
     77 
     78 	    case FFI_TYPE_UINT8:
     79 	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
     80 	      break;
     81 
     82 	    case FFI_TYPE_SINT16:
     83 	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
     84 	      break;
     85 
     86 	    case FFI_TYPE_UINT16:
     87 	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
     88 	      break;
     89 
     90 	    case FFI_TYPE_SINT32:
     91 	      *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
     92 	      break;
     93 
     94 	    case FFI_TYPE_UINT32:
     95 	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
     96 	      break;
     97 
     98 	    case FFI_TYPE_STRUCT:
     99 	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
    100 	      break;
    101 
    102 	    default:
    103 	      FFI_ASSERT(0);
    104 	    }
    105 	}
    106       else
    107 	{
    108 	  memcpy(argp, *p_argv, z);
    109 	}
    110       p_argv++;
    111       argp += z;
    112     }
    113 
    114   return;
    115 }
    116 
    117 /* Perform machine dependent cif processing */
    118 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
    119 {
    120   /* Set the return type flag */
    121   switch (cif->rtype->type)
    122     {
    123     case FFI_TYPE_VOID:
    124 #ifdef X86
    125     case FFI_TYPE_STRUCT:
    126 #endif
    127 #if defined(X86) || defined(X86_DARWIN)
    128     case FFI_TYPE_UINT8:
    129     case FFI_TYPE_UINT16:
    130     case FFI_TYPE_SINT8:
    131     case FFI_TYPE_SINT16:
    132 #endif
    133 
    134     case FFI_TYPE_SINT64:
    135     case FFI_TYPE_FLOAT:
    136     case FFI_TYPE_DOUBLE:
    137     case FFI_TYPE_LONGDOUBLE:
    138       cif->flags = (unsigned) cif->rtype->type;
    139       break;
    140 
    141     case FFI_TYPE_UINT64:
    142       cif->flags = FFI_TYPE_SINT64;
    143       break;
    144 
    145 #ifndef X86
    146     case FFI_TYPE_STRUCT:
    147       if (cif->rtype->size == 1)
    148         {
    149           cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
    150         }
    151       else if (cif->rtype->size == 2)
    152         {
    153           cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
    154         }
    155       else if (cif->rtype->size == 4)
    156         {
    157           cif->flags = FFI_TYPE_INT; /* same as int type */
    158         }
    159       else if (cif->rtype->size == 8)
    160         {
    161           cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
    162         }
    163       else
    164         {
    165           cif->flags = FFI_TYPE_STRUCT;
    166         }
    167       break;
    168 #endif
    169 
    170     default:
    171       cif->flags = FFI_TYPE_INT;
    172       break;
    173     }
    174 
    175 #ifdef X86_DARWIN
    176   cif->bytes = (cif->bytes + 15) & ~0xF;
    177 #endif
    178 
    179   return FFI_OK;
    180 }
    181 
    182 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
    183 			  unsigned, unsigned, unsigned *, void (*fn)(void));
    184 
    185 #ifdef X86_WIN32
    186 extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
    187 			  unsigned, unsigned, unsigned *, void (*fn)(void));
    188 
    189 #endif /* X86_WIN32 */
    190 
    191 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
    192 {
    193   extended_cif ecif;
    194 
    195   ecif.cif = cif;
    196   ecif.avalue = avalue;
    197 
    198   /* If the return value is a struct and we don't have a return	*/
    199   /* value address then we need to make one		        */
    200 
    201   if ((rvalue == NULL) &&
    202       (cif->flags == FFI_TYPE_STRUCT))
    203     {
    204       ecif.rvalue = alloca(cif->rtype->size);
    205     }
    206   else
    207     ecif.rvalue = rvalue;
    208 
    209 
    210   switch (cif->abi)
    211     {
    212     case FFI_SYSV:
    213       ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
    214 		    fn);
    215       break;
    216 #ifdef X86_WIN32
    217     case FFI_STDCALL:
    218       ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
    219 		       ecif.rvalue, fn);
    220       break;
    221 #endif /* X86_WIN32 */
    222     default:
    223       FFI_ASSERT(0);
    224       break;
    225     }
    226 }
    227 
    228 
    229 /** private members **/
    230 
    231 static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
    232 					 void** args, ffi_cif* cif);
    233 void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
    234      __attribute__ ((regparm(1)));
    235 unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
    236      __attribute__ ((regparm(1)));
    237 void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
    238      __attribute__ ((regparm(1)));
    239 #ifdef X86_WIN32
    240 void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
    241      __attribute__ ((regparm(1)));
    242 #endif
    243 
    244 /* This function is jumped to by the trampoline */
    245 
    246 unsigned int FFI_HIDDEN
    247 ffi_closure_SYSV_inner (closure, respp, args)
    248      ffi_closure *closure;
    249      void **respp;
    250      void *args;
    251 {
    252   /* our various things...  */
    253   ffi_cif       *cif;
    254   void         **arg_area;
    255 
    256   cif         = closure->cif;
    257   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));
    258 
    259   /* this call will initialize ARG_AREA, such that each
    260    * element in that array points to the corresponding
    261    * value on the stack; and if the function returns
    262    * a structure, it will re-set RESP to point to the
    263    * structure return address.  */
    264 
    265   ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
    266 
    267   (closure->fun) (cif, *respp, arg_area, closure->user_data);
    268 
    269   return cif->flags;
    270 }
    271 
    272 static void
    273 ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
    274 			    ffi_cif *cif)
    275 {
    276   register unsigned int i;
    277   register void **p_argv;
    278   register char *argp;
    279   register ffi_type **p_arg;
    280 
    281   argp = stack;
    282 
    283   if ( cif->flags == FFI_TYPE_STRUCT ) {
    284     *rvalue = *(void **) argp;
    285     argp += 4;
    286   }
    287 
    288   p_argv = avalue;
    289 
    290   for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
    291     {
    292       size_t z;
    293 
    294       /* Align if necessary */
    295       if ((sizeof(int) - 1) & (unsigned) argp) {
    296 	argp = (char *) ALIGN(argp, sizeof(int));
    297       }
    298 
    299       z = (*p_arg)->size;
    300 
    301       /* because we're little endian, this is what it turns into.   */
    302 
    303       *p_argv = (void*) argp;
    304 
    305       p_argv++;
    306       argp += z;
    307     }
    308 
    309   return;
    310 }
    311 
    312 /* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
    313 
    314 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
    315 ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
    316    unsigned int  __fun = (unsigned int)(FUN); \
    317    unsigned int  __ctx = (unsigned int)(CTX); \
    318    unsigned int  __dis = __fun - (__ctx + 10);	\
    319    *(unsigned char*) &__tramp[0] = 0xb8; \
    320    *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
    321    *(unsigned char *)  &__tramp[5] = 0xe9; \
    322    *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
    323  })
    324 
    325 #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE)  \
    326 ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
    327    unsigned int  __fun = (unsigned int)(FUN); \
    328    unsigned int  __ctx = (unsigned int)(CTX); \
    329    unsigned int  __dis = __fun - (__ctx + 10); \
    330    unsigned short __size = (unsigned short)(SIZE); \
    331    *(unsigned char*) &__tramp[0] = 0xb8; \
    332    *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
    333    *(unsigned char *)  &__tramp[5] = 0xe8; \
    334    *(unsigned int*)  &__tramp[6] = __dis; /* call __fun  */ \
    335    *(unsigned char *)  &__tramp[10] = 0xc2; \
    336    *(unsigned short*)  &__tramp[11] = __size; /* ret __size  */ \
    337  })
    338 
    339 /* the cif must already be prep'ed */
    340 
    341 ffi_status
    342 ffi_prep_closure_loc (ffi_closure* closure,
    343 		      ffi_cif* cif,
    344 		      void (*fun)(ffi_cif*,void*,void**,void*),
    345 		      void *user_data,
    346 		      void *codeloc)
    347 {
    348   if (cif->abi == FFI_SYSV)
    349     {
    350       FFI_INIT_TRAMPOLINE (&closure->tramp[0],
    351                            &ffi_closure_SYSV,
    352                            (void*)codeloc);
    353     }
    354 #ifdef X86_WIN32
    355   else if (cif->abi == FFI_STDCALL)
    356     {
    357       FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
    358                                    &ffi_closure_STDCALL,
    359                                    (void*)codeloc, cif->bytes);
    360     }
    361 #endif
    362   else
    363     {
    364       return FFI_BAD_ABI;
    365     }
    366 
    367   closure->cif  = cif;
    368   closure->user_data = user_data;
    369   closure->fun  = fun;
    370 
    371   return FFI_OK;
    372 }
    373 
    374 /* ------- Native raw API support -------------------------------- */
    375 
    376 #if !FFI_NO_RAW_API
    377 
    378 ffi_status
    379 ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
    380 			  ffi_cif* cif,
    381 			  void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
    382 			  void *user_data,
    383 			  void *codeloc)
    384 {
    385   int i;
    386 
    387   if (cif->abi != FFI_SYSV) {
    388     return FFI_BAD_ABI;
    389   }
    390 
    391   // we currently don't support certain kinds of arguments for raw
    392   // closures.  This should be implemented by a separate assembly language
    393   // routine, since it would require argument processing, something we
    394   // don't do now for performance.
    395 
    396   for (i = cif->nargs-1; i >= 0; i--)
    397     {
    398       FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
    399       FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
    400     }
    401 
    402 
    403   FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
    404 		       codeloc);
    405 
    406   closure->cif  = cif;
    407   closure->user_data = user_data;
    408   closure->fun  = fun;
    409 
    410   return FFI_OK;
    411 }
    412 
    413 static void
    414 ffi_prep_args_raw(char *stack, extended_cif *ecif)
    415 {
    416   memcpy (stack, ecif->avalue, ecif->cif->bytes);
    417 }
    418 
    419 /* we borrow this routine from libffi (it must be changed, though, to
    420  * actually call the function passed in the first argument.  as of
    421  * libffi-1.20, this is not the case.)
    422  */
    423 
    424 extern void
    425 ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned,
    426 	      unsigned, unsigned *, void (*fn)(void));
    427 
    428 #ifdef X86_WIN32
    429 extern void
    430 ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
    431 		 unsigned, unsigned *, void (*fn)(void));
    432 #endif /* X86_WIN32 */
    433 
    434 void
    435 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
    436 {
    437   extended_cif ecif;
    438   void **avalue = (void **)fake_avalue;
    439 
    440   ecif.cif = cif;
    441   ecif.avalue = avalue;
    442 
    443   /* If the return value is a struct and we don't have a return	*/
    444   /* value address then we need to make one		        */
    445 
    446   if ((rvalue == NULL) &&
    447       (cif->rtype->type == FFI_TYPE_STRUCT))
    448     {
    449       ecif.rvalue = alloca(cif->rtype->size);
    450     }
    451   else
    452     ecif.rvalue = rvalue;
    453 
    454 
    455   switch (cif->abi)
    456     {
    457     case FFI_SYSV:
    458       ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
    459 		    ecif.rvalue, fn);
    460       break;
    461 #ifdef X86_WIN32
    462     case FFI_STDCALL:
    463       ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
    464 		       ecif.rvalue, fn);
    465       break;
    466 #endif /* X86_WIN32 */
    467     default:
    468       FFI_ASSERT(0);
    469       break;
    470     }
    471 }
    472 
    473 #endif
    474 
    475 #endif /* __x86_64__  */
    476