diff options
Diffstat (limited to 'libffi/doc/libffi.texi')
-rw-r--r-- | libffi/doc/libffi.texi | 382 |
1 files changed, 333 insertions, 49 deletions
diff --git a/libffi/doc/libffi.texi b/libffi/doc/libffi.texi index b9887a8..7fd3625 100644 --- a/libffi/doc/libffi.texi +++ b/libffi/doc/libffi.texi @@ -1,7 +1,8 @@ \input texinfo @c -*-texinfo-*- @c %**start of header @setfilename libffi.info -@settitle libffi +@include version.texi +@settitle libffi: the portable foreign function interface library @setchapternewpage off @c %**end of header @@ -12,32 +13,43 @@ @syncodeindex pg cp @syncodeindex tp cp -@include version.texi - @copying -This manual is for Libffi, a portable foreign-function interface +This manual is for libffi, a portable foreign function interface library. -Copyright @copyright{} 2008, 2010, 2011 Red Hat, Inc. +Copyright @copyright{} 2008--2019, 2021 Anthony Green and Red Hat, Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -@quotation -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. A copy of the license is included in the -section entitled ``GNU General Public License''. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -@end quotation @end copying @dircategory Development @direntry -* libffi: (libffi). Portable foreign-function interface library. +* libffi: (libffi). Portable foreign function interface library. @end direntry @titlepage -@title Libffi +@title libffi: a foreign function interface library +@subtitle For Version @value{VERSION} of libffi +@author Anthony Green @page @vskip 0pt plus 1filll @insertcopying @@ -53,6 +65,7 @@ section entitled ``GNU General Public License''. @menu * Introduction:: What is libffi? * Using libffi:: How to use libffi. +* Memory Usage:: Where memory for closures comes from. * Missing Features:: Things libffi can't do. * Index:: Index. @end menu @@ -107,6 +120,7 @@ values passed between the two languages. * Multiple ABIs:: Different passing styles on one platform. * The Closure API:: Writing a generic function. * Closure Example:: A closure example. +* Thread Safety:: Thread safety. @end menu @@ -152,16 +166,21 @@ If the function being called is variadic (varargs) then @code{ffi_prep_cif_var} must be used instead of @code{ffi_prep_cif}. @findex ffi_prep_cif_var -@defun ffi_status ffi_prep_cif_var (ffi_cif *@var{cif}, ffi_abi var{abi}, unsigned int @var{nfixedargs}, unsigned int var{ntotalargs}, ffi_type *@var{rtype}, ffi_type **@var{argtypes}) +@defun ffi_status ffi_prep_cif_var (ffi_cif *@var{cif}, ffi_abi @var{abi}, unsigned int @var{nfixedargs}, unsigned int @var{ntotalargs}, ffi_type *@var{rtype}, ffi_type **@var{argtypes}) This initializes @var{cif} according to the given parameters for -a call to a variadic function. In general it's operation is the +a call to a variadic function. In general its operation is the same as for @code{ffi_prep_cif} except that: @var{nfixedargs} is the number of fixed arguments, prior to any variadic arguments. It must be greater than zero. @var{ntotalargs} the total number of arguments, including variadic -and fixed arguments. +and fixed arguments. @var{argtypes} must have this many elements. + +@code{ffi_prep_cif_var} will return @code{FFI_BAD_ARGTYPE} if any of +the variable argument types are @code{ffi_type_float} (promote to +@code{ffi_type_double} first), or any integer type small than an int +(promote to an int-sized type first). Note that, different cif's must be prepped for calls to the same function when different numbers of arguments are passed. @@ -172,6 +191,10 @@ Also note that a call to @code{ffi_prep_cif_var} with @end defun +Note that the resulting @code{ffi_cif} holds pointers to all the +@code{ffi_type} objects that were used during initialization. You +must ensure that these type objects have a lifetime at least as long +as that of the @code{ffi_cif}. To call a function using an initialized @code{ffi_cif}, use the @code{ffi_call} function: @@ -190,12 +213,29 @@ to ensure this. If @var{cif} declares that the function returns @code{void} (using @code{ffi_type_void}), then @var{rvalue} is ignored. +In most situations, @samp{libffi} will handle promotion according to +the ABI. However, for historical reasons, there is a special case +with return values that must be handled by your code. In particular, +for integral (not @code{struct}) types that are narrower than the +system register size, the return value will be widened by +@samp{libffi}. @samp{libffi} provides a type, @code{ffi_arg}, that +can be used as the return type. For example, if the CIF was defined +with a return type of @code{char}, @samp{libffi} will try to store a +full @code{ffi_arg} into the return value. + @var{avalues} is a vector of @code{void *} pointers that point to the memory locations holding the argument values for a call. If @var{cif} declares that the function has no arguments (i.e., @var{nargs} was 0), then @var{avalues} is ignored. Note that argument values may be modified by the callee (for instance, structs passed by value); the burden of copying pass-by-value arguments is placed on the caller. + +Note that while the return value must be register-sized, arguments +should exactly match their declared type. For example, if an argument +is a @code{short}, then the entry in @var{avalues} should point to an +object declared as @code{short}; but if the return type is +@code{short}, then @var{rvalue} should point to an object declared as +a larger type -- usually @code{ffi_arg}. @end defun @@ -215,26 +255,26 @@ int main() void *values[1]; char *s; ffi_arg rc; - - /* Initialize the argument info vectors */ + + /* Initialize the argument info vectors */ args[0] = &ffi_type_pointer; values[0] = &s; - + /* Initialize the cif */ - if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, + if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_sint, args) == FFI_OK) @{ s = "Hello World!"; ffi_call(&cif, puts, &rc, values); /* rc now holds the result of the call to puts */ - - /* values holds a pointer to the function's arg, so to - call puts() again all we need to do is change the + + /* values holds a pointer to the function's arg, so to + call puts() again all we need to do is change the value of s */ s = "This is cool!"; ffi_call(&cif, puts, &rc, values); @} - + return 0; @} @end example @@ -246,6 +286,8 @@ int main() @menu * Primitive Types:: Built-in types. * Structures:: Structure types. +* Size and Alignment:: Size and alignment of types. +* Arrays Unions Enums:: Arrays, unions, and enumerations. * Type Example:: Structure type example. * Complex:: Complex types. * Complex Type Example:: Complex type example. @@ -370,8 +412,7 @@ when passing to @code{ffi_prep_cif}. @node Structures @subsection Structures -Although @samp{libffi} has no special support for unions or -bit-fields, it is perfectly happy passing structures back and forth. +@samp{libffi} is perfectly happy passing structures back and forth. You must first describe the structure to @samp{libffi} by creating a new @code{ffi_type} object for it. @@ -391,9 +432,166 @@ For a structure, this should be set to @code{FFI_TYPE_STRUCT}. @item ffi_type **elements This is a @samp{NULL}-terminated array of pointers to @code{ffi_type} objects. There is one element per field of the struct. + +Note that @samp{libffi} has no special support for bit-fields. You +must manage these manually. @end table @end deftp +The @code{size} and @code{alignment} fields will be filled in by +@code{ffi_prep_cif} or @code{ffi_prep_cif_var}, as needed. + +@node Size and Alignment +@subsection Size and Alignment + +@code{libffi} will set the @code{size} and @code{alignment} fields of +an @code{ffi_type} object for you. It does so using its knowledge of +the ABI. + +You might expect that you can simply read these fields for a type that +has been laid out by @code{libffi}. However, there are some caveats. + +@itemize @bullet +@item +The size or alignment of some of the built-in types may vary depending +on the chosen ABI. + +@item +The size and alignment of a new structure type will not be set by +@code{libffi} until it has been passed to @code{ffi_prep_cif} or +@code{ffi_get_struct_offsets}. + +@item +A structure type cannot be shared across ABIs. Instead each ABI needs +its own copy of the structure type. +@end itemize + +So, before examining these fields, it is safest to pass the +@code{ffi_type} object to @code{ffi_prep_cif} or +@code{ffi_get_struct_offsets} first. This function will do all the +needed setup. + +@example +ffi_type *desired_type; +ffi_abi desired_abi; +@dots{} +ffi_cif cif; +if (ffi_prep_cif (&cif, desired_abi, 0, desired_type, NULL) == FFI_OK) + @{ + size_t size = desired_type->size; + unsigned short alignment = desired_type->alignment; + @} +@end example + +@code{libffi} also provides a way to get the offsets of the members of +a structure. + +@findex ffi_get_struct_offsets +@defun ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, size_t *offsets) +Compute the offset of each element of the given structure type. +@var{abi} is the ABI to use; this is needed because in some cases the +layout depends on the ABI. + +@var{offsets} is an out parameter. The caller is responsible for +providing enough space for all the results to be written -- one +element per element type in @var{struct_type}. If @var{offsets} is +@code{NULL}, then the type will be laid out but not otherwise +modified. This can be useful for accessing the type's size or layout, +as mentioned above. + +This function returns @code{FFI_OK} on success; @code{FFI_BAD_ABI} if +@var{abi} is invalid; or @code{FFI_BAD_TYPEDEF} if @var{struct_type} +is invalid in some way. Note that only @code{FFI_STRUCT} types are +valid here. +@end defun + +@node Arrays Unions Enums +@subsection Arrays, Unions, and Enumerations + +@subsubsection Arrays + +@samp{libffi} does not have direct support for arrays or unions. +However, they can be emulated using structures. + +To emulate an array, simply create an @code{ffi_type} using +@code{FFI_TYPE_STRUCT} with as many members as there are elements in +the array. + +@example +ffi_type array_type; +ffi_type **elements +int i; + +elements = malloc ((n + 1) * sizeof (ffi_type *)); +for (i = 0; i < n; ++i) + elements[i] = array_element_type; +elements[n] = NULL; + +array_type.size = array_type.alignment = 0; +array_type.type = FFI_TYPE_STRUCT; +array_type.elements = elements; +@end example + +Note that arrays cannot be passed or returned by value in C -- +structure types created like this should only be used to refer to +members of real @code{FFI_TYPE_STRUCT} objects. + +However, a phony array type like this will not cause any errors from +@samp{libffi} if you use it as an argument or return type. This may +be confusing. + +@subsubsection Unions + +A union can also be emulated using @code{FFI_TYPE_STRUCT}. In this +case, however, you must make sure that the size and alignment match +the real requirements of the union. + +One simple way to do this is to ensue that each element type is laid +out. Then, give the new structure type a single element; the size of +the largest element; and the largest alignment seen as well. + +This example uses the @code{ffi_prep_cif} trick to ensure that each +element type is laid out. + +@example +ffi_abi desired_abi; +ffi_type union_type; +ffi_type **union_elements; + +int i; +ffi_type element_types[2]; + +element_types[1] = NULL; + +union_type.size = union_type.alignment = 0; +union_type.type = FFI_TYPE_STRUCT; +union_type.elements = element_types; + +for (i = 0; union_elements[i]; ++i) + @{ + ffi_cif cif; + if (ffi_prep_cif (&cif, desired_abi, 0, union_elements[i], NULL) == FFI_OK) + @{ + if (union_elements[i]->size > union_type.size) + @{ + union_type.size = union_elements[i]; + size = union_elements[i]->size; + @} + if (union_elements[i]->alignment > union_type.alignment) + union_type.alignment = union_elements[i]->alignment; + @} + @} +@end example + +@subsubsection Enumerations + +@code{libffi} does not have any special support for C @code{enum}s. +Although any given @code{enum} is implemented using a specific +underlying integral type, exactly which type will be used cannot be +determined by @code{libffi} -- it may depend on the values in the +enumeration or on compiler flags such as @option{-fshort-enums}. +@xref{Structures unions enumerations and bit-fields implementation, , , gcc}, +for more information about how GCC handles enumerations. @node Type Example @subsection Type Example @@ -432,7 +630,7 @@ Here is the corresponding code to describe this struct to tm_type.size = tm_type.alignment = 0; tm_type.type = FFI_TYPE_STRUCT; tm_type.elements = &tm_type_elements; - + for (i = 0; i < 9; i++) tm_type_elements[i] = &ffi_type_sint; @@ -630,30 +828,47 @@ the closure function: @findex ffi_prep_closure_loc @defun ffi_status ffi_prep_closure_loc (ffi_closure *@var{closure}, ffi_cif *@var{cif}, void (*@var{fun}) (ffi_cif *@var{cif}, void *@var{ret}, void **@var{args}, void *@var{user_data}), void *@var{user_data}, void *@var{codeloc}) -Prepare a closure function. +Prepare a closure function. The arguments to +@code{ffi_prep_closure_loc} are: -@var{closure} is the address of a @code{ffi_closure} object; this is -the writable address returned by @code{ffi_closure_alloc}. +@table @var +@item closure +The address of a @code{ffi_closure} object; this is the writable +address returned by @code{ffi_closure_alloc}. + +@item cif +The @code{ffi_cif} describing the function parameters. Note that this +object, and the types to which it refers, must be kept alive until the +closure itself is freed. -@var{cif} is the @code{ffi_cif} describing the function parameters. +@item user_data +An arbitrary datum that is passed, uninterpreted, to your closure +function. -@var{user_data} is an arbitrary datum that is passed, uninterpreted, -to your closure function. +@item codeloc +The executable address returned by @code{ffi_closure_alloc}. -@var{codeloc} is the executable address returned by -@code{ffi_closure_alloc}. +@item fun +The function which will be called when the closure is invoked. It is +called with the arguments: -@var{fun} is the function which will be called when the closure is -invoked. It is called with the arguments: @table @var @item cif The @code{ffi_cif} passed to @code{ffi_prep_closure_loc}. @item ret A pointer to the memory used for the function's return value. -@var{fun} must fill this, unless the function is declared as returning -@code{void}. -@c FIXME: is this NULL for void-returning functions? + +If the function is declared as returning @code{void}, then this value +is garbage and should not be used. + +Otherwise, @var{fun} must fill the object to which this points, +following the same special promotion behavior as @code{ffi_call}. +That is, in most cases, @var{ret} points to an object of exactly the +size of the type specified when @var{cif} was constructed. However, +integral types narrower than the system register size are widened. In +these cases your program may assume that @var{ret} points to an +@code{ffi_arg} object. @item args A vector of pointers to memory holding the arguments to the function. @@ -662,10 +877,10 @@ A vector of pointers to memory holding the arguments to the function. The same @var{user_data} that was passed to @code{ffi_prep_closure_loc}. @end table +@end table @code{ffi_prep_closure_loc} will return @code{FFI_OK} if everything -went ok, and something else on error. -@c FIXME: what? +went ok, and one of the other @code{ffi_status} values on error. After calling @code{ffi_prep_closure_loc}, you can cast @var{codeloc} to the appropriate pointer-to-function type. @@ -678,7 +893,7 @@ writable and executable addresses. @node Closure Example @section Closure Example -A trivial example that creates a new @code{puts} by binding +A trivial example that creates a new @code{puts} by binding @code{fputs} with @code{stdout}. @example @@ -733,6 +948,77 @@ int main() @end example +@node Thread Safety +@section Thread Safety + +@code{libffi} is not completely thread-safe. However, many parts are, +and if you follow some simple rules, you can use it safely in a +multi-threaded program. + +@itemize @bullet +@item +@code{ffi_prep_cif} may modify the @code{ffi_type} objects passed to +it. It is best to ensure that only a single thread prepares a given +@code{ffi_cif} at a time. + +@item +On some platforms, @code{ffi_prep_cif} may modify the size and +alignment of some types, depending on the chosen ABI. On these +platforms, if you switch between ABIs, you must ensure that there is +only one call to @code{ffi_prep_cif} at a time. + +Currently the only affected platform is PowerPC and the only affected +type is @code{long double}. +@end itemize + +@node Memory Usage +@chapter Memory Usage + +Note that memory allocated by @code{ffi_closure_alloc} and freed by +@code{ffi_closure_free} does not come from the same general pool of +memory that @code{malloc} and @code{free} use. To accomodate security +settings, @samp{libffi} may aquire memory, for example, by mapping +temporary files into multiple places in the address space (once to +write out the closure, a second to execute it). The search follows +this list, using the first that works: + +@itemize @bullet + +@item +A anonymous mapping (i.e. not file-backed) + +@item +@code{memfd_create()}, if the kernel supports it. + +@item +A file created in the directory referenced by the environment variable +@code{LIBFFI_TMPDIR}. + +@item +Likewise for the environment variable @code{TMPDIR}. + +@item +A file created in @code{/tmp}. + +@item +A file created in @code{/var/tmp}. + +@item +A file created in @code{/dev/shm}. + +@item +A file created in the user's home directory (@code{$HOME}). + +@item +A file created in any directory listed in @code{/etc/mtab}. + +@item +A file created in any directory listed in @code{/proc/mounts}. + +@end itemize + +If security settings prohibit using any of these for closures, +@code{ffi_closure_alloc} will fail. @node Missing Features @chapter Missing Features @@ -749,13 +1035,11 @@ There is no support for bit fields in structures. @item The ``raw'' API is undocumented. -@c argument promotion? -@c unions? @c anything else? -@end itemize -Note that variadic support is very new and tested on a relatively -small number of platforms. +@item +The Go API is undocumented. +@end itemize @node Index @unnumbered Index |