/* 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