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