summaryrefslogtreecommitdiffstats
path: root/libsyscalls.h
diff options
context:
space:
mode:
Diffstat (limited to 'libsyscalls.h')
-rw-r--r--libsyscalls.h1327
1 files changed, 1327 insertions, 0 deletions
diff --git a/libsyscalls.h b/libsyscalls.h
new file mode 100644
index 0000000..f63d023
--- /dev/null
+++ b/libsyscalls.h
@@ -0,0 +1,1327 @@
+/* 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(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 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")
+
+/**
+ * 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,
+ LIBSYSCALLS_ARCH_AMD64,
+ LIBSYSCALLS_ARCH_AMD64_X32, /* 32-bit ABI, not traditional 32-bit x86 ISA */
+ LIBSYSCALLS_ARCH_ARM_OABI,
+ LIBSYSCALLS_ARCH_ARM_EABI,
+ LIBSYSCALLS_ARCH_IA64,
+ LIBSYSCALLS_ARCH_M68K,
+ LIBSYSCALLS_ARCH_MICROBLAZE,
+ LIBSYSCALLS_ARCH_MIPS_O32,
+ LIBSYSCALLS_ARCH_MIPS_N32,
+ LIBSYSCALLS_ARCH_MIPS_N64,
+ LIBSYSCALLS_ARCH_PARISC_32,
+ LIBSYSCALLS_ARCH_PARISC_64,
+ LIBSYSCALLS_ARCH_POWERPC_32,
+ LIBSYSCALLS_ARCH_POWERPC_64,
+ LIBSYSCALLS_ARCH_POWERPC_NOSPU,
+ LIBSYSCALLS_ARCH_POWERPC_SPU,
+ LIBSYSCALLS_ARCH_S390_32,
+ LIBSYSCALLS_ARCH_S390_64,
+ LIBSYSCALLS_ARCH_SH,
+ LIBSYSCALLS_ARCH_SPARC_32,
+ LIBSYSCALLS_ARCH_SPARC_64,
+ LIBSYSCALLS_ARCH_I386,
+ LIBSYSCALLS_ARCH_XTENSA
+};
+
+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
+ * infered 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 or 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)) */\
+ 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_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_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_ITIMERSPEC ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_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_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 /* size is always in the next argument */\
+ 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_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 */
+
+ /* 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 unless returned */
+
+ /* 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
+};
+
+enum libsyscalls_syscall_category {
+ LIBSYSCALLS_CAT_SUPPORT_PENDING,
+ LIBSYSCALLS_CAT_NOT_IMPLEMENTED,
+ LIBSYSCALLS_CAT_NETWORK_ENABLED_IPC,
+ LIBSYSCALLS_CAT_IPC,
+ LIBSYSCALLS_CAT_FILESYSTEM,
+ LIBSYSCALLS_CAT_FILE_DESCRIPTORS,
+ LIBSYSCALLS_CAT_PROCESSES,
+ LIBSYSCALLS_CAT_LOGGING,
+ LIBSYSCALLS_CAT_TIME,
+ LIBSYSCALLS_CAT_SIGNALS,
+ LIBSYSCALLS_CAT_MEMORY,
+ LIBSYSCALLS_CAT_SYSTEM,
+ LIBSYSCALLS_CAT_SCHEDULING
+};
+
+/* IPC that can but does not have to be over a network,
+ * "bind" system calls can create inodes in the file system */
+enum libsyscalls_syscall_network_enabled_ipc_subcategory {
+ LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_ACCEPT,
+ LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_LISTEN,
+ LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_BIND,
+ LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_CONNECT,
+ LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_STAT
+};
+
+enum libsyscalls_syscall_ipc_subcategory {
+ LIBSYSCALLS_IPC_SUBCAT_ADVISORY_FILE_LOCK,
+ LIBSYSCALLS_IPC_SUBCAT_MANDATORY_FILE_LOCK,
+ LIBSYSCALLS_IPC_SUBCAT_FILE_LOCK, /* may or may not be advisory (e.g. flock(2) since Linux 5.5) */
+ LIBSYSCALLS_IPC_SUBCAT_CONTROL, /* includes creation, deletion, and stat */
+ LIBSYSCALLS_IPC_SUBCAT_ATTACH,
+ LIBSYSCALLS_IPC_SUBCAT_DETACH,
+ LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE,
+ LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE_WITH_RELATIVE_TIMEOUT,
+ LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE_WITH_ABSOLUTE_TIMEOUT
+};
+
+/* syscalls that can work on either paths or FDs ([1]) are located here */
+enum libsyscalls_syscall_filesystem_subcategory {
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_STAT,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_MODIFY,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_SYNC, /* [1] some of these only work on file descriptors or memory maps */
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_UNLINK,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK_OR_UNLINK,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_UMASK, /* modifies the process, not the filesystem */
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_MOUNTPOINT,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_STATFS,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_WRITE,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_READLINK,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_MONITOR,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_QUOTA
+};
+
+/* syscalls that work FDs but not paths are located here */
+enum libsyscalls_syscall_file_descriptors_subcategory {
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_STAT,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_MODIFY,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_DUP_OR_CLOSE, /* includes partial close (shutdown) */
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CLOSE_OR_UNSHARE,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ, /* may have timeout */
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_WRITE, /* may have timeout */
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_SEEK,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_PEEK, /* may have timeout */
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_AND_WRITE,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_PEEK_AND_WRITE,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK_AND_WRITE,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK_AND_STAT,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_ADVISE,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_STATFS,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CREATE,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CREATE_POLL,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_POLL /* can work as pause or relative sleep */
+};
+
+enum libsyscalls_syscall_processes_subcategory {
+ LIBSYSCALLS_PROCESSES_SUBCAT_EXIT,
+ LIBSYSCALLS_PROCESSES_SUBCAT_STAT_SELF,
+ LIBSYSCALLS_PROCESSES_SUBCAT_STAT_CHILD, /* may also stat self */
+ LIBSYSCALLS_PROCESSES_SUBCAT_STAT_PARENT, /* may also stat self or children */
+ LIBSYSCALLS_PROCESSES_SUBCAT_STAT_OTHER,
+ LIBSYSCALLS_PROCESSES_SUBCAT_CHANGE_PERMISSIONS,
+ LIBSYSCALLS_PROCESSES_SUBCAT_CLONE,
+ LIBSYSCALLS_PROCESSES_SUBCAT_EXEC,
+ LIBSYSCALLS_PROCESSES_SUBCAT_CHDIR,
+ LIBSYSCALLS_PROCESSES_SUBCAT_CHROOT,
+ LIBSYSCALLS_PROCESSES_SUBCAT_SESSION /* vhangup, setsid, setpgid */
+};
+
+enum libsyscalls_syscall_logging_subcategory {
+ LIBSYSCALLS_LOGGING_SUBCAT_PROCESSES
+};
+
+enum libsyscalls_syscall_time_subcategory {
+ LIBSYSCALLS_TIME_SUBCAT_GET_OR_SET,
+ LIBSYSCALLS_TIME_SUBCAT_GET,
+ LIBSYSCALLS_TIME_SUBCAT_SET,
+ LIBSYSCALLS_TIME_SUBCAT_INTROSPECT,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_READ,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_READ,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_READ,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_WITH_READ,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_WITH_READ,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_WITH_READ,
+ LIBSYSCALLS_TIME_SUBCAT_SLEEP_RELATIVE,
+ LIBSYSCALLS_TIME_SUBCAT_SLEEP_ABSOLUTE,
+ LIBSYSCALLS_TIME_SUBCAT_SLEEP
+};
+
+enum libsyscalls_syscall_signals_subcategory {
+ LIBSYSCALLS_SIGNALS_SUBCAT_PAUSE,
+ LIBSYSCALLS_SIGNALS_SUBCAT_KILL
+};
+
+/* These may work on memory mapped files */
+enum libsyscalls_syscall_memory_subcategory {
+ LIBSYSCALLS_MEMORY_SUBCAT_ALLOCATE,
+ LIBSYSCALLS_MEMORY_SUBCAT_READ,
+ LIBSYSCALLS_MEMORY_SUBCAT_WRITE,
+ LIBSYSCALLS_MEMORY_SUBCAT_ADVISE,
+ LIBSYSCALLS_MEMORY_SUBCAT_WRITE_OR_ADVISE,
+ LIBSYSCALLS_MEMORY_SUBCAT_LOCK,
+ LIBSYSCALLS_MEMORY_SUBCAT_UNLOCK,
+ LIBSYSCALLS_MEMORY_SUBCAT_STAT /* stats memory allocated to the process, not system resources */
+};
+
+enum libsyscalls_syscall_system_subcategory {
+ LIBSYSCALLS_SYSTEM_SUBCAT_SWAP,
+ LIBSYSCALLS_SYSTEM_SUBCAT_REBOOT,
+ LIBSYSCALLS_SYSTEM_SUBCAT_GET_NAME,
+ LIBSYSCALLS_SYSTEM_SUBCAT_SET_NAME,
+ LIBSYSCALLS_SYSTEM_SUBCAT_STAT,
+ LIBSYSCALLS_SYSTEM_SUBCAT_RANDOM,
+ LIBSYSCALLS_SYSTEM_SUBCAT_FUNDAMENTAL
+};
+
+enum libsyscalls_syscall_scheduling_subcategory {
+ LIBSYSCALLS_SCHEDULING_SUBCAT_YEILD,
+ LIBSYSCALLS_SCHEDULING_SUBCAT_SET,
+ LIBSYSCALLS_SCHEDULING_SUBCAT_GET,
+ LIBSYSCALLS_SCHEDULING_SUBCAT_INTROSPECT
+};
+
+union libsyscalls_syscall_subcategory {
+ enum_libsyscalls_syscall_network_enabled_ipc_subcategory network_enabled_ipc;
+ enum_libsyscalls_syscall_ipc_subcategory ipc;
+ enum_libsyscalls_syscall_filesystem_subcategory filesystem;
+ enum_libsyscalls_syscall_file_descriptors_subcategory file_descriptors;
+ enum_libsyscalls_syscall_processes_subcategory processes;
+ enum_libsyscalls_syscall_logging_subcategory logging;
+ enum_libsyscalls_syscall_time_subcategory time;
+ enum_libsyscalls_syscall_signals_subcategory signals;
+ enum_libsyscalls_syscall_memory_subcategory memory;
+ enum_libsyscalls_syscall_system_subcategory system;
+ enum_libsyscalls_syscall_scheduling_subcategory 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
+ * 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
+ * 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 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 *, unsigned long long int *, char *);
+
+/**
+ * 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(long) / 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 to print
+ * 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 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 the data type was split into
+ *
+ * @param S:enum libsyscalls_datatype_section The data type section information
+ * @return :unsigned int The number registers 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)
+};
+
+/**
+ * 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
+ */
+ 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
+ */
+ unsigned array_size;
+
+ /**
+ * Only used if .array_size is 0
+ *
+ * The position of the arrays size in the parameter list
+ * relative to the array, e.g. 1 for the next parameter
+ * or -1 for the previous parameter
+ *
+ * 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 arrays size in the parameter 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 if it
+ * is marked as an output parameter 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;
+
+ /**
+ * Additional information about what the value represents
+ */
+ enum libsyscalls_datatype_annotation annotation;
+
+ /**
+ * What part of the value is stored in the instance
+ */
+ enum libsyscalls_datatype_section section;
+
+ /**
+ * This is a ~0 terminated 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 ARE NOT shifted,
+ * there is always a value in .byteorder that is 0,
+ * unless .byteorder[0] is ~0
+ */
+ unsigned char byteorder[32];
+};
+
+
+/**
+ * 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);
+
+/**
+ * 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 *, enum libsyscalls_error);
+
+/**
+ * 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`)
+ *
+ * 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__)
+enum libsyscalls_error
+libsyscalls_get_syscall_range(enum libsyscalls_os, enum libsyscalls_arch, long long int *, long long int *);
+
+/**
+ * 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 syscallnr 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 - `syscallnr` does not correspond to a known
+ * system call for the selected architecture (`arch`)
+ * on the selected operating system (`os`)
+ */
+LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__)
+enum libsyscalls_error
+libsyscalls_get_syscall(enum libsyscalls_os, enum libsyscalls_arch, long long int, const struct libsyscalls_syscall **);
+
+/**
+ * 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)
+ * @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
+ */
+enum libsyscalls_error
+libsyscalls_get_syscall_errors(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_named_number **, size_t *);
+
+/**
+ * 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)
+ * @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
+ */
+enum libsyscalls_error
+libsyscalls_get_signals(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_named_number **, size_t *);
+
+/**
+ * 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
+ * @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__)
+enum libsyscalls_error
+libsyscalls_get_syscall_display_info(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_syscall_abi *,
+ long long int, unsigned long long int *, struct libsyscalls_syscall_display_info **);
+
+/**
+ * Get information on how an instance of data type is to be parsed
+ *
+ * @param os The operating system the data type is used on
+ * @param arch The architecture the data type is used on
+ * @param datatype The datatype, `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
+ *
+ * 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__)
+enum libsyscalls_error
+libsyscalls_get_datatype_description(enum libsyscalls_os, enum libsyscalls_arch, enum libsyscalls_datatype,
+ struct libsyscalls_datatype_description *);
+
+
+#include "libsyscalls/internal-end.h"
+#endif