Skip to content
/ call.h Public

Single-header dynamic function invocation in C

Notifications You must be signed in to change notification settings

loglob/call.h

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 

Repository files navigation

call.h

Single-header dynamic function invocation in C

How to include

Simply clone this repo or copy call.h and include it.

This can be achieved with a make rule like this:

call.h:
	wget https://raw.githubusercontent.com/loglob/call.h/main/call.h

How to use

Prerequisites

The header only works for 64-bit x86_64 Linux/System-V executables.

I've only tested this with GCC and it uses a few GCC extensions (such as inline assembly), so it probably won't work for other compilers.

It also requires at least C11 for the _Generic keyword.

Initializing an argument list

After including call.h, use this declaration

argls s = {};

to initialize a new, empty argument list.

Adding arguments

After initializing an argument list, arguments can be appended to it by calling various functions and macros, beginning with the leftmost argument.

The simplest way of adding an argument is argls_add() which uses a generic to attempt to find the correct argument class automatically for most primitive types. Note that pointers should be cast to void* to use this macro.

If the argument class of an argument is known, one of argls_add_memory(), argls_add_memv(), argls_add_integer() or argls_add_sse() can be used.

Note that argls_add_memory() takes the address of an object and argls_add_memv() assumes that the object is already in the memory class and copies data from its own argument list.

All of these macros return a boolean, with false indicated error due to malloc failure when expansing the stack.

Passing non-primitives

All of these macros are only intended for primitive types and won't handle most structs or unions properly.

Unfortunately, there is no way to automatically detect the argument class(es) for those types, so in order to use them in a dynamic invocation, you will have to look into the Linux/System-V ABI documentation yourself and determine the correct argument classes and order.

Invoking a function

After settings up an argument list, the call() function is used to call a function address.

The return value of the function should be considered lost, although integer or sse class arguments have a good chance to still be in their respective registers, but this should absolutely not be relied upon.

After invokation, the argument list is not mutated, so it can be used in another call, or be further modified.

It is destroyed by using argls_end().

Preprocessor switches

By declaring DYNAMIC_REGS, the register arrays of the argument list struct are stored in dynamic memory instead of on the stack (the default behaviour).

This reduces the size of an argument list from 192 bytes down to 32.

About

Single-header dynamic function invocation in C

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages