/* See LICENSE file for copyright and license details. */
#ifndef LIBSYSCALLS_H
#define LIBSYSCALLS_H
#include "libsyscalls/internal-begin.h"
#include "libsyscalls/short-enums.h"
#include "libsyscalls/advanced.h"
/**
* Macro for enumerating libsyscall error numbers
*
* The numbers are stored in `libsyscalls_error`
*
* @param X:macro(NAME, STR) Macro that expands, will be given two arguments:
* the enum value name of the error (identifier),
* and the description of the error (string literal)
* @param D:code Macro that expands between each expansion of X
*
* The primary purpose of the existance of this macro
* is to ease implementation of the library; it will
* probably not disappear (no promises)
*/
#define LIBSYSCALLS_LIST_ERRORS(X, D)\
X(LIBSYSCALLS_E_OK, "Success") D\
X(LIBSYSCALLS_E_OSNOSUP, "Operating system not supported") D\
X(LIBSYSCALLS_E_ARCHNOSUP, "Architecture not supported for selected operating system") D\
X(LIBSYSCALLS_E_NOSUCHSYSCALL, "No such system call") D\
X(LIBSYSCALLS_E_NOERRORS, "There is no error listing for selected operating system") D\
X(LIBSYSCALLS_E_NOSIGNALS, "There is no signal listing for selected operating system") D\
X(LIBSYSCALLS_E_NOMEM, "Failed to allocate required memory") D\
X(LIBSYSCALLS_E_INVAL, "Invalid arguments passed to function") D\
X(LIBSYSCALLS_E_NOSUCHTYPE, "Type does not exist on the selected operating system or architecture") D\
X(LIBSYSCALLS_E_ISSTRUCT, "Type is a structure or union") D\
X(LIBSYSCALLS_E_ISNOTSTRUCT, "Type is not a structure or union")
/**
* libsyscall error numbers
*/
enum libsyscalls_error {
LIBSYSCALLS_LIST_ERRORS(LIBSYSCALLS_LIST_ERRORS_X_, LIBSYSCALLS_COMMA_)
};
/**
* Operating systems
*/
enum libsyscalls_os {
LIBSYSCALLS_OS_LINUX
};
/**
* Architectures
*/
enum libsyscalls_arch {
LIBSYSCALLS_ARCH_ALPHA_LE,
LIBSYSCALLS_ARCH_ALPHA_BE,
LIBSYSCALLS_ARCH_AMD64,
LIBSYSCALLS_ARCH_AMD64_X32, /* 32-bit ABI on 64-bit ISA */
LIBSYSCALLS_ARCH_ARM_OABI_LE,
LIBSYSCALLS_ARCH_ARM_OABI_BE,
LIBSYSCALLS_ARCH_ARM_EABI_LE,
LIBSYSCALLS_ARCH_ARM_EABI_BE,
LIBSYSCALLS_ARCH_IA64_LE, /* 64-bit pointers */
LIBSYSCALLS_ARCH_IA64_BE, /* 64-bit pointers */
LIBSYSCALLS_ARCH_IA64_P32_LE, /* 32-bit pointers */
LIBSYSCALLS_ARCH_IA64_P32_BE, /* 32-bit pointers */
LIBSYSCALLS_ARCH_M68K,
LIBSYSCALLS_ARCH_MICROBLAZE_32_LE,
LIBSYSCALLS_ARCH_MICROBLAZE_32_BE,
LIBSYSCALLS_ARCH_MICROBLAZE_64_LE,
LIBSYSCALLS_ARCH_MICROBLAZE_64_BE,
LIBSYSCALLS_ARCH_MIPS_O32_LE,
LIBSYSCALLS_ARCH_MIPS_O32_BE,
LIBSYSCALLS_ARCH_MIPS_N32_LE, /* 32-bit ABI on 64-bit ISA */
LIBSYSCALLS_ARCH_MIPS_N32_BE, /* 32-bit ABI on 64-bit ISA */
LIBSYSCALLS_ARCH_MIPS_N64_LE,
LIBSYSCALLS_ARCH_MIPS_N64_BE,
LIBSYSCALLS_ARCH_PARISC_32,
LIBSYSCALLS_ARCH_PARISC_64,
LIBSYSCALLS_ARCH_POWERPC_32_LE,
LIBSYSCALLS_ARCH_POWERPC_32_BE,
LIBSYSCALLS_ARCH_POWERPC_64_LE,
LIBSYSCALLS_ARCH_POWERPC_64_BE,
LIBSYSCALLS_ARCH_POWERPC_NOSPU_LE,
LIBSYSCALLS_ARCH_POWERPC_NOSPU_BE,
LIBSYSCALLS_ARCH_POWERPC_SPU_LE,
LIBSYSCALLS_ARCH_POWERPC_SPU_BE,
LIBSYSCALLS_ARCH_S390_32,
LIBSYSCALLS_ARCH_S390_64,
LIBSYSCALLS_ARCH_SH_LE, /* does not cover SH-5 */
LIBSYSCALLS_ARCH_SH_BE, /* does not cover SH-5 */
LIBSYSCALLS_ARCH_SPARC_32,
LIBSYSCALLS_ARCH_SPARC_64_LE,
LIBSYSCALLS_ARCH_SPARC_64_BE,
LIBSYSCALLS_ARCH_I386,
LIBSYSCALLS_ARCH_XTENSA_LE,
LIBSYSCALLS_ARCH_XTENSA_BE
};
/**
* Data types
*
* Be aware that some values in this enumeration may have
* multiple names, especially structs and unions: up to
* one name per combination of operating system and
* architecture. Each value may have very different
* meaning per name. This may be done because the number
* of available values is limited. Also note that functions
* may return values that do not have a name at all, these
* are anonymous structs and unions whose definitions also
* depend on the operating system and architecture.
*/
enum libsyscalls_datatype {
/* Type renaming, these macros will be undefined later */
#define LIBSYSCALLS_TYPE_CHAR_ARRAY LIBSYSCALLS_TYPE_BUFFER
#define LIBSYSCALLS_TYPE_CHAR_ARRAY_UNKNOWN_FILL LIBSYSCALLS_TYPE_BUFFER_UNKNOWN_FILL
/* You can use these macros classify and convert data types */
#define LIBSYSCALLS_TYPEBITSMASK 0xF000
#define LIBSYSCALLS_TYPEBITS_SCALAR 0x0000 /* predefined total width, even if aggregate */
#define LIBSYSCALLS_TYPEBITS_ARRAY 0x1000 /* count is stored in next parameter, and is
* updated with fill or returned if no outputable
* to the next parameter */
#define LIBSYSCALLS_TYPEBITS_ARRAY_UNKNOWN_FILL 0x2000 /* count is stored in next parameter, fill is
* in no way returned, this chould either be
* because the array is always (unless an error
* is returned) entirely filled or because the
* end is inferred from the contents (e.g. null
* byte termination) */
#define LIBSYSCALLS_LIST_SPECIAL_TYPES(X, SUFFIX, D, FIRST)\
/* the type used in the system call has not yet be
* added recorded in the library */\
X(LIBSYSCALLS_TYPE_UNKNOWN ## SUFFIX, FIRST, "(unknown type)") D\
/* the type depends on the system call input or output */\
X(LIBSYSCALLS_TYPE_DYNAMIC ## SUFFIX,, "(undetermined type)") D\
/* the system call should never returned to the calling
* process (return to tracer is usually expected) */\
X(LIBSYSCALLS_TYPE_NO_RETURN ## SUFFIX,, "no_return") D\
/* either used as return type, to skip a register in the
* parameters (do not dismiss this, on some architectures
* a system call may need padding with dummy arguments to
* align latter register pairs; an application printing
* the system call must choose between omitting, printing
* the argument, or indicating that there is a dummy
* parameter (of course the latter two can be combined)),
* or to add padding (or reserved space for future
* expansion) to a struct */\
X(LIBSYSCALLS_TYPE_VOID ## SUFFIX,, "void")
#define LIBSYSCALLS_LIST_SPLIT_PRIMITIVES(X, SUFFIX, D, FIRST)\
X(LIBSYSCALLS_TYPE_UINT64_HIGH_32 ## SUFFIX, FIRST, "uint64_t {. << 32}") D\
X(LIBSYSCALLS_TYPE_UINT64_LOW_32 ## SUFFIX,, "uint64_t {. & 0xFFFFFFFF}") D\
X(LIBSYSCALLS_TYPE_UINT64_FRONT_32 ## SUFFIX,, "uint64_t {((uint32_t *)&.)[0]}") D\
X(LIBSYSCALLS_TYPE_UINT64_BACK_32 ## SUFFIX,, "uint64_t {((uint32_t *)&.)[1]}") D\
X(LIBSYSCALLS_TYPE_INT64_HIGH_32 ## SUFFIX,, "int64_t {. << 32}") D\
X(LIBSYSCALLS_TYPE_INT64_LOW_32 ## SUFFIX,, "int64_t {. & 0xFFFFFFFF}") D\
X(LIBSYSCALLS_TYPE_INT64_FRONT_32 ## SUFFIX,, "int64_t {((uint32_t *)&.)[0]}") D\
X(LIBSYSCALLS_TYPE_INT64_BACK_32 ## SUFFIX,, "int64_t {((uint32_t *)&.)[1]}")
#define LIBSYSCALLS_LIST_COMPOSITE_PRIMITIVES(X, SUFFIX, D, FIRST)\
X(LIBSYSCALLS_TYPE_STRING ## SUFFIX, FIRST, "const char *") D\
X(LIBSYSCALLS_TYPE_STRINGS_THEN_NULL ## SUFFIX,, "const char **")
#define LIBSYSCALLS_LIST_UNANNOTATED_NUMERICALS(X, SUFFIX, D, FIRST)\
X(LIBSYSCALLS_TYPE_MEMORY_ADDRESS ## SUFFIX, FIRST, "void *") D\
X(LIBSYSCALLS_TYPE_CHAR ## SUFFIX,, "char") D\
X(LIBSYSCALLS_TYPE_SCHAR ## SUFFIX,, "signed char") D\
X(LIBSYSCALLS_TYPE_UCHAR ## SUFFIX,, "unsigned char") D\
X(LIBSYSCALLS_TYPE_SHORT ## SUFFIX,, "short int") D\
X(LIBSYSCALLS_TYPE_USHORT ## SUFFIX,, "unsigned short int") D\
X(LIBSYSCALLS_TYPE_INT ## SUFFIX,, "int") D\
X(LIBSYSCALLS_TYPE_UINT ## SUFFIX,, "unsigned int") D\
X(LIBSYSCALLS_TYPE_LONG ## SUFFIX,, "long int") D\
X(LIBSYSCALLS_TYPE_ULONG ## SUFFIX,, "unsigned long int") D\
X(LIBSYSCALLS_TYPE_LLONG ## SUFFIX,, "long long int") D\
X(LIBSYSCALLS_TYPE_ULLONG ## SUFFIX,, "unsigned long long int") D\
X(LIBSYSCALLS_TYPE_SSIZE ## SUFFIX,, "ssize_t") D\
X(LIBSYSCALLS_TYPE_SIZE ## SUFFIX,, "size_t") D\
X(LIBSYSCALLS_TYPE_PTRDIFF ## SUFFIX,, "ptrdiff_t") D\
X(LIBSYSCALLS_TYPE_UPTRDIFF ## SUFFIX,, "uptrdiff_t") D\
X(LIBSYSCALLS_TYPE_INTPTR ## SUFFIX,, "intptr_t") D\
X(LIBSYSCALLS_TYPE_UINTPTR ## SUFFIX,, "uintptr_t") D\
X(LIBSYSCALLS_TYPE_INT8 ## SUFFIX,, "int8_t") D\
X(LIBSYSCALLS_TYPE_UINT8 ## SUFFIX,, "uint8_t") D\
X(LIBSYSCALLS_TYPE_INT16 ## SUFFIX,, "int16_t") D\
X(LIBSYSCALLS_TYPE_UINT16 ## SUFFIX,, "uint16_t") D\
X(LIBSYSCALLS_TYPE_INT32 ## SUFFIX,, "int32_t") D\
X(LIBSYSCALLS_TYPE_UINT32 ## SUFFIX,, "uint32_t") D\
X(LIBSYSCALLS_TYPE_INT64 ## SUFFIX,, "int64_t") D\
X(LIBSYSCALLS_TYPE_UINT64 ## SUFFIX,, "uint64_t")
#define LIBSYSCALLS_LIST_ANNOTATED_NUMERICALS(X, SUFFIX, D, FIRST)\
X(LIBSYSCALLS_TYPE_INT_SIGNAL ## SUFFIX, FIRST, "int") D /* OS signal */\
X(LIBSYSCALLS_TYPE_INT_FD ## SUFFIX,, "int") D /* file descriptor */ \
X(LIBSYSCALLS_TYPE_INT_ATFD ## SUFFIX,, "int") D /* file descriptor or current working directory */ \
X(LIBSYSCALLS_TYPE_LONG_FD ## SUFFIX,, "long int") D\
X(LIBSYSCALLS_TYPE_LONG_ATFD ## SUFFIX,, "long int")
#define LIBSYSCALLS_LIST_STRUCTS_AND_UNIONS(X, SUFFIX, D, FIRST)\
X(LIBSYSCALLS_TYPE_STRUCT_AIO_SIGSET ## SUFFIX, FIRST, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_COMPAT_AIO_SIGSET ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_CACHESTAT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_CACHESTAT_RANGE ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_CLONE_ARGS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_EPOLL_EVENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OABI_EPOLL_EVENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_FILE_HANDLE ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_FUTEX_WAITV ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_IOB ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_IOVEC ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_IO_EVENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_IO_URING_PARAMS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_ITIMERVAL ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_ITIMERSPEC ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_ITIMERSPEC64 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_KEXEC_SEGMENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_COMPAT_KEXEC_SEGMENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_LANDLOCK_RULESET_ATTR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT64 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MMAP_ARG_STRUCT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MMSGHDR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MOUNT_ATTR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MQ_ATTR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MSGBUF ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MSGHDR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MSQID_DS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_NEW_UTSNAME ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLDOLD_UTSNAME ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_ITIMERSPEC32 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_ITIMERVAL ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_LINUX_DIRENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_SIGACTION ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_STAT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMESPEC32 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEVAL ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEVAL32 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEX32 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_UTIMBUF32 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_UTSNAME ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OPEN_HOW ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_PERF_EVENT_ATTR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_POLLFD ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_RLIMIT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_RLIMIT64 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_COMPAT_RLIMIT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_ROBUST_LIST_HEAD ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_RSEQ ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_RUSAGE ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SCHED_ATTR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SCHED_PARAM ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SEL_ARG_STRUCT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SEMBUF ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SEMID_DS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SHMID_DS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SIGACTION ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SIGALTSTACK ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SIGEVENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SIGINFO ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SOCKADDR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_STAT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_STAT64 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_STATFS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_STATFS64 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_STATX ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SYSINFO ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TIMESPEC ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TIMESPEC64 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TIMEVAL ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TIMEX ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TIMEZONE ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TMS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_USTAT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_UTIMBUF ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_UNION_BPF_ATTR ## SUFFIX,, "union")
#define LIBSYSCALLS_LIST_FIXED_ARRAYS(X, SUFFIX, D, FIRST)\
X(LIBSYSCALLS_TYPE_2_INTS ## SUFFIX, FIRST, "int[2]") D\
X(LIBSYSCALLS_TYPE_2_INTS_FD ## SUFFIX,, "int[2]") D\
X(LIBSYSCALLS_TYPE_2_UINT32S ## SUFFIX,, "uint32[2]") D\
X(LIBSYSCALLS_TYPE_FD_SET ## SUFFIX,, "unsigned long[]") /* size depends on OS, (1024/CHAR_BIT/sizeof(long)) in Linux */ D\
X(LIBSYSCALLS_TYPE_BUFFER_9 ## SUFFIX,, "char[9]") D\
X(LIBSYSCALLS_TYPE_BUFFER_65 ## SUFFIX,, "char[65]")
/* these don't have any suffix */
LIBSYSCALLS_MAKE_SPECIAL_TYPES_(),
LIBSYSCALLS_MAKE_SPLIT_PRIMITIVES_(),
LIBSYSCALLS_MAKE_COMPOSITE_PRIMITIVES_(),
LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_(),
LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(),
LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(),
/* the following are always pointers if used as a parameter */
/* size in next parameter (or the previous parameter if there is no next parameter),
* updated with fill if possible, otherwise returned (these use the suffix _ARRAY) */
LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_(_ARRAY),
LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(_ARRAY),
LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(_ARRAY),
/* size in next parameter (or the previous parameter if there is no next parameter),
* fill is in no way returned (these use the suffix _ARRAY_UNKNOWN_FILL) */
LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_(_ARRAY_UNKNOWN_FILL),
LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(_ARRAY_UNKNOWN_FILL),
LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(_ARRAY_UNKNOWN_FILL),
/* these don't have any suffix */
LIBSYSCALLS_MAKE_FIXED_ARRAYS_()
#undef LIBSYSCALLS_TYPE_CHAR_ARRAY
#undef LIBSYSCALLS_TYPE_CHAR_ARRAY_UNKNOWN_FILL
};
/**
* Broad classification on system calls
*/
enum libsyscalls_syscall_category {
/**
* The library knows about the system calls but
* has not yet implemented detailed information
* about the system call
*/
LIBSYSCALLS_CAT_SUPPORT_PENDING,
/**
* The system call has a name but is not implemented
* in the kernel, and thus does not have an ABI either
*
* Be aware that this information may be outdated
* and that `LIBSYSCALLS_CAT_SUPPORT_PENDING` might
* actually be more appropriate
*
* This value is not used for system calls that have
* be removed, those are still described as if still
* implemented by the kernel
*/
LIBSYSCALLS_CAT_NOT_IMPLEMENTED,
LIBSYSCALLS_CAT_NETWORK_ENABLED_IPC, /**< See enum libsyscalls_network_enabled_ipc_syscall_subcategory */
LIBSYSCALLS_CAT_IPC, /**< See enum libsyscalls_ipc_syscall_subcategory */
LIBSYSCALLS_CAT_FILESYSTEM, /**< See enum libsyscalls_filesystem_syscall_subcategory */
LIBSYSCALLS_CAT_FILE_DESCRIPTORS, /**< See enum libsyscalls_file_descriptors_syscall_subcategory */
LIBSYSCALLS_CAT_PROCESSES, /**< See enum libsyscalls_processes_syscall_subcategory */
LIBSYSCALLS_CAT_LOGGING, /**< See enum libsyscalls_logging_syscall_subcategory */
LIBSYSCALLS_CAT_TIME, /**< See enum libsyscalls_time_syscall_subcategory */
LIBSYSCALLS_CAT_SIGNALS, /**< See enum libsyscalls_singals_syscall_subcategory */
LIBSYSCALLS_CAT_MEMORY, /**< See enum libsyscalls_memory_syscall_subcategory */
LIBSYSCALLS_CAT_SYSTEM, /**< See enum libsyscalls_system_syscall_subcategory */
LIBSYSCALLS_CAT_SCHEDULING /**< See enum libsyscalls_scheduling_syscall_subcategory */
};
/**
* Interprocess communication system calls that may
* either communicate other the a network or locally
* on the machine
*
* Generally these do not affect the filesystem, the only exception
* is LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_BIND may create index
* nodes and LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_CONNECT may
* access the index nodes
*
* May system calls used for this class of communication
* objects used LIBSYSCALLS_CAT_FILE_DESCRIPTORS system calls
*/
enum libsyscalls_network_enabled_ipc_syscall_subcategory {
/**
* System calls that create a non-persistent
* communication object (such as a file descriptor)
* for this category of interprocess communication;
* meaning a file descriptor or similar object
* that causes the shared resource to be deallocated
* once all instances of the object has been released
*
* socket(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_CREATE,
/**
* System calls that accept incoming connections and
* create a new communication object, or rejects them
*
* accept(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_ACCEPT,
/**
* System calls that enable a communication object to
* use LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_ACCEPT
* system calls
*
* listen(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_LISTEN,
/**
* System calls that assigns a communication object
* to an local address, this can be a filesystem path
* or a network address, or a local identifier; this
* system calls gives the communication an address,
* and may create an index node on the file system
*
* bind(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_BIND,
/**
* System calls that attaches a communication object
* to an local address, this can be a filesystem path
* or a network address, or a local identifier; this
* system calls tells the kernel which other communication
* object the object shall communicate with, it does
* not give explicitly the communication object an
* address, however the kernel may give it one if one
* has not already be assigned
*
* connect(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_CONNECT,
/**
* System calls that inspect details about a
* communication object
*
* getsockname(2), getpeername(2), and getsockopt(2)
* are examples of system calls in this category
*/
LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_STAT
};
/**
* Interprocess communication system calls that always
* local to the machine or a networked filesystem
*/
enum libsyscalls_ipc_syscall_subcategory {
/**
* System calls that create a non-persistent
* communication object (such as a file descriptor)
* for this category of interprocess communication;
* meaning a file descriptor or similar object
* that causes the shared resource to be deallocated
* once all instances of the object has been released
*
* pipe(2) and socketpair(2) are examples of system
* calls in this category
*/
LIBSYSCALLS_IPC_SUBCAT_CREATE,
/**
* System calls that lock, unlock or inspects a lock
* on a file, for locks that are strictly advisory
*
* Note this information can be out of date and the
* system call may deal with mandatory file locks,
* for example since Linux 5.5, flock(2) has mandatory
* on some network file systems; the library does not
* take into consideration which version of the kernel
* is used, but assumes the latest version (of course
* the library may be out of date in regard to this
* information even if it is build to the latest kernel)
*/
LIBSYSCALLS_IPC_SUBCAT_ADVISORY_FILE_LOCK,
/**
* System calls that lock, unlock or inspects a lock
* on a file, for locks that are strictly mandatory
*
* Note this information can be out of date and the
* system call may deal with advisory file locks; the
* library does not take into consideration which
* version of the kernel is used, but assumes the latest
* version (of course the library may be out of date in
* regard to this information even if it is build to the
* latest kernel)
*/
LIBSYSCALLS_IPC_SUBCAT_MANDATORY_FILE_LOCK,
/**
* System calls that lock, unlock or inspects a lock
* on a file, for locks that may be either advisory
* or mandatory
*
* flock(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_IPC_SUBCAT_FILE_LOCK,
/**
* System calls that create or deletes communication
* objects, or inspects or changes details about such
* objects
*
* Some system calls use LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CREATE
* instead
*
* shmget(2), shmctl(2), mq_open(2), mq_unlink(2),
* mq_notify(2), and mq_getsetattr(2) are examples of
* system calls in this category
*/
LIBSYSCALLS_IPC_SUBCAT_CONTROL,
/**
* System calls that attach to an existing IPC object
*
* shmat(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_IPC_SUBCAT_ATTACH,
/**
* System calls that detach from an IPC object
*
* shmdt(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_IPC_SUBCAT_DETACH,
/**
* Communication system calls that do not have a timeout
*/
LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE,
/**
* Communication system calls that may have a relative
* or absolute timeout
*/
LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE_WITH_TIMEOUT,
/**
* Communication system calls that may have a relative timeout
*/
LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE_WITH_RELATIVE_TIMEOUT,
/**
* Communication system calls that may have an absolute timeout
*/
LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE_WITH_ABSOLUTE_TIMEOUT
};
/**
* System calls that operate on the filesystem or can either
* operate on a filesystem or a file descriptor that does
* not involve the filesystem but is usually used with a
* filesystem; this category also include system calls that
* effect such systems but does not itself touch the filesystem
* but rather the process
*
* System calls in this category may have timeouts that may
* use relative or absolute time
*/
enum libsyscalls_filesystem_syscall_subcategory {
/**
* System calls that retrieve the metadata of file
*
* stat(2) and fstatat(2) are examples of system calls
* in this category; fstat(2) however is not
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_STAT,
/**
* System calls that motifies the metadata of file
*
* chmod(2) and fchmodat(2) are examples of system calls
* in this category; fchmod(2) however is not
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_MODIFY,
/**
* System calls that commit changes to one or more files
* to the filesystem or mmap(2)ed anonymous memory
*
* sync(2), fsync(2), and msync(2) are examples of system
* calls in this category
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_SYNC,
/**
* System calls the create named index nodes (links)
* on a filesystem
*
* Note that LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_BIND
* system calls may also create links
*
* linkat(2), link(2), symlink(2), mknod(2), and mkdir(2)
* are examples of system calls in this category
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK,
/**
* System calls the remove the path to an index node
* (removes a link) on a filesystem
*
* unlink(2) and rmdir(2) are examples of system calls
* in this category
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_UNLINK,
/**
* System calls that can operate both as
* LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK and
* LIBSYSCALLS_FILESYSTEM_SUBCAT_UNLINK system calls,
* either one at a time or both at the same them
*
* rename(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK_OR_UNLINK,
/**
* System calls that inspects or changes (or both
* at the same time) the process's or thread's
* umask, which affects the permissions that shall
* be eliminated when an index node or IPC object
* is created
*
* umask(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_UMASK,
/**
* System calles that in some way operate on
* mountpoints
*
* Note that some system calls in the category takes
* file descriptors as input or outputs
*
* mount(2), umount(2), and fsopen(2) are examples
* of system calls in this category
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_MOUNTPOINT,
/**
* System calls that retrieve the information about
* a mounted filesystem
*
* statfs(2) and the hypothetical fstatfsat(2) are
* examples of system calls in this category;
* fstatfs(2) however is not
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_STATFS,
/**
* System calls that make changes to a file
* content without requiring a file descriptor
* to it, however the system call may optionally
* accept a file descriptor
*
* Hypothetically an operating system could provide
* system calls that fall under this category and
* could be used to change the target path of an
* existing symbolic link
*
* truncate(2) and the hypothetical ftruncateat(2)
* are examples of system calls in this category;
* ftruncate(2) however is not
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_WRITE,
/**
* System calls that reads the contents of a file
* content without requiring a file descriptor
* to it, however the system call may optionally
* accept a file descriptor
*
* There currently are not such system calls,
* however, an operating system could not only
* provide such system call to read the contents
* of a file, but the read the file listing in
* a directory or the target path of a symbolic
* link
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_READ,
/**
* System calls that retrieves the target path
* of a symbolic link without requiring a file
* descriptor to it, however the system call
* may optionally accept a file descriptor
*
* readlink(2) and the readlinkat(2) are examples
* of system calls in this category; the
* hypothetical freadlink(2) however is not
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_READLINK,
/**
* System calls that are used to monitoring
* changes and accesses to a file or filesystem
*
* This system calls may create file descriptors
* or use such file descriptors
*
* All inotify(7) and fanotify(7) system calls are
* examples of system calls in this category;
* mq_notify(2) however is not
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_MONITOR,
/**
* System calls that are used dealing with
* filesystem quotas
*
* This system calls may create file descriptors
* or use such file descriptors
*
* quotactl(2) is an example of system call in
* this category
*/
LIBSYSCALLS_FILESYSTEM_SUBCAT_QUOTA
};
/**
* System calls that operate on or create a file descriptor
* without fitting into a special category
*
* System calls in this category may have timeouts that may
* use relative or absolute time
*/
enum libsyscalls_file_syscall_descriptors_subcategory {
/**
* System calls that retrieve metadata about a
* file through a file descriptor to it
*
* fstat(2) is an example of system call in
* this category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_STAT,
/**
* System calls that modifies metadata about a
* file through a file descriptor to it
*
* fchmod(2) and fchown(2) are examples of
* system calls in this category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_MODIFY,
/**
* System calls that duplicates or closes,
* possibly both at the same time, file descriptors,
* or closes the file descriptor in one or two
* directions
*
* dup(2), dup2(2), close(2), and shutdown(2)
* are examples of system calls in this category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_DUP_OR_CLOSE,
/**
* System calls that closes or unshares,
* possibly both at the same time, file descriptors,
* or closes the file descriptor in one or two
* directions
*
* close_range(2) is an example of a system call
* in this category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CLOSE_OR_UNSHARE,
/**
* System calls that read from a file descriptor
* and changes the file offset while doing so
*
* For IPC objects that do not have a file offset
* (such as pipes and sockets) this means that
* read data is removed from the object
*
* read(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ,
/**
* System calls that read from a file descriptor
* without changing the file offset
*
* For IPC objects that do not have a file offset
* (such as pipes and sockets) this means that
* read data will remain in the object, and if
* the system calls is made again, the same data
* will be read
*
* pread(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_PEEK,
/**
* System calls that changes the file offset for
* a file descriptor without changing reading
* or writing
*
* lseek(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_SEEK,
/**
* System calls that write to a file descriptor
* with or without changing the file offset
*
* write(2), pwrite(2), send(2), and sendto(2)
* are examples of system calls in this category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_WRITE,
/**
* System calls that read from a file descriptor
* with or without chaning the file offset
*
* recv(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK,
/**
* System calls that performs
* LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ actions
* on one file descriptor and
* LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_WRITE actions
* on another file descriptor, or possibly on the
* same file descriptor
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_AND_WRITE,
/**
* System calls that performs
* LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_PEEK actions
* on one file descriptor and
* LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_WRITE actions
* on another file descriptor
*
* tee(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_PEEK_AND_WRITE,
/**
* System calls that performs
* LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK
* actions on one file descriptor and
* LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_WRITE actions
* on another file descriptor
*
* splice(2) and sendfile(2) are examples of system
* calls in this category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK_AND_WRITE,
/**
* System calls that performs
* LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK
* actions on a file descriptor while receiving
* metadata (this metadata does not need to fall
* under the category of LIBSYSCALLS_STAT_FILE_DESCRIPTORS,
* indeed it unlikely will)
*
* System calls under this category may receive
* new file descriptors
*
* recvfrom(2) and recvmsg(2) is an example of a
* system call in this category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK_AND_STAT,
/**
* System calls that informs the kernel in what
* manner the process will use a file descriptor
*
* posix_fadvise(2) and readahead(2) are examples of
* system calls in this category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_ADVISE,
/**
* System calls that retrieve metadata about a
* filesystem through a file descriptor
*
* fstatfs(2) is an example of system call in
* this category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_STATFS,
/**
* System calls that create a resource that is used
* for LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_POLL
* actions
*
* epoll_create(2) is an example of system call in
* this category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CREATE_POLL,
/**
* System calls that configure a resource that is
* used for LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_POLL
* actions
*
* epoll_ctl(2) is an example of system call in
* this category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CONFIGURE_POLL,
/**
* System calls that wait until file descriptor
* are ready for writing or have data to read,
* or until some other event on the file descriptor
* has occurred
*
* epoll_wait(2), poll(2) and pselect6(2) are
* examples of system calls in this category
*/
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_POLL
};
/**
* System calls that affect a process itself
*
* Much of the information that can be queried
* with system calls in this category may be
* available through a virtual filesystem
*/
enum libsyscalls_processes_syscall_subcategory {
/**
* System calls that causes the thread, process,
* process group, or session to exit
*
* exit(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_PROCESSES_SUBCAT_EXIT,
/**
* System calls that retrive information about
* the thread, process, process group, or session
*
* gettid(2), getpid(2), getpgid(2), getsid(2),
* getuid(2), and getcwd(2) are examples of system
* calls in this category
*/
LIBSYSCALLS_PROCESSES_SUBCAT_STAT_SELF,
/**
* System calls that retrive information about the
* process's child processes, or other descendants,
* or itself
*/
LIBSYSCALLS_PROCESSES_SUBCAT_STAT_CHILD,
/**
* System calls that retrive information about the
* process's parent or other ancestors, or itself
* or its descendants
*
* getppid(2) and getxpid(2) are examples of system
* calls in this category
*/
LIBSYSCALLS_PROCESSES_SUBCAT_STAT_PARENT,
/**
* System calls that retrive information about any
* process
*/
LIBSYSCALLS_PROCESSES_SUBCAT_STAT_OTHER,
/**
* System calls that change the process's privileges
*
* The system call may also retrieve information
* about the process
*
* setuid(2) in an example of a system call in this
* category
*/
LIBSYSCALLS_PROCESSES_SUBCAT_CHANGE_PERMISSIONS,
/**
* System calls that forks the process, either
* the create a new process or a new thread
*
* fork(2) and clone(2) are examples of system
* calls in this category
*/
LIBSYSCALLS_PROCESSES_SUBCAT_CLONE,
/**
* System calls that changes the program the
* process is executing
*
* execve(2) and execveat(2) are examples of
* system calls in this category
*/
LIBSYSCALLS_PROCESSES_SUBCAT_EXEC,
/**
* System calls that change the working directory
* of the process or thread
*
* chdir(2) in an example of a system call in
* this category
*/
LIBSYSCALLS_PROCESSES_SUBCAT_CHDIR,
/**
* System calls that change the file system root
* of the process or thread
*
* chroot(2) and pivot_root(2) are examples of
* system calls in this category
*/
LIBSYSCALLS_PROCESSES_SUBCAT_CHROOT,
/**
* System calls that affect the process's session
* or process group
*
* setsid(2), setpgid(2), and vhangup(2) are
* examples of system calls in this category
*/
LIBSYSCALLS_PROCESSES_SUBCAT_SESSION
};
/**
* System calls that enables or disable system logging
*
* For each system call in this category, the system call
* may use the filesystem or a file descriptor
*/
enum libsyscalls_logging_syscall_subcategory {
/**
* System calls that turn on or off logging for
* processes
*
* acct(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_LOGGING_SUBCAT_PROCESSES
};
/**
* System calls whose primary function are time related
*/
enum libsyscalls_time_syscall_subcategory {
/**
* System calls that can either get or set (or both)
* the current time or time zone information, or the
* time of a virtual clock such as a process's run
* time
*
* adjtime(2), adjtimex(2), and clock_adjtime(2)
* are examples of system calls in this category
*/
LIBSYSCALLS_TIME_SUBCAT_GET_OR_SET,
/**
* System calls that can get the current time or
* time zone information, or the time of a virtual
* clock
*
* time(2), gettimeofday(2), and clock_gettime(2)
* are examples of system calls in this category
*/
LIBSYSCALLS_TIME_SUBCAT_GET,
/**
* System calls that can set the current time or
* time zone information, or the time of a virtual
* clock
*
* stime(2), settimeofday(2), and clock_settime(2)
* are examples of system calls in this category
*/
LIBSYSCALLS_TIME_SUBCAT_SET,
/**
* System calls that receive metadata about a
* clock
*
* clock_gettres(2) is an example of a system call
* in this category
*/
LIBSYSCALLS_TIME_SUBCAT_INTROSPECT,
/**
* System calls that arm or disarm a timer that
* uses relative time
*
* alarm(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE,
/**
* System calls that arm or disarm a timer that
* uses absolute time
*/
LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE,
/**
* System calls that arm or disarm a timer that
* can use either relative or absolute time
*/
LIBSYSCALLS_TIME_SUBCAT_TIMER,
/**
* System calls that read the amount of time
* remaining until a timer that uses relative
* time is run over (is triggered)
*
* These system calls may also retrieve a timer's
* overrun interval
*
* getitimer(2) is an example of a system call
* in this category
*/
LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_READ,
/**
* System calls that read the time a timer that
* uses absolute time runs over (is triggered)
*
* These system calls may also retrieve a
* timer's overrun interval
*/
LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_READ,
/**
* System calls that act both as
* LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_READ
* and LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_READ
* system calls
*/
LIBSYSCALLS_TIME_SUBCAT_TIMER_READ,
/**
* System calls that act both as
* LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE
* and LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_READ
* system calls and may more may not do both at
* the same time
*
* setitimer(2) is an example of a system call
* in this category
*/
LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_WITH_READ,
/**
* System calls that act both as
* LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE
* and LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_READ
* system calls and may more may not do both at
* the same time
*/
LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_WITH_READ,
/**
* System calls that act both as
* LIBSYSCALLS_TIME_SUBCAT_TIMER and
* LIBSYSCALLS_TIME_SUBCAT_TIMER_READ system calls
* and may more may not do both at the same time
*/
LIBSYSCALLS_TIME_SUBCAT_TIMER_WITH_READ,
/**
* System calls that suspends the process until
* a relative point in time (this could be virtual
* time such as a process's run time)
*
* The system call may return early for any reason,
* for example because the a signal was sent to
* the process
*
* nanosleep(2) is an example of a system call
* in this category
*/
LIBSYSCALLS_TIME_SUBCAT_SLEEP_RELATIVE,
/**
* System calls that suspends the process until
* an absolute point in time (this could be virtual
* time such as a process's run time)
*
* The system call may return early for any reason,
* for example because the a signal was sent to the
* process or the time of the clock was modified
*/
LIBSYSCALLS_TIME_SUBCAT_SLEEP_ABSOLUTE,
/**
* System calls that act both as
* LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_READ
* and LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_READ
* system calls
*
* clock_nanosleep(2) is an example of a system
* call in this category
*/
LIBSYSCALLS_TIME_SUBCAT_SLEEP
};
/**
* System calls that deal with signals (signal(7))
*/
enum libsyscalls_signals_syscall_subcategory {
/**
* System calls that only causes the process
* to suspend until it receives a signal
*
* Many system calls will be interrepted if
* there is a pending signal or one is received
* during the system call. There are also some
* system calls that can be used to emulating
* the behaviour of system calls in this category
* but that have another primary purpose.
*
* pause(2) in example of a system call in this
* category
*/
LIBSYSCALLS_SIGNALS_SUBCAT_PAUSE,
/**
* System calls that send a signal to a process
*
* kill(2) in example of a system call in this
* category
*/
LIBSYSCALLS_SIGNALS_SUBCAT_KILL
};
/**
* System calls that deal with memory allocations
* including memory mapped files
*/
enum libsyscalls_memory_syscall_subcategory {
/**
* System calls that allocate memory or change
* the allocation size of an allocated memory
* segment
*
* The system calls may also return information
* about how much memory has allocated
*
* These system calls may change the address of
* an allocated memory segment
*
* brk(2), mmap(2), mremap(2) are examples of system
* calls in this category
*/
LIBSYSCALLS_MEMORY_SUBCAT_ALLOCATE,
/**
* System calls that deallocate allocated memory
* segments
*
* munmap(2) is an example of a system call in
* this category
*/
LIBSYSCALLS_MEMORY_SUBCAT_DEALLOCATE,
/**
* System calls modifies memory
*/
LIBSYSCALLS_MEMORY_SUBCAT_WRITE,
/**
* System calls advises the kernel on issues
* regarding the process's memory
*/
LIBSYSCALLS_MEMORY_SUBCAT_ADVISE,
/**
* System calls that can operate both as
* LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK and
* LIBSYSCALLS_FILESYSTEM_SUBCAT_UNLINK system calls,
* either one at a time or both at the same them
*
* madvise(2) is an example of a system call in
* this category
*/
LIBSYSCALLS_MEMORY_SUBCAT_WRITE_OR_ADVISE,
/**
* System calls that prevent memory to be
* paged out into the swap area
*
* mlock(2) is an example of a system call in
* this category
*/
LIBSYSCALLS_MEMORY_SUBCAT_LOCK,
/**
* System calls that enables memory to be
* paged out into the swap area
*
* munlock(2) is an example of a system call in
* this category
*/
LIBSYSCALLS_MEMORY_SUBCAT_UNLOCK,
/**
* System calls that retrieves details about
* memory allocated to the process
*
* mincore(2) is an example of a system call in
* this category
*/
LIBSYSCALLS_MEMORY_SUBCAT_STAT,
/**
* System calls that changes details about
* memory allocated to the process
*
* mprotect(2) is an example of a system call
* in this category
*/
LIBSYSCALLS_MEMORY_SUBCAT_MODIFY
};
/**
* System calls that deal directly with the
* operating system or machine
*/
enum libsyscalls_system_syscall_subcategory {
/**
* System calls that deal set swap memory
*
* swapon(2) and swapoff(2) are examples of system
* calls in this category
*/
LIBSYSCALLS_SYSTEM_SUBCAT_SWAP,
/**
* System calls that poweroff, reboots, suspends
* the machine or live patches the kernel
*
* Note that it is common to preform this task by
* communicating with the init system
*
* reboot(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_SYSTEM_SUBCAT_REBOOT,
/**
* System calls that get the name of the machine
* or the operating system, as well as version
* and CPU details
*
* Note that this information may also be available
* through a virtual file system
*
* uname(2) and gethostname(2) are examples of
* system calls in this category
*/
LIBSYSCALLS_SYSTEM_SUBCAT_GET_NAME,
/**
* System calls that set the name of the machine
*
* Note that this information may also be settable
* via a virtual file system
*
* sethostname(2) is an example of a system call
* in this category
*/
LIBSYSCALLS_SYSTEM_SUBCAT_SET_NAME,
/**
* System calls that get runtime information about
* the system, such as CPU and memory usage and
* entropy
*
* Note that this information may also be settable
* via a virtual file system
*
* sysinfo(2) is an example of a system call
* in this category
*/
LIBSYSCALLS_SYSTEM_SUBCAT_STAT,
/**
* System calls that get generate random data, and
* may thereby deplete the systems entropy pool
*
* Note that this may also be possible to do via a
* virtual file system
*
* getrandom(2) is an example of a system call in
* this category
*/
LIBSYSCALLS_SYSTEM_SUBCAT_RANDOM,
/**
* System calls that are generally harmless and
* required for a process to perform important
* actions
*
* On Linux the following system calls have this
* classification:
* - getpagesize(2)
*/
LIBSYSCALLS_SYSTEM_SUBCAT_FUNDAMENTAL
};
/**
* System calls that affect process sheduling
*/
enum libsyscalls_scheduling_syscall_subcategory {
/**
* System calls that causes the thread, process,
* process group, session, or user the give up it's
* allotted time
*
* sched_yield(2) is an example of system call in
* this category
*/
LIBSYSCALLS_SCHEDULING_SUBCAT_YIELD,
/**
* System calls that changes a thread's, process's
* process group's, session's, or user's, or the
* machines scheduling parameters
*
* sched_setscheduler(2), sched_setaffinity(2),
* and setpriority(2) are examples of system calls
* in this category
*/
LIBSYSCALLS_SCHEDULING_SUBCAT_SET,
/**
* System calls that retrieves a thread's, process's
* process group's, session's, or user's, or the
* machines scheduling parameters
*
* sched_getscheduler(2), sched_getaffinity(2),
* and getpriority(2) are examples of system calls
* in this category
*/
LIBSYSCALLS_SCHEDULING_SUBCAT_GET,
/**
* System calls that can operate both as
* LIBSYSCALLS_SCHEDULING_SUBCAT_GET and
* LIBSYSCALLS_SCHEDULING_SUBCAT_SET system calls,
* either one at a time or both at the same them
*
* nice(2) is an example of a system call in this
* category
*/
LIBSYSCALLS_SCHEDULING_SUBCAT_GET_OR_SET,
/**
* System calls the retrieve metadata for the
* scheduling options that are available on the
* system
*
* sched_get_priority_max(2) is an example of
* a system call in this category
*/
LIBSYSCALLS_SCHEDULING_SUBCAT_INTROSPECT
};
/**
* Less broad classification on system calls
*
* Each value in `enum libsyscalls_syscall_category` have
* its own field (enumeration of values) name after the
* `enum` value; except that LIBSYSCALLS_CAT_SUPPORT_PENDING
* and LIBSYSCALLS_CAT_NOT_IMPLEMENTED does not have any,
* which also means that whereever this union is used, its
* value is undefined, if the broad classification is either
* LIBSYSCALLS_CAT_SUPPORT_PENDING or LIBSYSCALLS_CAT_NOT_IMPLEMENTED
*/
union libsyscalls_syscall_subcategory {
enum_libsyscalls_network_enabled_ipc_syscall_subcategory network_enabled_ipc; /**< If LIBSYSCALLS_CAT_NETWORK_ENABLED_IPC */
enum_libsyscalls_ipc_syscall_subcategory ipc; /**< If LIBSYSCALLS_CAT_IPC */
enum_libsyscalls_filesystem_syscall_subcategory filesystem; /**< If LIBSYSCALLS_CAT_FILESYSTEM */
enum_libsyscalls_file_descriptors_syscall_subcategory file_descriptors; /**< If LIBSYSCALLS_CAT_FILE_DESCRIPTORS */
enum_libsyscalls_processes_syscall_subcategory processes; /**< If LIBSYSCALLS_CAT_PROCESSES */
enum_libsyscalls_logging_syscall_subcategory logging; /**< If LIBSYSCALLS_CAT_LOGGING */
enum_libsyscalls_time_syscall_subcategory time; /**< If LIBSYSCALLS_CAT_TIME */
enum_libsyscalls_signals_syscall_subcategory signals; /**< If LIBSYSCALLS_CAT_SIGNALS */
enum_libsyscalls_memory_syscall_subcategory memory; /**< If LIBSYSCALLS_CAT_MEMORY */
enum_libsyscalls_system_syscall_subcategory system; /**< If LIBSYSCALLS_CAT_SYSTEM */
enum_libsyscalls_scheduling_syscall_subcategory scheduling; /**< If LIBSYSCALLS_CAT_SCHEDULING */
};
/**
* System call interface
*/
struct libsyscalls_syscall_abi {
/**
* Classification of what the system call does
*
* Check `.category` to se which group of
* classifications to used
*/
union libsyscalls_syscall_subcategory subcategory;
/**
* Broad classification of what the system calls does
*/
enum_libsyscalls_syscall_category category : 16;
/**
* For set any bit indexed I (starting from 0), the
* system call parameter I is a pointer that the
* system call reads from
*
* Note that there are types that fundamentally are
* pointers (such as strings), for these, this bit
* is not set unless it is a pointer to a string
*/
unsigned short int in_pointer_mask : 16;
/**
* For set any bit indexed I (starting from 0), the
* system call parameter I is a pointer that the
* system call write to
*
* Note that there are types that fundamentally are
* pointers (such as strings), for these, this bit
* is not set unless it is a pointer to a string
*/
unsigned short int out_pointer_mask : 16;
/**
* For set any bit indexed I (starting from 0), the
* system call parameter I can be resolved into a
* symbolic string by the library
*/
unsigned short int symbolic_mask : 16;
/**
* The minimum number of arguments that must be
* passed into the system call, -1 if unknown
*/
short int min_argument_count : 6;
/**
* The maximum number of arguments that can be
* passed into the system call, -1 if unknown
*/
short int max_argument_count : 6;
/**
* If set, the library can resolve the value the
* system call returns into a symbolic string
*/
unsigned short int symbolic_return : 1;
/**
* If 1, the system call shall always either return
* an error, return the value 0, or not return at all
*/
unsigned short int expect_zero : 1;
/**
* If 1, the system call invocation must be parsed
* especially as it is not does follow what is
* proscribed for the used data types
*
* The library may use this temporarily until it
* in a later version provides a convension that
* can be followed
*/
unsigned short int queer : 1;
short int : LIBSYSCALLS_PAD_(sizeof(short int)/sizeof(char)*CHAR_BIT,
4*16 + 2*6 + 3*1);
/**
* This is used internally by `libsyscalls_get_syscall_display_info`
* to find out how values ought to be printed to be both human
* and machines friendly (symbolic names are indeed easier for
* the application to deal with as their values can depend on
* the architecture), and occasionally to determine what types
* are used for on arguments whose type is argument dependent,
* and to figure which optional arguments are included in the
* system call
*
* If this is value is 0, `libsyscalls_get_syscall_display_info`
* will not be able to provide any useful information, which
* would either be because everything is provided here (in
* `struct libsyscalls_syscall_abi`) or because the library
* hasn't yet added full support for the system call
*/
LIBSYSCALLS_SYMBOL_PRINTER symbol_printer : 16;
/**
* The system call's return type
*/
enum_libsyscalls_datatype return_type : 16;
/**
* The type of each of the systems call's parameter
*
* The application must not read `.parameters_types[.max_argument_count]`
* or beyond, doing so will probably mean reading beyond the memory
* allocated for the instance of the structure
*/
enum_libsyscalls_datatype parameters_types[LIBSYSCALLS_FLEXABLE_OR_NPARAMS_];
};
/**
* System call description
*/
struct libsyscalls_syscall {
/**
* What system call is named
*/
const char *name;
/**
* The ABI for the system call for architecture it was
* queried for
*
* May or may not be `NULL` if the system call is defined
* but not implemented
*/
struct libsyscalls_syscall_abi *actual_syscall;
/**
* Like .actual_syscall except this is used for example when
* a 32-bit process is running on a 64-bit operating system
*
* If `NULL` use .actual_syscall
*/
struct libsyscalls_syscall_abi *actual_compat_syscall;
};
/**
* Named number (errors and signals)
*/
struct libsyscalls_named_number {
/**
* The value if the number, it is up to the
* application select signess
*
* It is usually safe to use unsigned (.u)
* as the numbers are usually positive but
* not so large that the sign bit would be
* set, unless the numbers are supposted to
* be unsigned
*/
union {
signed long long int s;
unsigned long long int u;
} number;
/**
* The name of the number, including namespacing
* (e.g. "E" prefix for errno numbers and "SIG"
* or "_SIG" prefix for singals)
*/
const char *name;
};
/**
* Function that returns a name for a value
*
* This function is called multiple times to extract
* names of multiple subvalues, for example, for
* the system call access() second parameter, it
* will return the string "X_OK", "W_OK", "R_OK",
* and "F_OK", or a subset thereof; one per invocation
*
* The proper way to use this function, is:
*
* static void
* print_unsigned(libsyscalls_symbol_printer_function *function,
* LIBSYSCALLS_SYMBOL_PRINTER_DATA *data,
* unsigned long long int value, FILE *output)
* {
* const char *sym, *prefix = "";
* char format[] = "%s%llu";
* char *fallback = strchr(format, '\0') - 1;
* do {
* sym = (*function)(data, &value, &fallback);
* if (!sym)
* break;
* fprintf(output, "%s%s", prefix, sym);
* prefix = "|";
* } while (value);
* if (value || !*prefix)
* fprintf(output, format, prefix, value);
* }
*
* @param data Data passed to the function (which that function
* has been paired with for the paramter/return),
* which it may require to known exactly what to do
* @param valuep The caller set a variable to the value pass in to
* the system call parameter (or the system call's
* return value), the value if any extract symbol
* will removed from from the variable. If the function
* return NULL, this value can be 0, in which case all
* values have been extract, otherwise (which it is not
* 0) there is some value (either invalid or not known
* to the library) that shall must be printed manually
* by the application (see `fallback_out` parameter).
* Note that, if the value 0 has a name, this function
* never return NULL if the variable reaches 0, instead
* it will repeated return the name of that value.
* @param fallback_out The caller set a variable to 0 and pointer to it,
* when this function return NULL, the variable MAY
* (even before that) have been set to 'x', 'o', or
* 'd', indicating a suggestion how any value left
* over in `*valuep` shall be displayed: 'x' for in
* hexadecimal, 'o' for octal, and 'd' for decimal
* (signness depends on the system call parameter's
* type's (or as the case may be, the system call's
* return type) signness).
* @return The name of some value in `*valuep`, or `NULL` if
* none was found. The returned string may be stored
* in `data` and those override at the next call.
*/
typedef const char *libsyscalls_symbol_printer_function(LIBSYSCALLS_SYMBOL_PRINTER_DATA *data,
unsigned long long int *valuep,
char *fallback_out);
/**
* Information about a system call parameter or return value
*/
struct libsyscalls_syscall_type_info {
/**
* Function for extracting names values from a variable
*/
libsyscalls_symbol_printer_function *function;
/**
* First argument to pass to `.function`
*/
LIBSYSCALLS_SYMBOL_PRINTER_DATA *data;
/**
* The data type used for the parameter or return value
* in the specific invocation of the system call
*
* If set to LIBSYSCALLS_TYPE_VOID for an optional
* parameter, that parameter was not used
*/
enum_libsyscalls_datatype type;
char padding__[LIBSYSCALLS_PAD_(sizeof(void *)/sizeof(char),
sizeof(enum_libsyscalls_datatype)/sizeof(char) + 1)];
unsigned char : CHAR_BIT - 1;
/**
* Only used for the return value
*
* Same as `.expect_zero` in `struct libsyscalls_syscall_abi`,
* however if 0 in `struct libsyscalls_syscall_abi`, it can
* still be 1 here if if it is determined that for the specificly
* used system call arguments, the system call shall always
* return 0 (or not return) or an error
*/
unsigned char expect_zero : 1;
};
/**
* System call information tweak for the arguments passed
* to the system call, as well as information about how
* to print named values in the arguments and return
*/
struct libsyscalls_syscall_display_info {
/**
* The size of this structure, this can be used
* by the application to test what is available
* in the case it may have compiled against a
* newer version than used in the version of the
* library the application is linked with
*
* Data is stored beyond this, do not try to make
* a copy; that will not go well
*/
size_t size;
/**
* Information about each system call parameter
*
* All positive integer within [0, .max_argument_count]
* for the `struct libsyscalls_syscall_abi` are valid,
* but no index beyond `.max_argument_count` is valid
*/
struct libsyscalls_syscall_type_info *params;
/**
* Information about the system call's return value
*/
struct libsyscalls_syscall_type_info *retvalue;
};
/**
* Signed number representation
*/
enum libsyscalls_datatype_sign_representation {
/**
* The data type was LIBSYSCALLS_TYPE_UNKNOWN
* or LIBSYSCALLS_TYPE_DYNAMIC
*/
LIBSYSCALLS_SIGN_UNDETERMINED,
/**
* Two's complement
*
* -x is ~x + 1, -0 is +0
*/
LIBSYSCALLS_SIGN_TWOS_COMPLEMENT,
/**
* One's cmplement
*
* -x is ~x, -0 is not +0
*/
LIBSYSCALLS_SIGN_ONES_COMPLEMENT,
/**
* Sign–magnitude
*
* -x is (x | most significant bit), -0 is not +0
*/
LIBSYSCALLS_SIGN_SIGN_MAGNITUDE,
/**
* Excess-K, with K being (unsigned maximum + 1)/2
*
* 0 is represented with just the most significant bit set,
* any offset from 0 is added to this value, i.e., x is
* represented by ((unsigned maximum + 1)/2 + x); -0 is +0
*/
LIBSYSCALLS_SIGN_EXCESS_HALF
};
/**
* Data type usage annotation
*/
enum libsyscalls_datatype_annotation {
/**
* The data type was LIBSYSCALLS_TYPE_UNKNOWN or
* LIBSYSCALLS_TYPE_DYNAMIC
*/
LIBSYSCALLS_ANNOTATION_UNDETERMINED,
/**
* The value does not have usage annotation
*/
LIBSYSCALLS_ANNOTATION_NONE,
/**
* The value represents an operating system signal
* (e.g. SIGKILL)
*
* This affords the application the opportunity
* to print more detail information about a signal
* (such as when it is used, whether it is a
* realtime signal, default action, whether it
* can be caught, and what its normal usage is)
*/
LIBSYSCALLS_ANNOTATION_SIGNAL,
/**
* The value represents a file descriptor
*
* This affords the application the opportunity
* toprint file information (such as file name,
* address, file type, and offset)
*/
LIBSYSCALLS_ANNOTATION_FD,
/**
* The value represents a file descriptor or a
* special value for a known file such as AT_FDCWD
*
* This affords the application the opportunity
* to print file information (such as file name,
* address, file type, and offset)
*/
LIBSYSCALLS_ANNOTATION_ATFD
};
/**
* Register-split/struct field-split information
* for a data type
*/
enum libsyscalls_datatype_section {
/**
* The data type was LIBSYSCALLS_TYPE_UNKNOWN
* or LIBSYSCALLS_TYPE_DYNAMIC
*/
LIBSYSCALLS_SECTION_UNDETERMINED,
/**
* The whole value is represented
*
* The value is contained within a single parameter
*/
LIBSYSCALLS_SECTION_WHOLE,
/**
* This whether a data type represents a half section
* of larger data type
*
* @param S:enum libsyscalls_datatype_section
* The data type section information
*
* @return :int Whether the larger that type was
* split into two halves
*/
#define LIBSYSCALLS_IS_SECTION_HALF(S)\
(((S) >= LIBSYSCALLS_SECTION_UPPER_HALF) &&\
((S) <= LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF))
/**
* The most significant half of the value is represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0xFFFFFFFF00000000 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_LOWER_HALF)
*/
LIBSYSCALLS_SECTION_UPPER_HALF,
/**
* The least significant half of the value is represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0x00000000FFFFFFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_UPPER_HALF)
*/
LIBSYSCALLS_SECTION_LOWER_HALF,
/**
* The second most and second least significant quarters
* of the value represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0x0000FFFFFFFF0000 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_OUTER_HALF)
*/
LIBSYSCALLS_SECTION_INNER_HALF,
/**
* The most and least significant quarters of the value
* represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0xFFFF00000000FFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_INNER_HALF)
*/
LIBSYSCALLS_SECTION_OUTER_HALF,
/**
* The second most and least significant quarters of the
* value represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0x0000FFFF0000FFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF)
*/
LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF,
/**
* The most and second least significant quarters of the
* value represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0xFFFF0000FFFF0000 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF)
*/
LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF,
/**
* The bytes that would be indexed (starting from 0) with
* an even number in big endian (how humans write numbers)
* are represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0x00FF00FF00FF00FF if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_EVEN_BYTES_AS_HALF)
*/
LIBSYSCALLS_SECTION_EVEN_BYTES_AS_HALF,
/**
* The bytes that would be indexed (starting from 0) with
* an odd number in big endian (how humans write numbers)
* are represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0xFF00FF00FF00FF00 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF)
*/
LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF,
/**
* This whether a data type represents a quarter section
* of larger data type
*
* @param S:enum libsyscalls_datatype_section
* The data type section information
*
* @return :int Whether the larger that type was
* split into four quarters
*/
#define LIBSYSCALLS_IS_SECTION_QUARTER(S)\
(((S) >= LIBSYSCALLS_SECTION_UPPER_QUARTER) &&\
((S) <= LIBSYSCALLS_SECTION_LOWER_QUARTER))
/**
* The most significant quarter of the value is represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 16-bits —
* 0xFFFF000000000000 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with three neighbouring parameter
* (a LIBSYSCALLS_SECTION_UPPER_MID_QUARTER,
* a LIBSYSCALLS_SECTION_LOWER_MID_QUARTER, and
* a LIBSYSCALLS_SECTION_LOWER_QUARTER)
*/
LIBSYSCALLS_SECTION_UPPER_QUARTER,
/**
* The second most significant quarter of the value is represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 16-bits —
* 0x0000FFFF00000000 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with three neighbouring parameter
* (a LIBSYSCALLS_SECTION_UPPER_QUARTER,
* a LIBSYSCALLS_SECTION_LOWER_MID_QUARTER, and
* a LIBSYSCALLS_SECTION_LOWER_QUARTER)
*/
LIBSYSCALLS_SECTION_UPPER_MID_QUARTER,
/**
* The least most significant quarter of the value is represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 16-bits —
* 0x00000000FFFF0000 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with three neighbouring parameter
* (a LIBSYSCALLS_SECTION_UPPER_QUARTER,
* a LIBSYSCALLS_SECTION_UPPER_MID_QUARTER, and
* a LIBSYSCALLS_SECTION_LOWER_QUARTER)
*/
LIBSYSCALLS_SECTION_LOWER_MID_QUARTER,
/**
* The least significant quarter of the value is represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 16-bits —
* 0x000000000000FFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with three neighbouring parameter
* (a LIBSYSCALLS_SECTION_UPPER_QUARTER,
* a LIBSYSCALLS_SECTION_UPPER_MID_QUARTER, and
* a LIBSYSCALLS_SECTION_LOWER_MID_QUARTER)
*/
LIBSYSCALLS_SECTION_LOWER_QUARTER
/**
* Get the number of registers/fields the data type
* was split into
*
* @param S:enum libsyscalls_datatype_section
* The data type section information
*
* @return :unsigned int
* The number registers/fields the data
* type was split into; invalid if `S`
* is LIBSYSCALLS_SECTION_UNDETERMINED
*/
#define LIBSYSCALLS_GET_SECTION_FRACTION(S)\
(LIBSYSCALLS_IS_SECTION_HALF(S) ? 2U :\
LIBSYSCALLS_IS_SECTION_QUARTER(S) ? 4U : 1U)
};
/**
* Macro for enumerating type-split sections
*
* The numbers are stored in `enum libsyscalls_datatype_section`
*
* @param X:macro(NAME, ...) Macro that expands, will a number of arguments:
* 1) The name of the enum value
* 2) 1 if the section is both compatible with 16-bit
* integers and is the first section with its
* pattern of covered bits for 16-bit integers,
* 0 otherwise
* 3) Mask of bits the section covers for a 16-bit integer
* 4) 1 if the section is both compatible with 32-bit
* integers and is the first section with its
* pattern of covered bits for 32-bit integers,
* 0 otherwise
* 5) Mask of bits the section covers for a 32-bit integer
* 6) 1 if the section is both compatible with 64-bit
* integers and is the first section with its
* pattern of covered bits for 64-bit integers,
* 0 otherwise
* 7) Mask of bits the section covers for a 64-bit integer
* Arguments 3, 5, and 7 are `0` when the section is not
* compatible with the data type and otherwise a `0x`
* prefixed uppercase hexadecimal number without any type
* suffix.
* Addition arguments may be added in the future.
* @param D:code Macro that expands between each expansion of X
*
* The primary purpose of the existance of this macro
* is to ease implementation of the library; it will
* probably not disappear (no promises)
*/
#define LIBSYSCALLS_LIST_SECTIONS(X, D)\
X(LIBSYSCALLS_SECTION_WHOLE, 1, 0xFFFF, 1, 0xFFFFFFFF, 1, 0xFFFFFFFFFFFFFFFF) D\
X(LIBSYSCALLS_SECTION_UPPER_HALF, 1, 0xFF00, 1, 0xFFFF0000, 1, 0xFFFFFFFF00000000) D\
X(LIBSYSCALLS_SECTION_LOWER_HALF, 1, 0x00FF, 1, 0x0000FFFF, 1, 0x00000000FFFFFFFF) D\
X(LIBSYSCALLS_SECTION_INNER_HALF, 0, 0, 1, 0x00FFFF00, 1, 0x0000FFFFFFFF0000) D\
X(LIBSYSCALLS_SECTION_OUTER_HALF, 0, 0, 1, 0xFF0000FF, 1, 0xFFFF00000000FFFF) D\
X(LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF, 0, 0, 1, 0x00FF00FF, 1, 0x0000FFFF0000FFFF) D\
X(LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF, 0, 0, 1, 0xFF00FF00, 1, 0xFFFF0000FFFF0000) D\
X(LIBSYSCALLS_SECTION_EVEN_BYTES_AS_HALF, 0, 0, 0, 0x00FF00FF, 1, 0x00FF00FF00FF00FF) D\
X(LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF, 0, 0, 0, 0xFF00FF00, 1, 0xFF00FF00FF00FF00) D\
X(LIBSYSCALLS_SECTION_UPPER_QUARTER, 0, 0, 1, 0xFF000000, 1, 0xFFFF000000000000) D\
X(LIBSYSCALLS_SECTION_UPPER_MID_QUARTER, 0, 0, 1, 0x00FF0000, 1, 0x0000FFFF00000000) D\
X(LIBSYSCALLS_SECTION_LOWER_MID_QUARTER, 0, 0, 1, 0x0000FF00, 1, 0x00000000FFFF0000) D\
X(LIBSYSCALLS_SECTION_LOWER_QUARTER, 0, 0, 1, 0x000000FF, 1, 0x000000000000FFFF)
/**
* Information on how an instance of data type is to be parsed
*
* Data types are usually either signed or unsigned, but there
* are a few exceptions: LIBSYSCALLS_TYPE_UNKNOWN and
* LIBSYSCALLS_TYPE_DYNAMIC are described as both signed and
* unsigned as their signness is unknown and could be either,
* or neither, which brings us to the next exception: some
* data types are neither signed nor unsigned; these are types
* that are not numerical, i.e. non-values (LIBSYSCALLS_TYPE_NO_RETURN
* and LIBSYSCALLS_TYPE_VOID), memory addresses
* (LIBSYSCALLS_TYPE_MEMORY_ADDRESS) and textual types
* (LIBSYSCALLS_TYPE_CHAR, LIBSYSCALLS_TYPE_STRING, and
* LIBSYSCALLS_TYPE_STRINGS_THEN_NULL), as well as arrays of
* such types (including LIBSYSCALLS_TYPE_BUFFER and
* LIBSYSCALLS_TYPE_BUFFER_UNKNOWN_FILL), and finally bitset
* arrays (currently only LIBSYSCALLS_TYPE_FD_SET)
*/
struct libsyscalls_datatype_description {
/**
* The number of bits used for the represented section
* of the data type
*
* 0 for LIBSYSCALLS_TYPE_NO_RETURN and LIBSYSCALLS_TYPE_VOID
*
* if .section is LIBSYSCALLS_SECTION_WHOLE, this is the
* number of bits in the entire data type, otherwise the data
* type may have been split (LIBSYSCALLS_SECTION_UNDETERMINED,
* guaranteed to be split otherwise) and this value is just
* the number of bits stored in the register or struct field
*
* It is possible for the data type to contain unused dummy
* bits in order to make it a power of 2 or a multiple of
* a smaller data type. For example, on x86, `long double`
* uses 128 bits, even though the value only uses 80 bits.
* The dummy bits are included in the value on this field.
*/
unsigned width_in_bits;
/**
* The size (in number of elements) of the array the data type
* is used in, or 1 if the data type was not an array or
* 0 if the array size is determined by another parameter/field
*/
unsigned array_size;
/**
* Only used if .array_size is 0
*
* The position of the array's size in the parameter/field list
* relative to the array, e.g. 1 for the next parameter/field
* or -1 for the previous parameter/field
*
* If 0, use .absolute_position_of_array_size instead
*/
signed relative_position_of_array_size : 5;
/**
* Only used if .array_size is 0
*
* The position of the array's size in the parameter/field list,
* indexed starting from 0
*
* If -1, use .relative_position_of_array_size instead
*/
signed absolute_position_of_array_size : 5;
/**
* Only used if .array_size is 0
*
* Assuming the kernel writes into the array, if 1, the number
* of elements written to the array (starting from its beginning)
* is writting into the array size parameter/field if it is
* marked as an output parameter/field and return otherwise;
* if 0, the number of bits written must be infered from its
* contents, e.g. via null byte termination (how this is done
* depends on the system call)
*/
unsigned fill_is_known : 1;
/**
* Whether the data type is signed
*/
unsigned is_signed : 1;
/**
* Whether the data type is unsigned
*/
unsigned is_unsigned : 1;
/**
* Only used if .is_signed is 1 and .sign_representation
* is not LIBSYSCALLS_SIGN_UNDETERMINED
*
* This value can be inferred from .sign_representation;
* its 1 if the data type's minimum value is the negative
* of its maximum value (which also means that -0 and +0
* are distinct), and 0 otherwise, which means that the
* minimum value is the negative of (the minimum value + 1)
* (it also means that -0 and +0 are the identical)
*/
unsigned min_is_minus_max : 1;
int padding__ : LIBSYSCALLS_PAD_(sizeof(int)/sizeof(char)*CHAR_BIT,
2*5 + 4*1);
/**
* Only used if .is_signed is 1
*
* How signed numbers are represented
*/
enum libsyscalls_datatype_sign_representation sign_representation : 8;
/**
* Additional information about what the value represents
*/
enum libsyscalls_datatype_annotation annotation : 8;
/**
* What part of the value is stored in the instance
*/
enum libsyscalls_datatype_section section : 16;
/**
* This is a ~0 terminated array — but, it can also
* be terminated by the end of the array — describing
* the order of the bytes the the data type
*
* The lowest non-zero values contains the width of
* a byte (in bytes), however no such value exists
* in this array if the data type is just one byte
* (or none)
*
* For each unsigned byte in the data type, indexed
* I from 0, it shall be shifted left .byteorder[i]
* bits; the bitwise OR of the results is the
* unsigned value used in the instance of the data type
*
* Data types for register-splits/struct field-splits
* ARE NOT shifted, there is always a value in
* .byteorder that is 0, unless .byteorder[0] is ~0
*
* To avoid problems checking for ~0, use the
* LIBSYSCALLS_IS_BYTEORDER_END macro; please also be
* aware that both the type and length can change in
* the future: do not assume it's `unsigned char`,
* and do not assume it has 32 elements, do not only
* `LIBSYSCALLS_IS_BYTEORDER_END` to detect ~0, but
* also check that no more than
* `sizeof(x.byteorder) / sizeof(*x.byteorder)`
* elements are read (where x is the instance of the
* structure) (you should definitely have your own
* macro for that one). As an alternative to
* `LIBSYSCALLS_IS_BYTEORDER_END`, you may use the
* LIBSYSCALLS_IS_BYTEORDER_END_AT macro
*/
unsigned char byteorder[32];
/**
* Test whether a value in `struct
* libsyscalls_datatype_description.byteorder`
* marks the end of the byteorder's shift value
* (testing that the value is ~0). Using this
* macro helps avoiding bugs caused by integer
* type promotion.
*
* @param SHIFT The value to test `struct
* libsyscalls_datatype_description.byteorder`
* @return :int Whether the value is ~0
*/
#ifdef UINTMAX_C
# define LIBSYSCALLS_IS_BYTEORDER_END(SHIFT)\
(!~((SHIFT) | ~LIBSYSCALLS_FIELD_MASK_(UINTMAX_C(1),\
struct libsyscalls_datatype_description, byteorder[0])))
#else
# define LIBSYSCALLS_IS_BYTEORDER_END(SHIFT)\
(!~((SHIFT) | ~LIBSYSCALLS_FIELD_MASK_(1ULL,\
struct libsyscalls_datatype_description, byteorder[0])))
#endif
/**
* Test whether `DESC->byteorder[INDEX]` is
* the (post-last) end of `DESC->byteorder`
*/
#define LIBSYSCALLS_IS_BYTEORDER_END_AT(DESC, INDEX)\
((size_t)(INDEX) == sizeof((DESC)->byteorder) / sizeof(*(DESC)->byteorder) || \
LIBSYSCALLS_IS_BYTEORDER_END((DESC)->byteorder[INDEX]))
};
/**
* Details about of field in a `struct` or `union`
*/
struct libsyscalls_structure_field {
/**
* The name of the field, or `NULL` if anonymous
*/
const char *name;
/**
* The fields data type
*/
enum_libsyscalls_datatype type : 16;
/**
* The number bytes from the data type that is used
* for the field, 0 if the field is not a bit field
*/
unsigned short int bitlength : 16;
/**
* If 1, the field is expected to be populated
* before the system call is entered
*/
unsigned short int input_field : 1;
/**
* If 1, the field is expected to be populated
* by the system call unless it returns an error
*/
unsigned short int output_field : 1;
/**
* If 1, the field is expected to be populated
* by the system call provided that it returns
* an error
*/
unsigned short int error_field : 1;
/**
* If 1, if the field's value can be resolved
* into a symbolic string by the library
*/
unsigned short int symbolic_field : 1;
/**
* Only used with .input_field set to 1
*
* If 1, it is probably not an error if the
* field is partially initialised as long as all
* its memory is allocated
*
* In the case that a field is split using for
* example one field with the type
* LIBSYSCALLS_TYPE_UINT64_FRONT_32 and another
* field with the type
* LIBSYSCALLS_TYPE_UINT64_BACK_32 (these two
* (for some split types, their may be more than
* two fields) fields will have the same name),
* it is one is partially initialised and the
* other completely uninitialised. Generally,
* as long as at least one of the parts are
* partially initialised, the application should
* not, unless it has more detailed knowledge
* about the system call, assume that there is
* an error. This happens because kernel's version
* of the library uses a scalar field, where as
* the userspace version (usually libc's version)
* uses a union of differently sized field. It
* is not necessarily the case that it can be
* known which field in the union is used: for
* example in epoll_ctl(2), it is completely up
* to the application, and the application has
* no way of telling the kernel which is used,
* and the kernel will in epoll_wait(2) simply
* return the union's value as it was set, meaning
* that some bits may be effectively uninitialised.
* Even if the field is complete uninitialised,
* it may still be the case that this is not an
* error, however, it probably is an error; for
* example in the case of epoll(7), it is completely
* possible, albeit unlikely (because it's silly),
* that the user calls epoll_ctl(2) without the
* `.data` field set, because it doesn't look at
* in when epoll_wait(2) returns, but insteads
* just does unblocking I/O one each file
* descriptor it has added to the epoll(7).
*/
unsigned short int partial_init_ok : 1;
/**
* If 1, the field is a pointer that the reads from
*
* Note that there are types that fundamentally are
* pointers (such as strings), for these, this bit
* is not set unless it is a pointer to a string
*
* This field may always 0 when .input_field is 0
*/
unsigned short int input_pointer : 1;
/**
* If 1, the field is a pointer that the writes to
*
* Note that there are types that fundamentally are
* pointers (such as strings), for these, this bit
* is not set unless it is a pointer to a string
*/
unsigned short int output_pointer : 1;
/**
* If 1, it has been determined that the field is
* not being used (usually because that it's not
* the active field in a `union` or because a
* flag somewhere in the `struct` is either set or
* cleared)
*/
unsigned short int unused : 1;
unsigned short int padding1__ : 16 - (8*1);
#if LIBSYSCALLS_IS_PADDING_REQUIRED_(3, 16, LIBSYSCALLS_POINTER_BIT_)
# if !LIBSYSCALLS_CAN_ALIGN_(3, 16, CHAR_BIT)
# error Sorry, we require that the a byte is no longer than (3*16) bits while evenly dividing (3*16) bits
# endif
char padding2__[LIBSYSCALLS_PAD_(sizeof(void *)/sizeof(char), (3*16)/CHAR_BIT)];
#endif
/**
* Data type description
*
* The application is free to make changes, however,
* however the pointers themselves must not be touched
*/
union {
/**
* Description to use if `.type` refers to a
* `struct` or `union`; that is, if
* `(.type & ~LIBSYSCALLS_TYPEBITSMASK) >=
* LIBSYSCALLS_TYPEOFFSET_STRUCTS_AND_UNIONS`
*/
struct libsyscalls_structure_description *structure;
/**
* Description to use if `.type` does not refer
* to a `struct` or `union`; that is, if
* `(.type & ~LIBSYSCALLS_TYPEBITSMASK) <
* LIBSYSCALLS_TYPEOFFSET_STRUCTS_AND_UNIONS`
*/
struct libsyscalls_datatype_description *nonstructure;
} type_description;
};
/**
* Details about a `struct` or `union`
*/
struct libsyscalls_structure_description {
/**
* The alignment, in bits, that shall
* be used for the data type; never 0
*/
unsigned short int alignment : 16;
/**
* The size of the data type, in bits
*
* If 0, the data type's size is flexible and its
* size is determined by its content but not enough of
* it was provided to determine its size.
* .relative_position_of_size or .absolute_position_of_size
* may or may not be useful to determine the size of the
* data type, if .size is 0 (and .array_size is 1, which
* it in such case must be).
*/
unsigned short int size : 16;
/**
* The number of fields in the `struct`/`union`
*/
unsigned short int num_fields : 14;
/**
* If 1, the data type is a `union`,
* if 0, the data type is a `struct`
*/
unsigned short int is_union : 1;
/**
* Only used if .array_size is 0
*
* Assuming the kernel writes into the array, if 1, the number
* of elements written to the array (starting from its beginning)
* is writting into the array size parameter/field if it is
* marked as an output parameter/field and return otherwise;
* if 0, the number of bits written must be infered from its
* contents, e.g. via null byte termination (how this is done
* depends on the system call)
*/
unsigned short int fill_is_known : 1;
/**
* The size (in number of elements) of the array the data type
* is used in, or 1 if the data type was not an array or
* 0 if the array size is determined by another parameter/field
*
* If 1, .relative_position_of_size will be set to 0,
* and .absolute_position_of_size -1, however if that is not
* the case and this field is set to 1, then .size (which may
* or may not be 0 at this point) is determined by the indicated
* parameter
*/
unsigned short int array_size : 16;
/**
* The position of the array's or structure's size in the
* parameter/field list relative to the array/structure,
* e.g. 1 for the next parameter/field or -1 for the previous
* parameter/field
*
* If 0, use .absolute_position_of_size instead
*/
signed short int relative_position_of_size : 16;
/**
* The position of the array's or structure's size in the
* parameter/field list, indexed starting from 0
*
* If -1, use .relative_position_of_size instead
*/
signed short int absolute_position_of_size : 16;
/**
* This is used internally by `libsyscalls_get_struct_display_info`
* to find out how values ought to be printed to be both human
* and machines friendly (symbolic names are indeed easier for
* the application to deal with as their values can depend on
* the architecture)
*
* If this is value is 0, `libsyscalls_get_struct_display_info`
* will not be able to provide any useful information, which
* would either be because everything is provided here (in
* `struct libsyscalls_structure_description`) or because the
* library hasn't yet added full support for the structure
*/
LIBSYSCALLS_SYMBOL_PRINTER symbol_printer : 16;
#if LIBSYSCALLS_IS_PADDING_REQUIRED_(7, 16, LIBSYSCALLS_POINTER_BIT_)
# if !LIBSYSCALLS_CAN_ALIGN_(7, 16, CHAR_BIT)
# error Sorry, we require that the a byte is no longer than (7*16) bits while evenly dividing (7*16) bits
# endif
char padding__[LIBSYSCALLS_PAD_(sizeof(void *)/sizeof(char),
(7*16)/CHAR_BIT)];
#endif
/**
* Information about each field in the `struct`/`union`
*/
struct libsyscalls_structure_field fields[LIBSYSCALLS_FLEXABLE_OR_NFIELDS_];
};
/**
* Return a description of a libsyscalls error
*
* @param error The libsyscalls error
* @return Description of the error, the first
* character will be in uppercase
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__const__, __returns_nonnull__, __warn_unused_result__)
const char *
libsyscalls_strerror(enum libsyscalls_error error);
/**
* Print a line with a description of a
* libsyscalls error to standard error
*
* @param prefix Unless NULL or the empty string, the description
* will be prefixed with this string followed by ": "
* @param error The libsyscalls error
*/
void
libsyscalls_perror(const char *prefix, enum libsyscalls_error err);
/**
* Get the valid range system call numbers
*
* @param os The operating system the range shall valid for
* @param arch The architecture the range shall valid for
* @param min_out Output parameter for the lowest used
* system call number (may be NULL)
* @param max_out Output parameter for the highest used
* system call number (may be NULL)
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
*
* This function always fails if the selected combination
* of operating system (`os`) and architecture (`arch`) is
* unsupported
*
* Beware that range is used system call numbers are [*min_out, *max_out]
* (not [*min_out, *max_out - 1]) but there may still be numbers within
* this range that does not correspond to a system call
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__,
__access__(__write_only__, 3),
__access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_get_syscall_range(enum libsyscalls_os os, enum libsyscalls_arch arch,
long long int *min_out, long long int *max_out);
/**
* Get the description of a system call
*
* @param os The operating system the range shall valid for
* @param arch The architecture the range shall valid for
* @param syscall_nr The system call's number
* @param syscall_out Output parameter for the system call description
* (the argument may be NULL, *syscall_out will
* never be set to NULL)
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
* LIBSYSCALLS_E_NOSUCHSYSCALL - `syscall_nr` does not correspond to a known
* system call for the selected architecture (`arch`)
* on the selected operating system (`os`)
*
* This function always fails if the selected combination
* of operating system (`os`) and architecture (`arch`) is
* unsupported
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__,
__access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_get_syscall(enum libsyscalls_os os, enum libsyscalls_arch arch,
long long int syscall_nr,
const struct libsyscalls_syscall **syscall_out);
/**
* Get the system call errors defined by an operating system
*
* If an error has multiple names, it is only listed once
* and the listed name is arbitrary
*
* The returned listing will be sorted by the error numbers
* in ascending order
*
* @param os The operating system whose errors shall be returned
* @param arch The architecture the error numbers shall be valid for
* @param errors_out Output parameter for the error list
* (may be NULL, never filled with NULL)
* @param num_errors_out Output parameter for the number of errors returned
* in `*errors_out` (may be NULL) (if `errors_out` is NULL,
* the number that would be returned is stored)
* @param are_signed_out Output parameter for whether the error numbers are
* signed (may be NULL)
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
* LIBSYSCALLS_E_NOERRORS - The operating system does not use named error numbers
*
* This function will always fail if the operating system (`os`)
* is not supported, however it may be successful even if the
* architecture (`arch`) not supported
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 3),
__access__(__write_only__, 4),
__access__(__write_only__, 5))
enum libsyscalls_error
libsyscalls_get_syscall_errors(enum libsyscalls_os os, enum libsyscalls_arch arch,
const struct libsyscalls_named_number **errors_out,
size_t *num_errors_out, int *are_signed_out);
/**
* Get the system signals defined by an operating system
*
* If a signal has multiple names, it is only listed once
* and the listed name is arbitrary
*
* The returned listing will be sorted by the signal
* numbers in ascending order
*
* @param os The operating system whose errors shall be returned
* @param arch The architecture the error numbers shall be valid for
* @param signals_out Output parameter for the signal list
* (may be NULL, never filled with NULL)
* @param num_signals_out Output parameter for the number of signals returned
* in `*signals_out` (may be NULL) (if `signals_out` is
* NULL, the number that would be returned is stored)
* @param are_signed_out Output parameter for whether the signal numbers are
* signed (may be NULL)
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
* LIBSYSCALLS_E_NOSIGNALS - The operating system does not use named signal numbers
*
* This function will always fail if the operating system (`os`)
* is not supported, however it may be successful even if the
* architecture (`arch`) not supported
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 3),
__access__(__write_only__, 4),
__access__(__write_only__, 5))
enum libsyscalls_error
libsyscalls_get_signals(enum libsyscalls_os os, enum libsyscalls_arch arch,
const struct libsyscalls_named_number **signals_out,
size_t *num_signals_out, int *are_signed_out);
/**
* Finds a named number in a sorted array by its signed number
*
* @param key The signed number of the named number to find
* @param base The array of named numbers, sorted in ascending
* order by their signed numbers
* @param n The number of elements in `base`
* @return The element in `base` whose signed number is `key`,
* `NULL` if not found
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __pure__,
__access__(__read_only__, 2, 3))
const struct libsyscalls_named_number *
libsyscalls_find_signed_named_number(signed long long int key,
const struct libsyscalls_named_number *base, size_t n);
/**
* Finds a named number in a sorted array by its unsigned number
*
* @param key The unsigned number of the named number to find
* @param base The array of named numbers, sorted in ascending
* order by their unsigned numbers
* @param n The number of elements in `base`
* @return The element in `base` whose unsigned number is `key`,
* `NULL` if not found
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __pure__,
__access__(__read_only__, 2, 3))
const struct libsyscalls_named_number *
libsyscalls_find_unsigned_named_number(unsigned long long int key,
const struct libsyscalls_named_number *base, size_t n);
/**
* Finds a named number in a sorted array by its number
*
* @param key The number of the named number to find
* @param is_signed Whether the numbers are signed
* @param base The array of named numbers, sorted in ascending
* order by their numbers
* @param n The number of elements in `base`
* @return The element in `base` whose number is `key`,
* `NULL` if not found
*
* If `is_signed` is non-zero, `key` is reinterpreted (not cast) as a signed number;
* thus it is important that if `key` uses all bits in `long long int`,
* would be an error to take a `int`, reinterpret it as an `unsigned int`,
* and input it to as `key` casting it to `unsigned long long int`; rather
* an `int` must first be cast to `long long int`, and then reinterpreted
* as a `unsigned long long int` before it is input as `key`. Using
* `libsyscalls_find_signed_named_number` instead removes this complication
* in such a senario.
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __pure__,
__access__(__read_only__, 3, 4))
inline const struct libsyscalls_named_number *
libsyscalls_find_named_number(unsigned long long int key, int is_signed,
const struct libsyscalls_named_number *base, size_t n)
{
signed long long int skey = *(signed long long int *)&key;
return is_signed ? libsyscalls_find_signed_named_number(skey, base, n)
: libsyscalls_find_unsigned_named_number(key, base, n);
}
/**
* Get system call information tweak for the arguments passed
* to the system call, as well as information about how to
* print named values in the arguments and return
*
* @param os The operating system the system call was invoked on
* @param arch The architecture the system call was invoked on
* @param syscall The ABI of the system call (see libsyscalls_get_syscall)
* @param syscall_number The system call's number
* @param syscall_arguments The values store in register (as upon system call entry)
* the used for the system call, in the order the registers
* are used as system call arguments
* @param info_out Output parameter for the additional system call information;
* the caller responsible for deallocating the `*info_out`
* with free(3) when it is no longer needed. Be aware that
* `*info_out` will only be set when LIBSYSCALLS_E_OK is
* returned.
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
* LIBSYSCALLS_E_NOMEM - Failed to allocate memory for `*info_out`
* LIBSYSCALLS_E_INVAL - One of the arguments was NULL
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __nonnull__,
__access__(__read_only__, 3),
__access__(__write_only__, 6))
enum libsyscalls_error
libsyscalls_get_syscall_display_info(enum libsyscalls_os os, enum libsyscalls_arch arch,
const struct libsyscalls_syscall_abi *syscall,
long long int syscall_number,
const unsigned long long int *syscall_arguments,
struct libsyscalls_syscall_display_info **info_out);
/**
* Get information on how an instance of non-struct, non-union
* data type is to be parsed
*
* Do not use for data types inside structures,
* instead, use `.type_description.nonstructure`
* in the structure's field, as it may contain
* important adjustments
*
* @param os The operating system the data type is used on
* @param arch The architecture the data type is used on
* @param datatype The data type, `LIBSYSCALLS_TYPE_DYNAMIC` can
* be used to get the size of the registers used
* as system call parameters
* @param description_out Output parameter for the type description
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
* LIBSYSCALLS_E_INVAL - `datatype` is not a valid data type
* LIBSYSCALLS_E_NOSUCHTYPE - `datatype` does not exist on the selected
* operating system (`os`) or architecture (`arch`)
* LIBSYSCALLS_E_ISSTRUCT - `datatype` represents a structure or union,
* or an array of a structure or union
*
* The function may complete successfully for some data
* types even if it for other data types would return
* LIBSYSCALLS_E_OSNOSUP or LIBSYSCALLS_E_ARCHNOSUP
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__,
__access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_get_datatype_description(enum libsyscalls_os os, enum libsyscalls_arch arch,
enum libsyscalls_datatype datatype,
struct libsyscalls_datatype_description *description_out);
/**
* Get the alignment used for or a scalar integer data type
*
* This function does not discriminate between optimal and mandatory
* alignment; some CPUs operate on misalign data for some types,
* whereas other CPUs cannot, but even if it can operate on misalign
* data it will be less efficient. This function returns (into
* `*alignment_out` the optional (default) alignment even there is
* a mandatory alignment that is smaller. As a caveat, the operating
* system may proscribe an multiple of the optimal alignment
* (usually this would be the size of the data type instead of the
* optimal alignment), in such cases, that proscribed alignment will
* be returned instead.
*
* @param os The operating system the data type is used on
* @param arch The architecture the data type is used on
* @param width_in_bits The width of the integer, in bits
* @param alignment_out Output parameter for the alignment, in bits
* (may be NULL, will never be filled with 0)
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
* LIBSYSCALLS_E_INVAL - `width_in_bits` is 0
* LIBSYSCALLS_E_NOSUCHTYPE - The selected architecture (`arch`) does not
* support any integer width the specified
* width (`width_in_bits`), or the operating
* system (`os`) does not support the data type
* (that would only be the case if the data type
* uses a new register that must be specifically
* supported in the operating system's context
* switching)
*
* The function may complete successfully even if out ought to
* return LIBSYSCALLS_E_ARCHNOSUP, in such cases, the result
* is indeed reliable
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__,
__access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_get_integer_alignment(enum libsyscalls_os os, enum libsyscalls_arch arch,
unsigned width_in_bits, unsigned *alignment_out);
/**
* Parse a string of bits as a signed integer
*
* In case `representation` is LIBSYSCALLS_SIGN_UNDETERMINED,
* the bits are parsed as an unsigned integer
*
* @param value_in The bits to parse as a signed integer
* @param representation The sign representation used on the interger
* @param bits The number of bits in the integer
* @param value_out Output parameter for the absolute value
* of the signed integer (may be NULL)
* @param negative_out Output parameter for whether the signed
* integer is negative (may be NULL)
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library
* LIBSYSCALLS_E_INVAL - `bits` is 0
* LIBSYSCALLS_E_INVAL - `bits > sizeof(long long int) * CHAR_BIT`
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 4),
__access__(__write_only__, 5))
enum libsyscalls_error
libsyscalls_parse_signed_integer(unsigned long long int value_in,
enum libsyscalls_datatype_sign_representation representation,
size_t bits, unsigned long long int *value_out, int *negative_out);
/**
* Create a string of bits representing a signed integer
*
* In case `representation` is LIBSYSCALLS_SIGN_UNDETERMINED,
* the bit string will represent an unsigned integer
*
* @param value_in The absolute value if the signed integer
* @param negative Whether the signed integer is negative
* @param representation The sign representation used on the interger
* @param bits The number of bits in the integer
* @param value_out Output parameter for the bit string (may be NULL)
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library
* LIBSYSCALLS_E_INVAL - `bits` is 0
* LIBSYSCALLS_E_INVAL - `bits > sizeof(long long int) * CHAR_BIT`
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 5))
enum libsyscalls_error
libsyscalls_make_signed_integer(unsigned long long int value_in, int negative,
enum libsyscalls_datatype_sign_representation representation,
size_t bits, unsigned long long int *value_out);
/**
* Take bits from a section of a split value
* and shift its bit into place, so that the OR
* of the result for each section creates the
* original unsplit value
*
* If `section` is LIBSYSCALLS_SECTION_UNDETERMINED,
* no changes will be made
*
* @param value_in The contiguous bits in the section of the value
* @param bits The number of bits in the section of the value
* @param section The section of the value
* @param value_out Output parameter for the value with its
* bits shifted into place (may be NULL)
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library
* LIBSYSCALLS_E_INVAL - `bits` is invalid for `section`
* LIBSYSCALLS_E_INVAL - `bits > sizeof(long long int) * CHAR_BIT`
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_unsection_value(unsigned long long int value_in, size_t bits,
enum libsyscalls_datatype_section section,
unsigned long long int *value_out);
/**
* Create a split section from a value
*
* If `section` is LIBSYSCALLS_SECTION_UNDETERMINED,
* no changes will be made
*
* @param value_in The whole value
* @param bits The number of bits in the whole value
* @param section The section of the value to return
* @param value_out Output parameter for bits in the section
* value shifted into contiguity (may be NULL)
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library
* LIBSYSCALLS_E_INVAL - `bits` is invalid for `section`
* LIBSYSCALLS_E_INVAL - `bits > sizeof(long long int) * CHAR_BIT`
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_section_value(unsigned long long int value_in, size_t bits,
enum libsyscalls_datatype_section section,
unsigned long long int *value_out);
/**
* Converts a value from the tracee's endian to the tracer's endian
*
* @param value_in Buffer containing the value to convert
* (does not need to be aligned)
* @param offset_in Offset in `value_in`, in bits
* @param type Details about the data type
* @param value_out Output parameter for the value in the tracer's endian
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_INVAL - Either parameter is NULL
* LIBSYSCALLS_E_INVAL - The data type is too wide
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__nonnull__,
__access__(__read_only__, 1),
__access__(__read_only__, 3),
__access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_to_tracer_endian(const void *value_in, size_t offset_in,
const struct libsyscalls_datatype_description *type,
unsigned long long int *value_out);
/**
* Converts a value from the tracer's endian to the tracee's endian
*
* @param value_in Buffer containing the value to convert
* @param type Details about the data type
* @param value_out Output parameter for the value in the tracee's
* endian (does not need to be aligned); preexisting
* bits that do not overlap with the position of the
* value will be retained
* @param out_offset Offset in `value_out`, in bits
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_INVAL - Either parameter is NULL
* LIBSYSCALLS_E_INVAL - The data type is too wide
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__nonnull__,
__access__(__read_only__, 2),
__access__(__read_write__, 3))
enum libsyscalls_error
libsyscalls_to_tracee_endian(unsigned long long int value_in,
const struct libsyscalls_datatype_description *type,
void *value_out, size_t out_offset);
/**
* Get information on how an instance of struct or union is to be parsed
*
* Do not use for structures inside other structures,
* instead, use `.type_description.structure` in the
* structure's field, as it may contain important
* adjustments
*
* @param os The operating system the data type is used on
* @param arch The architecture the data type is used on
* @param datatype The data type
* @param data The data that is to be parsed
* (may be `NULL` if `data_size` is 0)
* @param data_size The number of bytes available in `data`,
* may be short or in excess
* @param description_out Output parameter for the type description;
* the caller responsible for deallocating the `*info_out`
* with free(3) when it is no longer needed. Be aware that
* `*info_out` will only be set when LIBSYSCALLS_E_OK is
* returned.
*
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
* LIBSYSCALLS_E_INVAL - `datatype` is not a valid data type
* LIBSYSCALLS_E_NOSUCHTYPE - `datatype` does not exist on the selected
* operating system (`os`) or architecture (`arch`)
* LIBSYSCALLS_E_ISNOTSTRUCT - `datatype` does not represent a structure or
* union, nor an array of structure or union
*
* The function may complete successfully for some data
* types even if it for other data types would return
* LIBSYSCALLS_E_ARCHNOSUP
*/
#if 0 /* work in progress */
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__,
__access__(__read_only__, 4, 5),
__access__(__write_only__, 6))
enum libsyscalls_error
libsyscalls_get_struct_description(enum libsyscalls_os os, enum libsyscalls_arch arch,
enum libsyscalls_datatype datatype,
const void *data, size_t data_size,
struct libsyscalls_structure_description **description_out);
#endif
/* TODO add libsyscalls_get_struct_display_info */
#include "libsyscalls/internal-end.h"
#endif