1%////////////////////////////////////////////////////////////////////////////// 2% 3% Copyright (c) 2007-2019 Daniel Adler <dadler@uni-goettingen.de>, 4% Tassilo Philipp <tphilipp@potion-studios.com> 5% 6% Permission to use, copy, modify, and distribute this software for any 7% purpose with or without fee is hereby granted, provided that the above 8% copyright notice and this permission notice appear in all copies. 9% 10% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17% 18%////////////////////////////////////////////////////////////////////////////// 19 20\newpage 21 22\section{Overview} 23 24The \product{dyncall} library encapsulates architecture-, OS- and compiler-specific 25function call semantics in a virtual % 26% 27\casehtml{\Tg<span class="marker">}{\begin{center}}% 28\emph{bind argument parameters from left to right and then call} 29\casehtml{\Tg</span>}{\end{center}}% 30 % 31interface allowing programmers to call C functions 32in a completely dynamic manner. In other words, instead of calling a function 33directly, the \product{dyncall} library provides a mechanism to push the function parameters 34manually and to issue the call afterwards.\\ 35Since the idea behind this concept is similar to call dispatching mechanisms 36of virtual machines, the object that can be dynamically loaded with arguments, 37and then used to actually invoke the call, is called CallVM. It is possible to 38change the calling convention used by the CallVM at run-time. 39Due to the fact that nearly every platform comes with one or more distinct calling 40conventions, the \product{dyncall} library project intends to be a portable and open-source 41approach to the variety of compiler-specific binary interfaces, platform specific 42subtleties, and so on\ldots\\ 43\\ 44The core of the library consists of dynamic implementations of different 45calling conventions written in assembler. 46Although the library aims to be highly portable, some assembler code needs to 47be written for nearly every platform/compiler/OS combination. 48Unfortunately, there are architectures we just don't have at home or work. If 49you want to see \product{dyncall} running on such a platform, feel free to send 50in code and patches, or even to donate hardware you don't need anymore. 51Check the \textbf{supported platforms} section for an overview of the supported 52platforms and the different calling convention sections for details about the 53support. 54\\ 55\begin{comment} 56@@@ 57A typical binary library consists of symbolic names that map to variables and 58functions, the latter being pre-compiled for a 59specific calling convention and architecture. Given \product{dyncall} has been ported to 60that binary platform, it is possible to call such a function dynamically 61without writing glue code or prototypes or even knowing its C declaration - 62all that is needed is a pointer to it.\\ 63To avoid confusion, note that from the point of view of the library all 64parameters are handled the same way, even though the implementation might use 65other ways to pass parameters in order to suit specific calling conventions.\\ 66\end{comment} 67 68 69\subsection{Features} 70 71\begin{itemize} 72\item A portable and extendable function call interface for the C programming 73language. 74\item Ports to major platforms including Windows, Mac OS X, Linux, BSD derivates, iPhone and embedded devices and more, including lesser known and/or older platforms like Plan 9, Playstation Portable, Nintendo DS, etc.. 75\item Add-on language bindings to Python, R, Ruby, Go, Erlang, Java, Lua, sh, ... 76\item High-level state machine design using C to model calling convention 77parameter transfer. 78\item One assembly \emph{hybrid} call routine per calling convention. 79\item Formatted call, vararg function API. 80\item Comprehensive test suite. 81\end{itemize} 82 83\pagebreak 84 85\subsection{Showcase} 86 87\paragraph{Foreign function call in C} 88This section demonstrates how the foreign function call is issued without, and then 89with, the help of the \product{dyncall} library and scripting language 90bindings. 91 92\begin{lstlisting}[language=c,caption=Foreign function call in C] 93double call_as_sqrt(void* funptr, double x) 94{ 95 return ( ( double (*)(double) )funptr)(x); 96} 97\end{lstlisting} 98 99\paragraph{\product{Dyncall} C library example} 100 101The same operation can be broken down into atomic pieces 102(specify calling convention, binding arguments, invoking the call) 103using the \dc\ library. 104 105\begin{lstlisting}[language=c,caption=Dyncall C library example] 106#include <dyncall.h> 107double call_as_sqrt(void* funptr, double x) 108{ 109 double r; 110 DCCallVM* vm = dcNewCallVM(4096); 111 dcMode(vm, DC_CALL_C_DEFAULT); 112 dcReset(vm); 113 dcArgDouble(vm, x); 114 r = dcCallDouble(vm, funptr); 115 dcFree(vm); 116 return r; 117} 118\end{lstlisting} 119 120This is more code than a direct, hardcoded function call, however it's completely dynamic. 121Also, despite this coming with an overhead of more executed code per single function call, 122compared to function interface wrapper tools that generate per call glue-code less code is 123used overall, . % might want to test this claim against swig, etc. 124 125The following are examples from script bindings: 126 127\paragraph{Python example} 128 129\begin{lstlisting}[language=python,caption=Dyncall Python bindings example] 130import pydc 131def call_as_sqrt(funptr,x): 132 return pydc.call(funptr,"d)d", x) 133\end{lstlisting} 134 135 136\paragraph{R example} 137 138\begin{lstlisting}[language=R,caption=Dyncall R bindings example,escapeinside={TEX}{XET}] % escapeinside is a workaround for issues with '<' in lstlisting+tex4ht 139library(rdyncall) 140call.as.sqrt TEX\textlessXET- function(funptr,x) 141 .dyncall(funptr,"d)d", x) 142\end{lstlisting} 143 144 145\pagebreak 146 147\subsection{Supported platforms/architectures} 148 149The feature matrix below gives a brief overview of the currently supported 150platforms. Different colors are used, where a green cell indicates a supported 151platform, yellow a platform that might work (but is untested) and red a platform 152that is currently unsupported. Gray cells are combinations that don't exist 153at the time of writing, or that are not taken into account.\\ 154Light green cells mark complete feature support, as in dyncall and dyncallback. Dark green means basic support but lacking features (e.g. dyncall support, but not dyncallback). 155Please note that a green cell (even a light-green one) doesn't imply that all existing calling conventions/features/build tools are supported for that platform (but the most 156important). % @@@ The rightmost column gives a brief info about calling convention support or other notes. 157For detailed info about a platform's support consult the calling convention appendix. 158 159 160% colors used to signalize undefined, not used, supported, etc. states. 161\newcommand{\marknull}{\cellcolor{white}} 162\newcommand{\markcmpl}{\cellcolor{lightgreen}} 163\newcommand{\markimpl}{\cellcolor{darkgreen}} 164\newcommand{\marknimp}{\cellcolor{red}} 165\newcommand{\markunkn}{\cellcolor{yellow}} 166\newcommand{\marknotx}{\cellcolor{gray1}} 167 168\newcommand{\OSwinfam} {\ninety{Windows family} } 169\newcommand{\OSlinux} {\ninety{Linux} } 170\newcommand{\OSdarwin} {\ninety{macOS / iOS / Darwin}} 171\newcommand{\OSfreebsd}{\ninety{FreeBSD} } 172\newcommand{\OSnetbsd} {\ninety{NetBSD} } 173\newcommand{\OSopenbsd}{\ninety{OpenBSD} } 174\newcommand{\OSdflybsd}{\ninety{DragonFlyBSD} } 175\newcommand{\OSsunos} {\ninety{Solaris / SunOS} } 176\newcommand{\OSplanN} {\ninety{Plan 9 / 9front} } 177\newcommand{\OSbeos} {\ninety{Haiku / BeOS} } 178\newcommand{\OSminix} {\ninety{Minix} } 179\newcommand{\OSpsp} {\ninety{Playstation Portable}} 180\newcommand{\OSnds} {\ninety{Nintendo DS} } 181 182% also include hardfloat/softfloat @@@ 183\begin{table}[h] 184\begin{tabular}{r>{\rule{0pt}{2.5ex}\tiny}l*{12}{c!{\color{gray3}\vrule}}c>{\tiny}l} 185 & & \OSwinfam & \OSlinux & \OSdarwin & \OSfreebsd & \OSnetbsd & \OSopenbsd & \OSdflybsd & \OSsunos & \OSplanN & \OSbeos & \OSminix & \OSpsp & \OSnds \\%& \\ 186\arrayrulecolor{gray3}% 187\multirow{2}{*}{ARM} & EB & \marknotx & \markunkn & \marknotx & \markunkn & \markunkn & \markunkn & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \multirow{2}{*}{atpcs (arm \& thumb), eabi (arm \& thumb), armhf} \\ 188\hhline{*{1}{|~}*{14}{|-}}% ^- checked ^- find@@@ ^- checked ^- find@@@ ^- find@@@ ^- find@@@ ^- checked ^- checked ^- checked ^- new@@@ ^- checked ^- checked ^- checked 189 & EL & \markunkn & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \marknotx & \marknotx & \marknimp & \marknotx & \markunkn & \marknotx & \markcmpl \\%& \\ 190\hline% ^- find@@@ ^- dynOS ^- real ^- dynOS ^- dynOS ^- real/bbb ^- checked ^- checked ^- checked ^- new@@@ ^- new@@@ ^- checked ^- checked 191\multirow{2}{*}{ARM64} & EB & \marknotx & \markunkn & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \multirow{2}{*}{aapcs64, apple} \\ 192\hhline{*{1}{|~}*{14}{|-}}% ^- checked ^- find@@@ ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked 193 & EL & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \markunkn & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \\ 194\hline% ^- checked ^- find@@@ ^- checked ^- checked ^- find@@@ ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked 195\multirow{2}{*}{MIPS} & EB & \marknotx & \markcmpl & \marknotx & \markcmpl & \markunkn & \marknotx & \marknotx & \marknotx & \marknimp & \marknotx & \marknotx & \marknotx & \marknotx \\%& \multirow{2}{*}{o32 (hf \& sf), eabi (hf only)} \\ 196\hhline{*{1}{|~}*{14}{|-}}% ^- checked ^- dynOS ^- checked ^- checked ^- find@@@ ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked 197 & EL & \marknotx & \markunkn & \marknotx & \markcmpl & \markcmpl & \markunkn & \marknotx & \marknotx & \marknimp & \marknotx & \marknotx & \markcmpl & \marknotx \\%& \\ 198\hline% ^- checked ^- find@@@ ^- checked ^- checked ^- dynOS ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked 199\multirow{2}{*}{MIPS64} & EB & \marknotx & \markunkn & \marknotx & \markcmpl & \markunkn & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \multirow{2}{*}{n64 (hf only), n32 (hf only)} \\ 200\hhline{*{1}{|~}*{14}{|-}}% ^- checked ^- find@@@ ^- checked ^- checked ^- find@@@ ^- real/ERlt ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked 201 & EL & \marknotx & \markcmpl & \marknotx & \markcmpl & \markunkn & \markunkn & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \\ 202\hline% ^- checked ^- dynOS ^- checked ^- checked ^- find@@@ ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked 203\multirow{2}{*}{SuperH} & EB & \marknotx & \marknimp & \marknotx & \marknotx & \marknimp & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \\ 204\hhline{*{1}{|~}*{14}{|-}}% ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked 205 & EL & \marknotx & \marknimp & \marknotx & \marknotx & \marknimp & \marknimp & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \\ 206\hline% ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked 207\multirow{2}{*}{PowerPC} & EB & \marknotx & \markcmpl & \markcmpl & \markimpl & \markcmpl & \markunkn & \marknotx & \marknotx & \marknimp & \marknotx & \marknotx & \marknotx & \marknotx \\%& \multirow{2}{*}{apple, sysv}\\ 208\hhline{*{1}{|~}*{14}{|-}}% ^- checked ^- dynOS ^-dynOS ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked 209 & EL & \marknotx & \markunkn & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \\ 210\hline% ^- checked ^- find@@@ ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked 211\multirow{2}{*}{PowerPC64} & EB & \marknotx & \markcmpl & \markunkn & \markcmpl & \marknotx & \markunkn & \marknotx & \marknotx & \marknimp & \marknotx & \marknotx & \marknotx & \marknotx \\%& \multirow{2}{*}{elf} \\ 212\hhline{*{1}{|~}*{14}{|-}}% ^- checked ^- masanori@ ^- checked ^- dynOS ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked 213 & EL & \marknotx & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \\ 214\hline% ^- checked ^- masanori@ ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked ^- checked 215m68k & & \marknotx & \marknimp & \marknotx & \marknotx & \marknimp & \marknimp & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \\ 216\hline 217m88k & & \marknotx & \marknimp & \marknotx & \marknotx & \marknimp & \marknimp & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \\ 218\hline 219x86 & & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \marknotx & \marknotx \\%& cdecl, stdcall, fastcall (MS \& GNU), thiscall (MS \& GNU), plan9 \\ 220\hline 221x64 & & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \markcmpl & \marknimp & \markcmpl & \marknotx & \marknotx & \marknotx \\%& ms, sysv\\ 222\hline 223Itanium & & \marknimp & \marknimp & \marknotx & \marknimp & \marknimp & \marknimp & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \\ 224\hline 225SPARC & & \marknotx & \markcmpl & \marknotx & \marknotx & \markcmpl & \markcmpl & \marknotx & \markcmpl & \marknimp & \marknotx & \marknotx & \marknotx & \marknotx \\%& v7, v8\\ 226\hline 227SPARC64 & & \marknotx & \markcmpl & \marknotx & \markcmpl & \markcmpl & \markcmpl & \marknotx & \markimpl & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& v9 \\ 228\hline 229RISC-V & & \marknotx & \marknimp & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \\ 230\hline 231RISC-V 64 & & \marknotx & \marknimp & \marknotx & \marknimp & \marknotx & \marknimp & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\%& \\ 232 233\end{tabular} 234\caption{Supported platforms}% 235\end{table} 236 237% OLD support matrix 238%\begin{table}[h] 239%\begin{tabular}{r|*{3}{c!{\color{gray2}\vrule}}*{4}{c!{\color{gray2}\vrule}}*{11}{c!{\color{gray2}\vrule}}} 240% & \ninety{\bf Alpha} & \ninety{\bf ARM} & \ninety{\bf ARM64} & \multicolumn{2}{c!{\color{gray2}\vrule}}{\ninety{\bf MIPS}} & \multicolumn{2}{c!{\color{gray2}\vrule}}{\ninety{\bf MIPS64}} & \ninety{\bf SuperH} & \ninety{\bf PowerPC} & \ninety{\bf PowerPC64} & \ninety{\bf m68k} & \ninety{\bf m88k} & \ninety{\bf x86} & \ninety{\bf x64} & \ninety{\bf Itanium} & \ninety{\bf SPARC} & \ninety{\bf SPARC64} & \ninety{\bf RISC-V} \\ 241% & & & & \ninety{\tiny EB} & \ninety{\tiny EL} & \ninety{\tiny EB} & \ninety{\tiny EL} & & & & & & & & & & & \\ 242%\hline 243%{\bf Windows family} & \marknotx & \markunkn & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \markcmpl & \markcmpl & \marknimp & \marknotx & \marknotx & \marknotx \\ 244%{\bf Linux} & \marknimp & \markcmpl & \markcmpl & \markcmpl & \markunkn & \markunkn & \markcmpl & \marknimp & \markcmpl & \markcmpl & \marknimp & \marknimp & \markcmpl & \markcmpl & \marknimp & \markcmpl & \markcmpl & \marknimp \\ 245%{\bf macOS / iOS / Darwin} & \marknotx & \markcmpl & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \markcmpl & \markunkn & \marknotx & \marknotx & \markcmpl & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx \\ 246%{\bf FreeBSD} & \marknimp & \markcmpl & \markcmpl & \markunkn & \markunkn & \markunkn & \markunkn & \marknotx & \markimpl & \markcmpl & \marknotx & \marknotx & \markcmpl & \markcmpl & \marknimp & \marknotx & \markcmpl & \marknimp \\ 247%{\bf NetBSD} & \marknimp & \markcmpl & \marknotx & \markunkn & \markcmpl & \markunkn & \markunkn & \marknimp & \markimpl & \marknotx & \marknimp & \marknimp & \markcmpl & \markcmpl & \marknimp & \markcmpl & \markcmpl & \marknimp \\ 248%{\bf OpenBSD} & \marknimp & \markcmpl & \markunkn & \markunkn & \markunkn & \markcmpl & \markunkn & \marknimp & \markunkn & \marknotx & \marknimp & \marknimp & \markcmpl & \markcmpl & \marknimp & \markcmpl & \markcmpl & \marknotx \\ 249%{\bf DragonFlyBSD} & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \markcmpl & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx \\ 250%{\bf Solaris / SunOS} & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \markcmpl & \markcmpl & \marknotx & \markcmpl & \markimpl & \marknotx \\ 251%{\bf Plan 9 / 9front} & \marknimp & \marknimp & \marknotx & \marknimp & \marknimp & \marknotx & \marknotx & \marknotx & \marknimp & \marknotx & \marknotx & \marknotx & \markcmpl & \marknimp & \marknotx & \marknimp & \marknotx & \marknotx \\ 252%{\bf Haiku / BeOS} & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\ 253%{\bf Minix} & \marknotx & \markunkn & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\ 254%{\bf Playstation Portable} & \marknotx & \marknotx & \marknotx & \marknotx & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\ 255%{\bf Nintendo DS} & \marknotx & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\ 256%\end{tabular} 257%\caption{Supported platforms}% 258%\end{table} 259 260 261\subsection{Build Requirements} 262 263The library needs at least a c99 compiler with additional support for anonymous 264structs/unions (which were introduced officially in c11). Given that those are 265generally supported by pretty much all major c99 conforming compilers (as 266default extension), it should build fine with a c99 toolchain. 267 268