Ruby  2.4.2p198(2017-09-14revision59899)
ffi.c
Go to the documentation of this file.
1 /* -----------------------------------------------------------------------
2  ffi.c - Copyright (c) 2011 Anthony Green
3  Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
4 
5  AVR32 Foreign Function Interface
6 
7  Permission is hereby granted, free of charge, to any person obtaining
8  a copy of this software and associated documentation files (the
9  ``Software''), to deal in the Software without restriction, including
10  without limitation the rights to use, copy, modify, merge, publish,
11  distribute, sublicense, and/or sell copies of the Software, and to
12  permit persons to whom the Software is furnished to do so, subject to
13  the following conditions:
14 
15  The above copyright notice and this permission notice shall be included
16  in all copies or substantial portions of the Software.
17 
18  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  DEALINGS IN THE SOFTWARE.
26  ----------------------------------------------------------------------- */
27 
28 #include <ffi.h>
29 #include <ffi_common.h>
30 
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <asm/unistd.h>
35 
36 /* #define DEBUG */
37 
38 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
39  unsigned int, unsigned int, unsigned int*, unsigned int,
40  void (*fn)(void));
41 extern void ffi_closure_SYSV (ffi_closure *);
42 
43 unsigned int pass_struct_on_stack(ffi_type *type)
44 {
45  if(type->type != FFI_TYPE_STRUCT)
46  return 0;
47 
48  if(type->alignment < type->size &&
49  !(type->size == 4 || type->size == 8) &&
50  !(type->size == 8 && type->alignment >= 4))
51  return 1;
52 
53  if(type->size == 3 || type->size == 5 || type->size == 6 ||
54  type->size == 7)
55  return 1;
56 
57  return 0;
58 }
59 
60 /* ffi_prep_args is called by the assembly routine once stack space
61  * has been allocated for the function's arguments
62  *
63  * This is annoyingly complex since we need to keep track of used
64  * registers.
65  */
66 
67 void ffi_prep_args(char *stack, extended_cif *ecif)
68 {
69  unsigned int i;
70  void **p_argv;
71  ffi_type **p_arg;
72  char *reg_base = stack;
73  char *stack_base = stack + 20;
74  unsigned int stack_offset = 0;
75  unsigned int reg_mask = 0;
76 
77  p_argv = ecif->avalue;
78 
79  /* If cif->flags is struct then we know it's not passed in registers */
80  if(ecif->cif->flags == FFI_TYPE_STRUCT)
81  {
82  *(void**)reg_base = ecif->rvalue;
83  reg_mask |= 1;
84  }
85 
86  for(i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
87  i++, p_arg++)
88  {
89  size_t z = (*p_arg)->size;
90  int alignment = (*p_arg)->alignment;
91  int type = (*p_arg)->type;
92  char *addr = 0;
93 
94  if(z % 4 != 0)
95  z += (4 - z % 4);
96 
97  if(reg_mask != 0x1f)
98  {
99  if(pass_struct_on_stack(*p_arg))
100  {
101  addr = stack_base + stack_offset;
102  stack_offset += z;
103  }
104  else if(z == sizeof(int))
105  {
106  char index = 0;
107 
108  while((reg_mask >> index) & 1)
109  index++;
110 
111  addr = reg_base + (index * 4);
112  reg_mask |= (1 << index);
113  }
114  else if(z == 2 * sizeof(int))
115  {
116  if(!((reg_mask >> 1) & 1))
117  {
118  addr = reg_base + 4;
119  reg_mask |= (3 << 1);
120  }
121  else if(!((reg_mask >> 3) & 1))
122  {
123  addr = reg_base + 12;
124  reg_mask |= (3 << 3);
125  }
126  }
127  }
128 
129  if(!addr)
130  {
131  addr = stack_base + stack_offset;
132  stack_offset += z;
133  }
134 
135  if(type == FFI_TYPE_STRUCT && (*p_arg)->elements[1] == NULL)
136  type = (*p_arg)->elements[0]->type;
137 
138  switch(type)
139  {
140  case FFI_TYPE_UINT8:
141  *(unsigned int *)addr = (unsigned int)*(UINT8 *)(*p_argv);
142  break;
143  case FFI_TYPE_SINT8:
144  *(signed int *)addr = (signed int)*(SINT8 *)(*p_argv);
145  break;
146  case FFI_TYPE_UINT16:
147  *(unsigned int *)addr = (unsigned int)*(UINT16 *)(*p_argv);
148  break;
149  case FFI_TYPE_SINT16:
150  *(signed int *)addr = (signed int)*(SINT16 *)(*p_argv);
151  break;
152  default:
153  memcpy(addr, *p_argv, z);
154  }
155 
156  p_argv++;
157  }
158 
159 #ifdef DEBUG
160  /* Debugging */
161  for(i = 0; i < 5; i++)
162  {
163  if((reg_mask & (1 << i)) == 0)
164  printf("r%d: (unused)\n", 12 - i);
165  else
166  printf("r%d: 0x%08x\n", 12 - i, ((unsigned int*)reg_base)[i]);
167  }
168 
169  for(i = 0; i < stack_offset / 4; i++)
170  {
171  printf("sp+%d: 0x%08x\n", i*4, ((unsigned int*)stack_base)[i]);
172  }
173 #endif
174 }
175 
176 /* Perform machine dependent cif processing */
177 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
178 {
179  /* Round the stack up to a multiple of 8 bytes. This isn't needed
180  * everywhere, but it is on some platforms, and it doesn't harm
181  * anything when it isn't needed. */
182  cif->bytes = (cif->bytes + 7) & ~7;
183 
184  /* Flag to indicate that he return value is in fact a struct */
185  cif->rstruct_flag = 0;
186 
187  /* Set the return type flag */
188  switch(cif->rtype->type)
189  {
190  case FFI_TYPE_SINT8:
191  case FFI_TYPE_UINT8:
192  cif->flags = (unsigned)FFI_TYPE_UINT8;
193  break;
194  case FFI_TYPE_SINT16:
195  case FFI_TYPE_UINT16:
196  cif->flags = (unsigned)FFI_TYPE_UINT16;
197  break;
198  case FFI_TYPE_FLOAT:
199  case FFI_TYPE_SINT32:
200  case FFI_TYPE_UINT32:
201  case FFI_TYPE_POINTER:
202  cif->flags = (unsigned)FFI_TYPE_UINT32;
203  break;
204  case FFI_TYPE_DOUBLE:
205  case FFI_TYPE_SINT64:
206  case FFI_TYPE_UINT64:
207  cif->flags = (unsigned)FFI_TYPE_UINT64;
208  break;
209  case FFI_TYPE_STRUCT:
210  cif->rstruct_flag = 1;
211  if(!pass_struct_on_stack(cif->rtype))
212  {
213  if(cif->rtype->size <= 1)
214  cif->flags = (unsigned)FFI_TYPE_UINT8;
215  else if(cif->rtype->size <= 2)
216  cif->flags = (unsigned)FFI_TYPE_UINT16;
217  else if(cif->rtype->size <= 4)
218  cif->flags = (unsigned)FFI_TYPE_UINT32;
219  else if(cif->rtype->size <= 8)
220  cif->flags = (unsigned)FFI_TYPE_UINT64;
221  else
222  cif->flags = (unsigned)cif->rtype->type;
223  }
224  else
225  cif->flags = (unsigned)cif->rtype->type;
226  break;
227  default:
228  cif->flags = (unsigned)cif->rtype->type;
229  break;
230  }
231 
232  return FFI_OK;
233 }
234 
235 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
236 {
237  extended_cif ecif;
238 
239  unsigned int size = 0, i = 0;
240  ffi_type **p_arg;
241 
242  ecif.cif = cif;
243  ecif.avalue = avalue;
244 
245  for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++)
246  size += (*p_arg)->size + (4 - (*p_arg)->size % 4);
247 
248  /* If the return value is a struct and we don't have a return value
249  * address then we need to make one */
250 
251  /* If cif->flags is struct then it's not suitable for registers */
252  if((rvalue == NULL) && (cif->flags == FFI_TYPE_STRUCT))
253  ecif.rvalue = alloca(cif->rtype->size);
254  else
255  ecif.rvalue = rvalue;
256 
257  switch(cif->abi)
258  {
259  case FFI_SYSV:
260  ffi_call_SYSV(ffi_prep_args, &ecif, size, cif->flags,
261  ecif.rvalue, cif->rstruct_flag, fn);
262  break;
263  default:
264  FFI_ASSERT(0);
265  break;
266  }
267 }
268 
269 static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
270  void **avalue, ffi_cif *cif)
271 {
272  register unsigned int i, reg_mask = 0;
273  register void **p_argv;
274  register ffi_type **p_arg;
275  register char *reg_base = stack;
276  register char *stack_base = stack + 20;
277  register unsigned int stack_offset = 0;
278 
279 #ifdef DEBUG
280  /* Debugging */
281  for(i = 0; i < cif->nargs + 7; i++)
282  {
283  printf("sp+%d: 0x%08x\n", i*4, ((unsigned int*)stack)[i]);
284  }
285 #endif
286 
287  /* If cif->flags is struct then we know it's not passed in registers */
288  if(cif->flags == FFI_TYPE_STRUCT)
289  {
290  *rvalue = *(void **)reg_base;
291  reg_mask |= 1;
292  }
293 
294  p_argv = avalue;
295 
296  for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++)
297  {
298  size_t z = (*p_arg)->size;
299  int alignment = (*p_arg)->alignment;
300 
301  *p_argv = 0;
302 
303  if(z % 4 != 0)
304  z += (4 - z % 4);
305 
306  if(reg_mask != 0x1f)
307  {
308  if(pass_struct_on_stack(*p_arg))
309  {
310  *p_argv = (void*)stack_base + stack_offset;
311  stack_offset += z;
312  }
313  else if(z <= sizeof(int))
314  {
315  char index = 0;
316 
317  while((reg_mask >> index) & 1)
318  index++;
319 
320  *p_argv = (void*)reg_base + (index * 4);
321  reg_mask |= (1 << index);
322  }
323  else if(z == 2 * sizeof(int))
324  {
325  if(!((reg_mask >> 1) & 1))
326  {
327  *p_argv = (void*)reg_base + 4;
328  reg_mask |= (3 << 1);
329  }
330  else if(!((reg_mask >> 3) & 1))
331  {
332  *p_argv = (void*)reg_base + 12;
333  reg_mask |= (3 << 3);
334  }
335  }
336  }
337 
338  if(!*p_argv)
339  {
340  *p_argv = (void*)stack_base + stack_offset;
341  stack_offset += z;
342  }
343 
344  if((*p_arg)->type != FFI_TYPE_STRUCT ||
345  (*p_arg)->elements[1] == NULL)
346  {
347  if(alignment == 1)
348  **(unsigned int**)p_argv <<= 24;
349  else if(alignment == 2)
350  **(unsigned int**)p_argv <<= 16;
351  }
352 
353  p_argv++;
354  }
355 
356 #ifdef DEBUG
357  /* Debugging */
358  for(i = 0; i < cif->nargs; i++)
359  {
360  printf("sp+%d: 0x%08x\n", i*4, *(((unsigned int**)avalue)[i]));
361  }
362 #endif
363 }
364 
365 /* This function is jumped to by the trampoline */
366 
367 unsigned int ffi_closure_SYSV_inner(ffi_closure *closure, void **respp,
368  void *args)
369 {
370  ffi_cif *cif;
371  void **arg_area;
372  unsigned int i, size = 0;
373  ffi_type **p_arg;
374 
375  cif = closure->cif;
376 
377  for(i = 0, p_arg = cif->arg_types; i < cif->nargs; i++, p_arg++)
378  size += (*p_arg)->size + (4 - (*p_arg)->size % 4);
379 
380  arg_area = (void **)alloca(size);
381 
382  /* this call will initialize ARG_AREA, such that each element in that
383  * array points to the corresponding value on the stack; and if the
384  * function returns a structure, it will re-set RESP to point to the
385  * structure return address. */
386 
387  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
388 
389  (closure->fun)(cif, *respp, arg_area, closure->user_data);
390 
391  return cif->flags;
392 }
393 
394 ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
395  void (*fun)(ffi_cif*, void*, void**, void*), void *user_data,
396  void *codeloc)
397 {
398  if (cif->abi != FFI_SYSV)
399  return FFI_BAD_ABI;
400 
401  unsigned char *__tramp = (unsigned char*)(&closure->tramp[0]);
402  unsigned int __fun = (unsigned int)(&ffi_closure_SYSV);
403  unsigned int __ctx = (unsigned int)(codeloc);
404  unsigned int __rstruct_flag = (unsigned int)(cif->rstruct_flag);
405  unsigned int __inner = (unsigned int)(&ffi_closure_SYSV_inner);
406  *(unsigned int*) &__tramp[0] = 0xebcd1f00; /* pushm r8-r12 */
407  *(unsigned int*) &__tramp[4] = 0xfefc0010; /* ld.w r12, pc[16] */
408  *(unsigned int*) &__tramp[8] = 0xfefb0010; /* ld.w r11, pc[16] */
409  *(unsigned int*) &__tramp[12] = 0xfefa0010; /* ld.w r10, pc[16] */
410  *(unsigned int*) &__tramp[16] = 0xfeff0010; /* ld.w pc, pc[16] */
411  *(unsigned int*) &__tramp[20] = __ctx;
412  *(unsigned int*) &__tramp[24] = __rstruct_flag;
413  *(unsigned int*) &__tramp[28] = __inner;
414  *(unsigned int*) &__tramp[32] = __fun;
415  syscall(__NR_cacheflush, 0, (&__tramp[0]), 36);
416 
417  closure->cif = cif;
418  closure->user_data = user_data;
419  closure->fun = fun;
420 
421  return FFI_OK;
422 }
423 
void FFI_HIDDEN ffi_closure_SYSV_inner(ffi_closure *closure, struct call_context *context, void *stack)
Definition: ffi.c:964
#define FFI_ASSERT(x)
Definition: ffi_common.h:72
void ffi_call_SYSV(unsigned(*)(struct call_context *context, unsigned char *, extended_cif *), struct call_context *context, extended_cif *, size_t, void(*fn)(void))
ffi_cif * cif
Definition: ffi_common.h:88
unsigned int pass_struct_on_stack(ffi_type *type)
Definition: ffi.c:43
ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void(*fun)(ffi_cif *, void *, void **, void *), void *user_data, void *codeloc)
Definition: ffi.c:928
void * rvalue
Definition: ffi_common.h:89
static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue, ffi_cif *cif)
Definition: ffi.c:269
void ffi_call(ffi_cif *cif, void(*fn)(void), void *rvalue, void **avalue)
Definition: ffi.c:813
char * alloca()
int size
Definition: encoding.c:57
#define memcpy(d, s, n)
Definition: ffi_common.h:55
void ffi_prep_args(char *stack, extended_cif *ecif)
Definition: ffi.c:46
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
Definition: ffi.c:758
#define NULL
Definition: _sdbm.c:102
void ** avalue
Definition: ffi_common.h:90
void ffi_closure_SYSV(ffi_closure *)
Definition: ffi.c:420