Coverage Report

Created: 2026-02-14 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libffi/src/prep_cif.c
Line
Count
Source
1
/* -----------------------------------------------------------------------
2
   prep_cif.c - Copyright (c) 2011, 2012, 2021, 2025  Anthony Green
3
                Copyright (c) 1996, 1998, 2007  Red Hat, Inc.
4
                Copyright (c) 2022 Oracle and/or its affiliates.
5
6
   Permission is hereby granted, free of charge, to any person obtaining
7
   a copy of this software and associated documentation files (the
8
   ``Software''), to deal in the Software without restriction, including
9
   without limitation the rights to use, copy, modify, merge, publish,
10
   distribute, sublicense, and/or sell copies of the Software, and to
11
   permit persons to whom the Software is furnished to do so, subject to
12
   the following conditions:
13
14
   The above copyright notice and this permission notice shall be included
15
   in all copies or substantial portions of the Software.
16
17
   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
   DEALINGS IN THE SOFTWARE.
25
   ----------------------------------------------------------------------- */
26
27
#include <ffi.h>
28
#include <ffi_common.h>
29
#include <stdlib.h>
30
31
/* Round up to FFI_SIZEOF_ARG. */
32
33
#define STACK_ARG_SIZE(x) FFI_ALIGN(x, FFI_SIZEOF_ARG)
34
35
/* Perform machine independent initialization of aggregate type
36
   specifications. */
37
38
static ffi_status initialize_aggregate(ffi_type *arg, size_t *offsets)
39
0
{
40
0
  ffi_type **ptr;
41
42
0
  if (UNLIKELY(arg == NULL || arg->elements == NULL))
43
0
    return FFI_BAD_TYPEDEF;
44
45
0
  arg->size = 0;
46
0
  arg->alignment = 0;
47
48
0
  ptr = &(arg->elements[0]);
49
50
0
  if (UNLIKELY(ptr == 0))
51
0
    return FFI_BAD_TYPEDEF;
52
53
0
  while ((*ptr) != NULL)
54
0
    {
55
0
      if (UNLIKELY(((*ptr)->size == 0)
56
0
        && (initialize_aggregate((*ptr), NULL) != FFI_OK)))
57
0
  return FFI_BAD_TYPEDEF;
58
59
      /* Perform a sanity check on the argument type */
60
0
      FFI_ASSERT_VALID_TYPE(*ptr);
61
62
0
      arg->size = FFI_ALIGN(arg->size, (*ptr)->alignment);
63
0
      if (offsets)
64
0
  *offsets++ = arg->size;
65
0
      arg->size += (*ptr)->size;
66
67
0
      arg->alignment = (arg->alignment > (*ptr)->alignment) ?
68
0
  arg->alignment : (*ptr)->alignment;
69
70
0
      ptr++;
71
0
    }
72
73
  /* Structure size includes tail padding.  This is important for
74
     structures that fit in one register on ABIs like the PowerPC64
75
     Linux ABI that right justify small structs in a register.
76
     It's also needed for nested structure layout, for example
77
     struct A { long a; char b; }; struct B { struct A x; char y; };
78
     should find y at an offset of 2*sizeof(long) and result in a
79
     total size of 3*sizeof(long).  */
80
0
  arg->size = FFI_ALIGN (arg->size, arg->alignment);
81
82
  /* On some targets, the ABI defines that structures have an additional
83
     alignment beyond the "natural" one based on their elements.  */
84
#ifdef FFI_AGGREGATE_ALIGNMENT
85
  if (FFI_AGGREGATE_ALIGNMENT > arg->alignment)
86
    arg->alignment = FFI_AGGREGATE_ALIGNMENT;
87
#endif
88
89
0
  if (arg->size == 0)
90
0
    return FFI_BAD_TYPEDEF;
91
0
  else
92
0
    return FFI_OK;
93
0
}
94
95
#ifndef __CRIS__
96
/* The CRIS ABI specifies structure elements to have byte
97
   alignment only, so it completely overrides this functions,
98
   which assumes "natural" alignment and padding.  */
99
100
/* Perform machine independent ffi_cif preparation, then call
101
   machine dependent routine. */
102
103
/* For non variadic functions isvariadic should be 0 and
104
   nfixedargs==ntotalargs.
105
106
   For variadic calls, isvariadic should be 1 and nfixedargs
107
   and ntotalargs set as appropriate. nfixedargs must always be >=1 */
108
109
110
ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
111
           unsigned int isvariadic,
112
                             unsigned int nfixedargs,
113
                             unsigned int ntotalargs,
114
           ffi_type *rtype, ffi_type **atypes)
115
0
{
116
0
  unsigned bytes = 0;
117
0
  unsigned int i;
118
0
  ffi_type **ptr;
119
120
0
  FFI_ASSERT(cif != NULL);
121
0
  FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
122
0
  FFI_ASSERT(nfixedargs <= ntotalargs);
123
124
0
  if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
125
0
    return FFI_BAD_ABI;
126
127
0
  cif->abi = abi;
128
0
  cif->arg_types = atypes;
129
0
  cif->nargs = ntotalargs;
130
0
  cif->rtype = rtype;
131
132
0
  cif->flags = 0;
133
#if (defined(_M_ARM64) || defined(__aarch64__)) && defined(_WIN32)
134
  cif->is_variadic = isvariadic;
135
#endif
136
#if HAVE_LONG_DOUBLE_VARIANT
137
  ffi_prep_types (abi);
138
#endif
139
140
  /* Initialize the return type if necessary */
141
0
  if ((cif->rtype->size == 0)
142
0
      && (initialize_aggregate(cif->rtype, NULL) != FFI_OK))
143
0
    return FFI_BAD_TYPEDEF;
144
145
#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
146
  if (rtype->type == FFI_TYPE_COMPLEX)
147
    abort();
148
#endif
149
  /* Perform a sanity check on the return type */
150
0
  FFI_ASSERT_VALID_TYPE(cif->rtype);
151
152
  /* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
153
#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
154
  /* Make space for the return structure pointer */
155
  if (cif->rtype->type == FFI_TYPE_STRUCT
156
#ifdef TILE
157
      && (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
158
#endif
159
#ifdef XTENSA
160
      && (cif->rtype->size > 16)
161
#endif
162
     )
163
    bytes = STACK_ARG_SIZE(sizeof(void*));
164
#endif
165
166
0
  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
167
0
    {
168
169
      /* Initialize any uninitialized aggregate type definitions */
170
0
      if (((*ptr)->size == 0)
171
0
    && (initialize_aggregate((*ptr), NULL) != FFI_OK))
172
0
  return FFI_BAD_TYPEDEF;
173
174
#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
175
      if ((*ptr)->type == FFI_TYPE_COMPLEX)
176
  abort();
177
#endif
178
      /* Perform a sanity check on the argument type, do this
179
   check after the initialization.  */
180
0
      FFI_ASSERT_VALID_TYPE(*ptr);
181
182
#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
183
  {
184
    /* Add any padding if necessary */
185
    if (((*ptr)->alignment - 1) & bytes)
186
      bytes = (unsigned)FFI_ALIGN(bytes, (*ptr)->alignment);
187
188
#ifdef TILE
189
    if (bytes < 10 * FFI_SIZEOF_ARG &&
190
        bytes + STACK_ARG_SIZE((*ptr)->size) > 10 * FFI_SIZEOF_ARG)
191
      {
192
        /* An argument is never split between the 10 parameter
193
     registers and the stack.  */
194
        bytes = 10 * FFI_SIZEOF_ARG;
195
      }
196
#endif
197
#ifdef XTENSA
198
    if (bytes <= 6*4 && bytes + STACK_ARG_SIZE((*ptr)->size) > 6*4)
199
      bytes = 6*4;
200
#endif
201
202
    bytes += (unsigned int)STACK_ARG_SIZE((*ptr)->size);
203
  }
204
#endif
205
0
    }
206
207
0
  cif->bytes = bytes;
208
209
  /* Perform machine dependent cif processing */
210
#ifdef FFI_TARGET_SPECIFIC_VARIADIC
211
  if (isvariadic)
212
  return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs);
213
#endif
214
215
0
  return ffi_prep_cif_machdep(cif);
216
0
}
217
#endif /* not __CRIS__ */
218
219
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
220
           ffi_type *rtype, ffi_type **atypes)
221
0
{
222
0
  return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, atypes);
223
0
}
224
225
ffi_status ffi_prep_cif_var(ffi_cif *cif,
226
                            ffi_abi abi,
227
                            unsigned int nfixedargs,
228
                            unsigned int ntotalargs,
229
                            ffi_type *rtype,
230
                            ffi_type **atypes)
231
0
{
232
0
  ffi_status rc;
233
0
  size_t int_size = ffi_type_sint.size;
234
0
  unsigned int i;
235
236
0
  rc = ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
237
238
0
  if (rc != FFI_OK)
239
0
    return rc;
240
241
0
  for (i = nfixedargs; i < ntotalargs; i++)
242
0
    {
243
0
      ffi_type *arg_type = atypes[i];
244
0
      if (arg_type == &ffi_type_float
245
0
          || ((arg_type->type != FFI_TYPE_STRUCT
246
0
               && arg_type->type != FFI_TYPE_COMPLEX)
247
0
              && arg_type->size < int_size))
248
0
        return FFI_BAD_ARGTYPE;
249
0
    }
250
251
0
  return FFI_OK;
252
0
}
253
254
#if FFI_CLOSURES
255
256
ffi_status
257
ffi_prep_closure (ffi_closure* closure,
258
      ffi_cif* cif,
259
      void (*fun)(ffi_cif*,void*,void**,void*),
260
      void *user_data)
261
0
{
262
0
  return ffi_prep_closure_loc (closure, cif, fun, user_data, closure);
263
0
}
264
265
#endif
266
267
ffi_status
268
ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, size_t *offsets)
269
0
{
270
0
  if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
271
0
    return FFI_BAD_ABI;
272
0
  if (struct_type->type != FFI_TYPE_STRUCT)
273
0
    return FFI_BAD_TYPEDEF;
274
275
#if HAVE_LONG_DOUBLE_VARIANT
276
  ffi_prep_types (abi);
277
#endif
278
279
0
  return initialize_aggregate(struct_type, offsets);
280
0
}