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