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
ffi_prep_args(char * stack,extended_cif * ecif)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 */
ffi_prep_cif_machdep(ffi_cif * cif)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
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)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
ffi_closure_SYSV_inner(closure,respp,args)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
ffi_prep_incoming_args_SYSV(char * stack,void ** rvalue,void ** avalue,ffi_cif * cif)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
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)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
ffi_prep_raw_closure_loc(ffi_raw_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,ffi_raw *,void *),void * user_data,void * codeloc)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
ffi_prep_args_raw(char * stack,extended_cif * ecif)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
ffi_raw_call(ffi_cif * cif,void (* fn)(void),void * rvalue,ffi_raw * fake_avalue)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