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