From 225f1408e03f2e66198f3da20c42a746e2729ab0 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Thu, 7 Dec 2023 20:35:16 +0100 Subject: Fourth commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 5 + TODO | 1 - libsyscalls.h | 1406 ++++++++++++++++++++++++++++++-- libsyscalls/advanced.h | 19 +- libsyscalls/internal-begin.h | 85 +- libsyscalls/internal-end.h | 3 + libsyscalls_get_datatype_description.c | 25 +- libsyscalls_get_integer_alignment.c | 58 ++ linux/integers.c | 21 + linux/integers.mk | 4 + linux/linux-support.mk | 2 + linux/syscalls.h | 14 +- linux/tests/os-dependent-integers | 4 + linux/what-architecture-am-i-using | 7 + mk/generate.mk | 10 +- test | 23 +- tests/default-integers | 21 + tests/load-functions | 4 + tests/os-dependent-integers | 9 + testutil/get-integer-alignment.c | 45 + 20 files changed, 1643 insertions(+), 123 deletions(-) create mode 100644 libsyscalls_get_integer_alignment.c create mode 100644 linux/integers.c create mode 100644 linux/integers.mk create mode 100644 linux/tests/os-dependent-integers create mode 100644 tests/default-integers create mode 100644 tests/os-dependent-integers create mode 100644 testutil/get-integer-alignment.c diff --git a/Makefile b/Makefile index 996315d..ebd5e71 100644 --- a/Makefile +++ b/Makefile @@ -57,9 +57,13 @@ TEST_ENV = #extended for each support operating system with the number of syscall parameters they use NPARAMS = +#extended for each support operating system with the maximum used number of fields in its structs and unions +NFIELDS = + #extended for each support operating system OBJ =\ libsyscalls_get_datatype_description.o\ + libsyscalls_get_integer_alignment.o\ libsyscalls_get_signals.o\ libsyscalls_get_syscall.o\ libsyscalls_get_syscall_display_info.o\ @@ -88,6 +92,7 @@ SUBHDR =\ TESTUTILS =\ testutil/get-datatype-description.tu\ testutil/get-error.tu\ + testutil/get-integer-alignment.tu\ testutil/get-section-fraction.tu\ testutil/get-signals.tu\ testutil/get-syscall-errors.tu\ diff --git a/TODO b/TODO index c140623..0dffc6b 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,3 @@ -Add support for describing structs and unions (and arrays thereof) Add calling convention Add value decoding Add value encoding diff --git a/libsyscalls.h b/libsyscalls.h index 066de20..caf4a4b 100644 --- a/libsyscalls.h +++ b/libsyscalls.h @@ -77,6 +77,19 @@ enum libsyscalls_arch { LIBSYSCALLS_ARCH_XTENSA }; +/** + * 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 */ @@ -100,13 +113,14 @@ enum libsyscalls_datatype { 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 + /* 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)) */\ + * 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)\ @@ -263,166 +277,1183 @@ enum libsyscalls_datatype { #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, - 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 + + 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 */ }; -/* IPC that can but does not have to be over a network, - * "bind" system calls can create inodes in the file system */ +/** + * 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, - 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 */ + + /** + * 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 }; -/* syscalls that can work on either paths or FDs ([1]) are located here */ +/** + * 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, - LIBSYSCALLS_FILESYSTEM_SUBCAT_SYNC, /* [1] some of these only work on file descriptors or memory maps */ + + /** + * 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, - LIBSYSCALLS_FILESYSTEM_SUBCAT_UMASK, /* modifies the process, not the filesystem */ + + /** + * 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 }; -/* syscalls that work FDs but not paths are located here */ +/** + * 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, - LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_DUP_OR_CLOSE, /* includes partial close (shutdown) */ + + /** + * 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, - LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ, /* may have timeout */ - LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK, - LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_WRITE, /* may have timeout */ + + /** + * 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, - LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_PEEK, /* may have timeout */ + + /** + * 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, - LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CREATE, + + /** + * 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, - LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_POLL /* can work as pause or relative sleep */ + + /** + * 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, - LIBSYSCALLS_PROCESSES_SUBCAT_STAT_CHILD, /* may also stat self */ - LIBSYSCALLS_PROCESSES_SUBCAT_STAT_PARENT, /* may also stat self or children */ + + /** + * 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, - LIBSYSCALLS_PROCESSES_SUBCAT_SESSION /* vhangup, setsid, setpgid */ + + /** + * 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 }; -/* These may work on memory mapped files */ +/** + * 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, - LIBSYSCALLS_MEMORY_SUBCAT_READ, + + /** + * 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, - LIBSYSCALLS_MEMORY_SUBCAT_STAT /* stats memory allocated to the process, not system resources */ + + /** + * 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 { - LIBSYSCALLS_SCHEDULING_SUBCAT_YEILD, + /** + * 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; - 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; + enum_libsyscalls_network_enabled_ipc_syscall_subcategory network_enabled_ipc; /**< Use for LIBSYSCALLS_CAT_NETWORK_ENABLED_IPC */ + enum_libsyscalls_ipc_syscall_subcategory ipc; /**< Use for LIBSYSCALLS_CAT_IPC */ + enum_libsyscalls_filesystem_syscall_subcategory filesystem; /**< Use for LIBSYSCALLS_CAT_FILESYSTEM */ + enum_libsyscalls_file_descriptors_syscall_subcategory file_descriptors; /**< Use for LIBSYSCALLS_CAT_FILE_DESCRIPTORS */ + enum_libsyscalls_processes_syscall_subcategory processes; /**< Use for LIBSYSCALLS_CAT_PROCESSES */ + enum_libsyscalls_logging_syscall_subcategory logging; /**< Use for LIBSYSCALLS_CAT_LOGGING */ + enum_libsyscalls_time_syscall_subcategory time; /**< Use for LIBSYSCALLS_CAT_TIME */ + enum_libsyscalls_signals_syscall_subcategory signals; /**< Use for LIBSYSCALLS_CAT_SIGNALS */ + enum_libsyscalls_memory_syscall_subcategory memory; /**< Use for LIBSYSCALLS_CAT_MEMORY */ + enum_libsyscalls_system_syscall_subcategory system; /**< Use for LIBSYSCALLS_CAT_SYSTEM */ + enum_libsyscalls_scheduling_syscall_subcategory scheduling; /**< Use for LIBSYSCALLS_CAT_SCHEDULING */ }; /** @@ -445,7 +1476,7 @@ struct libsyscalls_syscall_abi { /** * For set any bit indexed I (starting from 0), the * system call parameter I is a pointer that the - * the system call reads from + * system call reads from * * Note that there are types that fundamentally are * pointers (such as strings), for these, this bit @@ -456,7 +1487,7 @@ struct libsyscalls_syscall_abi { /** * For set any bit indexed I (starting from 0), the * system call parameter I is a pointer that the - * the system call write to + * system call write to * * Note that there are types that fundamentally are * pointers (such as strings), for these, this bit @@ -509,7 +1540,7 @@ struct libsyscalls_syscall_abi { 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` + * 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 @@ -521,8 +1552,8 @@ struct libsyscalls_syscall_abi { * 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 + * `struct libsyscalls_syscall_abi`) or because the library + * hasn't yet added full support for the system call */ LIBSYSCALLS_SYMBOL_PRINTER symbol_printer : 16; @@ -678,7 +1709,7 @@ struct libsyscalls_syscall_type_info { */ enum_libsyscalls_datatype type; - char padding__[LIBSYSCALLS_PAD_(sizeof(long) / sizeof(char), sizeof(enum_libsyscalls_datatype) / sizeof(char) + 1)]; + char padding__[LIBSYSCALLS_PAD_(sizeof(void *)/sizeof(char), sizeof(enum_libsyscalls_datatype)/sizeof(char) + 1)]; unsigned char : CHAR_BIT - 1; /** @@ -814,7 +1845,7 @@ enum libsyscalls_datatype_annotation { }; /** - * Register-split information for a data type + * Register-split/struct field-split information for a data type */ enum libsyscalls_datatype_section { /** @@ -1001,10 +2032,10 @@ enum libsyscalls_datatype_section { LIBSYSCALLS_SECTION_LOWER_QUARTER /* - * Get the number of registers the data type was split into + * 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 the data type was split into; + * @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)\ @@ -1041,23 +2072,29 @@ struct libsyscalls_datatype_description { * 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 + * the number of bits stored in the register or struct field + * + * It is possible for the datatype 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 + * 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 arrays size in the parameter list - * relative to the array, e.g. 1 for the next parameter - * or -1 for the previous parameter + * 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 */ @@ -1066,7 +2103,7 @@ struct libsyscalls_datatype_description { /** * Only used if .array_size is 0 * - * The position of the arrays size in the parameter list, + * 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 @@ -1077,10 +2114,10 @@ struct libsyscalls_datatype_description { * 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 + * 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) */ @@ -1116,17 +2153,17 @@ struct libsyscalls_datatype_description { * * How signed numbers are represented */ - enum libsyscalls_datatype_sign_representation sign_representation; + enum libsyscalls_datatype_sign_representation sign_representation : 8; /** * Additional information about what the value represents */ - enum libsyscalls_datatype_annotation annotation; + enum libsyscalls_datatype_annotation annotation : 8; /** * What part of the value is stored in the instance */ - enum libsyscalls_datatype_section section; + enum libsyscalls_datatype_section section : 16; /** * This is a ~0 terminated array — but, it can also @@ -1143,9 +2180,9 @@ struct libsyscalls_datatype_description { * 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 + * 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 @@ -1179,6 +2216,187 @@ struct libsyscalls_datatype_description { #endif }; +/** + * 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; + + /** + * 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; + + unsigned short int padding1__ : 16 - (6*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 +}; + +/** + * 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; + + /** + * 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; + + /** + * If 1, the data type is a `union`, + * if 0, the data type is a `struct` + */ + unsigned short int is_union : 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, hoever 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 @@ -1368,6 +2586,52 @@ enum libsyscalls_error libsyscalls_get_datatype_description(enum libsyscalls_os, enum libsyscalls_arch, enum libsyscalls_datatype, struct libsyscalls_datatype_description *); +/** + * 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__) +enum libsyscalls_error +libsyscalls_get_integer_alignment(enum libsyscalls_os, enum libsyscalls_arch, unsigned, unsigned *); + +/* TODO add libsyscalls_get_struct_description */ +/* TODO add libsyscalls_get_struct_display_info */ + #include "libsyscalls/internal-end.h" #endif diff --git a/libsyscalls/advanced.h b/libsyscalls/advanced.h index 22ed3d0..7876178 100644 --- a/libsyscalls/advanced.h +++ b/libsyscalls/advanced.h @@ -4,10 +4,15 @@ #endif -#define LIBSYSCALLS_TYPEOFFSET_SPECIAL_TYPES 0 /* does not use LIBSYSCALLS_TYPEBITSMASK */ -#define LIBSYSCALLS_TYPEOFFSET_SPLIT_PRIMITIVES 8 -#define LIBSYSCALLS_TYPEOFFSET_COMPOSITE_PRIMITIVES 48 -#define LIBSYSCALLS_TYPEOFFSET_UNANNOTATED_NUMERICALS 64 -#define LIBSYSCALLS_TYPEOFFSET_ANNOTATED_NUMERICALS 256 -#define LIBSYSCALLS_TYPEOFFSET_FIXED_ARRAYS 512 -#define LIBSYSCALLS_TYPEOFFSET_STRUCTS_AND_UNIONS 1024 +#define LIBSYSCALLS_TYPEOFFSET_SPECIAL_TYPES 0 /* does not use LIBSYSCALLS_TYPEBITSMASK */ +#define LIBSYSCALLS_TYPEOFFSET_SPLIT_PRIMITIVES 8 +#define LIBSYSCALLS_TYPEOFFSET_COMPOSITE_PRIMITIVES 48 +#define LIBSYSCALLS_TYPEOFFSET_UNANNOTATED_NUMERICALS 64 +#define LIBSYSCALLS_TYPEOFFSET_ANNOTATED_NUMERICALS 256 +#define LIBSYSCALLS_TYPEOFFSET_FIXED_ARRAYS 512 +#define LIBSYSCALLS_TYPEOFFSET_STRUCTS_AND_UNIONS 1024 +#define LIBSYSCALLS_TYPEOFFSET_ANON_STRUCTS_AND_UNIONS 3072 /* these are OS and maybe even architecture specific structures + * structures and unions that do not have a name (or has a name + * but is only used as a substructure); they are not listed in + * `enum libsyscalls_datatype`, but can appear when querying + * the layout of a struct or union */ diff --git a/libsyscalls/internal-begin.h b/libsyscalls/internal-begin.h index 5c42b7e..0d89bb7 100644 --- a/libsyscalls/internal-begin.h +++ b/libsyscalls/internal-begin.h @@ -7,6 +7,18 @@ #include #include + +/** + * Opaque type for symbol printer function identification + */ +typedef unsigned short int LIBSYSCALLS_SYMBOL_PRINTER; + +/** + * Opaque type for symbol printer function parameters + */ +typedef struct libsyscalls_symbol_printer_data LIBSYSCALLS_SYMBOL_PRINTER_DATA; + + /* a comma possible into a macro */ #define LIBSYSCALLS_COMMA_ , @@ -14,6 +26,9 @@ #ifndef LIBSYSCALLS_FLEXABLE_OR_NPARAMS_ # define LIBSYSCALLS_FLEXABLE_OR_NPARAMS_ #endif +#ifndef LIBSYSCALLS_FLEXABLE_OR_NFIELDS_ +# define LIBSYSCALLS_FLEXABLE_OR_NFIELDS_ +#endif #if defined(__GNUC__) # define LIBSYSCALLS_GCC_ATTRIBUTES_(...) __attribute__((__VA_ARGS__)) @@ -23,16 +38,65 @@ #define LIBSYSCALLS_PAD_(WANT, HAVE) (((WANT) - (HAVE) % (WANT)) % (WANT)) - -/** - * Opaque type for symbol printer function identification - */ -typedef unsigned short int LIBSYSCALLS_SYMBOL_PRINTER; - -/** - * Opaque type for symbol printer function parameters - */ -typedef struct libsyscalls_symbol_printer_data LIBSYSCALLS_SYMBOL_PRINTER_DATA; +#define LIBSYSCALLS_IS_PADDING_REQUIRED_(FIELDS, FIELD_BITSIZE, ALIGN_TO_BITS)\ + ((((FIELDS) & ~((FIELDS) - 1)) * (FIELD_BITSIZE)) % ALIGN_TO_BITS) + +#define LIBSYSCALLS_CAN_ALIGN_(FIELDS, FIELD_BITSIZE, ALIGN_BITS)\ + (!((FIELDS) * (FIELD_BITSIZE) % (ALIGN_BITS) || (ALIGN_BITS) > (FIELDS) * (FIELD_BITSIZE))) + +#if defined(__INTPTR_WIDTH__) +# define LIBSYSCALLS_POINTER_BIT_ __INTPTR_WIDTH__ +#elif defined(__SIZEOF_POINTER__) +# define LIBSYSCALLS_POINTER_BIT_ (__SIZEOF_POINTER__ * CHAR_BIT) +#elif defined(__LLP128__) || defined(_LLP128) +# define LIBSYSCALLS_POINTER_BIT_ 128 +#elif defined(__LLP64__) || defined(_LLP64) +# define LIBSYSCALLS_POINTER_BIT_ 64 +#elif defined(__LP64__) || defined(_LP64) +# define LIBSYSCALLS_POINTER_BIT_ 64 +#elif defined(__ILP64__) || defined(_ILP64) +# define LIBSYSCALLS_POINTER_BIT_ 64 +#elif defined(__SILP64__) || defined(_SILP64) +# define LIBSYSCALLS_POINTER_BIT_ 64 +#elif defined(__LLP32__) || defined(_LLP32) +# define LIBSYSCALLS_POINTER_BIT_ 32 +#elif defined(__LP32__) || defined(_LP32) +# define LIBSYSCALLS_POINTER_BIT_ 32 +#elif defined(__ILP32__) || defined(_ILP32) +# define LIBSYSCALLS_POINTER_BIT_ 32 +#elif defined(__SILP32__) || defined(_SILP32) +# define LIBSYSCALLS_POINTER_BIT_ 32 +#elif defined(__IP32__) || defined(_IP32) +# define LIBSYSCALLS_POINTER_BIT_ 32 +#elif defined(__SIP32__) || defined(_SIP32) +# define LIBSYSCALLS_POINTER_BIT_ 32 +#elif defined(__IP16__) || defined(_IP16) +# define LIBSYSCALLS_POINTER_BIT_ 16 +#elif defined(__SIP16__) || defined(_SIP16) +# define LIBSYSCALLS_POINTER_BIT_ 16 +#elif defined(__SP16__) || defined(_SP16) +# define LIBSYSCALLS_POINTER_BIT_ 16 +#elif defined(__INTPTR_MAX__) && defined(__LONG_MAX__) +# if __INTPTR_MAX__ == __LONG_MAX__ +# define LIBSYSCALLS_POINTER_BIT_ LONG_BIT +# elif __INTPTR_MAX__ / __LONG_MAX__ / __LONG_MAX__ == 2 +# define LIBSYSCALLS_POINTER_BIT_ (LONG_BIT + LONG_BIT) +# elif __INTPTR_MAX__ / __LONG_MAX__ / __LONG_MAX__ / __LONG_MAX__ / __LONG_MAX__ == 8 +# define LIBSYSCALLS_POINTER_BIT_ (LONG_BIT + LONG_BIT + LONG_BIT + LONG_BIT) +# endif +#endif +#if !defined(LIBSYSCALLS_POINTER_BIT_) && defined(__INTPTR_MAX__) +# if __INTPTR_MAX__ == 32767ULL +# define LIBSYSCALLS_POINTER_BIT_ 16 +# elif __INTPTR_MAX__ == 2147483647ULL +# define LIBSYSCALLS_POINTER_BIT_ 32 +# elif __INTPTR_MAX__ == 9223372036854775807ULL +# define LIBSYSCALLS_POINTER_BIT_ 64 +# endif +#endif +#if !defined(LIBSYSCALLS_POINTER_BIT_) +# error Cannot figure out bit width of (void *) +#endif #define LIBSYSCALLS_LIST_ERRORS_X_(ENUM, STR) ENUM @@ -75,6 +139,7 @@ typedef struct libsyscalls_symbol_printer_data LIBSYSCALLS_SYMBOL_PRINTER_DATA; = LIBSYSCALLS_TYPEOFFSET_FIXED_ARRAYS\ | LIBSYSCALLS_TYPEBITS##SUFFIX) + #define LIBSYSCALLS_BITSIZEOF_(T) (sizeof(T) / sizeof(char) * CHAR_BIT) #define LIBSYSCALLS_FIELD_BITSIZEOF_(S, F) LIBSYSCALLS_BITSIZEOF_(((S *)0)->F) diff --git a/libsyscalls/internal-end.h b/libsyscalls/internal-end.h index ed7af58..2aeb2f0 100644 --- a/libsyscalls/internal-end.h +++ b/libsyscalls/internal-end.h @@ -8,6 +8,9 @@ #undef LIBSYSCALLS_FLEXABLE_OR_NPARAMS_ #undef LIBSYSCALLS_GCC_ATTRIBUTES_ #undef LIBSYSCALLS_PAD_ +#undef LIBSYSCALLS_IS_PADDING_REQUIRED_ +#undef LIBSYSCALLS_CAN_ALIGN_ +#undef LIBSYSCALLS_POINTER_BIT_ #undef LIBSYSCALLS_LIST_ERRORS_X_ #undef LIBSYSCALLS_DATATYPE_X_ diff --git a/libsyscalls_get_datatype_description.c b/libsyscalls_get_datatype_description.c index 8d46812..71a2170 100644 --- a/libsyscalls_get_datatype_description.c +++ b/libsyscalls_get_datatype_description.c @@ -17,29 +17,29 @@ enum endian { X(LIBSYSCALLS_ARCH_ALPHA, 8, 64, 64, TODO(bi), TWOS_COMPLEMENT) D\ */\ X(LIBSYSCALLS_ARCH_AMD64, 8, 64, 64, Little, TWOS_COMPLEMENT) D\ - X(LIBSYSCALLS_ARCH_AMD64_X32, 8, 32, 32, Little, TWOS_COMPLEMENT) D /* amd64, 32-bit convesion*/\ + X(LIBSYSCALLS_ARCH_AMD64_X32, 8, 32, 32, Little, TWOS_COMPLEMENT) D /* amd64, 32-bit convesion */\ /* - X(LIBSYSCALLS_ARCH_ARM_OABI, 8, TODO, TODO, TODO(bi), TWOS_COMPLEMENT) D\ - X(LIBSYSCALLS_ARCH_ARM_EABI, 8, TODO, TODO, TODO(bi), TWOS_COMPLEMENT) D\ + X(LIBSYSCALLS_ARCH_ARM_OABI, 8, TODO, TODO, TODO(bi), TWOS_COMPLEMENT) D / * TODO (alignment) * / \ + X(LIBSYSCALLS_ARCH_ARM_EABI, 8, TODO, TODO, TODO(bi), TWOS_COMPLEMENT) D / * TODO (alignment) * /\ X(LIBSYSCALLS_ARCH_IA64, 8, 64, 64, TODO, TWOS_COMPLEMENT) D\ */\ X(LIBSYSCALLS_ARCH_M68K, 8, 32, 32, Big, TWOS_COMPLEMENT) D\ /* - X(LIBSYSCALLS_ARCH_MICROBLAZE, 8, TODO, TODO, TODO, TODO) D\ + X(LIBSYSCALLS_ARCH_MICROBLAZE, 8, TODO, TODO, TODO, TODO) D / * TODO (alignment) * /\ X(LIBSYSCALLS_ARCH_MIPS_O32, 8, 32, 32, TODO(bi), TWOS_COMPLEMENT) D / * mips32 * /\ - X(LIBSYSCALLS_ARCH_MIPS_N32, 8, 32, 32, TODO(bi), TWOS_COMPLEMENT) D / * mips64, 32-bit convention * /\ - X(LIBSYSCALLS_ARCH_MIPS_N64, 8, 64, 64, TODO(bi), TWOS_COMPLEMENT) D / * mips64 * /\ + X(LIBSYSCALLS_ARCH_MIPS_N32, 8, 32, 32, TODO(bi), TWOS_COMPLEMENT) D / * TODO (alignment) * / / * mips64, 32-bit convention * /\ + X(LIBSYSCALLS_ARCH_MIPS_N64, 8, 64, 64, TODO(bi), TWOS_COMPLEMENT) D / * TODO (alignment) * / / * mips64 * /\ */\ X(LIBSYSCALLS_ARCH_PARISC_32, 8, 32, 32, Big, TWOS_COMPLEMENT) D\ X(LIBSYSCALLS_ARCH_PARISC_64, 8, 64, 64, Big, TWOS_COMPLEMENT) D\ /* X(LIBSYSCALLS_ARCH_POWERPC_32, 8, 32, 32, TODO(bi), TODO) D\ - X(LIBSYSCALLS_ARCH_POWERPC_64, 8, 64, 64, TODO(bi), TODO) D\ - X(LIBSYSCALLS_ARCH_POWERPC_NOSPU, 8, 64, 64, TODO(bi), TODO) D\ - X(LIBSYSCALLS_ARCH_POWERPC_SPU, 8, 64, 64, TODO(bi), TODO) D\ - X(LIBSYSCALLS_ARCH_S390_32, 8, 32, 32, Big, TODO) D\ - X(LIBSYSCALLS_ARCH_S390_64, 8, 64, 64, Big, TODO) D\ - X(LIBSYSCALLS_ARCH_SH, 8, 32, 32, TODO(bi), TODO) D / * not sh-5 * /\ + X(LIBSYSCALLS_ARCH_POWERPC_64, 8, 64, 64, TODO(bi), TODO) D / * TODO (alignment) * /\ + X(LIBSYSCALLS_ARCH_POWERPC_NOSPU, 8, 64, 64, TODO(bi), TODO) D / * TODO (alignment) * /\ + X(LIBSYSCALLS_ARCH_POWERPC_SPU, 8, 64, 64, TODO(bi), TODO) D / * TODO (alignment) * /\ + X(LIBSYSCALLS_ARCH_S390_32, 8, 32, 32, Big, TODO) D / * TODO (alignment) * /\ + X(LIBSYSCALLS_ARCH_S390_64, 8, 64, 64, Big, TODO) D / * TODO (alignment) * /\ + X(LIBSYSCALLS_ARCH_SH, 8, 32, 32, TODO(bi), TODO) D / * TODO (alignment) * / / * not sh-5 * /\ */\ X(LIBSYSCALLS_ARCH_SPARC_32, 8, 32, 32, Big, TWOS_COMPLEMENT) D\ /* @@ -50,6 +50,7 @@ enum endian { X(LIBSYSCALLS_ARCH_XTENSA, 8, 32, 32, TODO, TODO) */ /* Don't forget to update SUPPORTED_ARCHES in Makefile */ + /* TODO (alignment) means that it is missing in libsyscalls_get_integer_alignment.c and must also be added thither */ #include "generated/types.c" diff --git a/libsyscalls_get_integer_alignment.c b/libsyscalls_get_integer_alignment.c new file mode 100644 index 0000000..7802a06 --- /dev/null +++ b/libsyscalls_get_integer_alignment.c @@ -0,0 +1,58 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +#include "generated/integers.c" + +enum libsyscalls_error +libsyscalls_get_integer_alignment(enum libsyscalls_os os, enum libsyscalls_arch arch, unsigned width_in_bits, unsigned *alignment_out) +{ + unsigned maxalign; + + if (!width_in_bits) + return LIBSYSCALLS_E_INVAL; + + switch ((int)arch) { + case LIBSYSCALLS_ARCH_M68K: /* https://m680x0.github.io/doc/abi.html#scalar-types + * https://lists.nongnu.org/archive/html/qemu-devel/2015-02/msg04797.html */ + maxalign = 16; + break; + + case LIBSYSCALLS_ARCH_I386: + maxalign = 32; + break; + + case LIBSYSCALLS_ARCH_AMD64: + case LIBSYSCALLS_ARCH_AMD64_X32: + case LIBSYSCALLS_ARCH_ALPHA: /* https://static.lwn.net/images/pdf/LDD3/ch11.pdf */ + case LIBSYSCALLS_ARCH_IA64: /* https://static.lwn.net/images/pdf/LDD3/ch11.pdf */ + case LIBSYSCALLS_ARCH_MIPS_O32: /* https://static.lwn.net/images/pdf/LDD3/ch11.pdf */ + case LIBSYSCALLS_ARCH_PARISC_32: /* https://www.ece.lsu.edu/ee4720/doc/pa1.1.pdf (page 26) */ + case LIBSYSCALLS_ARCH_PARISC_64: + case LIBSYSCALLS_ARCH_POWERPC_32: /* https://static.lwn.net/images/pdf/LDD3/ch11.pdf */ + case LIBSYSCALLS_ARCH_SPARC_32: /* https://www.gaisler.com/doc/sparcv8.pdf (page 46) */ + case LIBSYSCALLS_ARCH_SPARC_64: /* https://static.lwn.net/images/pdf/LDD3/ch11.pdf */ + case LIBSYSCALLS_ARCH_XTENSA: /* https://loboris.eu/ESP32/Xtensa_lx%20Overview%20handbook.pdf (page 97) */ + maxalign = 64; + break; + + default: + return LIBSYSCALLS_E_ARCHNOSUP; + } + + if (width_in_bits & (width_in_bits - 1) || width_in_bits & 7 || width_in_bits > 64) + return LIBSYSCALLS_E_NOSUCHTYPE; + *alignment_out = width_in_bits < maxalign ? width_in_bits : maxalign; + +#define CASE(UPPERCASE, LOWERCASE)\ + case LIBSYSCALLS_OS_##UPPERCASE:\ + return get_##LOWERCASE##_integer_alignment(arch, width_in_bits, alignment_out) + + switch ((int)os) { + LIST_OSES(CASE, ;); + default: + return LIBSYSCALLS_E_OSNOSUP; + } + +#undef CASE +} diff --git a/linux/integers.c b/linux/integers.c new file mode 100644 index 0000000..469ede0 --- /dev/null +++ b/linux/integers.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ + +/* This file is included from ../libsyscalls_get_integer_alignment.c */ + + +#if 0 +static enum libsyscalls_error +get_linux_integer_alignment(enum libsyscalls_arch arch, unsigned width_in_bits, unsigned *alignmentp) +{ + /* ../libsyscalls_get_integer_alignment.c has already set `*alignmentp` + * according the the architectures specifications. Linux does not proscribe + * excess alignment and there is thus nothing for this function to do. */ + + (void) arch; + (void) width_in_bits; + (void) alignmentp; + return LIBSYSCALLS_E_OK; +} +#else +# define get_linux_integer_alignment(arch, width_in_bits, alignmentp) (LIBSYSCALLS_E_OK) +#endif diff --git a/linux/integers.mk b/linux/integers.mk new file mode 100644 index 0000000..93dacfd --- /dev/null +++ b/linux/integers.mk @@ -0,0 +1,4 @@ +# See LICENSE file for copyright and license details. + +libsyscalls_get_integer_alignment.o: linux/integers.c +libsyscalls_get_integer_alignment.lo: linux/integers.c diff --git a/linux/linux-support.mk b/linux/linux-support.mk index d596922..c4a3f94 100644 --- a/linux/linux-support.mk +++ b/linux/linux-support.mk @@ -33,6 +33,7 @@ SUPPORTED_LINUX_ARCHES =\ OPERATING_SYSTEMS += linux NPARAMS += 8 +NFIELDS += 60 SUPPORTED_LINUX_ARCHES != printf '%s\n' $(SUPPORTED_LINUX_ARCHES) $(SUPPORTED_ARCHES) | sort | uniq -d @@ -42,6 +43,7 @@ TEST_ENV += SUPPORTED_LINUX_ARCHES="$(SUPPORTED_LINUX_ARCHES)" include linux/download.mk include linux/errors.mk +include linux/integers.mk include linux/signals.mk include linux/syscalls.mk include linux/syscall-table.mk diff --git a/linux/syscalls.h b/linux/syscalls.h index ed278cd..e11120f 100644 --- a/linux/syscalls.h +++ b/linux/syscalls.h @@ -258,8 +258,8 @@ SYS(sys_stat, FILESYSTEM, STAT, 2, ZERO(INT), PARAMS(_,STRING, OUT,STRUCT_OLD_ST SYS(sys_newfstat, FILE_DESCRIPTORS, STAT, 2, ZERO(INT), PARAMS(_,INT_FD, OUT,STRUCT_STAT)); SYS(sys_fstat64, FILE_DESCRIPTORS, STAT, 2, ZERO(INT), PARAMS(_,LONG_FD, OUT,STRUCT_STAT64)); SYS(sys_fstat, FILE_DESCRIPTORS, STAT, 2, ZERO(INT), PARAMS(_,INT, OUT,STRUCT_OLD_STAT)); -SYS(sys_pipe, FILE_DESCRIPTORS, CREATE, 1, ZERO(INT), PARAMS(OUT,2_INTS_FD)); -SYS(sys_alpha_pipe, FILE_DESCRIPTORS, CREATE, 0, 2_INTS_FD, PARAMS()); +SYS(sys_pipe, IPC, CREATE, 1, ZERO(INT), PARAMS(OUT,2_INTS_FD)); +SYS(sys_alpha_pipe, IPC, CREATE, 0, 2_INTS_FD, PARAMS()); SYS(sys_readlink, FILESYSTEM, READLINK, 3, INT, PARAMS(_,STRING, OUT,BUFFER, _,INT)); SYS(sys_munlockall, MEMORY, UNLOCK, 0, ZERO(INT), PARAMS()); SYS(sys_munlock, MEMORY, UNLOCK, 2, ZERO(INT), PARAMS(_,MEMORY_ADDRESS, _,SIZE)); @@ -284,7 +284,7 @@ SYS(sys_mq_timedreceive_time32, IPC, COMMUNICATE_WITH_ABSOLUTE_TIMEOUT, 5, SSIZE SYS(sys_vhangup, PROCESSES, SESSION, 0, ZERO(INT), PARAMS()); SYS(sys_setsid, PROCESSES, SESSION, 0, INT, PARAMS()); SYS(sys_setpgid, PROCESSES, SESSION, 2, INT, PARAMS(_,INT, _,INT)); -SYS(sys_sched_yield, SCHEDULING, YEILD, 0, ZERO(INT), PARAMS()); +SYS(sys_sched_yield, SCHEDULING, YIELD, 0, ZERO(INT), PARAMS()); SYS(sys_sched_setparam, SCHEDULING, SET, 2, ZERO(INT), PARAMS(_,INT, IN,STRUCT_SCHED_PARAM)); SYS(sys_sched_getparam, SCHEDULING, GET, 2, ZERO(INT), PARAMS(_,INT, OUT,STRUCT_SCHED_PARAM)); SYS(sys_sched_rr_get_interval, SCHEDULING, GET, 2, ZERO(INT), PARAMS(_,INT, OUT,STRUCT_TIMESPEC)); @@ -339,7 +339,7 @@ SYS(sys_umount, FILESYSTEM, MOUNTPOINT, 2, ZERO(INT), PARAMS(_,STRING, SYM,UINT) SYS(sys_msync, FILESYSTEM, SYNC, 3, ZERO(INT), PARAMS(_,MEMORY_ADDRESS, _,SIZE, SYM,UINT), SYMBOLS(MSYNC)); SYS(sys_madvise, MEMORY, WRITE_OR_ADVISE, 3, ZERO(INT), PARAMS(_,MEMORY_ADDRESS, _,SIZE, SYM,INT), SYMBOLS(MADVISE)); SYS(sys_epoll_create1, FILE_DESCRIPTORS, CREATE_POLL, 1, INT_FD, PARAMS(SYM,UINT), SYMBOLS(EPOLL)); -SYS(sys_epoll_ctl, FILE_DESCRIPTORS, CREATE_POLL, 4, ZERO(INT), PARAMS(_,INT_FD, SYM,INT, _,INT, IN,STRUCT_EPOLL_EVENT), SYMBOLS(EPOLL_CTL)); +SYS(sys_epoll_ctl, FILE_DESCRIPTORS, CONFIGURE_POLL, 4, ZERO(INT), PARAMS(_,INT_FD, SYM,INT, _,INT, IN,STRUCT_EPOLL_EVENT), SYMBOLS(EPOLL_CTL)); SYS(sys_accept4, NETWORK_ENABLED_IPC, ACCEPT, 4, INT_FD, PARAMS(_,INT_FD, OUT,STRUCT_SOCKADDR, OUT,INT, _,UINT), SYMBOLS(SOCK_FD)); SYS(sys_clock_nanosleep, TIME, SLEEP, 4, ZERO(INT), PARAMS(SYM,INT, SYM,UINT, IN,STRUCT_TIMESPEC, OUT,STRUCT_TIMESPEC), SYMBOLS(CLOCKID, TIMER)); SYS(sys_clock_nanosleep_time32, TIME, SLEEP, 4, ZERO(INT), PARAMS(SYM,INT, SYM,UINT, IN,STRUCT_OLD_TIMESPEC32, OUT,STRUCT_OLD_TIMESPEC32), SYMBOLS(CLOCKID, TIMER)); @@ -376,7 +376,7 @@ SYS(sys_shmat, IPC, ATTACH, 3, MEMORY_ADDRESS, PARAMS(_,INT, _,MEMORY_ADDRESS, S SYS(sys_faccessat2, FILESYSTEM, STAT, 4, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING,SYM,UINT, SYM,UINT), SYMBOLS(FACCESSAT, FACCESSAT2)); SYS(sys_fsopen, FILESYSTEM, MOUNTPOINT, 2, INT_FD, PARAMS(_,STRING, SYM,UINT), SYMBOLS(FSOPEN)); SYS(sys_statx, FILESYSTEM, STAT, 5, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, SYM,UINT, SYM,UINT, OUT,STRUCT_STATX), SYMBOLS(3STATX)); -SYS(sys_pipe2, FILE_DESCRIPTORS, CREATE, 2, ZERO(INT), PARAMS(OUT,2_INTS_FD, SYM,UINT), SYMBOLS(PIPE)); +SYS(sys_pipe2, IPC, CREATE, 2, ZERO(INT), PARAMS(OUT,2_INTS_FD, SYM,UINT), SYMBOLS(PIPE)); SYS(sys_getrandom, SYSTEM, RANDOM, 3, SSIZE, PARAMS(OUT,BUFFER, _,SIZE, SYM,UINT), SYMBOLS(GRND)); SYS(sys_inotify_init1, FILESYSTEM, MONITOR, 1, INT_FD, PARAMS(SYM,UINT), SYMBOLS(INOTIFY_FD)); SYS(sys_inotify_add_watch, FILESYSTEM, MONITOR, 3, INT32, PARAMS(_,INT_FD, _,STRING, SYM,UINT32), SYMBOLS(INOTIFY_MASK)); @@ -388,8 +388,8 @@ SYS(sys_msgsnd, IPC, COMMUNICATE, 4, ZERO(SSIZE), PARAMS(_,INT, OUT,STRUCT_MSGBU SYS(sys_fanotify_mark, FILESYSTEM, MONITOR, 5, ZERO(INT), PARAMS(_,INT_FD, SYM,UINT, SYM,UINT64, SYM,INT_ATFD, _,STRING), SYMBOLS(FANOTIFY_MARK, ATFD)); SYS(sys_mq_open, IPC, CONTROL, 4, INT_FD, PARAMS(_,STRING, SYM,UINT, SYM,USHORT, IN,STRUCT_MQ_ATTR), SYMBOLS(MQ_OPEN, MODE)); SYS(sys_fanotify_init, FILESYSTEM, MONITOR, 2, INT_FD, PARAMS(SYM,UINT, SYM,UINT), SYMBOLS(FAN_CLASS, FAN_EVENT_F)); -SYS(sys_socket, FILE_DESCRIPTORS, CREATE, 3, INT_FD, PARAMS(SYM,INT, SYM,UINT, SYM,UINT), SYMBOLS(SOCKET)); -SYS(sys_socketpair, FILE_DESCRIPTORS, CREATE, 4, ZERO(INT), PARAMS(SYM,INT, SYM,UINT, SYM,UINT, OUT,2_INTS_FD), SYMBOLS(SOCKET)); +SYS(sys_socket, NETWORK_ENABLED_IPC, CREATE, 3, INT_FD, PARAMS(SYM,INT, SYM,UINT, SYM,UINT), SYMBOLS(SOCKET)); +SYS(sys_socketpair, IPC, CREATE, 4, ZERO(INT), PARAMS(SYM,INT, SYM,UINT, SYM,UINT, OUT,2_INTS_FD), SYMBOLS(SOCKET)); SYS(sys_epoll_wait, FILE_DESCRIPTORS, POLL, 4, INT, PARAMS(_,INT_FD, OUT,STRUCT_EPOLL_EVENT_ARRAY, _,INT, _,INT)); SYS(sys_epoll_pwait, FILE_DESCRIPTORS, POLL, 6, INT, PARAMS(_,INT_FD, OUT,STRUCT_EPOLL_EVENT_ARRAY, _,INT, _,INT, IN,ULONG_ARRAY, _,SIZE)); SYS(sys_epoll_pwait2, FILE_DESCRIPTORS, POLL, 6, INT, PARAMS(_,INT_FD, OUT,STRUCT_EPOLL_EVENT_ARRAY, _,INT, IN,STRUCT_TIMESPEC, IN,ULONG_ARRAY, _,SIZE)); diff --git a/linux/tests/os-dependent-integers b/linux/tests/os-dependent-integers new file mode 100644 index 0000000..73de229 --- /dev/null +++ b/linux/tests/os-dependent-integers @@ -0,0 +1,4 @@ +# -*- sh -*- +# See LICENSE file for copyright and license details. + +. tests/default-integers diff --git a/linux/what-architecture-am-i-using b/linux/what-architecture-am-i-using index 1c7a9ba..646c9e7 100755 --- a/linux/what-architecture-am-i-using +++ b/linux/what-architecture-am-i-using @@ -9,6 +9,13 @@ if uname -s | grep -i linux > /dev/null; then if test "$arch" = x86_64; then printf '%s\n' AMD64 if test $# = 0 || "$@"; then + if test ! -f /proc/config.gz; then + printf '%s\n' '/proc/config.gz is missing' >&2 + exit 1 + elif test ! -r /proc/config.gz; then + printf '%s\n' '/proc/config.gz is not readable' >&2 + exit 1 + fi if test $# = 0 || gunzip < /proc/config.gz | grep '^CONFIG_X86_X32_ABI=y$' > /dev/null; then printf '%s\n' AMD64_X32 fi diff --git a/mk/generate.mk b/mk/generate.mk index 17671f4..9575c34 100644 --- a/mk/generate.mk +++ b/mk/generate.mk @@ -1,7 +1,8 @@ # See LICENSE file for copyright and license details. NPARAMS != printf '%d\n' 1 $(NPARAMS) | sort -n | sed -n '$$p' +NFIELDS != printf '%d\n' 1 $(NFIELDS) | sort -n | sed -n '$$p' -IMPORTANT_CPPFLAGS += -DNPARAMS="$(NPARAMS)" +IMPORTANT_CPPFLAGS += -DNPARAMS="$(NPARAMS)" -DNFIELDS="$(NFIELDS)" GET_SYSCALL_RANGE_GEN != printf 'generated/get_syscall_range.%s.c\n' $(OPERATING_SYSTEMS) @@ -21,6 +22,9 @@ libsyscalls_get_syscall_errors.lo: generated/errors.c libsyscalls_get_datatype_description.o: generated/types.c libsyscalls_get_datatype_description.lo: generated/types.c +libsyscalls_get_integer_alignment.o: generated/integers.c +libsyscalls_get_integer_alignment.lo: generated/integers.c + $(GET_SYSCALL_RANGE_GEN): get_syscall_range.template.c mk/generate.mk mkdir -p -- generated @@ -48,6 +52,10 @@ generated/types.c: Makefile mk/generate.mk mkdir -p -- generated printf '\43include "../%s/types.c"\n' $(OPERATING_SYSTEMS) > $@ +generated/integers.c: Makefile mk/generate.mk + mkdir -p -- generated + printf '\43include "../%s/integers.c"\n' $(OPERATING_SYSTEMS) > $@ + generated/arches.h: Makefile mk/generate.mk mkdir -p -- generated printf '\43include "%s-arches.h"\n' $(OPERATING_SYSTEMS) > $@ diff --git a/test b/test index c825493..185d915 100755 --- a/test +++ b/test @@ -29,11 +29,15 @@ alias t=. # have already been written and passed, set to . otherwise -set -v - -test -n "${SUPPORTED_OSES}" # This check that the test's environment has set up, if this fails, run through `make check` +if ! env | grep '^SUPPORTED_OSES=' >/dev/null; then + printf '%s\n' \ + "The test's environment has not been set up;" \ + 'you should run the test via `make check`' + exit 1 +fi -(. tests/test-self-check;) >/dev/null 2>/dev/null +set -v +(. tests/test-self-check) >/dev/null 2>/dev/null @@ -41,31 +45,22 @@ t tests/enums . tests/load-types t tests/errors - t tests/syscall-ranges - t tests/syscall-errors - t tests/signals - t tests/split-register-classes . tests/load-archinfo t tests/archinfo t tests/fundamental-primitives - t tests/is-struct - t tests/array-types - t tests/fixed-array-types - t tests/split-register-types - t tests/os-dependent-primitives - t tests/os-dependent-arrays +t tests/os-dependent-integers diff --git a/tests/default-integers b/tests/default-integers new file mode 100644 index 0000000..12faa5a --- /dev/null +++ b/tests/default-integers @@ -0,0 +1,21 @@ +# -*- sh -*- +# See LICENSE file for copyright and license details. + +for arch in $(getnamelist ARCH); do + archn=$(getnum ARCH $arch) + if ! issupported $os $arch; then + continue + fi + + if test $arch = M68K; then + maxalign=16 + elif test $arch = I386; then + maxalign=32 + else + maxalign=64 + fi + + for width in 8 16 32 64; do + test "$(get-integer-alignment.tu $osn $archn $width $os $arch)" = $(min $maxalign $width) + done +done diff --git a/tests/load-functions b/tests/load-functions index f0c5311..a31f236 100644 --- a/tests/load-functions +++ b/tests/load-functions @@ -58,3 +58,7 @@ issupported () { cpp_enum_clean () { $CPP < libsyscalls.h 2>/dev/null | grep -v '#' | tr '\n,{}' ' \n\n\n' } + +min () { + printf '%s\n' "$@" | tr -d + | sort -n | sed -n 1p +} diff --git a/tests/os-dependent-integers b/tests/os-dependent-integers new file mode 100644 index 0000000..09a11e3 --- /dev/null +++ b/tests/os-dependent-integers @@ -0,0 +1,9 @@ +# -*- sh -*- +# See LICENSE file for copyright and license details. + +for os in $(getnamelist OS); do + osn=$(getnum OS $os) + if issupported $os; then + . $(printf '%s\n' $os | tr '[A-Z]' '[a-z]')/tests/os-dependent-integers + fi +done diff --git a/testutil/get-integer-alignment.c b/testutil/get-integer-alignment.c new file mode 100644 index 0000000..6c91824 --- /dev/null +++ b/testutil/get-integer-alignment.c @@ -0,0 +1,45 @@ +/* See LICENSE file for copyright and license details. */ +#include "../libsyscalls.h" + +#include +#include +#include +#include + +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunsafe-buffer-usage" /* clang is just being silly */ +#endif + + +int +main(int argc, char **argv) +{ + int os, arch, width; + unsigned alignment = -1; + enum libsyscalls_error err; + + if (argc != 6) { + fprintf(stderr, "usage error\n"); + return 3; + } + + os = atoi(argv[1]); + arch = atoi(argv[2]); + width = atoi(argv[3]); + + err = libsyscalls_get_integer_alignment((enum libsyscalls_os)os, (enum libsyscalls_arch)arch, + (unsigned)width, &alignment); + if (err) { + fprintf(stderr, "libsyscalls_get_integer_alignment %s %s %s: ", argv[4], argv[5], argv[3]); + libsyscalls_perror(NULL, err); + return 1; + } + + printf("%u\n", alignment); + + if (fflush(stdout) || fclose(stdout)) { + perror(NULL); + return 1; + } + return 0; +} -- cgit v1.2.3-70-g09d2