1 /* ----------------------------------------------------------------------- 2 ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc. 3 Copyright (c) 2002 Ranjit Mathew 4 Copyright (c) 2002 Bo Thorsen 5 Copyright (c) 2002 Roger Sayle 6 7 x86 Foreign Function Interface 8 9 Permission is hereby granted, free of charge, to any person obtaining 10 a copy of this software and associated documentation files (the 11 ``Software''), to deal in the Software without restriction, including 12 without limitation the rights to use, copy, modify, merge, publish, 13 distribute, sublicense, and/or sell copies of the Software, and to 14 permit persons to whom the Software is furnished to do so, subject to 15 the following conditions: 16 17 The above copyright notice and this permission notice shall be included 18 in all copies or substantial portions of the Software. 19 20 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR 24 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 OTHER DEALINGS IN THE SOFTWARE. 27 ----------------------------------------------------------------------- */ 28 29 #include <ffi.h> 30 #include <ffi_common.h> 31 32 #include <stdlib.h> 33 34 /* ffi_prep_args is called by the assembly routine once stack space 35 has been allocated for the function's arguments */ 36 37 extern void Py_FatalError(const char *msg); 38 39 /*@-exportheader@*/ 40 void ffi_prep_args(char *stack, extended_cif *ecif) 41 /*@=exportheader@*/ 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 if (ecif->cif->rtype->type == FFI_TYPE_STRUCT) 50 { 51 *(void **) argp = ecif->rvalue; 52 argp += sizeof(void *); 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(void *) - 1) & (size_t) argp) 65 argp = (char *) ALIGN(argp, sizeof(void *)); 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 #ifdef _WIN64 106 else if (z > 8) 107 { 108 /* On Win64, if a single argument takes more than 8 bytes, 109 then it is always passed by reference. */ 110 *(void **)argp = *p_argv; 111 z = 8; 112 } 113 #endif 114 else 115 { 116 memcpy(argp, *p_argv, z); 117 } 118 p_argv++; 119 argp += z; 120 } 121 122 if (argp - stack > ecif->cif->bytes) 123 { 124 Py_FatalError("FFI BUG: not enough stack space for arguments"); 125 } 126 return; 127 } 128 129 /* Perform machine dependent cif processing */ 130 ffi_status ffi_prep_cif_machdep(ffi_cif *cif) 131 { 132 /* Set the return type flag */ 133 switch (cif->rtype->type) 134 { 135 case FFI_TYPE_VOID: 136 case FFI_TYPE_SINT64: 137 case FFI_TYPE_FLOAT: 138 case FFI_TYPE_DOUBLE: 139 case FFI_TYPE_LONGDOUBLE: 140 cif->flags = (unsigned) cif->rtype->type; 141 break; 142 143 case FFI_TYPE_STRUCT: 144 /* MSVC returns small structures in registers. Put in cif->flags 145 the value FFI_TYPE_STRUCT only if the structure is big enough; 146 otherwise, put the 4- or 8-bytes integer type. */ 147 if (cif->rtype->size <= 4) 148 cif->flags = FFI_TYPE_INT; 149 else if (cif->rtype->size <= 8) 150 cif->flags = FFI_TYPE_SINT64; 151 else 152 cif->flags = FFI_TYPE_STRUCT; 153 break; 154 155 case FFI_TYPE_UINT64: 156 #ifdef _WIN64 157 case FFI_TYPE_POINTER: 158 #endif 159 cif->flags = FFI_TYPE_SINT64; 160 break; 161 162 default: 163 cif->flags = FFI_TYPE_INT; 164 break; 165 } 166 167 return FFI_OK; 168 } 169 170 #ifdef _WIN32 171 extern int 172 ffi_call_x86(void (*)(char *, extended_cif *), 173 /*@out@*/ extended_cif *, 174 unsigned, unsigned, 175 /*@out@*/ unsigned *, 176 void (*fn)()); 177 #endif 178 179 #ifdef _WIN64 180 extern int 181 ffi_call_AMD64(void (*)(char *, extended_cif *), 182 /*@out@*/ extended_cif *, 183 unsigned, unsigned, 184 /*@out@*/ unsigned *, 185 void (*fn)()); 186 #endif 187 188 int 189 ffi_call(/*@dependent@*/ ffi_cif *cif, 190 void (*fn)(), 191 /*@out@*/ void *rvalue, 192 /*@dependent@*/ void **avalue) 193 { 194 extended_cif ecif; 195 196 ecif.cif = cif; 197 ecif.avalue = avalue; 198 199 /* If the return value is a struct and we don't have a return */ 200 /* value address then we need to make one */ 201 202 if ((rvalue == NULL) && 203 (cif->rtype->type == FFI_TYPE_STRUCT)) 204 { 205 /*@-sysunrecog@*/ 206 ecif.rvalue = alloca(cif->rtype->size); 207 /*@=sysunrecog@*/ 208 } 209 else 210 ecif.rvalue = rvalue; 211 212 213 switch (cif->abi) 214 { 215 #if !defined(_WIN64) 216 case FFI_SYSV: 217 case FFI_STDCALL: 218 return ffi_call_x86(ffi_prep_args, &ecif, cif->bytes, 219 cif->flags, ecif.rvalue, fn); 220 break; 221 #else 222 case FFI_SYSV: 223 /*@-usedef@*/ 224 return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes, 225 cif->flags, ecif.rvalue, fn); 226 /*@=usedef@*/ 227 break; 228 #endif 229 230 default: 231 FFI_ASSERT(0); 232 break; 233 } 234 return -1; /* theller: Hrm. */ 235 } 236 237 238 /** private members **/ 239 240 static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, 241 void** args, ffi_cif* cif); 242 /* This function is jumped to by the trampoline */ 243 244 #ifdef _WIN64 245 void * 246 #else 247 static void __fastcall 248 #endif 249 ffi_closure_SYSV (ffi_closure *closure, char *argp) 250 { 251 // this is our return value storage 252 long double res; 253 254 // our various things... 255 ffi_cif *cif; 256 void **arg_area; 257 unsigned short rtype; 258 void *resp = (void*)&res; 259 void *args = argp + sizeof(void*); 260 261 cif = closure->cif; 262 arg_area = (void**) alloca (cif->nargs * sizeof (void*)); 263 264 /* this call will initialize ARG_AREA, such that each 265 * element in that array points to the corresponding 266 * value on the stack; and if the function returns 267 * a structure, it will re-set RESP to point to the 268 * structure return address. */ 269 270 ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif); 271 272 (closure->fun) (cif, resp, arg_area, closure->user_data); 273 274 rtype = cif->flags; 275 276 #if defined(_WIN32) && !defined(_WIN64) 277 #ifdef _MSC_VER 278 /* now, do a generic return based on the value of rtype */ 279 if (rtype == FFI_TYPE_INT) 280 { 281 _asm mov eax, resp ; 282 _asm mov eax, [eax] ; 283 } 284 else if (rtype == FFI_TYPE_FLOAT) 285 { 286 _asm mov eax, resp ; 287 _asm fld DWORD PTR [eax] ; 288 // asm ("flds (%0)" : : "r" (resp) : "st" ); 289 } 290 else if (rtype == FFI_TYPE_DOUBLE) 291 { 292 _asm mov eax, resp ; 293 _asm fld QWORD PTR [eax] ; 294 // asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" ); 295 } 296 else if (rtype == FFI_TYPE_LONGDOUBLE) 297 { 298 // asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" ); 299 } 300 else if (rtype == FFI_TYPE_SINT64) 301 { 302 _asm mov edx, resp ; 303 _asm mov eax, [edx] ; 304 _asm mov edx, [edx + 4] ; 305 // asm ("movl 0(%0),%%eax;" 306 // "movl 4(%0),%%edx" 307 // : : "r"(resp) 308 // : "eax", "edx"); 309 } 310 #else 311 /* now, do a generic return based on the value of rtype */ 312 if (rtype == FFI_TYPE_INT) 313 { 314 asm ("movl (%0),%%eax" : : "r" (resp) : "eax"); 315 } 316 else if (rtype == FFI_TYPE_FLOAT) 317 { 318 asm ("flds (%0)" : : "r" (resp) : "st" ); 319 } 320 else if (rtype == FFI_TYPE_DOUBLE) 321 { 322 asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" ); 323 } 324 else if (rtype == FFI_TYPE_LONGDOUBLE) 325 { 326 asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" ); 327 } 328 else if (rtype == FFI_TYPE_SINT64) 329 { 330 asm ("movl 0(%0),%%eax;" 331 "movl 4(%0),%%edx" 332 : : "r"(resp) 333 : "eax", "edx"); 334 } 335 #endif 336 #endif 337 338 #ifdef _WIN64 339 /* The result is returned in rax. This does the right thing for 340 result types except for floats; we have to 'mov xmm0, rax' in the 341 caller to correct this. 342 */ 343 return *(void **)resp; 344 #endif 345 } 346 347 /*@-exportheader@*/ 348 static void 349 ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, 350 void **avalue, ffi_cif *cif) 351 /*@=exportheader@*/ 352 { 353 register unsigned int i; 354 register void **p_argv; 355 register char *argp; 356 register ffi_type **p_arg; 357 358 argp = stack; 359 360 if ( cif->rtype->type == FFI_TYPE_STRUCT ) { 361 *rvalue = *(void **) argp; 362 argp += sizeof(void *); 363 } 364 365 p_argv = avalue; 366 367 for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) 368 { 369 size_t z; 370 371 /* Align if necessary */ 372 if ((sizeof(char *) - 1) & (size_t) argp) { 373 argp = (char *) ALIGN(argp, sizeof(char*)); 374 } 375 376 z = (*p_arg)->size; 377 378 /* because we're little endian, this is what it turns into. */ 379 380 #ifdef _WIN64 381 if (z > 8) { 382 /* On Win64, if a single argument takes more than 8 bytes, 383 * then it is always passed by reference. 384 */ 385 *p_argv = *((void**) argp); 386 z = 8; 387 } 388 else 389 #endif 390 *p_argv = (void*) argp; 391 392 p_argv++; 393 argp += z; 394 } 395 396 return; 397 } 398 399 /* the cif must already be prep'ed */ 400 extern void ffi_closure_OUTER(); 401 402 ffi_status 403 ffi_prep_closure_loc (ffi_closure* closure, 404 ffi_cif* cif, 405 void (*fun)(ffi_cif*,void*,void**,void*), 406 void *user_data, 407 void *codeloc) 408 { 409 short bytes; 410 char *tramp; 411 #ifdef _WIN64 412 int mask = 0; 413 #endif 414 FFI_ASSERT (cif->abi == FFI_SYSV); 415 416 if (cif->abi == FFI_SYSV) 417 bytes = 0; 418 #if !defined(_WIN64) 419 else if (cif->abi == FFI_STDCALL) 420 bytes = cif->bytes; 421 #endif 422 else 423 return FFI_BAD_ABI; 424 425 tramp = &closure->tramp[0]; 426 427 #define BYTES(text) memcpy(tramp, text, sizeof(text)), tramp += sizeof(text)-1 428 #define POINTER(x) *(void**)tramp = (void*)(x), tramp += sizeof(void*) 429 #define SHORT(x) *(short*)tramp = x, tramp += sizeof(short) 430 #define INT(x) *(int*)tramp = x, tramp += sizeof(int) 431 432 #ifdef _WIN64 433 if (cif->nargs >= 1 && 434 (cif->arg_types[0]->type == FFI_TYPE_FLOAT 435 || cif->arg_types[0]->type == FFI_TYPE_DOUBLE)) 436 mask |= 1; 437 if (cif->nargs >= 2 && 438 (cif->arg_types[1]->type == FFI_TYPE_FLOAT 439 || cif->arg_types[1]->type == FFI_TYPE_DOUBLE)) 440 mask |= 2; 441 if (cif->nargs >= 3 && 442 (cif->arg_types[2]->type == FFI_TYPE_FLOAT 443 || cif->arg_types[2]->type == FFI_TYPE_DOUBLE)) 444 mask |= 4; 445 if (cif->nargs >= 4 && 446 (cif->arg_types[3]->type == FFI_TYPE_FLOAT 447 || cif->arg_types[3]->type == FFI_TYPE_DOUBLE)) 448 mask |= 8; 449 450 /* 41 BB ---- mov r11d,mask */ 451 BYTES("\x41\xBB"); INT(mask); 452 453 /* 48 B8 -------- mov rax, closure */ 454 BYTES("\x48\xB8"); POINTER(closure); 455 456 /* 49 BA -------- mov r10, ffi_closure_OUTER */ 457 BYTES("\x49\xBA"); POINTER(ffi_closure_OUTER); 458 459 /* 41 FF E2 jmp r10 */ 460 BYTES("\x41\xFF\xE2"); 461 462 #else 463 464 /* mov ecx, closure */ 465 BYTES("\xb9"); POINTER(closure); 466 467 /* mov edx, esp */ 468 BYTES("\x8b\xd4"); 469 470 /* call ffi_closure_SYSV */ 471 BYTES("\xe8"); POINTER((char*)&ffi_closure_SYSV - (tramp + 4)); 472 473 /* ret bytes */ 474 BYTES("\xc2"); 475 SHORT(bytes); 476 477 #endif 478 479 if (tramp - &closure->tramp[0] > FFI_TRAMPOLINE_SIZE) 480 Py_FatalError("FFI_TRAMPOLINE_SIZE too small in " __FILE__); 481 482 closure->cif = cif; 483 closure->user_data = user_data; 484 closure->fun = fun; 485 return FFI_OK; 486 } 487