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@*/
ffi_prep_args(char * stack,extended_cif * ecif)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->flags == 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 > (long)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 */
ffi_prep_cif_machdep(ffi_cif * cif)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
ffi_call(ffi_cif * cif,void (* fn)(),void * rvalue,void ** avalue)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->flags == 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
ffi_closure_SYSV(ffi_closure * closure,char * argp)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
ffi_prep_incoming_args_SYSV(char * stack,void ** rvalue,void ** avalue,ffi_cif * cif)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->flags == FFI_TYPE_STRUCT ) {
361 *rvalue = *(void **) argp;
362 argp += 4;
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 {
383 /* On Win64, if a single argument takes more than 8 bytes,
384 then it is always passed by reference. */
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
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)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