/* 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")
/**
* libsyscall error numbers
*/
enum libsyscalls_error {
LIBSYSCALLS_LIST_ERRORS(LIBSYSCALLS_LIST_ERRORS_X_, LIBSYSCALLS_COMMA_)
};
/**
* Operating systems
*/
enum libsyscalls_os {
LIBSYSCALLS_OS_LINUX
};
/**
* Architectures
*/
enum libsyscalls_arch {
LIBSYSCALLS_ARCH_ALPHA,
LIBSYSCALLS_ARCH_AMD64,
LIBSYSCALLS_ARCH_AMD64_X32, /* 32-bit ABI, not traditional 32-bit x86 ISA */
LIBSYSCALLS_ARCH_ARM_OABI,
LIBSYSCALLS_ARCH_ARM_EABI,
LIBSYSCALLS_ARCH_IA64,
LIBSYSCALLS_ARCH_M68K,
LIBSYSCALLS_ARCH_MICROBLAZE,
LIBSYSCALLS_ARCH_MIPS_O32,
LIBSYSCALLS_ARCH_MIPS_N32,
LIBSYSCALLS_ARCH_MIPS_N64,
LIBSYSCALLS_ARCH_PARISC_32,
LIBSYSCALLS_ARCH_PARISC_64,
LIBSYSCALLS_ARCH_POWERPC_32,
LIBSYSCALLS_ARCH_POWERPC_64,
LIBSYSCALLS_ARCH_POWERPC_NOSPU,
LIBSYSCALLS_ARCH_POWERPC_SPU,
LIBSYSCALLS_ARCH_S390_32,
LIBSYSCALLS_ARCH_S390_64,
LIBSYSCALLS_ARCH_SH,
LIBSYSCALLS_ARCH_SPARC_32,
LIBSYSCALLS_ARCH_SPARC_64,
LIBSYSCALLS_ARCH_I386,
LIBSYSCALLS_ARCH_XTENSA
};
enum libsyscalls_datatype {
/* Type renaming, these macros will be undefined later */
#define LIBSYSCALLS_TYPE_CHAR_ARRAY LIBSYSCALLS_TYPE_BUFFER
#define LIBSYSCALLS_TYPE_CHAR_ARRAY_UNKNOWN_FILL LIBSYSCALLS_TYPE_BUFFER_UNKNOWN_FILL
/* You can use these macros classify and convert data types */
#define LIBSYSCALLS_TYPEBITSMASK 0xF000
#define LIBSYSCALLS_TYPEBITS_SCALAR 0x0000 /* predefined total width, even if aggregate */
#define LIBSYSCALLS_TYPEBITS_ARRAY 0x1000 /* count is stored in next parameter, and is updated with fill
* or returned if no outputable to the next parameter */
#define LIBSYSCALLS_TYPEBITS_ARRAY_UNKNOWN_FILL 0x2000 /* count is stored in next parameter, fill is in no way returned,
* this chould either be because the array is always (unless an
* error is returned) entirely filled or because the end is
* infered from the contents (e.g. null byte termination) */
#define LIBSYSCALLS_LIST_SPECIAL_TYPES(X, SUFFIX, D, FIRST)\
/* the type used in the system call has not yet be added recorded in the library */\
X(LIBSYSCALLS_TYPE_UNKNOWN ## SUFFIX, FIRST, "(unknown type)") D\
/* the type depends on the system call input or output */\
X(LIBSYSCALLS_TYPE_DYNAMIC ## SUFFIX,, "(undetermined type)") D\
/* the system call should never returned to the calling process (return to tracer is usually expected) */\
X(LIBSYSCALLS_TYPE_NO_RETURN ## SUFFIX,, "no_return") D\
/* either used as return type or to skip a register in the parameters
* (do not dismiss this, on some architectures a system call
* may need padding with dummy arguments to align latter
* register pairs; an application printing the system call
* must choose between omitting, printing the argument, or
* indicating that there is a dummy parameter (of course
* the latter two can be combined)) */\
X(LIBSYSCALLS_TYPE_VOID ## SUFFIX,, "void")
#define LIBSYSCALLS_LIST_SPLIT_PRIMITIVES(X, SUFFIX, D, FIRST)\
X(LIBSYSCALLS_TYPE_UINT64_HIGH_32 ## SUFFIX, FIRST, "uint64_t {. << 32}") D\
X(LIBSYSCALLS_TYPE_UINT64_LOW_32 ## SUFFIX,, "uint64_t {. & 0xFFFFFFFF}") D\
X(LIBSYSCALLS_TYPE_UINT64_FRONT_32 ## SUFFIX,, "uint64_t {((uint32_t *)&.)[0]}") D\
X(LIBSYSCALLS_TYPE_UINT64_BACK_32 ## SUFFIX,, "uint64_t {((uint32_t *)&.)[1]}") D\
X(LIBSYSCALLS_TYPE_INT64_HIGH_32 ## SUFFIX,, "int64_t {. << 32}") D\
X(LIBSYSCALLS_TYPE_INT64_LOW_32 ## SUFFIX,, "int64_t {. & 0xFFFFFFFF}") D\
X(LIBSYSCALLS_TYPE_INT64_FRONT_32 ## SUFFIX,, "int64_t {((uint32_t *)&.)[0]}") D\
X(LIBSYSCALLS_TYPE_INT64_BACK_32 ## SUFFIX,, "int64_t {((uint32_t *)&.)[1]}")
#define LIBSYSCALLS_LIST_COMPOSITE_PRIMITIVES(X, SUFFIX, D, FIRST)\
X(LIBSYSCALLS_TYPE_STRING ## SUFFIX, FIRST, "const char *") D\
X(LIBSYSCALLS_TYPE_STRINGS_THEN_NULL ## SUFFIX,, "const char **")
#define LIBSYSCALLS_LIST_UNANNOTATED_NUMERICALS(X, SUFFIX, D, FIRST)\
X(LIBSYSCALLS_TYPE_MEMORY_ADDRESS ## SUFFIX, FIRST, "void *") D\
X(LIBSYSCALLS_TYPE_CHAR ## SUFFIX,, "char") D\
X(LIBSYSCALLS_TYPE_SCHAR ## SUFFIX,, "signed char") D\
X(LIBSYSCALLS_TYPE_UCHAR ## SUFFIX,, "unsigned char") D\
X(LIBSYSCALLS_TYPE_SHORT ## SUFFIX,, "short int") D\
X(LIBSYSCALLS_TYPE_USHORT ## SUFFIX,, "unsigned short int") D\
X(LIBSYSCALLS_TYPE_INT ## SUFFIX,, "int") D\
X(LIBSYSCALLS_TYPE_UINT ## SUFFIX,, "unsigned int") D\
X(LIBSYSCALLS_TYPE_LONG ## SUFFIX,, "long int") D\
X(LIBSYSCALLS_TYPE_ULONG ## SUFFIX,, "unsigned long int") D\
X(LIBSYSCALLS_TYPE_LLONG ## SUFFIX,, "long long int") D\
X(LIBSYSCALLS_TYPE_ULLONG ## SUFFIX,, "unsigned long long int") D\
X(LIBSYSCALLS_TYPE_SSIZE ## SUFFIX,, "ssize_t") D\
X(LIBSYSCALLS_TYPE_SIZE ## SUFFIX,, "size_t") D\
X(LIBSYSCALLS_TYPE_PTRDIFF ## SUFFIX,, "ptrdiff_t") D\
X(LIBSYSCALLS_TYPE_UPTRDIFF ## SUFFIX,, "uptrdiff_t") D\
X(LIBSYSCALLS_TYPE_INTPTR ## SUFFIX,, "intptr_t") D\
X(LIBSYSCALLS_TYPE_UINTPTR ## SUFFIX,, "uintptr_t") D\
X(LIBSYSCALLS_TYPE_INT8 ## SUFFIX,, "int8_t") D\
X(LIBSYSCALLS_TYPE_UINT8 ## SUFFIX,, "uint8_t") D\
X(LIBSYSCALLS_TYPE_INT16 ## SUFFIX,, "int16_t") D\
X(LIBSYSCALLS_TYPE_UINT16 ## SUFFIX,, "uint16_t") D\
X(LIBSYSCALLS_TYPE_INT32 ## SUFFIX,, "int32_t") D\
X(LIBSYSCALLS_TYPE_UINT32 ## SUFFIX,, "uint32_t") D\
X(LIBSYSCALLS_TYPE_INT64 ## SUFFIX,, "int64_t") D\
X(LIBSYSCALLS_TYPE_UINT64 ## SUFFIX,, "uint64_t")
#define LIBSYSCALLS_LIST_ANNOTATED_NUMERICALS(X, SUFFIX, D, FIRST)\
X(LIBSYSCALLS_TYPE_INT_SIGNAL ## SUFFIX, FIRST, "int") D /* OS signal */\
X(LIBSYSCALLS_TYPE_INT_FD ## SUFFIX,, "int") D /* file descriptor */ \
X(LIBSYSCALLS_TYPE_INT_ATFD ## SUFFIX,, "int") D /* file descriptor or current working directory */ \
X(LIBSYSCALLS_TYPE_LONG_FD ## SUFFIX,, "long int") D\
X(LIBSYSCALLS_TYPE_LONG_ATFD ## SUFFIX,, "long int")
#define LIBSYSCALLS_LIST_STRUCTS_AND_UNIONS(X, SUFFIX, D, FIRST)\
X(LIBSYSCALLS_TYPE_STRUCT_AIO_SIGSET ## SUFFIX, FIRST, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_CACHESTAT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_CACHESTAT_RANGE ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_CLONE_ARGS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_EPOLL_EVENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_FILE_HANDLE ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_FUTEX_WAITV ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_IOB ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_IOVEC ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_IO_EVENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_IO_URING_PARAMS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_ITIMERSPEC ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_KEXEC_SEGMENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_LANDLOCK_RULESET_ATTR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT64 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MMAP_ARG_STRUCT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MMSGHDR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MOUNT_ATTR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MQ_ATTR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MSGBUF ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MSGHDR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_MSQID_DS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_NEW_UTSNAME ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLDOLD_UTSNAME ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_ITIMERSPEC32 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_ITIMERVAL ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_LINUX_DIRENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_SIGACTION ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_STAT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMESPEC32 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEVAL ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEVAL32 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEX32 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_UTIMBUF32 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OLD_UTSNAME ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_OPEN_HOW ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_PERF_EVENT_ATTR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_POLLFD ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_RLIMIT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_RLIMIT64 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_ROBUST_LIST_HEAD ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_RSEQ ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_RUSAGE ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SCHED_ATTR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SCHED_PARAM ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SEL_ARG_STRUCT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SEMBUF ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SEMID_DS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SHMID_DS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SIGACTION ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SIGALTSTACK ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SIGEVENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SIGINFO ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SOCKADDR ## SUFFIX,, "struct") D /* size is always in the next argument */\
X(LIBSYSCALLS_TYPE_STRUCT_STAT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_STAT64 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_STATFS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_STATFS64 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_STATX ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SYSINFO ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TIMESPEC ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TIMEX ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TIMEZONE ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TMS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_USTAT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_UTIMBUF ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_UNION_BPF_ATTR ## SUFFIX,, "union")
#define LIBSYSCALLS_LIST_FIXED_ARRAYS(X, SUFFIX, D, FIRST)\
X(LIBSYSCALLS_TYPE_2_INTS ## SUFFIX, FIRST, "int[2]") D\
X(LIBSYSCALLS_TYPE_2_INTS_FD ## SUFFIX,, "int[2]") D\
X(LIBSYSCALLS_TYPE_2_UINT32S ## SUFFIX,, "uint32[2]") D\
X(LIBSYSCALLS_TYPE_FD_SET ## SUFFIX,, "unsigned long[]") /* size depends on OS, (1024 / CHAR_BIT / sizeof(long)) in Linux */
/* these don't have any suffix */
LIBSYSCALLS_MAKE_SPECIAL_TYPES_(),
LIBSYSCALLS_MAKE_SPLIT_PRIMITIVES_(),
LIBSYSCALLS_MAKE_COMPOSITE_PRIMITIVES_(),
LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_(),
LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(),
LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(),
/* the following are always pointers unless returned */
/* size in next parameter (or the previous parameter if there is no next parameter),
* updated with fill if possible, otherwise returned (these use the suffix _ARRAY) */
LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_(_ARRAY),
LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(_ARRAY),
LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(_ARRAY),
/* size in next parameter (or the previous parameter if there is no next parameter),
* fill is in no way returned (these use the suffix _ARRAY_UNKNOWN_FILL) */
LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_(_ARRAY_UNKNOWN_FILL),
LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(_ARRAY_UNKNOWN_FILL),
LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(_ARRAY_UNKNOWN_FILL),
/* these don't have any suffix */
LIBSYSCALLS_MAKE_FIXED_ARRAYS_()
#undef LIBSYSCALLS_TYPE_CHAR_ARRAY
#undef LIBSYSCALLS_TYPE_CHAR_ARRAY_UNKNOWN_FILL
};
enum libsyscalls_syscall_category {
LIBSYSCALLS_CAT_SUPPORT_PENDING,
LIBSYSCALLS_CAT_NOT_IMPLEMENTED,
LIBSYSCALLS_CAT_NETWORK_ENABLED_IPC,
LIBSYSCALLS_CAT_IPC,
LIBSYSCALLS_CAT_FILESYSTEM,
LIBSYSCALLS_CAT_FILE_DESCRIPTORS,
LIBSYSCALLS_CAT_PROCESSES,
LIBSYSCALLS_CAT_LOGGING,
LIBSYSCALLS_CAT_TIME,
LIBSYSCALLS_CAT_SIGNALS,
LIBSYSCALLS_CAT_MEMORY,
LIBSYSCALLS_CAT_SYSTEM,
LIBSYSCALLS_CAT_SCHEDULING
};
/* IPC that can but does not have to be over a network,
* "bind" system calls can create inodes in the file system */
enum libsyscalls_network_enabled_ipc_syscall_subcategory {
LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_ACCEPT,
LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_LISTEN,
LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_BIND,
LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_CONNECT,
LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_STAT
};
enum libsyscalls_ipc_syscall_subcategory {
LIBSYSCALLS_IPC_SUBCAT_ADVISORY_FILE_LOCK,
LIBSYSCALLS_IPC_SUBCAT_MANDATORY_FILE_LOCK,
LIBSYSCALLS_IPC_SUBCAT_FILE_LOCK, /* may or may not be advisory (e.g. flock(2) since Linux 5.5) */
LIBSYSCALLS_IPC_SUBCAT_CONTROL, /* includes creation, deletion, and stat */
LIBSYSCALLS_IPC_SUBCAT_ATTACH,
LIBSYSCALLS_IPC_SUBCAT_DETACH,
LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE,
LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE_WITH_RELATIVE_TIMEOUT,
LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE_WITH_ABSOLUTE_TIMEOUT
};
/* syscalls that can work on either paths or FDs ([1]) are located here */
enum libsyscalls_filesystem_syscall_subcategory {
LIBSYSCALLS_FILESYSTEM_SUBCAT_STAT,
LIBSYSCALLS_FILESYSTEM_SUBCAT_MODIFY,
LIBSYSCALLS_FILESYSTEM_SUBCAT_SYNC, /* [1] some of these only work on file descriptors or memory maps */
LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK,
LIBSYSCALLS_FILESYSTEM_SUBCAT_UNLINK,
LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK_OR_UNLINK,
LIBSYSCALLS_FILESYSTEM_SUBCAT_UMASK, /* modifies the process, not the filesystem */
LIBSYSCALLS_FILESYSTEM_SUBCAT_MOUNTPOINT,
LIBSYSCALLS_FILESYSTEM_SUBCAT_STATFS,
LIBSYSCALLS_FILESYSTEM_SUBCAT_WRITE,
LIBSYSCALLS_FILESYSTEM_SUBCAT_READLINK,
LIBSYSCALLS_FILESYSTEM_SUBCAT_MONITOR,
LIBSYSCALLS_FILESYSTEM_SUBCAT_QUOTA
};
/* syscalls that work FDs but not paths are located here */
enum libsyscalls_file_syscall_descriptors_subcategory {
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_STAT,
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_MODIFY,
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_DUP_OR_CLOSE, /* includes partial close (shutdown) */
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CLOSE_OR_UNSHARE,
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ, /* may have timeout */
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK,
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_WRITE, /* may have timeout */
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_SEEK,
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_PEEK, /* may have timeout */
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_AND_WRITE,
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_PEEK_AND_WRITE,
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK_AND_WRITE,
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK_AND_STAT,
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_ADVISE,
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_STATFS,
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CREATE,
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CREATE_POLL,
LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_POLL /* can work as pause or relative sleep */
};
enum libsyscalls_processes_syscall_subcategory {
LIBSYSCALLS_PROCESSES_SUBCAT_EXIT,
LIBSYSCALLS_PROCESSES_SUBCAT_STAT_SELF,
LIBSYSCALLS_PROCESSES_SUBCAT_STAT_CHILD, /* may also stat self */
LIBSYSCALLS_PROCESSES_SUBCAT_STAT_PARENT, /* may also stat self or children */
LIBSYSCALLS_PROCESSES_SUBCAT_STAT_OTHER,
LIBSYSCALLS_PROCESSES_SUBCAT_CHANGE_PERMISSIONS,
LIBSYSCALLS_PROCESSES_SUBCAT_CLONE,
LIBSYSCALLS_PROCESSES_SUBCAT_EXEC,
LIBSYSCALLS_PROCESSES_SUBCAT_CHDIR,
LIBSYSCALLS_PROCESSES_SUBCAT_CHROOT,
LIBSYSCALLS_PROCESSES_SUBCAT_SESSION /* vhangup, setsid, setpgid */
};
enum libsyscalls_logging_syscall_subcategory {
LIBSYSCALLS_LOGGING_SUBCAT_PROCESSES
};
enum libsyscalls_time_syscall_subcategory {
LIBSYSCALLS_TIME_SUBCAT_GET_OR_SET,
LIBSYSCALLS_TIME_SUBCAT_GET,
LIBSYSCALLS_TIME_SUBCAT_SET,
LIBSYSCALLS_TIME_SUBCAT_INTROSPECT,
LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE,
LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE,
LIBSYSCALLS_TIME_SUBCAT_TIMER,
LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_READ,
LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_READ,
LIBSYSCALLS_TIME_SUBCAT_TIMER_READ,
LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_WITH_READ,
LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_WITH_READ,
LIBSYSCALLS_TIME_SUBCAT_TIMER_WITH_READ,
LIBSYSCALLS_TIME_SUBCAT_SLEEP_RELATIVE,
LIBSYSCALLS_TIME_SUBCAT_SLEEP_ABSOLUTE,
LIBSYSCALLS_TIME_SUBCAT_SLEEP
};
enum libsyscalls_signals_syscall_subcategory {
LIBSYSCALLS_SIGNALS_SUBCAT_PAUSE,
LIBSYSCALLS_SIGNALS_SUBCAT_KILL
};
/* These may work on memory mapped files */
enum libsyscalls_memory_syscall_subcategory {
LIBSYSCALLS_MEMORY_SUBCAT_ALLOCATE,
LIBSYSCALLS_MEMORY_SUBCAT_READ,
LIBSYSCALLS_MEMORY_SUBCAT_WRITE,
LIBSYSCALLS_MEMORY_SUBCAT_ADVISE,
LIBSYSCALLS_MEMORY_SUBCAT_WRITE_OR_ADVISE,
LIBSYSCALLS_MEMORY_SUBCAT_LOCK,
LIBSYSCALLS_MEMORY_SUBCAT_UNLOCK,
LIBSYSCALLS_MEMORY_SUBCAT_STAT /* stats memory allocated to the process, not system resources */
};
enum libsyscalls_system_syscall_subcategory {
LIBSYSCALLS_SYSTEM_SUBCAT_SWAP,
LIBSYSCALLS_SYSTEM_SUBCAT_REBOOT,
LIBSYSCALLS_SYSTEM_SUBCAT_GET_NAME,
LIBSYSCALLS_SYSTEM_SUBCAT_SET_NAME,
LIBSYSCALLS_SYSTEM_SUBCAT_STAT,
LIBSYSCALLS_SYSTEM_SUBCAT_RANDOM,
LIBSYSCALLS_SYSTEM_SUBCAT_FUNDAMENTAL
};
enum libsyscalls_scheduling_syscall_subcategory {
LIBSYSCALLS_SCHEDULING_SUBCAT_YEILD,
LIBSYSCALLS_SCHEDULING_SUBCAT_SET,
LIBSYSCALLS_SCHEDULING_SUBCAT_GET,
LIBSYSCALLS_SCHEDULING_SUBCAT_INTROSPECT
};
union libsyscalls_syscall_subcategory {
enum_libsyscalls_network_enabled_ipc_syscall_subcategory network_enabled_ipc;
enum_libsyscalls_ipc_syscall_subcategory ipc;
enum_libsyscalls_filesystem_syscall_subcategory filesystem;
enum_libsyscalls_file_descriptors_syscall_subcategory file_descriptors;
enum_libsyscalls_processes_syscall_subcategory processes;
enum_libsyscalls_logging_syscall_subcategory logging;
enum_libsyscalls_time_syscall_subcategory time;
enum_libsyscalls_signals_syscall_subcategory signals;
enum_libsyscalls_memory_syscall_subcategory memory;
enum_libsyscalls_system_syscall_subcategory system;
enum_libsyscalls_scheduling_syscall_subcategory scheduling;
};
/**
* System call interface
*/
struct libsyscalls_syscall_abi {
/**
* Classification of what the system call does
*
* Check `.category` to se which group of
* classifications to used
*/
union libsyscalls_syscall_subcategory subcategory;
/**
* Broad classification of what the system calls does
*/
enum_libsyscalls_syscall_category category : 16;
/**
* For set any bit indexed I (starting from 0), the
* system call parameter I is a pointer that the
* the system call reads from
*
* Note that there are types that fundamentally are
* pointers (such as strings), for these, this bit
* is not set unless it is a pointer to a string
*/
unsigned short int in_pointer_mask : 16;
/**
* For set any bit indexed I (starting from 0), the
* system call parameter I is a pointer that the
* the system call write to
*
* Note that there are types that fundamentally are
* pointers (such as strings), for these, this bit
* is not set unless it is a pointer to a string
*/
unsigned short int out_pointer_mask : 16;
/**
* For set any bit indexed I (starting from 0), the
* system call parameter I can be resolved into a
* symbolic string by the library
*/
unsigned short int symbolic_mask : 16;
/**
* The minimum number of arguments that must be
* passed into the system call, -1 if unknown
*/
short int min_argument_count : 6;
/**
* The maximum number of arguments that can be
* passed into the system call, -1 if unknown
*/
short int max_argument_count : 6;
/**
* If set, the library can resolve the value the
* system call returns into a symbolic string
*/
unsigned short int symbolic_return : 1;
/**
* If 1, the system call shall always either return
* an error, return the value 0, or not return at all
*/
unsigned short int expect_zero : 1;
/**
* If 1, the system call invocation must be parsed
* especially as it is not does follow what is
* proscribed for the used data types
*
* The library may use this temporarily until it
* in a later version provides a convension that
* can be followed
*/
unsigned short int queer : 1;
short int : LIBSYSCALLS_PAD_(sizeof(short int)/sizeof(char)*CHAR_BIT, 4*16 + 2*6 + 3*1);
/**
* This is internally by `libsyscalls_get_syscall_display_info`
* to find out how values ought to be printed to be both human
* and machines friendly (symbolic names are indeed easier for
* the application to deal with as their values can depend on
* the architecture), and occasionally to determine what types
* are used for on arguments whose type is argument dependent,
* and to figure which optional arguments are included in the
* system call
*
* If this is value is 0, `libsyscalls_get_syscall_display_info`
* will not be able to provide any useful information, which
* would either be because everything is provided here (in
* struct libsyscalls_syscall_abi) or because the library hasn't
* yet added full support for the system call
*/
LIBSYSCALLS_SYMBOL_PRINTER symbol_printer : 16;
/**
* The system call's return type
*/
enum_libsyscalls_datatype return_type : 16;
/**
* The type of each of the systems call's parameter
*
* The application must not read `.parameters_types[.max_argument_count]`
* or beyond, doing so will probably mean reading beyond the memory
* allocated for the instance of the structure
*/
enum_libsyscalls_datatype parameters_types[LIBSYSCALLS_FLEXABLE_OR_NPARAMS_];
};
/**
* System call description
*/
struct libsyscalls_syscall {
/**
* What system call is named
*/
const char *name;
/**
* The ABI for the system call for architecture it was
* queried for
*
* May or may not be `NULL` if the system call is defined
* but not implemented
*/
struct libsyscalls_syscall_abi *actual_syscall;
/**
* Like .actual_syscall except this is used for example when
* a 32-bit process is running on a 64-bit operating system
*
* If `NULL` use .actual_syscall
*/
struct libsyscalls_syscall_abi *actual_compat_syscall;
};
/**
* Named number (errors and signals)
*/
struct libsyscalls_named_number {
/**
* The value if the number, it is up to the
* application select signess
*
* It is usually safe to use unsigned (.u)
* as the numbers are usually positive but
* not so large that the sign bit would be
* set, unless the numbers are supposted to
* be unsigned
*/
union {
signed long long int s;
unsigned long long int u;
} number;
/**
* The name of the number, including namespacing
* (e.g. "E" prefix for errno numbers and "SIG"
* or "_SIG" prefix for singals)
*/
const char *name;
};
/**
* Function that returns a name for a value
*
* This function is called multiple times to extract
* names of multiple subvalues, for example, for
* the system call access() second parameter, it
* will return the string "X_OK", "W_OK", "R_OK",
* and "F_OK", or a subset thereof; one per invocation
*
* The proper way to use this function, is:
*
* static void
* print_unsigned(libsyscalls_symbol_printer_function *function,
* LIBSYSCALLS_SYMBOL_PRINTER_DATA *data,
* unsigned long long int value, FILE *output)
* {
* const char *sym, *prefix = "";
* char format[] = "%s%llu";
* char *fallback = strchr(format, '\0') - 1;
* do {
* sym = (*function)(data, &value, &fallback);
* if (!sym)
* break;
* fprintf(output, "%s%s", prefix, sym);
* prefix = "|";
* } while (value);
* if (value || !*prefix)
* fprintf(output, format, prefix, value);
* }
*
* @param data Data passed to the function (which that function
* has been paired with for the paramter/return),
* which it may require to known exactly what to do
* @param valuep The caller set a variable to the value pass in to
* the system call parameter (or the system call's
* return value), the value if any extract symbol
* will removed from from the variable. If the function
* return NULL, this value can be 0, in which case all
* values have been extract, otherwise (which it is not
* 0) there is some value (either invalid or not known
* to the library) that shall must be printed manually
* by the application (see `fallback_out` parameter).
* Note that, if the value 0 has a name, this function
* never return NULL if the variable reaches 0, instead
* it will repeated return the name of that value.
* @param fallback_out The caller set a variable to 0 and pointer to it,
* when this function return NULL, the variable MAY
* (even before that) have been set to 'x', 'o', or
* 'd', indicating a suggestion how any value left
* over in `*valuep` shall be displayed: 'x' for in
* hexadecimal, 'o' for octal, and 'd' for decimal
* (signness depends on the system call parameter's
* type's (or as the case may be, the system call's
* return type) signness).
* @return The name of some value in `*valuep`, or `NULL` if
* none was found. The returned string may be stored
* in `data` and those override at the next call.
*/
typedef const char *libsyscalls_symbol_printer_function(LIBSYSCALLS_SYMBOL_PRINTER_DATA *, unsigned long long int *, char *);
/**
* Information about a system call parameter or return value
*/
struct libsyscalls_syscall_type_info {
/**
* Function for extracting names values from a variable
*/
libsyscalls_symbol_printer_function *function;
/**
* First argument to pass to `.function`
*/
LIBSYSCALLS_SYMBOL_PRINTER_DATA *data;
/**
* The data type used for the parameter or return value
* in the specific invocation of the system call
*
* If set to LIBSYSCALLS_TYPE_VOID for an optional
* parameter, that parameter was not used
*/
enum_libsyscalls_datatype type;
char padding__[LIBSYSCALLS_PAD_(sizeof(long) / sizeof(char), sizeof(enum_libsyscalls_datatype) / sizeof(char) + 1)];
unsigned char : CHAR_BIT - 1;
/**
* Only used for the return value
*
* Same as `.expect_zero` in `struct libsyscalls_syscall_abi`,
* however if 0 in `struct libsyscalls_syscall_abi`, it can
* still be 1 here if if it is determined that for the specificly
* used system call arguments, the system call shall always
* return 0 (or not return) or an error
*/
unsigned char expect_zero : 1;
};
/**
* System call information tweak for the arguments passed
* to the system call, as well as information about how
* to print named values in the arguments and return
*/
struct libsyscalls_syscall_display_info {
/**
* The size of this structure, this can be used
* by the application to test what is available
* in the case it may have compiled against a
* newer version than used in the version of the
* library the application is linked with
*
* Data is stored beyond this, do not try to make
* a copy; that will not go well
*/
size_t size;
/**
* Information about each system call parameter
*
* All positive integer within [0, .max_argument_count]
* for the `struct libsyscalls_syscall_abi` are valid,
* but no index beyond `.max_argument_count` is valid
*/
struct libsyscalls_syscall_type_info *params;
/**
* Information about the system call's return value
*/
struct libsyscalls_syscall_type_info *retvalue;
};
/**
* Signed number representation
*/
enum libsyscalls_datatype_sign_representation {
/**
* The data type was LIBSYSCALLS_TYPE_UNKNOWN or
* LIBSYSCALLS_TYPE_DYNAMIC
*/
LIBSYSCALLS_SIGN_UNDETERMINED,
/**
* Two's complement
*
* -x is ~x + 1, -0 is +0
*/
LIBSYSCALLS_SIGN_TWOS_COMPLEMENT,
/**
* One's cmplement
*
* -x is ~x, -0 is not +0
*/
LIBSYSCALLS_SIGN_ONES_COMPLEMENT,
/**
* Sign–magnitude
*
* -x is (x | most significant bit), -0 is not +0
*/
LIBSYSCALLS_SIGN_SIGN_MAGNITUDE,
/**
* Excess-K, with K being (unsigned maximum + 1)/2
*
* 0 is represented with just the most significant bit set,
* any offset from 0 is added to this value, i.e., x is
* represented by ((unsigned maximum + 1)/2 + x); -0 is +0
*/
LIBSYSCALLS_SIGN_EXCESS_HALF
};
/**
* Data type usage annotation
*/
enum libsyscalls_datatype_annotation {
/**
* The data type was LIBSYSCALLS_TYPE_UNKNOWN or
* LIBSYSCALLS_TYPE_DYNAMIC
*/
LIBSYSCALLS_ANNOTATION_UNDETERMINED,
/**
* The value does not have usage annotation
*/
LIBSYSCALLS_ANNOTATION_NONE,
/**
* The value represents an operating system signal (e.g. SIGKILL)
*
* This affords the application the opportunity to print
* more detail information about a signal (such as when
* it is used, whether it is a realtime signal, default
* action, whether it can be caught, and what its normal
* usage is)
*/
LIBSYSCALLS_ANNOTATION_SIGNAL,
/**
* The value represents a file descriptor
*
* This affords the application the opportunity to print
* file information (such as file name, address, file type,
* and offset)
*/
LIBSYSCALLS_ANNOTATION_FD,
/**
* The value represents a file descriptor or a special value
* for a known file such as AT_FDCWD
*
* This affords the application the opportunity to print
* file information (such as file name, address, file type,
* and offset)
*/
LIBSYSCALLS_ANNOTATION_ATFD
};
/**
* Register-split information for a data type
*/
enum libsyscalls_datatype_section {
/**
* The data type was LIBSYSCALLS_TYPE_UNKNOWN or
* LIBSYSCALLS_TYPE_DYNAMIC
*/
LIBSYSCALLS_SECTION_UNDETERMINED,
/**
* The whole value is represented
*
* The value is contained within a single parameter
*/
LIBSYSCALLS_SECTION_WHOLE,
/*
* This whether a data type represents a half section
* of larger data type
*
* @param S:enum libsyscalls_datatype_section The data type section information
* @return :int Whether the larger that type was split into two halves
*/
#define LIBSYSCALLS_IS_SECTION_HALF(S)\
(((S) >= LIBSYSCALLS_SECTION_UPPER_HALF) &&\
((S) <= LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF))
/**
* The most significant half of the value is represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0xFFFFFFFF00000000 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_LOWER_HALF)
*/
LIBSYSCALLS_SECTION_UPPER_HALF,
/**
* The least significant half of the value is represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0x00000000FFFFFFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_UPPER_HALF)
*/
LIBSYSCALLS_SECTION_LOWER_HALF,
/**
* The second most and second least significant quarters
* of the value represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0x0000FFFFFFFF0000 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_OUTER_HALF)
*/
LIBSYSCALLS_SECTION_INNER_HALF,
/**
* The most and least significant quarters of the value
* represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0xFFFF00000000FFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_INNER_HALF)
*/
LIBSYSCALLS_SECTION_OUTER_HALF,
/**
* The second most and least significant quarters of the
* value represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0x0000FFFF0000FFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF)
*/
LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF,
/**
* The most and second least significant quarters of the
* value represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0xFFFF0000FFFF0000 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF)
*/
LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF,
/**
* The bytes that would be indexed (starting from 0) with
* an even number in big endian (how humans write numbers)
* are represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0x00FF00FF00FF00FF if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_EVEN_BYTES_AS_HALF)
*/
LIBSYSCALLS_SECTION_EVEN_BYTES_AS_HALF,
/**
* The bytes that would be indexed (starting from 0) with
* an odd number in big endian (how humans write numbers)
* are represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 32-bits —
* 0xFF00FF00FF00FF00 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with another neighbouring parameter
* (a LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF)
*/
LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF,
/*
* This whether a data type represents a quarter section
* of larger data type
*
* @param S:enum libsyscalls_datatype_section The data type section information
* @return :int Whether the larger that type was split into four quarters
*/
#define LIBSYSCALLS_IS_SECTION_QUARTER(S)\
(((S) >= LIBSYSCALLS_SECTION_UPPER_QUARTER) &&\
((S) <= LIBSYSCALLS_SECTION_LOWER_QUARTER))
/**
* The most significant quarter of the value is represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 16-bits —
* 0xFFFF000000000000 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with three neighbouring parameter
* (a LIBSYSCALLS_SECTION_UPPER_MID_QUARTER,
* a LIBSYSCALLS_SECTION_LOWER_MID_QUARTER, and
* a LIBSYSCALLS_SECTION_LOWER_QUARTER)
*/
LIBSYSCALLS_SECTION_UPPER_QUARTER,
/**
* The second most significant quarter of the value is represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 16-bits —
* 0x0000FFFF00000000 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with three neighbouring parameter
* (a LIBSYSCALLS_SECTION_UPPER_QUARTER,
* a LIBSYSCALLS_SECTION_LOWER_MID_QUARTER, and
* a LIBSYSCALLS_SECTION_LOWER_QUARTER)
*/
LIBSYSCALLS_SECTION_UPPER_MID_QUARTER,
/**
* The least most significant quarter of the value is represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 16-bits —
* 0x00000000FFFF0000 if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with three neighbouring parameter
* (a LIBSYSCALLS_SECTION_UPPER_QUARTER,
* a LIBSYSCALLS_SECTION_UPPER_MID_QUARTER, and
* a LIBSYSCALLS_SECTION_LOWER_QUARTER)
*/
LIBSYSCALLS_SECTION_LOWER_MID_QUARTER,
/**
* The least significant quarter of the value is represented
*
* Example: if the data type is 64-bits, the value stored
* in parameter whose type was queried is just 16-bits —
* 0x000000000000FFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
* — and most combined with three neighbouring parameter
* (a LIBSYSCALLS_SECTION_UPPER_QUARTER,
* a LIBSYSCALLS_SECTION_UPPER_MID_QUARTER, and
* a LIBSYSCALLS_SECTION_LOWER_MID_QUARTER)
*/
LIBSYSCALLS_SECTION_LOWER_QUARTER
/*
* Get the number of registers the data type was split into
*
* @param S:enum libsyscalls_datatype_section The data type section information
* @return :unsigned int The number registers the data type was split into;
* invalid if `S` is LIBSYSCALLS_SECTION_UNDETERMINED
*/
#define LIBSYSCALLS_GET_SECTION_FRACTION(S)\
(LIBSYSCALLS_IS_SECTION_HALF(S) ? 2U :\
LIBSYSCALLS_IS_SECTION_QUARTER(S) ? 4U : 1U)
};
/**
* Information on how an instance of data type is to be parsed
*
* Data types are usually either signed or unsigned, but there
* are a few exceptions: LIBSYSCALLS_TYPE_UNKNOWN and
* LIBSYSCALLS_TYPE_DYNAMIC are described as both signed and
* unsigned as their signness is unknown and could be either,
* or neither, which brings us to the next exception: some
* data types are neither signed nor unsigned; these are types
* that are not numerical, i.e. non-values (LIBSYSCALLS_TYPE_NO_RETURN
* and LIBSYSCALLS_TYPE_VOID), memory addresses
* (LIBSYSCALLS_TYPE_MEMORY_ADDRESS) and textual types
* (LIBSYSCALLS_TYPE_CHAR, LIBSYSCALLS_TYPE_STRING, and
* LIBSYSCALLS_TYPE_STRINGS_THEN_NULL), as well as arrays of
* such types (including LIBSYSCALLS_TYPE_BUFFER and
* LIBSYSCALLS_TYPE_BUFFER_UNKNOWN_FILL), and finally bitset
* arrays (currently only LIBSYSCALLS_TYPE_FD_SET)
*/
struct libsyscalls_datatype_description {
/**
* The number of bits used for the represented section
* of the data type
*
* 0 for LIBSYSCALLS_TYPE_NO_RETURN and LIBSYSCALLS_TYPE_VOID
*
* if .section is LIBSYSCALLS_SECTION_WHOLE, this is the
* number of bits in the entire data type, otherwise the data
* type may have been split (LIBSYSCALLS_SECTION_UNDETERMINED,
* guaranteed to be split otherwise) and this value is just
* the number of bits stored in the register
*/
unsigned width_in_bits;
/**
* The size (in number of elements) of the array the data type
* is used in, or 1 if the data type was not an array or
* 0 if the array size is determined by another parameter
*/
unsigned array_size;
/**
* Only used if .array_size is 0
*
* The position of the arrays size in the parameter list
* relative to the array, e.g. 1 for the next parameter
* or -1 for the previous parameter
*
* If 0, use .absolute_position_of_array_size instead
*/
signed relative_position_of_array_size : 5;
/**
* Only used if .array_size is 0
*
* The position of the arrays size in the parameter list,
* indexed starting from 0
*
* If -1, use .relative_position_of_array_size instead
*/
signed absolute_position_of_array_size : 5;
/**
* Only used if .array_size is 0
*
* Assuming the kernel writes into the array, if 1, the number
* of elements written to the array (starting from its
* beginning) is writting into the array size parameter if it
* is marked as an output parameter and return otherwise; if
* 0, the number of bits written must be infered from its
* contents, e.g. via null byte termination (how this is done
* depends on the system call)
*/
unsigned fill_is_known : 1;
/**
* Whether the data type is signed
*/
unsigned is_signed : 1;
/**
* Whether the data type is unsigned
*/
unsigned is_unsigned : 1;
/**
* Only used if .is_signed is 1 and .sign_representation
* is not LIBSYSCALLS_SIGN_UNDETERMINED
*
* This value can be inferred from .sign_representation;
* its 1 if the data type's minimum value is the negative
* of its maximum value (which also means that -0 and +0
* are distinct), and 0 otherwise, which means that the
* minimum value is the negative of (the minimum value + 1)
* (it also means that -0 and +0 are the identical)
*/
unsigned min_is_minus_max : 1;
int padding__ : LIBSYSCALLS_PAD_(sizeof(int)/sizeof(char)*CHAR_BIT, 2*5 + 4*1);
/**
* Only used if .is_signed is 1
*
* How signed numbers are represented
*/
enum libsyscalls_datatype_sign_representation sign_representation;
/**
* Additional information about what the value represents
*/
enum libsyscalls_datatype_annotation annotation;
/**
* What part of the value is stored in the instance
*/
enum libsyscalls_datatype_section section;
/**
* This is a ~0 terminated array — 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 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)
*/
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
};
/**
* Return a description of a libsyscalls error
*
* @param error The libsyscalls error
* @return Description of the error, the first character will be in uppercase
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__const__, __returns_nonnull__, __warn_unused_result__)
const char *
libsyscalls_strerror(enum libsyscalls_error);
/**
* Print a line with a description of a
* libsyscalls error to standard error
*
* @param prefix Unless NULL or the empty string, the description
* will be prefixed with this string followed by ": "
* @param error The libsyscalls error
*/
void
libsyscalls_perror(const char *, enum libsyscalls_error);
/**
* Get the valid range system call numbers
*
* @param os The operating system the range shall valid for
* @param arch The architecture the range shall valid for
* @param min_out Output parameter for the lowest used system call number (may be NULL)
* @param max_out Output parameter for the highest used system call number (may be NULL)
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
*
* 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__)
enum libsyscalls_error
libsyscalls_get_syscall_range(enum libsyscalls_os, enum libsyscalls_arch, long long int *, long long int *);
/**
* Get the description of a system call
*
* @param os The operating system the range shall valid for
* @param arch The architecture the range shall valid for
* @param syscallnr The system call's number
* @param syscall_out Output parameter for the system call description
* (the argument may be NULL, *syscall_out will
* never be set to NULL)
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
* LIBSYSCALLS_E_NOSUCHSYSCALL - `syscallnr` does not correspond to a known
* system call for the selected architecture (`arch`)
* on the selected operating system (`os`)
*
* This function always fails if the selected combination
* of operating system (`os`) and architecture (`arch`) is
* unsupported
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__)
enum libsyscalls_error
libsyscalls_get_syscall(enum libsyscalls_os, enum libsyscalls_arch, long long int, const struct libsyscalls_syscall **);
/**
* Get the system call errors defined by an operating system
*
* If an error has multiple names, it is only listed once
* and the listed name is arbitrary
*
* The returned listing will be sorted by the error numbers
* in ascending order
*
* @param os The operating system whose errors shall be returned
* @param arch The architecture the error numbers shall be valid for
* @param errors_out Output parameter for the error list (may be NULL, never filled with NULL)
* @param num_errors_out Output parameter for the number of errors returned in `*errors_out` (may be NULL)
* (if `errors_out` is NULL, the number that would be returned is stored)
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
* LIBSYSCALLS_E_NOERRORS - The operating system does not use named error numbers
*
* 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
*/
enum libsyscalls_error
libsyscalls_get_syscall_errors(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_named_number **, size_t *);
/**
* Get the system signals defined by an operating system
*
* If a signal has multiple names, it is only listed once
* and the listed name is arbitrary
*
* The returned listing will be sorted by the signal
* numbers in ascending order
*
* @param os The operating system whose errors shall be returned
* @param arch The architecture the error numbers shall be valid for
* @param signals_out Output parameter for the signal list (may be NULL, never filled with NULL)
* @param num_signals_out Output parameter for the number of signals returned in `*signals_out` (may be NULL)
* (if `signals_out` is NULL, the number that would be returned is stored)
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
* LIBSYSCALLS_E_NOSIGNALS - The operating system does not use named signal numbers
*
* 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
*/
enum libsyscalls_error
libsyscalls_get_signals(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_named_number **, size_t *);
/**
* Get system call information tweak for the arguments passed
* to the system call, as well as information about how to
* print named values in the arguments and return
*
* @param os The operating system the system call was invoked on
* @param arch The architecture the system call was invoked on
* @param syscall The ABI of the system call (see libsyscalls_get_syscall)
* @param syscall_number The system call's number
* @param syscall_arguments The values store in register (as upon system call entry)
* the used for the system call, in the order the registers
* are used as system call arguments
* @param info_out Output parameter for the additional system call information
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
* LIBSYSCALLS_E_NOMEM - Failed to allocate memory for `*info_out`
* LIBSYSCALLS_E_INVAL - One of the arguments was NULL
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __nonnull__)
enum libsyscalls_error
libsyscalls_get_syscall_display_info(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_syscall_abi *,
long long int, unsigned long long int *, struct libsyscalls_syscall_display_info **);
/**
* Get information on how an instance of data type is to be parsed
*
* @param os The operating system the data type is used on
* @param arch The architecture the data type is used on
* @param datatype The datatype, `LIBSYSCALLS_TYPE_DYNAMIC` can
* be used to get the size of the registers used
* as system call parameters
* @param description_out Output parameter for the type description
* @return LIBSYSCALLS_E_OK - On success
* LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
* the selected operating system (`os`)
* LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
* the selected architecture (`arch`) on the
* selected operating system (`os`)
* LIBSYSCALLS_E_INVAL - `datatype` is not a valid data type
* LIBSYSCALLS_E_NOSUCHTYPE - `datatype` does not exist on the selected
* operating system (`os`) or architecture (`arch`)
* LIBSYSCALLS_E_ISSTRUCT - `datatype` represents a structure
*
* The function may complete successfully for some data
* types even if it for other data types would return
* LIBSYSCALLS_E_OSNOSUP or LIBSYSCALLS_E_ARCHNOSUP
*/
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__)
enum libsyscalls_error
libsyscalls_get_datatype_description(enum libsyscalls_os, enum libsyscalls_arch, enum libsyscalls_datatype,
struct libsyscalls_datatype_description *);
#include "libsyscalls/internal-end.h"
#endif