• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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