summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2023-12-03 19:23:35 +0100
committerMattias Andrée <maandree@kth.se>2023-12-03 19:23:35 +0100
commitc131f122778c62f920a99bbf854ced4a37ee8b03 (patch)
tree14c933f98f4d64dffb0a594bc40dd5121c6c5a8e
downloadlibsyscalls-c131f122778c62f920a99bbf854ced4a37ee8b03.tar.gz
libsyscalls-c131f122778c62f920a99bbf854ced4a37ee8b03.tar.bz2
libsyscalls-c131f122778c62f920a99bbf854ced4a37ee8b03.tar.xz
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--.gitignore16
-rw-r--r--LICENSE15
-rw-r--r--Makefile149
-rw-r--r--TODO8
-rw-r--r--common.h75
-rw-r--r--config-figure-this-out-for-me.mk59
-rw-r--r--config.mk47
-rwxr-xr-xdevtools/create-linux-syscall332
-rwxr-xr-xdevtools/find-type-definition8
-rw-r--r--get_syscall_range.template.c23
-rw-r--r--libsyscalls.h1327
-rw-r--r--libsyscalls/advanced.h13
-rw-r--r--libsyscalls/internal-begin.h76
-rw-r--r--libsyscalls/internal-end.h21
-rw-r--r--libsyscalls_get_datatype_description.c418
-rw-r--r--libsyscalls_get_signals.c32
-rw-r--r--libsyscalls_get_syscall.c37
-rw-r--r--libsyscalls_get_syscall_display_info.c148
-rw-r--r--libsyscalls_get_syscall_errors.c32
-rw-r--r--libsyscalls_get_syscall_range.c26
-rw-r--r--libsyscalls_perror.c15
-rw-r--r--libsyscalls_strerror.c18
-rw-r--r--libsyscalls_syscalls_tables_.c10
-rw-r--r--linux/download.mk33
-rw-r--r--linux/errors.c130
-rw-r--r--linux/errors.mk52
-rw-r--r--linux/linux-support.mk54
-rw-r--r--linux/no.mk0
-rw-r--r--linux/signals.c130
-rw-r--r--linux/signals.mk138
-rw-r--r--linux/symbols.c321
-rw-r--r--linux/symbols.mk73
-rw-r--r--linux/syscall-table.c58
-rw-r--r--linux/syscall-table.mk60
-rw-r--r--linux/syscalls.h988
-rw-r--r--linux/syscalls.mk450
-rw-r--r--linux/types.c54
-rw-r--r--linux/types.mk2
-rwxr-xr-xlinux/what-architecture-am-i-using26
l---------linux/yes.mk1
-rw-r--r--mk/generate.mk127
-rw-r--r--mk/linux.mk6
-rw-r--r--mk/macos.mk6
-rw-r--r--mk/windows.mk6
-rwxr-xr-xutil/getdefs27
-rwxr-xr-xutil/getenum21
-rwxr-xr-xutil/make-enum45
-rwxr-xr-xutil/make-mask55
-rwxr-xr-xutil/make-multiextractor25
-rwxr-xr-xutil/make-sym-extractor25
-rwxr-xr-xutil/what-architecture-am-i-using22
51 files changed, 5840 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..df605d8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,16 @@
+*\#*
+*~
+*.o
+*.a
+*.lo
+*.su
+*.so
+*.so.*
+*.gch
+*.gcov
+*.gcno
+*.gcda
+*.tmp
+/*-src/
+/generated/
+/libsyscalls/short-enums.h
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..0be2ccf
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+© 2023 Mattias Andrée <maandree@kth.se>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7b0ecb3
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,149 @@
+.POSIX:
+
+# Choose either yes or no (determines whether system call,
+# signal, and error tables, for the list operating systems,
+# shall be compiled into the library)
+LINUX_SUPPORT = $(DEFAULT_OS_SUPPORT_SELECTION)
+
+# Choose operating system to compile the library for
+OS = linux
+# Linux: linux
+# Mac OS: macos
+# Windows: windows
+
+CONFIGFILE = config.mk
+include $(CONFIGFILE)
+
+
+
+
+include mk/$(OS).mk
+
+LIB_MAJOR = 1
+LIB_MINOR = 0
+LIB_VERSION = $(LIB_MAJOR).$(LIB_MINOR)
+LIB_NAME = syscalls
+
+
+all: libsyscalls.a libsyscalls.$(LIBEXT)
+
+#extended for each support operating system to download the operating system's source code
+download:
+
+
+SUPPORTED_ARCHES =\
+ AMD64\
+ AMD64_X32\
+ M68K\
+ PARISC_32\
+ PARISC_64\
+ SPARC_32\
+ I386
+# Excluded because of missing support in libsyscalls_get_datatype_description.c:
+# ALPHA ARM_OABI ARM_EABI IA64 MICROBLAZE MIPS_O32 MIPS_N32 MIPS_N64 POWERPC_32
+# POWERPC_64 POWERPC_NOSPU POWERPC_SPU S390_32 S390_64 SH SPARC_64 XTENSA
+
+include $(CONFIGFILE)
+# Reloading the user's config in case it limits supported architectures
+
+
+#extended for each support operating system with the operating system's name as appropriate for filenames
+OPERATING_SYSTEMS =
+
+#extended for each support operating system with the number of syscall parameters they use
+NPARAMS =
+
+#extended for each support operating system
+OBJ =\
+ libsyscalls_get_datatype_description.o\
+ libsyscalls_get_signals.o\
+ libsyscalls_get_syscall.o\
+ libsyscalls_get_syscall_display_info.o\
+ libsyscalls_get_syscall_errors.o\
+ libsyscalls_get_syscall_range.o\
+ libsyscalls_perror.o\
+ libsyscalls_strerror.o\
+ libsyscalls_syscalls_tables_.o
+
+#extended for each support operating system
+HDR =\
+ libsyscalls.h\
+ common.h\
+ generated/arches.h\
+ generated/lowercase.h\
+ generated/oses.h\
+ generated/macros.h\
+ $(SUBHDR)
+
+SUBHDR =\
+ libsyscalls/advanced.h\
+ libsyscalls/internal-begin.h\
+ libsyscalls/internal-end.h\
+ libsyscalls/short-enums.h
+
+
+.SUFFIXES:
+.SUFFIXES: .lo .o .c
+
+
+include linux/$(LINUX_SUPPORT).mk
+include mk/generate.mk
+
+include $(CONFIGFILE)
+# Reloading the user's config as the makefiles for the OS
+# may have made changes to what is supported
+
+LOBJ = $(OBJ:.o=.lo)
+
+
+$(OBJ): $(HDR)
+$(LOBJ): $(HDR)
+
+.c.o:
+ $(CC) -c -o $@ $< $(CFLAGS) $(IMPORTANT_CFLAGS) $(CPPFLAGS) $(IMPORTANT_CPPFLAGS)
+
+.c.lo:
+ $(CC) -fPIC -c -o $@ $< $(CFLAGS) $(IMPORTANT_CFLAGS) $(CPPFLAGS) $(IMPORTANT_CPPFLAGS)
+
+libsyscalls.a: $(OBJ)
+ @rm -f -- $@
+ $(AR) rc $@ $(OBJ)
+ $(AR) ts $@ > /dev/null
+
+libsyscalls.$(LIBEXT): $(LOBJ)
+ $(CC) $(LIBFLAGS) -o $@ $(LOBJ) $(LDFLAGS)
+
+install: libsyscalls.a libsyscalls.$(LIBEXT)
+ mkdir -p -- "$(DESTDIR)$(PREFIX)/lib"
+ mkdir -p -- "$(DESTDIR)$(PREFIX)/include/libsyscalls"
+ cp -- libsyscalls.a "$(DESTDIR)$(PREFIX)/lib/"
+ cp -- libsyscalls.$(LIBEXT) "$(DESTDIR)$(PREFIX)/lib/libsyscalls.$(LIBMINOREXT)"
+ $(FIX_INSTALL_NAME) "$(DESTDIR)$(PREFIX)/lib/libsyscalls.$(LIBMINOREXT)"
+ ln -sf -- libsyscalls.$(LIBMINOREXT) "$(DESTDIR)$(PREFIX)/lib/libsyscalls.$(LIBMAJOREXT)"
+ ln -sf -- libsyscalls.$(LIBMAJOREXT) "$(DESTDIR)$(PREFIX)/lib/libsyscalls.$(LIBEXT)"
+ cp -- libsyscalls.h "$(DESTDIR)$(PREFIX)/include/"
+ cp -- $(SUBHDR) "$(DESTDIR)$(PREFIX)/include/libsyscalls/"
+
+uninstall:
+ -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libsyscalls.a"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libsyscalls.$(LIBMAJOREXT)"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libsyscalls.$(LIBMINOREXT)"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libsyscalls.$(LIBEXT)"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/include/libsyscalls.h"
+ -cd -- "$(DESTDIR)$(PREFIX)/include/" && rm -f -- $(SUBHDR)
+ -rmdir -- "$(DESTDIR)$(PREFIX)/include/libsyscalls"
+
+
+clean: buildclean
+ -rm -rf -- $(OPERATING_SYSTEMS:=-src/)
+
+buildclean: semiclean
+ -rm -rf -- generated/ $(OPERATING_SYSTEMS:=-src/*/)
+
+semiclean:
+ -rm -f -- *.o *.lo *.su *.gch *.gcov *.gcno *.gcda .*.tmp
+ -rm -f -- */*.o */*.lo */*.su */*.gch */*.gcov */*.gcno */*.gcda
+ -rm -f -- *.a *.so *.so.* *.dll *.dylib *.$(LIBEXT)
+ -rm -f -- libsyscalls/short-enums.h
+
+.PHONY: all download install uninstall clean semiclean
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..38e1a93
--- /dev/null
+++ b/TODO
@@ -0,0 +1,8 @@
+Add extraction tool
+Add test generation and regression testing
+Add support for describing structs and unions
+Add calling convention
+Add value decoding
+Add value encoding
+Add man pages and README
+The syscall table is too big and should be compressed
diff --git a/common.h b/common.h
new file mode 100644
index 0000000..f2ac824
--- /dev/null
+++ b/common.h
@@ -0,0 +1,75 @@
+/* See LICENSE file for copyright and license details. */
+#ifdef REQUIRE_FLEXABLE_OR_NPARAMS
+# if defined(__clang__) || defined(__GNUC__)
+# define LIBSYSCALLS_FLEXABLE_OR_NPARAMS_
+# else
+# define LIBSYSCALLS_FLEXABLE_OR_NPARAMS_ NPARAMS
+# warning Setting LIBSYSCALLS_FLEXABLE_OR_NPARAMS_ to NPARAMS as it is not known that the compiler supports static allocation of structs with flexible arrays
+# endif
+#endif
+#include "libsyscalls.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define COMMA ,
+
+
+#define MISALIGNMENT(ADDR, ALIGN) (((ADDR) - ((ADDR) % (uintptr_t)(ALIGN))) % (uintptr_t)(ALIGN))
+#define ALIGN_BUF(BUF, ALIGN) (&(BUF)[(size_t)MISALIGNMENT((uintptr_t)(char *)(BUF), (ALIGN))])
+
+
+struct libsyscalls_symbol_printer_data {
+ enum libsyscalls_arch arch;
+ int nr;
+ char buf[];
+};
+
+
+#include "generated/oses.h"
+#include "generated/arches.h"
+#include "generated/lowercase.h"
+#include "generated/macros.h"
+
+
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
+#endif
+extern const struct libsyscalls_syscall *const *const *const libsyscalls_syscalls_tables_[];
+#define X(UPPERCASE, LOWERCASE)\
+ extern const struct libsyscalls_syscall *const *const libsyscalls_##LOWERCASE##_syscalls_table_[];
+LIST_OSES(X,)
+#undef X
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+
+
+#define COUNT_ARG_PAIRS(...) (0 __VA_OPT__(+ COUNT_ARG_PAIRS_1(__VA_ARGS__)))
+
+/* mk/generate.mk reads these two lines, do not format them as multiline macros! */
+#define COUNT_ARG_PAIRS_1(x1, x2, ...) 1 __VA_OPT__(+ COUNT_ARG_PAIRS_2(__VA_ARGS__))
+#define PARAMS_BUILD_TYPES_1(x, A, ...) LIBSYSCALLS_TYPE_##A __VA_OPT__(, PARAMS_BUILD_TYPES_2(__VA_ARGS__))
+
+#define PARAMS(...)\
+ .max_argument_count = COUNT_ARG_PAIRS(__VA_ARGS__),\
+ .in_pointer_mask = PARAMS_BUILD_MASK(IN, __VA_ARGS__),\
+ .out_pointer_mask = PARAMS_BUILD_MASK(OUT, __VA_ARGS__), \
+ .symbolic_mask = PARAMS_BUILD_MASK(SYM, __VA_ARGS__)\
+ __VA_OPT__(, .parameters_types = {PARAMS_BUILD_TYPES_1(__VA_ARGS__)})
+
+#define ZERO(TYPE) TYPE, .expect_zero = 1
+#define LIBSYSCALLS_TYPE_ZERO(TYPE) ZERO(LIBSYSCALLS_TYPE_##TYPE)
+
+#define SYMB(TYPE) TYPE, .symbolic_return = 1
+#define LIBSYSCALLS_TYPE_SYMB(TYPE) SYMB(LIBSYSCALLS_TYPE_##TYPE)
+
+#define SYSCALL_ABI(OS, NAME, CATEGORY, SUBCATEGORY, MIN_ARGS, RETURN_TYPE, ...)\
+ static struct libsyscalls_syscall_abi OS##_syscall_##NAME = {\
+ .category = LIBSYSCALLS_CAT_##CATEGORY,\
+ .subcategory.LOWERCASE_##CATEGORY = LIBSYSCALLS_##CATEGORY##_SUBCAT_##SUBCATEGORY,\
+ .min_argument_count = MIN_ARGS,\
+ .return_type = LIBSYSCALLS_TYPE_##RETURN_TYPE,\
+ __VA_ARGS__\
+ }
diff --git a/config-figure-this-out-for-me.mk b/config-figure-this-out-for-me.mk
new file mode 100644
index 0000000..2d470f7
--- /dev/null
+++ b/config-figure-this-out-for-me.mk
@@ -0,0 +1,59 @@
+BASECONFIG !=\
+ set -e; \
+ if test -n "$(BASECONFIG)"; then \
+ printf '%s\n' "$(BASECONFIG)"; \
+ else \
+ rm -f -- .config.mk.tmp; \
+ (set -e; \
+ sed 's/^\s*DOWNLOAD\s*=/\x23&/' < config.mk; \
+ for testscript in */what-architecture-am-i-using; do \
+ if test "$$testscript" = "util/what-architecture-am-i-using"; then \
+ continue; \
+ fi; \
+ os="$$(printf '%s\n' "$$testscript" | cut -d / -f 1 | tr '[a-z]' '[A-Z]')"; \
+ support="$${os}_SUPPORT"; \
+ q=\'; \
+ printf '%s_ != test -z "$$(%s_)" || printf %s%%s\\n%s "$$(%s)"\n' \
+ "$$support" "$$support" $$q $$q "$$support"; \
+ printf '%s !=\\\n' \
+ "$$support"; \
+ printf '\tif test -n "$$(%s_)"; then \\\n' \
+ "$$support"; \
+ printf '\t\tprintf '\''%%s\\n'\'' "$$(%s_)"; \\\n' \
+ "$$support"; \
+ printf '\telse \\\n'; \
+ printf '\t\tset +e; \\\n'; \
+ printf '\t\t%s false >/dev/null 2>&1; \\\n' \
+ "$${testscript}"; \
+ printf '\t\tif test $$$$? -lt 2; then printf %syes\\n%s; else printf %sno\\n%s; fi; \\\n' \
+ $$q $$q $$q $$q; \
+ printf '\tfi\n'; \
+ done \
+ ) > .config.mk.tmp; \
+ printf '%s\n' .config.mk.tmp; \
+ fi;
+
+include $(BASECONFIG)
+
+DOWNLOAD !=\
+ if test -n "$(DOWNLOAD)"; then printf '%s\n' "$(DOWNLOAD)"; \
+ elif curl --version >/dev/null 2>&1; then printf 'curl --\n'; \
+ elif wget --version >/dev/null 2>&1; then printf 'wget -O - --\n'; \
+ else printf 'curl --\n'; fi
+
+DEFAULT_OS_SUPPORT_SELECTION != :
+
+SUPPORTED_ARCHES_ != test -z "$(SUPPORTED_ARCHES_)" || printf '%s\n' "$(SUPPORTED_ARCHES)"
+
+SUPPORTED_ARCHES !=\
+ if test -n "$(SUPPORTED_ARCHES_)"; then printf '%s\n' "$(SUPPORTED_ARCHES_)"; \
+ else util/what-architecture-am-i-using true; fi
+
+DEFAULT_OS_SUPPORT_SELECTION != printf 'no\n'
+
+IMPORTANT_CFLAGS !=\
+ printf '%s\n' $(IMPORTANT_CFLAGS) &&\
+ if ! printf '%s\n' $(CC) $(CFLAGS) $(IMPORTANT_CFLAGS) | grep '^-std=c..$$' > /dev/null; then \
+ sed -n 's/^.*\(-std=c..\).*$$/\1/p' < .config.mk.tmp | sed 1q; \
+ fi
+
diff --git a/config.mk b/config.mk
new file mode 100644
index 0000000..144b7ac
--- /dev/null
+++ b/config.mk
@@ -0,0 +1,47 @@
+PREFIX = /usr
+MANPREFIX = $(PREFIX)/share/man
+
+CC = cc -std=c2x
+
+CC_DEF_EXTRACT =
+# If set, it will be used with -E -dM (must have the same meaning
+# as in GCC and clang), otherwise $(CC) is used if it is GCC or
+# clang, otherwise a gcc or clang from PATH is used
+
+CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE
+CFLAGS = -Os
+LDFLAGS =
+# It is important that CFLAGS at least specifies some optimisation,
+# otherwise you may get binaries containing a lot of unused symbols
+# and so be unnecessarily large. (The build deduplicates identical
+# system call description, but only references to them, not their
+# instantiations (which have static storage), for that it it relies
+# on compiler optimisation.)
+
+DOWNLOAD = curl --
+
+DEFAULT_OS_SUPPORT_SELECTION = yes
+# You may for example put `DEFAULT_OS_SUPPORT_SELECTION = no` but add
+# `LINUX_SUPPORT = yes` to this file if you always only want to have
+# Linux supported.
+
+#SUPPORTED_ARCHES != util/what-architecture-am-i-using true
+# Uncomment this limit supported architectures. You will find which
+# architectures are support in Makefile (don't add anything else).
+# If you uncomment this without editing it ('!=' means it will execute
+# that text behind it as a shell commend; change to '=' to list
+# manually), the architecture you are running on, and modes
+# (e.g. i386 and x32 on amd64, however if the kernel is built to
+# support them)[1], its supports, will be selected.
+# [1] Change 'true' to 'false' to exclude them, or remove 'true'
+# to support even ones that the kernel is not compiled to support
+
+# You can also limit supported architectures on an per-OS basis, by
+# setting SUPPORTED_${NAME_OF_OS}_ARCHES; you will find the list of
+# support architectures in ${name-of-os}/${name-of-os}-support.mk,
+# however architectures not support in libsyscalls's core may be listed;
+# do not add anything that is not supported by both libsyscalls's core
+# and it's OS support
+
+
+# This file is included multiple times, don't do anything weird
diff --git a/devtools/create-linux-syscall b/devtools/create-linux-syscall
new file mode 100755
index 0000000..0b8e800
--- /dev/null
+++ b/devtools/create-linux-syscall
@@ -0,0 +1,332 @@
+#!/usr/bin/env python3
+
+import sys
+
+lines = []
+try:
+ while True:
+ lines.append(input())
+except EOFError:
+ pass
+
+def remove_comments(text):
+ return ' '.join(t.split('/*')[0] for t in text.split('*/'))
+
+functions = frozenset(sys.argv[1:]) if len(sys.argv) > 1 else None
+
+lines = remove_comments(' '.join(lines)).replace('\t', ' ')
+lines = [line.strip() for line in lines.split(';') if line]
+lines = [' '.join(word for word in line.split(' ')[1:] if word) for line in lines
+ if line.replace('//', '').strip().startswith('asmlinkage ')]
+lines = sorted(lines)
+
+def map_type(typ):
+ orig_typ = typ
+ if typ.startswith('signed ') and typ != 'signed char':
+ typ = typ[len('signed '):]
+ typemap = {
+ 'void' : 'LIBSYSCALLS_TYPE_VOID',
+ 'char' : 'LIBSYSCALLS_TYPE_CHAR',
+ 'signed char' : 'LIBSYSCALLS_TYPE_SCHAR',
+ 'unsigned char' : 'LIBSYSCALLS_TYPE_UCHAR',
+ 'short int' : 'LIBSYSCALLS_TYPE_SHORT',
+ 'unsigned short int' : 'LIBSYSCALLS_TYPE_USHORT',
+ 'int' : 'LIBSYSCALLS_TYPE_INT',
+ 'unsigned int' : 'LIBSYSCALLS_TYPE_UINT',
+ 'long int' : 'LIBSYSCALLS_TYPE_LONG',
+ 'unsigned long int' : 'LIBSYSCALLS_TYPE_ULONG',
+ 'long long int' : 'LIBSYSCALLS_TYPE_LLONG',
+ 'unsigned long long int' : 'LIBSYSCALLS_TYPE_ULLONG',
+ 'size_t' : 'LIBSYSCALLS_TYPE_SIZE',
+ 'ssize_t' : 'LIBSYSCALLS_TYPE_SSIZE',
+ 'ptrdiff_t' : 'LIBSYSCALLS_TYPE_PTRDIFF',
+ 'float' : 'LIBSYSCALLS_TYPE_FLOAT',
+ 'double' : 'LIBSYSCALLS_TYPE_DOUBLE',
+ 'long double' : 'LIBSYSCALLS_TYPE_LDOUBLE',
+ 'int8_t' : 'LIBSYSCALLS_TYPE_INT8',
+ 'uint8_t' : 'LIBSYSCALLS_TYPE_UINT8',
+ 'int16_t' : 'LIBSYSCALLS_TYPE_INT16',
+ 'uint16_t' : 'LIBSYSCALLS_TYPE_UINT16',
+ 'int32_t' : 'LIBSYSCALLS_TYPE_INT32',
+ 'uint32_t' : 'LIBSYSCALLS_TYPE_UINT32',
+ 'int64_t' : 'LIBSYSCALLS_TYPE_INT64',
+ 'uint64_t' : 'LIBSYSCALLS_TYPE_UINT64',
+ 'struct sockaddr' : 'LIBSYSCALLS_TYPE_STRUCT_SOCKADDR',
+ 'struct timex' : 'LIBSYSCALLS_TYPE_STRUCT_TIMEX',
+ 'struct old_timex32' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEX32',
+ 'struct iovec' : 'LIBSYSCALLS_TYPE_STRUCT_IOVEC_ARRAY',
+ 'struct statfs' : 'LIBSYSCALLS_TYPE_STRUCT_STATFS',
+ 'struct statfs64' : 'LIBSYSCALLS_TYPE_STRUCT_STATFS64',
+ 'struct stat' : 'LIBSYSCALLS_TYPE_STRUCT_STAT',
+ 'struct stat64' : 'LIBSYSCALLS_TYPE_STRUCT_STAT64',
+ 'struct old_stat' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_STAT',
+ 'struct mount_attr' : 'LIBSYSCALLS_TYPE_STRUCT_MOUNT_ATTR',
+ 'struct ustat' : 'LIBSYSCALLS_TYPE_STRUCT_USTAT',
+ 'struct statx' : 'LIBSYSCALLS_TYPE_STRUCT_STATX',
+ 'struct linux_dirent' : 'LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT',
+ 'struct linux_dirent64' : 'LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT64',
+ 'struct old_linux_dirent' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_LINUX_DIRENT',
+ 'struct open_how' : 'LIBSYSCALLS_TYPE_STRUCT_OPEN_HOW',
+ 'struct iob' : 'LIBSYSCALLS_TYPE_STRUCT_IOB',
+ 'struct io_event' : 'LIBSYSCALLS_TYPE_STRUCT_IO_EVENT',
+ 'struct timespec' : 'LIBSYSCALLS_TYPE_STRUCT_TIMESPEC',
+ 'struct old_timespec32' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_TIMESPEC32',
+ 'struct aio_sigset' : 'LIBSYSCALLS_TYPE_STRUCT_AIO_SIGSET',
+ 'struct io_uring_params' : 'LIBSYSCALLS_TYPE_STRUCT_IO_URING_PARAMS',
+ 'struct epoll_event' : 'LIBSYSCALLS_TYPE_STRUCT_EPOLL_EVENT',
+ 'struct pollfd' : 'LIBSYSCALLS_TYPE_STRUCT_POLLFD',
+ 'struct utimbuf' : 'LIBSYSCALLS_TYPE_STRUCT_UTIMBUF',
+ 'struct old_utimbuf32' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_UTIMBUF32',
+ 'struct old_timeval' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEVAL',
+ 'struct old_timeval32' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEVAL32',
+ 'struct sel_arg_struct' : 'LIBSYSCALLS_TYPE_STRUCT_SEL_ARG_STRUCT',
+ 'struct tms' : 'LIBSYSCALLS_TYPE_STRUCT_TMS',
+ 'struct itimerspec' : 'LIBSYSCALLS_TYPE_STRUCT_ITIMERSPEC',
+ 'struct old_itimerspec32' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_ITIMERSPEC32',
+ 'struct siginfo' : 'LIBSYSCALLS_TYPE_STRUCT_SIGINFO',
+ 'struct rusage' : 'LIBSYSCALLS_TYPE_STRUCT_RUSAGE',
+ 'struct robust_list_head' : 'LIBSYSCALLS_TYPE_STRUCT_ROBUST_LIST_HEAD',
+ 'struct futex_waitv' : 'LIBSYSCALLS_TYPE_STRUCT_FUTEX_WAITV',
+ 'struct old_itimerval' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_ITIMERVAL',
+ 'struct kexec_segment' : 'LIBSYSCALLS_TYPE_STRUCT_KEXEC_SEGMENT',
+ 'struct sigevent' : 'LIBSYSCALLS_TYPE_STRUCT_SIGEVENT',
+ 'struct sched_param' : 'LIBSYSCALLS_TYPE_STRUCT_SCHED_PARAM',
+ 'struct sigaltstack' : 'LIBSYSCALLS_TYPE_STRUCT_SIGALTSTACK',
+ 'struct sigaction' : 'LIBSYSCALLS_TYPE_STRUCT_SIGACTION',
+ 'struct old_sigaction' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_SIGACTION',
+ 'struct new_utsname' : 'LIBSYSCALLS_TYPE_STRUCT_NEW_UTSNAME',
+ 'struct old_utsname' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_UTSNAME',
+ 'struct oldold_utsname' : 'LIBSYSCALLS_TYPE_STRUCT_OLDOLD_UTSNAME',
+ 'struct rlimit' : 'LIBSYSCALLS_TYPE_STRUCT_RLIMIT',
+ 'struct rlimit64' : 'LIBSYSCALLS_TYPE_STRUCT_RLIMIT64',
+ 'struct file_handle' : 'LIBSYSCALLS_TYPE_STRUCT_FILE_HANDLE',
+ 'struct timezone' : 'LIBSYSCALLS_TYPE_STRUCT_TIMEZONE',
+ 'struct sysinfo' : 'LIBSYSCALLS_TYPE_STRUCT_SYSINFO',
+ 'struct mq_attr' : 'LIBSYSCALLS_TYPE_STRUCT_MQ_ATTR',
+ 'struct msqid_ds' : 'LIBSYSCALLS_TYPE_STRUCT_MSQID_DS',
+ 'struct msgbuf' : 'LIBSYSCALLS_TYPE_STRUCT_MSGBUF',
+ 'struct semid_ds' : 'LIBSYSCALLS_TYPE_STRUCT_SEMID_DS',
+ 'struct sembuf' : 'LIBSYSCALLS_TYPE_STRUCT_SEMBUF',
+ 'struct shmid_ds' : 'LIBSYSCALLS_TYPE_STRUCT_SHMID_DS',
+ 'struct user_msghdr' : 'LIBSYSCALLS_TYPE_STRUCT_MSGHDR',
+ 'struct mmsghdr' : 'LIBSYSCALLS_TYPE_STRUCT_MMSGHDR',
+ 'struct clone_args' : 'LIBSYSCALLS_TYPE_STRUCT_CLONE_ARGS',
+ 'struct perf_event_attr' : 'LIBSYSCALLS_TYPE_STRUCT_PERF_EVENT_ATTR',
+ 'struct sched_attr' : 'LIBSYSCALLS_TYPE_STRUCT_SCHED_ATTR',
+ 'struct rseq' : 'LIBSYSCALLS_TYPE_STRUCT_RSEQ',
+ 'struct landlock_ruleset_attr' : 'LIBSYSCALLS_TYPE_STRUCT_LANDLOCK_RULESET_ATTR',
+ 'struct cachestat_range' : 'LIBSYSCALLS_TYPE_STRUCT_CACHESTAT_RANGE',
+ 'struct cachestat' : 'LIBSYSCALLS_TYPE_STRUCT_CACHESTAT',
+ 'struct mmap_arg_struct' : 'LIBSYSCALLS_TYPE_STRUCT_MMAP_ARG_STRUCT',
+ 'union bpf_attr' : 'LIBSYSCALLS_TYPE_UNION_BPF_ATTR',
+ 'u8' : 'uint8_t',
+ 'u16' : 'uint16_t',
+ 'u32' : 'uint32_t',
+ 'u64' : 'uint64_t',
+ 's8' : 'int8_t',
+ 's16' : 'int16_t',
+ 's32' : 'int32_t',
+ 's64' : 'int64_t',
+ 'gid_t' : 'gid32_t',
+ 'compat_gid_t' : 'gid32_t',
+ 'gid32_t' : 'u32',
+ 'old_gid_t' : 'unsigned short int',
+ 'uid_t' : 'uid32_t',
+ 'compat_uid_t' : 'uid32_t',
+ 'uid32_t' : 'u32',
+ 'old_uid_t' : 'unsigned short int',
+ 'gid16_t' : 'u16',
+ 'uid16_t' : 'u16',
+ 'pid_t' : 'int',
+ 'umode_t' : 'unsigned short int',
+ 'aio_context_t' : 'unsigned long int',
+ 'sigset_t' : 'unsigned long int',
+ 'loff_t' : 'long long int',
+ 'off_t' : 'long int',
+ 'qid_t' : 'uid32_t',
+ 'clockid_t' : 'int',
+ 'timer_t' : 'int',
+ 'mqd_t' : 'int',
+ 'key_t' : 'int',
+ 'rwf_t' : 'int',
+ 'time_t' : 'long int',
+ 'old_time_t' : 'long int',
+ 'old_time32_t' : 's32',
+ 'time64_t' : 's64', # also defined as `long long int`
+ 'key_serial_t' : 'int32_t',
+ 'old_sigset_t' : 'unsigned long int',
+ 'intptr_t' : 'long int',
+ 'uintptr_t' : 'unsigned long int',
+ 'compat_ulong_t' : 'u32',
+ 'fd_set' : 'LIBSYSCALLS_TYPE_FD_SET'
+ }
+ while not typ.startswith('LIBSYSCALLS'):
+ if typ == '???':
+ typ = typemap.get(typ, 'LIBSYSCALLS_TYPE_UNKNOWN /* TO'+'DO */')
+ else:
+ typ = typemap.get(typ, 'LIBSYSCALLS_TYPE_UNKNOWN /* TO'+'DO (%s) */' % typ)
+ if typ.startswith('LIBSYSCALLS_TYPE_UNKNOWN') and (orig_typ.split(' ')[0] in ('struct', 'union')):
+ typ = 'LIBSYSCALLS_TYPE_STRUCT /* TO'+'DO */'
+ return typ
+
+def get_type(param):
+ old_param = [p for p in param.replace('*', ' * ').split(' ') if p and p != '__user']
+ param = []
+ width = ''
+ sign = ''
+ constness = ''
+ require = None
+ have_type = False
+ for p in old_param:
+ if p == 'volatile':
+ pass
+ elif p == 'restrict':
+ pass
+ elif p == 'long':
+ width += 'long '
+ require = 'int'
+ elif p == 'short':
+ width += 'short '
+ require = 'int'
+ elif p == 'signed':
+ sign += 'signed '
+ require = 'int'
+ elif p == 'unsigned':
+ sign += 'unsigned '
+ require = 'int'
+ elif p == 'struct':
+ sign += 'struct '
+ elif p == 'union':
+ sign += 'union '
+ elif p == 'enum':
+ sign += 'enum '
+ elif p == 'const':
+ constness = 'const'
+ else:
+ if require and p != require:
+ param.append(sign + width + require)
+ have_type = True
+ if p == '*':
+ param.append(constness + p)
+ constness = ''
+ elif not have_type:
+ p = sign + width + p
+ if p.startswith('struct __kernel_'):
+ p = 'struct ' + p[len('struct __kernel_'):]
+ elif p.startswith('struct __old_kernel_'):
+ p = 'struct old_' + p[len('struct __old_kernel_'):]
+ elif p.startswith('__kernel_'):
+ p = p[len('__kernel_'):]
+ elif p.startswith('__old_kernel_'):
+ p = 'old_' + p[len('__old_kernel_'):]
+ elif p.startswith('__'):
+ p = p[len('__'):]
+ param.append(p)
+ have_type = True
+ sign = ''
+ width = ''
+ require = None
+ if require:
+ param.append(sign + width.strip() + require)
+ if len(param) == 1:
+ return (map_type(param[0]), False, False)
+ if param == ['char', 'const*']:
+ return ('LIBSYSCALLS_TYPE_STRING', False, False)
+ if param == ['void', '*']:
+ return ('LIBSYSCALLS_TYPE_MEMORY_ADDRESS', False, False)
+ if len(param) == 2 and param[1] == '*':
+ return (map_type(param[0]), False, True)
+ if len(param) == 2 and param[1] == 'const*':
+ return (map_type(param[0]), True, False)
+ return ('LIBSYSCALLS_TYPE_UNKNOWN /* TO'+'DO */', False, False)
+
+def format_mask(args):
+ if len(args) == 0:
+ return '0'
+ if len(args) == 1:
+ return '_' + str(args[0] + 1)
+ return '(%s)' % ' | ' .join('_' + str(arg + 1) for arg in sorted(args))
+
+queued = {}
+for line in lines:
+ line = line.split(')')[0]
+ [name, params] = line.split('(')
+ name = name.split(' ')
+ return_type, name = ' '.join(name[:-1]), name[-1]
+ while name[0] == '*':
+ return_type += '*'
+ name = name[1:]
+ if functions is not None and name not in functions:
+ continue
+ if return_type == 'long':
+ return_type = '???'
+ params = [param.strip() for param in params.split(',')]
+ if params == ['void']:
+ params = []
+ param_types = []
+ in_pointer_mask = []
+ out_pointer_mask = []
+ for i, param in enumerate(params):
+ (typ, is_in, is_out) = get_type(param)
+ param_types.append(typ)
+ if is_in:
+ in_pointer_mask.append(i)
+ if is_out:
+ out_pointer_mask.append(i)
+ code = []
+ (return_type, return_type_ptr_in, return_type_ptr_out) = get_type(return_type)
+ if return_type_ptr_in or return_type_ptr_out:
+ return_type += ' *'
+ return_type = return_type.replace('* *', '**')
+ if False:
+ code.append('\nstatic struct libsyscalls_syscall_abi libsyscalls_linux_syscall_%s = {' % name)
+ code.append('\t.category = LIBSYSCALLS_CAT_SUPPORT_PENDING /* TO'+'DO */,')
+ code.append('\t/* TO'+'DO .subcategory = , */')
+ code.append('\t.min_argument_count = %i,%s' % (len(params), (' /* TO'+'DO */' if len(params) > 1 else '')))
+ code.append('\t.max_argument_count = %i,' % len(params))
+ code.append('\t.in_pointer_mask = %s,' % format_mask(in_pointer_mask))
+ code.append('\t.out_pointer_mask = %s,' % format_mask(out_pointer_mask))
+ code.append('\t.symbolic_mask = 0, /* TO'+'DO */')
+ code.append('\t.symbolic_return = 0,')
+ code.append('\t.expect_zero = 1, /* TO'+'DO */')
+ code.append('\t.symbol_printer = ~0, /* TO'+'DO */')
+ code.append('\t.return_type = %s%s' % (return_type, (',' if len(params) else '')))
+ if len(params):
+ code.append('\t.parameters_types = {')
+ for i, param_type in enumerate(param_types):
+ code.append('\t\t' + param_type + ('' if i + 1 == len(param_types) else ','))
+ code.append('\t}')
+ code.append('};')
+ else:
+ paramstr = ''
+ for i, param_type in enumerate(param_types):
+ if i:
+ paramstr += ', '
+ paramstr += {(False, False) : '_',
+ (True, False) : 'IN',
+ (False, True) : 'OUT',
+ (True, True) : 'BI'}[(i in in_pointer_mask), (i in out_pointer_mask)]
+ paramstr += ',' + param_type.replace('LIBSYSCALLS_TYPE_', '')
+ code.append('\nSYS(%s, /*CATEGORY*/, /*SUBCATEGORY*/, %i, ZERO(%s),' %
+ (name, len(params), return_type.replace('LIBSYSCALLS_TYPE_', '')))
+ code.append('\tPARAMS(%s),' % paramstr)
+ code.append('\t.symbolic_return = 0,')
+ code.append('\t.symbol_printer = ~0')
+ code.append(');')
+ code = '\n'.join(code)
+ if functions is None:
+ print(code)
+ else:
+ queued[name] = code
+
+not_found = []
+for name in sys.argv[1:]:
+ if name in queued:
+ print(queued[name])
+ else:
+ not_found.append(name)
+
+if not_found:
+ for name in not_found:
+ print('Could not find ' + name, file = sys.stderr)
+ sys.exit(1)
diff --git a/devtools/find-type-definition b/devtools/find-type-definition
new file mode 100755
index 0000000..26e19f2
--- /dev/null
+++ b/devtools/find-type-definition
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+type="$1"
+shift 1
+
+grep -r '\(define\s\+\(__kernel_\)\?'"$type"'\s\|typedef\s.*\s\(__kernel_\)\?'"$type"'\b\)' "$@" \
+| sed 's/^\([^:]*\):/\x1b[35m\1\x1b[m /' \
+| sed 's/\(__kernel_\)\?'"$type"'/\x1b[1;31m&\x1b[m/g'
diff --git a/get_syscall_range.template.c b/get_syscall_range.template.c
new file mode 100644
index 0000000..ad35cf4
--- /dev/null
+++ b/get_syscall_range.template.c
@@ -0,0 +1,23 @@
+/* See LICENSE file for copyright and license details. */
+
+
+#include "zzz-syscalls.h" /* in generated/ */
+
+static enum libsyscalls_error
+get_zzz_syscall_range(enum libsyscalls_arch arch, long long int *min_out, long long int *max_out)
+{
+#define CASE(ARCH)\
+ case LIBSYSCALLS_ARCH_##ARCH:\
+ *min_out = MIN_ZZZ_SYSCALL_FOR_##ARCH;\
+ *max_out = MAX_ZZZ_SYSCALL_FOR_##ARCH;\
+ break
+
+ switch ((int)arch) {
+ LIST_ZZZ_ARCHES(CASE, ;);
+ default:
+ return LIBSYSCALLS_E_ARCHNOSUP;
+ }
+ return LIBSYSCALLS_E_OK;
+
+#undef CASE
+}
diff --git a/libsyscalls.h b/libsyscalls.h
new file mode 100644
index 0000000..f63d023
--- /dev/null
+++ b/libsyscalls.h
@@ -0,0 +1,1327 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef LIBSYSCALLS_H
+#define LIBSYSCALLS_H
+
+#include "libsyscalls/internal-begin.h"
+#include "libsyscalls/short-enums.h"
+#include "libsyscalls/advanced.h"
+
+
+/**
+ * Macro for enumerating libsyscall error numbers
+ *
+ * The numbers are stored in `libsyscalls_error`
+ *
+ * @param X(NAME, STR) Macro that expands, will be given two arguments:
+ * the enum value name of the error (identifier),
+ * and the description of the error (string literal)
+ * @param D Macro that expands between each expansion of X
+ *
+ * The primary purpose of the existance of this macro
+ * is to ease implementation of the library; it will
+ * probably not disappear (no promises)
+ */
+#define LIBSYSCALLS_LIST_ERRORS(X, D)\
+ X(LIBSYSCALLS_E_OK, "Success") D\
+ X(LIBSYSCALLS_E_OSNOSUP, "Operating system not supported") D\
+ X(LIBSYSCALLS_E_ARCHNOSUP, "Architecture not supported for selected operating system") D\
+ X(LIBSYSCALLS_E_NOSUCHSYSCALL, "No such system call") D\
+ X(LIBSYSCALLS_E_NOERRORS, "There is no error listing for selected operating system") D\
+ X(LIBSYSCALLS_E_NOSIGNALS, "There is no signal listing for selected operating system") D\
+ X(LIBSYSCALLS_E_NOMEM, "Failed to allocate required memory") D\
+ X(LIBSYSCALLS_E_INVAL, "Invalid arguments passed to function") D\
+ X(LIBSYSCALLS_E_NOSUCHTYPE, "Type does not exist on the selected operating system or architecture") D\
+ X(LIBSYSCALLS_E_ISSTRUCT, "Type is a structure or union")
+
+/**
+ * libsyscall error numbers
+ */
+enum libsyscalls_error {
+ LIBSYSCALLS_LIST_ERRORS(LIBSYSCALLS_LIST_ERRORS_X_, LIBSYSCALLS_COMMA_)
+};
+
+/**
+ * Operating systems
+ */
+enum libsyscalls_os {
+ LIBSYSCALLS_OS_LINUX
+};
+
+/**
+ * Architectures
+ */
+enum libsyscalls_arch {
+ LIBSYSCALLS_ARCH_ALPHA,
+ LIBSYSCALLS_ARCH_AMD64,
+ LIBSYSCALLS_ARCH_AMD64_X32, /* 32-bit ABI, not traditional 32-bit x86 ISA */
+ LIBSYSCALLS_ARCH_ARM_OABI,
+ LIBSYSCALLS_ARCH_ARM_EABI,
+ LIBSYSCALLS_ARCH_IA64,
+ LIBSYSCALLS_ARCH_M68K,
+ LIBSYSCALLS_ARCH_MICROBLAZE,
+ LIBSYSCALLS_ARCH_MIPS_O32,
+ LIBSYSCALLS_ARCH_MIPS_N32,
+ LIBSYSCALLS_ARCH_MIPS_N64,
+ LIBSYSCALLS_ARCH_PARISC_32,
+ LIBSYSCALLS_ARCH_PARISC_64,
+ LIBSYSCALLS_ARCH_POWERPC_32,
+ LIBSYSCALLS_ARCH_POWERPC_64,
+ LIBSYSCALLS_ARCH_POWERPC_NOSPU,
+ LIBSYSCALLS_ARCH_POWERPC_SPU,
+ LIBSYSCALLS_ARCH_S390_32,
+ LIBSYSCALLS_ARCH_S390_64,
+ LIBSYSCALLS_ARCH_SH,
+ LIBSYSCALLS_ARCH_SPARC_32,
+ LIBSYSCALLS_ARCH_SPARC_64,
+ LIBSYSCALLS_ARCH_I386,
+ LIBSYSCALLS_ARCH_XTENSA
+};
+
+enum libsyscalls_datatype {
+
+ /* Type renaming, these macros will be undefined later */
+#define LIBSYSCALLS_TYPE_CHAR_ARRAY LIBSYSCALLS_TYPE_BUFFER
+#define LIBSYSCALLS_TYPE_CHAR_ARRAY_UNKNOWN_FILL LIBSYSCALLS_TYPE_BUFFER_UNKNOWN_FILL
+
+ /* You can use these macros classify and convert data types */
+#define LIBSYSCALLS_TYPEBITSMASK 0xF000
+#define LIBSYSCALLS_TYPEBITS_SCALAR 0x0000 /* predefined total width, even if aggregate */
+#define LIBSYSCALLS_TYPEBITS_ARRAY 0x1000 /* count is stored in next parameter, and is updated with fill
+ * or returned if no outputable to the next parameter */
+#define LIBSYSCALLS_TYPEBITS_ARRAY_UNKNOWN_FILL 0x2000 /* count is stored in next parameter, fill is in no way returned,
+ * this chould either be because the array is always (unless an
+ * error is returned) entirely filled or because the end is
+ * infered from the contents (e.g. null byte termination) */
+
+#define LIBSYSCALLS_LIST_SPECIAL_TYPES(X, SUFFIX, D, FIRST)\
+ /* the type used in the system call has not yet be added recorded in the library */\
+ X(LIBSYSCALLS_TYPE_UNKNOWN ## SUFFIX, FIRST, "(unknown type)") D\
+ /* the type depends on the system call input or output */\
+ X(LIBSYSCALLS_TYPE_DYNAMIC ## SUFFIX,, "(undetermined type)") D\
+ /* the system call should never returned to the calling process (return to tracer is usually expected) */\
+ X(LIBSYSCALLS_TYPE_NO_RETURN ## SUFFIX,, "no_return") D\
+ /* either used as return type or to skip a register in the parameters
+ * (do not dismiss this, on some architectures a system call
+ * may need padding with dummy arguments to align latter
+ * register pairs; an application printing the system call
+ * must choose between omitting, printing the argument, or
+ * indicating that there is a dummy parameter (of course
+ * the latter two can be combined)) */\
+ X(LIBSYSCALLS_TYPE_VOID ## SUFFIX,, "void")
+
+#define LIBSYSCALLS_LIST_SPLIT_PRIMITIVES(X, SUFFIX, D, FIRST)\
+ X(LIBSYSCALLS_TYPE_UINT64_HIGH_32 ## SUFFIX, FIRST, "uint64_t {. << 32}") D\
+ X(LIBSYSCALLS_TYPE_UINT64_LOW_32 ## SUFFIX,, "uint64_t {. & 0xFFFFFFFF}") D\
+ X(LIBSYSCALLS_TYPE_UINT64_FRONT_32 ## SUFFIX,, "uint64_t {((uint32_t *)&.)[0]}") D\
+ X(LIBSYSCALLS_TYPE_UINT64_BACK_32 ## SUFFIX,, "uint64_t {((uint32_t *)&.)[1]}") D\
+ X(LIBSYSCALLS_TYPE_INT64_HIGH_32 ## SUFFIX,, "int64_t {. << 32}") D\
+ X(LIBSYSCALLS_TYPE_INT64_LOW_32 ## SUFFIX,, "int64_t {. & 0xFFFFFFFF}") D\
+ X(LIBSYSCALLS_TYPE_INT64_FRONT_32 ## SUFFIX,, "int64_t {((uint32_t *)&.)[0]}") D\
+ X(LIBSYSCALLS_TYPE_INT64_BACK_32 ## SUFFIX,, "int64_t {((uint32_t *)&.)[1]}")
+
+#define LIBSYSCALLS_LIST_COMPOSITE_PRIMITIVES(X, SUFFIX, D, FIRST)\
+ X(LIBSYSCALLS_TYPE_STRING ## SUFFIX, FIRST, "const char *") D\
+ X(LIBSYSCALLS_TYPE_STRINGS_THEN_NULL ## SUFFIX,, "const char **")
+
+#define LIBSYSCALLS_LIST_UNANNOTATED_NUMERICALS(X, SUFFIX, D, FIRST)\
+ X(LIBSYSCALLS_TYPE_MEMORY_ADDRESS ## SUFFIX, FIRST, "void *") D\
+ X(LIBSYSCALLS_TYPE_CHAR ## SUFFIX,, "char") D\
+ X(LIBSYSCALLS_TYPE_SCHAR ## SUFFIX,, "signed char") D\
+ X(LIBSYSCALLS_TYPE_UCHAR ## SUFFIX,, "unsigned char") D\
+ X(LIBSYSCALLS_TYPE_SHORT ## SUFFIX,, "short int") D\
+ X(LIBSYSCALLS_TYPE_USHORT ## SUFFIX,, "unsigned short int") D\
+ X(LIBSYSCALLS_TYPE_INT ## SUFFIX,, "int") D\
+ X(LIBSYSCALLS_TYPE_UINT ## SUFFIX,, "unsigned int") D\
+ X(LIBSYSCALLS_TYPE_LONG ## SUFFIX,, "long int") D\
+ X(LIBSYSCALLS_TYPE_ULONG ## SUFFIX,, "unsigned long int") D\
+ X(LIBSYSCALLS_TYPE_LLONG ## SUFFIX,, "long long int") D\
+ X(LIBSYSCALLS_TYPE_ULLONG ## SUFFIX,, "unsigned long long int") D\
+ X(LIBSYSCALLS_TYPE_SSIZE ## SUFFIX,, "ssize_t") D\
+ X(LIBSYSCALLS_TYPE_SIZE ## SUFFIX,, "size_t") D\
+ X(LIBSYSCALLS_TYPE_PTRDIFF ## SUFFIX,, "ptrdiff_t") D\
+ X(LIBSYSCALLS_TYPE_UPTRDIFF ## SUFFIX,, "uptrdiff_t") D\
+ X(LIBSYSCALLS_TYPE_INTPTR ## SUFFIX,, "intptr_t") D\
+ X(LIBSYSCALLS_TYPE_UINTPTR ## SUFFIX,, "uintptr_t") D\
+ X(LIBSYSCALLS_TYPE_INT8 ## SUFFIX,, "int8_t") D\
+ X(LIBSYSCALLS_TYPE_UINT8 ## SUFFIX,, "uint8_t") D\
+ X(LIBSYSCALLS_TYPE_INT16 ## SUFFIX,, "int16_t") D\
+ X(LIBSYSCALLS_TYPE_UINT16 ## SUFFIX,, "uint16_t") D\
+ X(LIBSYSCALLS_TYPE_INT32 ## SUFFIX,, "int32_t") D\
+ X(LIBSYSCALLS_TYPE_UINT32 ## SUFFIX,, "uint32_t") D\
+ X(LIBSYSCALLS_TYPE_INT64 ## SUFFIX,, "int64_t") D\
+ X(LIBSYSCALLS_TYPE_UINT64 ## SUFFIX,, "uint64_t")
+
+#define LIBSYSCALLS_LIST_ANNOTATED_NUMERICALS(X, SUFFIX, D, FIRST)\
+ X(LIBSYSCALLS_TYPE_INT_SIGNAL ## SUFFIX, FIRST, "int") D /* OS signal */\
+ X(LIBSYSCALLS_TYPE_INT_FD ## SUFFIX,, "int") D /* file descriptor */ \
+ X(LIBSYSCALLS_TYPE_INT_ATFD ## SUFFIX,, "int") D /* file descriptor or current working directory */ \
+ X(LIBSYSCALLS_TYPE_LONG_FD ## SUFFIX,, "long int") D\
+ X(LIBSYSCALLS_TYPE_LONG_ATFD ## SUFFIX,, "long int")
+
+#define LIBSYSCALLS_LIST_STRUCTS_AND_UNIONS(X, SUFFIX, D, FIRST)\
+ X(LIBSYSCALLS_TYPE_STRUCT_AIO_SIGSET ## SUFFIX, FIRST, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_CACHESTAT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_CACHESTAT_RANGE ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_CLONE_ARGS ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_EPOLL_EVENT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_FILE_HANDLE ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_FUTEX_WAITV ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_IOB ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_IOVEC ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_IO_EVENT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_IO_URING_PARAMS ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_ITIMERSPEC ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_KEXEC_SEGMENT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_LANDLOCK_RULESET_ATTR ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT64 ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_MMAP_ARG_STRUCT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_MMSGHDR ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_MOUNT_ATTR ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_MQ_ATTR ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_MSGBUF ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_MSGHDR ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_MSQID_DS ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_NEW_UTSNAME ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OLDOLD_UTSNAME ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OLD_ITIMERSPEC32 ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OLD_ITIMERVAL ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OLD_LINUX_DIRENT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OLD_SIGACTION ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OLD_STAT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMESPEC32 ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEVAL ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEVAL32 ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEX32 ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OLD_UTIMBUF32 ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OLD_UTSNAME ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OPEN_HOW ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_PERF_EVENT_ATTR ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_POLLFD ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_RLIMIT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_RLIMIT64 ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_ROBUST_LIST_HEAD ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_RSEQ ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_RUSAGE ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_SCHED_ATTR ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_SCHED_PARAM ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_SEL_ARG_STRUCT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_SEMBUF ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_SEMID_DS ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_SHMID_DS ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_SIGACTION ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_SIGALTSTACK ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_SIGEVENT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_SIGINFO ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_SOCKADDR ## SUFFIX,, "struct") D /* size is always in the next argument */\
+ X(LIBSYSCALLS_TYPE_STRUCT_STAT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_STAT64 ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_STATFS ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_STATFS64 ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_STATX ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_SYSINFO ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_TIMESPEC ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_TIMEX ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_TIMEZONE ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_TMS ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_USTAT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_UTIMBUF ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_UNION_BPF_ATTR ## SUFFIX,, "union")
+
+#define LIBSYSCALLS_LIST_FIXED_ARRAYS(X, SUFFIX, D, FIRST)\
+ X(LIBSYSCALLS_TYPE_2_INTS ## SUFFIX, FIRST, "int[2]") D\
+ X(LIBSYSCALLS_TYPE_2_INTS_FD ## SUFFIX,, "int[2]") D\
+ X(LIBSYSCALLS_TYPE_2_UINT32S ## SUFFIX,, "uint32[2]") D\
+ X(LIBSYSCALLS_TYPE_FD_SET ## SUFFIX,, "unsigned long[]") /* size depends on OS, (1024 / CHAR_BIT / sizeof(long)) in Linux */
+
+ /* these don't have any suffix */
+ LIBSYSCALLS_MAKE_SPECIAL_TYPES_(),
+ LIBSYSCALLS_MAKE_SPLIT_PRIMITIVES_(),
+ LIBSYSCALLS_MAKE_COMPOSITE_PRIMITIVES_(),
+ LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_(),
+ LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(),
+ LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(),
+
+ /* the following are always pointers unless returned */
+
+ /* size in next parameter (or the previous parameter if there is no next parameter),
+ * updated with fill if possible, otherwise returned (these use the suffix _ARRAY) */
+ LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_(_ARRAY),
+ LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(_ARRAY),
+ LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(_ARRAY),
+
+ /* size in next parameter (or the previous parameter if there is no next parameter),
+ * fill is in no way returned (these use the suffix _ARRAY_UNKNOWN_FILL) */
+ LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_(_ARRAY_UNKNOWN_FILL),
+ LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(_ARRAY_UNKNOWN_FILL),
+ LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(_ARRAY_UNKNOWN_FILL),
+
+ /* these don't have any suffix */
+ LIBSYSCALLS_MAKE_FIXED_ARRAYS_()
+
+#undef LIBSYSCALLS_TYPE_CHAR_ARRAY
+#undef LIBSYSCALLS_TYPE_CHAR_ARRAY_UNKNOWN_FILL
+};
+
+enum libsyscalls_syscall_category {
+ LIBSYSCALLS_CAT_SUPPORT_PENDING,
+ LIBSYSCALLS_CAT_NOT_IMPLEMENTED,
+ LIBSYSCALLS_CAT_NETWORK_ENABLED_IPC,
+ LIBSYSCALLS_CAT_IPC,
+ LIBSYSCALLS_CAT_FILESYSTEM,
+ LIBSYSCALLS_CAT_FILE_DESCRIPTORS,
+ LIBSYSCALLS_CAT_PROCESSES,
+ LIBSYSCALLS_CAT_LOGGING,
+ LIBSYSCALLS_CAT_TIME,
+ LIBSYSCALLS_CAT_SIGNALS,
+ LIBSYSCALLS_CAT_MEMORY,
+ LIBSYSCALLS_CAT_SYSTEM,
+ LIBSYSCALLS_CAT_SCHEDULING
+};
+
+/* IPC that can but does not have to be over a network,
+ * "bind" system calls can create inodes in the file system */
+enum libsyscalls_syscall_network_enabled_ipc_subcategory {
+ LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_ACCEPT,
+ LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_LISTEN,
+ LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_BIND,
+ LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_CONNECT,
+ LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_STAT
+};
+
+enum libsyscalls_syscall_ipc_subcategory {
+ LIBSYSCALLS_IPC_SUBCAT_ADVISORY_FILE_LOCK,
+ LIBSYSCALLS_IPC_SUBCAT_MANDATORY_FILE_LOCK,
+ LIBSYSCALLS_IPC_SUBCAT_FILE_LOCK, /* may or may not be advisory (e.g. flock(2) since Linux 5.5) */
+ LIBSYSCALLS_IPC_SUBCAT_CONTROL, /* includes creation, deletion, and stat */
+ LIBSYSCALLS_IPC_SUBCAT_ATTACH,
+ LIBSYSCALLS_IPC_SUBCAT_DETACH,
+ LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE,
+ LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE_WITH_RELATIVE_TIMEOUT,
+ LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE_WITH_ABSOLUTE_TIMEOUT
+};
+
+/* syscalls that can work on either paths or FDs ([1]) are located here */
+enum libsyscalls_syscall_filesystem_subcategory {
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_STAT,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_MODIFY,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_SYNC, /* [1] some of these only work on file descriptors or memory maps */
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_UNLINK,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK_OR_UNLINK,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_UMASK, /* modifies the process, not the filesystem */
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_MOUNTPOINT,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_STATFS,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_WRITE,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_READLINK,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_MONITOR,
+ LIBSYSCALLS_FILESYSTEM_SUBCAT_QUOTA
+};
+
+/* syscalls that work FDs but not paths are located here */
+enum libsyscalls_syscall_file_descriptors_subcategory {
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_STAT,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_MODIFY,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_DUP_OR_CLOSE, /* includes partial close (shutdown) */
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CLOSE_OR_UNSHARE,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ, /* may have timeout */
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_WRITE, /* may have timeout */
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_SEEK,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_PEEK, /* may have timeout */
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_AND_WRITE,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_PEEK_AND_WRITE,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK_AND_WRITE,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK_AND_STAT,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_ADVISE,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_STATFS,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CREATE,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CREATE_POLL,
+ LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_POLL /* can work as pause or relative sleep */
+};
+
+enum libsyscalls_syscall_processes_subcategory {
+ LIBSYSCALLS_PROCESSES_SUBCAT_EXIT,
+ LIBSYSCALLS_PROCESSES_SUBCAT_STAT_SELF,
+ LIBSYSCALLS_PROCESSES_SUBCAT_STAT_CHILD, /* may also stat self */
+ LIBSYSCALLS_PROCESSES_SUBCAT_STAT_PARENT, /* may also stat self or children */
+ LIBSYSCALLS_PROCESSES_SUBCAT_STAT_OTHER,
+ LIBSYSCALLS_PROCESSES_SUBCAT_CHANGE_PERMISSIONS,
+ LIBSYSCALLS_PROCESSES_SUBCAT_CLONE,
+ LIBSYSCALLS_PROCESSES_SUBCAT_EXEC,
+ LIBSYSCALLS_PROCESSES_SUBCAT_CHDIR,
+ LIBSYSCALLS_PROCESSES_SUBCAT_CHROOT,
+ LIBSYSCALLS_PROCESSES_SUBCAT_SESSION /* vhangup, setsid, setpgid */
+};
+
+enum libsyscalls_syscall_logging_subcategory {
+ LIBSYSCALLS_LOGGING_SUBCAT_PROCESSES
+};
+
+enum libsyscalls_syscall_time_subcategory {
+ LIBSYSCALLS_TIME_SUBCAT_GET_OR_SET,
+ LIBSYSCALLS_TIME_SUBCAT_GET,
+ LIBSYSCALLS_TIME_SUBCAT_SET,
+ LIBSYSCALLS_TIME_SUBCAT_INTROSPECT,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_READ,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_READ,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_READ,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_WITH_READ,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_WITH_READ,
+ LIBSYSCALLS_TIME_SUBCAT_TIMER_WITH_READ,
+ LIBSYSCALLS_TIME_SUBCAT_SLEEP_RELATIVE,
+ LIBSYSCALLS_TIME_SUBCAT_SLEEP_ABSOLUTE,
+ LIBSYSCALLS_TIME_SUBCAT_SLEEP
+};
+
+enum libsyscalls_syscall_signals_subcategory {
+ LIBSYSCALLS_SIGNALS_SUBCAT_PAUSE,
+ LIBSYSCALLS_SIGNALS_SUBCAT_KILL
+};
+
+/* These may work on memory mapped files */
+enum libsyscalls_syscall_memory_subcategory {
+ LIBSYSCALLS_MEMORY_SUBCAT_ALLOCATE,
+ LIBSYSCALLS_MEMORY_SUBCAT_READ,
+ LIBSYSCALLS_MEMORY_SUBCAT_WRITE,
+ LIBSYSCALLS_MEMORY_SUBCAT_ADVISE,
+ LIBSYSCALLS_MEMORY_SUBCAT_WRITE_OR_ADVISE,
+ LIBSYSCALLS_MEMORY_SUBCAT_LOCK,
+ LIBSYSCALLS_MEMORY_SUBCAT_UNLOCK,
+ LIBSYSCALLS_MEMORY_SUBCAT_STAT /* stats memory allocated to the process, not system resources */
+};
+
+enum libsyscalls_syscall_system_subcategory {
+ LIBSYSCALLS_SYSTEM_SUBCAT_SWAP,
+ LIBSYSCALLS_SYSTEM_SUBCAT_REBOOT,
+ LIBSYSCALLS_SYSTEM_SUBCAT_GET_NAME,
+ LIBSYSCALLS_SYSTEM_SUBCAT_SET_NAME,
+ LIBSYSCALLS_SYSTEM_SUBCAT_STAT,
+ LIBSYSCALLS_SYSTEM_SUBCAT_RANDOM,
+ LIBSYSCALLS_SYSTEM_SUBCAT_FUNDAMENTAL
+};
+
+enum libsyscalls_syscall_scheduling_subcategory {
+ LIBSYSCALLS_SCHEDULING_SUBCAT_YEILD,
+ LIBSYSCALLS_SCHEDULING_SUBCAT_SET,
+ LIBSYSCALLS_SCHEDULING_SUBCAT_GET,
+ LIBSYSCALLS_SCHEDULING_SUBCAT_INTROSPECT
+};
+
+union libsyscalls_syscall_subcategory {
+ enum_libsyscalls_syscall_network_enabled_ipc_subcategory network_enabled_ipc;
+ enum_libsyscalls_syscall_ipc_subcategory ipc;
+ enum_libsyscalls_syscall_filesystem_subcategory filesystem;
+ enum_libsyscalls_syscall_file_descriptors_subcategory file_descriptors;
+ enum_libsyscalls_syscall_processes_subcategory processes;
+ enum_libsyscalls_syscall_logging_subcategory logging;
+ enum_libsyscalls_syscall_time_subcategory time;
+ enum_libsyscalls_syscall_signals_subcategory signals;
+ enum_libsyscalls_syscall_memory_subcategory memory;
+ enum_libsyscalls_syscall_system_subcategory system;
+ enum_libsyscalls_syscall_scheduling_subcategory scheduling;
+};
+
+/**
+ * System call interface
+ */
+struct libsyscalls_syscall_abi {
+ /**
+ * Classification of what the system call does
+ *
+ * Check `.category` to se which group of
+ * classifications to used
+ */
+ union libsyscalls_syscall_subcategory subcategory;
+
+ /**
+ * Broad classification of what the system calls does
+ */
+ enum_libsyscalls_syscall_category category : 16;
+
+ /**
+ * For set any bit indexed I (starting from 0), the
+ * system call parameter I is a pointer that the
+ * the system call reads from
+ *
+ * Note that there are types that fundamentally are
+ * pointers (such as strings), for these, this bit
+ * is not set unless it is a pointer to a string
+ */
+ unsigned short int in_pointer_mask : 16;
+
+ /**
+ * For set any bit indexed I (starting from 0), the
+ * system call parameter I is a pointer that the
+ * the system call write to
+ *
+ * Note that there are types that fundamentally are
+ * pointers (such as strings), for these, this bit
+ * is not set unless it is a pointer to a string
+ */
+ unsigned short int out_pointer_mask : 16;
+
+ /**
+ * For set any bit indexed I (starting from 0), the
+ * system call parameter I can be resolved into a
+ * symbolic string by the library
+ */
+ unsigned short int symbolic_mask : 16;
+
+ /**
+ * The minimum number of arguments that must be
+ * passed into the system call, -1 if unknown
+ */
+ short int min_argument_count : 6;
+
+ /**
+ * The maximum number of arguments that can be
+ * passed into the system call, -1 if unknown
+ */
+ short int max_argument_count : 6;
+
+ /**
+ * If set, the library can resolve the value the
+ * system call returns into a symbolic string
+ */
+ unsigned short int symbolic_return : 1;
+
+ /**
+ * If 1, the system call shall always either return
+ * an error, return the value 0, or not return at all
+ */
+ unsigned short int expect_zero : 1;
+
+ /**
+ * If 1, the system call invocation must be parsed
+ * especially as it is not does follow what is
+ * proscribed for the used data types
+ *
+ * The library may use this temporarily until it
+ * in a later version provides a convension that
+ * can be followed
+ */
+ unsigned short int queer : 1;
+
+ short int : LIBSYSCALLS_PAD_(sizeof(short int)/sizeof(char)*CHAR_BIT, 4*16 + 2*6 + 3*1);
+
+ /**
+ * This is internally by `libsyscalls_get_syscall_display_info`
+ * to find out how values ought to be printed to be both human
+ * and machines friendly (symbolic names are indeed easier for
+ * the application to deal with as their values can depend on
+ * the architecture), and occasionally to determine what types
+ * are used for on arguments whose type is argument dependent,
+ * and to figure which optional arguments are included in the
+ * system call
+ *
+ * If this is value is 0, `libsyscalls_get_syscall_display_info`
+ * will not be able to provide any useful information, which
+ * would either be because everything is provided here (in
+ * struct libsyscalls_syscall_abi) or because the library hasn't
+ * yet added full support for the system call
+ */
+ LIBSYSCALLS_SYMBOL_PRINTER symbol_printer : 16;
+
+ /**
+ * The system call's return type
+ */
+ enum_libsyscalls_datatype return_type : 16;
+
+ /**
+ * The type of each of the systems call's parameter
+ *
+ * The application must not read `.parameters_types[.max_argument_count]`
+ * or beyond, doing so will probably mean reading beyond the memory
+ * allocated for the instance of the structure
+ */
+ enum_libsyscalls_datatype parameters_types[LIBSYSCALLS_FLEXABLE_OR_NPARAMS_];
+};
+
+/**
+ * System call description
+ */
+struct libsyscalls_syscall {
+ /**
+ * What system call is named
+ */
+ const char *name;
+
+ /**
+ * The ABI for the system call for architecture it was
+ * queried for
+ *
+ * May or may not be `NULL` if the system call is defined
+ * but not implemented
+ */
+ struct libsyscalls_syscall_abi *actual_syscall;
+
+ /**
+ * Like .actual_syscall except this is used for example when
+ * a 32-bit process is running on a 64-bit operating system
+ *
+ * If `NULL` use .actual_syscall
+ */
+ struct libsyscalls_syscall_abi *actual_compat_syscall;
+};
+
+/**
+ * Named number (errors and signals)
+ */
+struct libsyscalls_named_number {
+ /**
+ * The value if the number, it is up to the
+ * application select signess
+ *
+ * It is usually safe to use unsigned (.u)
+ * as the numbers are usually positive but
+ * not so large that the sign bit would be
+ * set, unless the numbers are supposted to
+ * be unsigned
+ */
+ union {
+ signed long long int s;
+ unsigned long long int u;
+ } number;
+
+ /**
+ * The name of the number, including namespacing
+ * (e.g. "E" prefix for errno numbers and "SIG"
+ * or "_SIG" prefix for singals)
+ */
+ const char *name;
+};
+
+/**
+ * Function that returns a name for a value
+ *
+ * This function is called multiple times to extract
+ * names of multiple subvalues, for example, for
+ * the system call access() second parameter, it
+ * will return the string "X_OK", "W_OK", "R_OK",
+ * and "F_OK", or a subset thereof; one per invocation
+ *
+ * The proper way to use this function, is:
+ *
+ * static void
+ * print_unsigned(libsyscalls_symbol_printer_function *function,
+ * LIBSYSCALLS_SYMBOL_PRINTER_DATA *data,
+ * unsigned long long int value, FILE *output)
+ * {
+ * const char *sym, *prefix = "";
+ * char format[] = "%s%llu";
+ * char *fallback = strchr(format, '\0') - 1;
+ * do {
+ * sym = (*function)(data, &value, &fallback);
+ * if (!sym)
+ * break;
+ * fprintf(output, "%s%s", prefix, sym);
+ * prefix = "|";
+ * } while (value);
+ * if (value || !*prefix)
+ * fprintf(output, format, prefix, value);
+ * }
+ *
+ * @param data Data passed to the function (which that function
+ * has been paired with for the paramter/return),
+ * which it may require to known exactly what to do
+ * @param valuep The caller set a variable to the value pass in to
+ * the system call parameter (or the system call's
+ * return value), the value if any extract symbol
+ * will removed from from the variable. If the function
+ * return NULL, this value can be 0, in which case all
+ * values have been extract, otherwise (which it is not
+ * 0) there is some value (either invalid or not known
+ * to the library) that shall must be printed manually
+ * by the application (see `fallback_out` parameter).
+ * Note that, if the value 0 has a name, this function
+ * never return NULL if the variable reaches 0, instead
+ * it will repeated return the name of that value.
+ * @param fallback_out The caller set a variable to 0 and pointer to it,
+ * when this function return NULL, the variable MAY
+ * (even before that) have been set to 'x', 'o', or
+ * 'd', indicating a suggestion how any value left
+ * over in `*valuep` shall be displayed: 'x' for in
+ * hexadecimal, 'o' for octal, and 'd' for decimal
+ * (signness depends on the system call parameter's
+ * type's (or as the case may be, the system call's
+ * return type) signness).
+ * @return The name of some value in `*valuep`, or `NULL` if
+ * none was found. The returned string may be stored
+ * in `data` and those override at the next call.
+ */
+typedef const char *libsyscalls_symbol_printer_function(LIBSYSCALLS_SYMBOL_PRINTER_DATA *, unsigned long long int *, char *);
+
+/**
+ * Information about a system call parameter or return value
+ */
+struct libsyscalls_syscall_type_info {
+ /**
+ * Function for extracting names values from a variable
+ */
+ libsyscalls_symbol_printer_function *function;
+
+ /**
+ * First argument to pass to `.function`
+ */
+ LIBSYSCALLS_SYMBOL_PRINTER_DATA *data;
+
+ /**
+ * The data type used for the parameter or return value
+ * in the specific invocation of the system call
+ *
+ * If set to LIBSYSCALLS_TYPE_VOID for an optional
+ * parameter, that parameter was not used
+ */
+ enum_libsyscalls_datatype type;
+
+ char padding__[LIBSYSCALLS_PAD_(sizeof(long) / sizeof(char), sizeof(enum_libsyscalls_datatype) / sizeof(char) + 1)];
+ unsigned char : CHAR_BIT - 1;
+
+ /**
+ * Only used for the return value
+ *
+ * Same as `.expect_zero` in `struct libsyscalls_syscall_abi`,
+ * however if 0 in `struct libsyscalls_syscall_abi`, it can
+ * still be 1 here if if it is determined that for the specificly
+ * used system call arguments, the system call shall always
+ * return 0 (or not return) or an error
+ */
+ unsigned char expect_zero : 1;
+};
+
+/**
+ * System call information tweak for the arguments passed
+ * to the system call, as well as information about how
+ * to print named values in the arguments and return
+ */
+struct libsyscalls_syscall_display_info {
+ /**
+ * The size of this structure, this can be used
+ * by the application to test what is available
+ * in the case it may have compiled against a
+ * newer version than used in the version of the
+ * library the application is linked with
+ *
+ * Data is stored beyond this, do not try to make
+ * a copy; that will not go well
+ */
+ size_t size;
+
+ /**
+ * Information about each system call parameter
+ *
+ * All positive integer within [0, .max_argument_count]
+ * for the `struct libsyscalls_syscall_abi` are valid,
+ * but no index beyond `.max_argument_count` is valid
+ */
+ struct libsyscalls_syscall_type_info *params;
+
+ /**
+ * Information about the system call's return value
+ */
+ struct libsyscalls_syscall_type_info *retvalue;
+};
+
+/**
+ * Signed number representation
+ */
+enum libsyscalls_datatype_sign_representation {
+ /**
+ * The data type was LIBSYSCALLS_TYPE_UNKNOWN or
+ * LIBSYSCALLS_TYPE_DYNAMIC
+ */
+ LIBSYSCALLS_SIGN_UNDETERMINED,
+
+ /**
+ * Two's complement
+ *
+ * -x is ~x + 1, -0 is +0
+ */
+ LIBSYSCALLS_SIGN_TWOS_COMPLEMENT,
+
+ /**
+ * One's cmplement
+ *
+ * -x is ~x, -0 is not +0
+ */
+ LIBSYSCALLS_SIGN_ONES_COMPLEMENT,
+
+ /**
+ * Sign–magnitude
+ *
+ * -x is (x | most significant bit), -0 is not +0
+ */
+ LIBSYSCALLS_SIGN_SIGN_MAGNITUDE,
+
+ /**
+ * Excess-K, with K being (unsigned maximum + 1)/2
+ *
+ * 0 is represented with just the most significant bit set,
+ * any offset from 0 is added to this value, i.e., x is
+ * represented by ((unsigned maximum + 1)/2 + x); -0 is +0
+ */
+ LIBSYSCALLS_SIGN_EXCESS_HALF
+};
+
+/**
+ * Data type usage annotation
+ */
+enum libsyscalls_datatype_annotation {
+ /**
+ * The data type was LIBSYSCALLS_TYPE_UNKNOWN or
+ * LIBSYSCALLS_TYPE_DYNAMIC
+ */
+ LIBSYSCALLS_ANNOTATION_UNDETERMINED,
+
+ /**
+ * The value does not have usage annotation
+ */
+ LIBSYSCALLS_ANNOTATION_NONE,
+
+ /**
+ * The value represents an operating system signal (e.g. SIGKILL)
+ *
+ * This affords the application the opportunity to print
+ * more detail information about a signal (such as when
+ * it is used, whether it is a realtime signal, default
+ * action, whether it can be caught, and what its normal
+ * usage is)
+ */
+ LIBSYSCALLS_ANNOTATION_SIGNAL,
+
+ /**
+ * The value represents a file descriptor
+ *
+ * This affords the application the opportunity to print
+ * file information (such as file name, address, file type,
+ * and offset)
+ */
+ LIBSYSCALLS_ANNOTATION_FD,
+
+ /**
+ * The value represents a file descriptor or a special value
+ * for a known file such as AT_FDCWD
+ *
+ * This affords the application the opportunity to print
+ * file information (such as file name, address, file type,
+ * and offset)
+ */
+ LIBSYSCALLS_ANNOTATION_ATFD
+};
+
+/**
+ * Register-split information for a data type
+ */
+enum libsyscalls_datatype_section {
+ /**
+ * The data type was LIBSYSCALLS_TYPE_UNKNOWN or
+ * LIBSYSCALLS_TYPE_DYNAMIC
+ */
+ LIBSYSCALLS_SECTION_UNDETERMINED,
+
+ /**
+ * The whole value is represented
+ *
+ * The value is contained within a single parameter
+ */
+ LIBSYSCALLS_SECTION_WHOLE,
+
+ /*
+ * This whether a data type represents a half section
+ * of larger data type
+ *
+ * @param S:enum libsyscalls_datatype_section The data type section information
+ * @return :int Whether the larger that type was split into two halves
+ */
+#define LIBSYSCALLS_IS_SECTION_HALF(S)\
+ (((S) >= LIBSYSCALLS_SECTION_UPPER_HALF) &&\
+ ((S) <= LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF))
+
+ /**
+ * The most significant half of the value is represented
+ *
+ * Example: if the data type is 64-bits, the value stored
+ * in parameter whose type was queried is just 32-bits —
+ * 0xFFFFFFFF00000000 if the whole value is 0xFFFFFFFFFFFFFFFF,
+ * — and most combined with another neighbouring parameter
+ * (a LIBSYSCALLS_SECTION_LOWER_HALF)
+ */
+ LIBSYSCALLS_SECTION_UPPER_HALF,
+
+ /**
+ * The least significant half of the value is represented
+ *
+ * Example: if the data type is 64-bits, the value stored
+ * in parameter whose type was queried is just 32-bits —
+ * 0x00000000FFFFFFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
+ * — and most combined with another neighbouring parameter
+ * (a LIBSYSCALLS_SECTION_UPPER_HALF)
+ */
+ LIBSYSCALLS_SECTION_LOWER_HALF,
+
+ /**
+ * The second most and second least significant quarters
+ * of the value represented
+ *
+ * Example: if the data type is 64-bits, the value stored
+ * in parameter whose type was queried is just 32-bits —
+ * 0x0000FFFFFFFF0000 if the whole value is 0xFFFFFFFFFFFFFFFF,
+ * — and most combined with another neighbouring parameter
+ * (a LIBSYSCALLS_SECTION_OUTER_HALF)
+ */
+ LIBSYSCALLS_SECTION_INNER_HALF,
+
+ /**
+ * The most and least significant quarters of the value
+ * represented
+ *
+ * Example: if the data type is 64-bits, the value stored
+ * in parameter whose type was queried is just 32-bits —
+ * 0xFFFF00000000FFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
+ * — and most combined with another neighbouring parameter
+ * (a LIBSYSCALLS_SECTION_INNER_HALF)
+ */
+ LIBSYSCALLS_SECTION_OUTER_HALF,
+
+ /**
+ * The second most and least significant quarters of the
+ * value represented
+ *
+ * Example: if the data type is 64-bits, the value stored
+ * in parameter whose type was queried is just 32-bits —
+ * 0x0000FFFF0000FFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
+ * — and most combined with another neighbouring parameter
+ * (a LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF)
+ */
+ LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF,
+
+ /**
+ * The most and second least significant quarters of the
+ * value represented
+ *
+ * Example: if the data type is 64-bits, the value stored
+ * in parameter whose type was queried is just 32-bits —
+ * 0xFFFF0000FFFF0000 if the whole value is 0xFFFFFFFFFFFFFFFF,
+ * — and most combined with another neighbouring parameter
+ * (a LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF)
+ */
+ LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF,
+
+ /**
+ * The bytes that would be indexed (starting from 0) with
+ * an even number in big endian (how humans write numbers)
+ * are represented
+ *
+ * Example: if the data type is 64-bits, the value stored
+ * in parameter whose type was queried is just 32-bits —
+ * 0x00FF00FF00FF00FF if the whole value is 0xFFFFFFFFFFFFFFFF,
+ * — and most combined with another neighbouring parameter
+ * (a LIBSYSCALLS_SECTION_EVEN_BYTES_AS_HALF)
+ */
+ LIBSYSCALLS_SECTION_EVEN_BYTES_AS_HALF,
+
+ /**
+ * The bytes that would be indexed (starting from 0) with
+ * an odd number in big endian (how humans write numbers)
+ * are represented
+ *
+ * Example: if the data type is 64-bits, the value stored
+ * in parameter whose type was queried is just 32-bits —
+ * 0xFF00FF00FF00FF00 if the whole value is 0xFFFFFFFFFFFFFFFF,
+ * — and most combined with another neighbouring parameter
+ * (a LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF)
+ */
+ LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF,
+
+ /*
+ * This whether a data type represents a quarter section
+ * of larger data type
+ *
+ * @param S:enum libsyscalls_datatype_section The data type section information
+ * @return :int Whether the larger that type was split into four quarters
+ */
+#define LIBSYSCALLS_IS_SECTION_QUARTER(S)\
+ (((S) >= LIBSYSCALLS_SECTION_UPPER_QUARTER) &&\
+ ((S) <= LIBSYSCALLS_SECTION_LOWER_QUARTER))
+
+ /**
+ * The most significant quarter of the value is represented
+ *
+ * Example: if the data type is 64-bits, the value stored
+ * in parameter whose type was queried is just 16-bits —
+ * 0xFFFF000000000000 if the whole value is 0xFFFFFFFFFFFFFFFF,
+ * — and most combined with three neighbouring parameter
+ * (a LIBSYSCALLS_SECTION_UPPER_MID_QUARTER,
+ * a LIBSYSCALLS_SECTION_LOWER_MID_QUARTER, and
+ * a LIBSYSCALLS_SECTION_LOWER_QUARTER)
+ */
+ LIBSYSCALLS_SECTION_UPPER_QUARTER,
+
+ /**
+ * The second most significant quarter of the value is represented
+ *
+ * Example: if the data type is 64-bits, the value stored
+ * in parameter whose type was queried is just 16-bits —
+ * 0x0000FFFF00000000 if the whole value is 0xFFFFFFFFFFFFFFFF,
+ * — and most combined with three neighbouring parameter
+ * (a LIBSYSCALLS_SECTION_UPPER_QUARTER,
+ * a LIBSYSCALLS_SECTION_LOWER_MID_QUARTER, and
+ * a LIBSYSCALLS_SECTION_LOWER_QUARTER)
+ */
+ LIBSYSCALLS_SECTION_UPPER_MID_QUARTER,
+
+ /**
+ * The least most significant quarter of the value is represented
+ *
+ * Example: if the data type is 64-bits, the value stored
+ * in parameter whose type was queried is just 16-bits —
+ * 0x00000000FFFF0000 if the whole value is 0xFFFFFFFFFFFFFFFF,
+ * — and most combined with three neighbouring parameter
+ * (a LIBSYSCALLS_SECTION_UPPER_QUARTER,
+ * a LIBSYSCALLS_SECTION_UPPER_MID_QUARTER, and
+ * a LIBSYSCALLS_SECTION_LOWER_QUARTER)
+ */
+ LIBSYSCALLS_SECTION_LOWER_MID_QUARTER,
+
+ /**
+ * The least significant quarter of the value is represented
+ *
+ * Example: if the data type is 64-bits, the value stored
+ * in parameter whose type was queried is just 16-bits —
+ * 0x000000000000FFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
+ * — and most combined with three neighbouring parameter
+ * (a LIBSYSCALLS_SECTION_UPPER_QUARTER,
+ * a LIBSYSCALLS_SECTION_UPPER_MID_QUARTER, and
+ * a LIBSYSCALLS_SECTION_LOWER_MID_QUARTER)
+ */
+ LIBSYSCALLS_SECTION_LOWER_QUARTER
+
+ /*
+ * Get the number of registers the data type was split into
+ *
+ * @param S:enum libsyscalls_datatype_section The data type section information
+ * @return :unsigned int The number registers the data type was split into;
+ * invalid if `S` is LIBSYSCALLS_SECTION_UNDETERMINED
+ */
+#define LIBSYSCALLS_GET_SECTION_FRACTION(S)\
+ (LIBSYSCALLS_IS_SECTION_HALF(S) ? 2U :\
+ LIBSYSCALLS_IS_SECTION_QUARTER(S) ? 4U : 1U)
+};
+
+/**
+ * Information on how an instance of data type is to be parsed
+ *
+ * Data types are usually either signed or unsigned, but there
+ * are a few exceptions: LIBSYSCALLS_TYPE_UNKNOWN and
+ * LIBSYSCALLS_TYPE_DYNAMIC are described as both signed and
+ * unsigned as their signness is unknown and could be either,
+ * or neither, which brings us to the next exception: some
+ * data types are neither signed nor unsigned; these are types
+ * that are not numerical, i.e. non-values (LIBSYSCALLS_TYPE_NO_RETURN
+ * and LIBSYSCALLS_TYPE_VOID), memory addresses
+ * (LIBSYSCALLS_TYPE_MEMORY_ADDRESS) and textual types
+ * (LIBSYSCALLS_TYPE_CHAR, LIBSYSCALLS_TYPE_STRING, and
+ * LIBSYSCALLS_TYPE_STRINGS_THEN_NULL), as well as arrays of
+ * such types (including LIBSYSCALLS_TYPE_BUFFER and
+ * LIBSYSCALLS_TYPE_BUFFER_UNKNOWN_FILL), and finally bitset
+ * arrays (currently only LIBSYSCALLS_TYPE_FD_SET)
+ */
+struct libsyscalls_datatype_description {
+ /**
+ * The number of bits used for the represented section
+ * of the data type
+ *
+ * 0 for LIBSYSCALLS_TYPE_NO_RETURN and LIBSYSCALLS_TYPE_VOID
+ *
+ * if .section is LIBSYSCALLS_SECTION_WHOLE, this is the
+ * number of bits in the entire data type, otherwise the data
+ * type may have been split (LIBSYSCALLS_SECTION_UNDETERMINED,
+ * guaranteed to be split otherwise) and this value is just
+ * the number of bits stored in the register
+ */
+ unsigned width_in_bits;
+
+ /**
+ * The size (in number of elements) of the array the data type
+ * is used in, or 1 if the data type was not an array or
+ * 0 if the array size is determined by another parameter
+ */
+ unsigned array_size;
+
+ /**
+ * Only used if .array_size is 0
+ *
+ * The position of the arrays size in the parameter list
+ * relative to the array, e.g. 1 for the next parameter
+ * or -1 for the previous parameter
+ *
+ * If 0, use .absolute_position_of_array_size instead
+ */
+ signed relative_position_of_array_size : 5;
+
+ /**
+ * Only used if .array_size is 0
+ *
+ * The position of the arrays size in the parameter list,
+ * indexed starting from 0
+ *
+ * If -1, use .relative_position_of_array_size instead
+ */
+ signed absolute_position_of_array_size : 5;
+
+ /**
+ * Only used if .array_size is 0
+ *
+ * Assuming the kernel writes into the array, if 1, the number
+ * of elements written to the array (starting from its
+ * beginning) is writting into the array size parameter if it
+ * is marked as an output parameter and return otherwise; if
+ * 0, the number of bits written must be infered from its
+ * contents, e.g. via null byte termination (how this is done
+ * depends on the system call)
+ */
+ unsigned fill_is_known : 1;
+
+ /**
+ * Whether the data type is signed
+ */
+ unsigned is_signed : 1;
+
+ /**
+ * Whether the data type is unsigned
+ */
+ unsigned is_unsigned : 1;
+
+ /**
+ * Only used if .is_signed is 1 and .sign_representation
+ * is not LIBSYSCALLS_SIGN_UNDETERMINED
+ *
+ * This value can be inferred from .sign_representation;
+ * its 1 if the data type's minimum value is the negative
+ * of its maximum value (which also means that -0 and +0
+ * are distinct), and 0 otherwise, which means that the
+ * minimum value is the negative of (the minimum value + 1)
+ * (it also means that -0 and +0 are the identical)
+ */
+ unsigned min_is_minus_max : 1;
+
+ int padding__ : LIBSYSCALLS_PAD_(sizeof(int)/sizeof(char)*CHAR_BIT, 2*5 + 4*1);
+
+ /**
+ * Only used if .is_signed is 1
+ *
+ * How signed numbers are represented
+ */
+ enum libsyscalls_datatype_sign_representation sign_representation;
+
+ /**
+ * Additional information about what the value represents
+ */
+ enum libsyscalls_datatype_annotation annotation;
+
+ /**
+ * What part of the value is stored in the instance
+ */
+ enum libsyscalls_datatype_section section;
+
+ /**
+ * This is a ~0 terminated array describing the order
+ * of the bytes the the data type
+ *
+ * The lowest non-zero values contains the width of
+ * a byte (in bytes), however no such value exists
+ * in this array if the data type is just one byte
+ * (or none)
+ *
+ * For each unsigned byte in the data type, indexed
+ * I from 0, it shall be shifted left .byteorder[i]
+ * bits; the bitwise OR of the results is the
+ * unsigned value used in the instance of the data type
+ *
+ * Data types for register-splits ARE NOT shifted,
+ * there is always a value in .byteorder that is 0,
+ * unless .byteorder[0] is ~0
+ */
+ unsigned char byteorder[32];
+};
+
+
+/**
+ * Return a description of a libsyscalls error
+ *
+ * @param error The libsyscalls error
+ * @return Description of the error, the first character will be in uppercase
+ */
+LIBSYSCALLS_GCC_ATTRIBUTES_(__const__, __returns_nonnull__, __warn_unused_result__)
+const char *
+libsyscalls_strerror(enum libsyscalls_error);
+
+/**
+ * Print a line with a description of a
+ * libsyscalls error to standard error
+ *
+ * @param prefix Unless NULL or the empty string, the description
+ * will be prefixed with this string followed by ": "
+ * @param error The libsyscalls error
+ */
+void
+libsyscalls_perror(const char *, enum libsyscalls_error);
+
+/**
+ * Get the valid range system call numbers
+ *
+ * @param os The operating system the range shall valid for
+ * @param arch The architecture the range shall valid for
+ * @param min_out Output parameter for the lowest used system call number (may be NULL)
+ * @param max_out Output parameter for the highest used system call number (may be NULL)
+ * @return LIBSYSCALLS_E_OK - On success
+ * LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
+ * the selected operating system (`os`)
+ * LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
+ * the selected architecture (`arch`) on the
+ * selected operating system (`os`)
+ *
+ * Beware that range is used system call numbers are [*min_out, *max_out]
+ * (not [*min_out, *max_out - 1]) but there may still be numbers within
+ * this range that does not correspond to a system call
+ */
+LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__)
+enum libsyscalls_error
+libsyscalls_get_syscall_range(enum libsyscalls_os, enum libsyscalls_arch, long long int *, long long int *);
+
+/**
+ * Get the description of a system call
+ *
+ * @param os The operating system the range shall valid for
+ * @param arch The architecture the range shall valid for
+ * @param syscallnr The system call's number
+ * @param syscall_out Output parameter for the system call description
+ * (the argument may be NULL, *syscall_out will
+ * never be set to NULL)
+ * @return LIBSYSCALLS_E_OK - On success
+ * LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
+ * the selected operating system (`os`)
+ * LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
+ * the selected architecture (`arch`) on the
+ * selected operating system (`os`)
+ * LIBSYSCALLS_E_NOSUCHSYSCALL - `syscallnr` does not correspond to a known
+ * system call for the selected architecture (`arch`)
+ * on the selected operating system (`os`)
+ */
+LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__)
+enum libsyscalls_error
+libsyscalls_get_syscall(enum libsyscalls_os, enum libsyscalls_arch, long long int, const struct libsyscalls_syscall **);
+
+/**
+ * Get the system call errors defined by an operating system
+ *
+ * If an error has multiple names, it is only listed once
+ * and the listed name is arbitrary
+ *
+ * The returned listing will be sorted by the error numbers
+ * in ascending order
+ *
+ * @param os The operating system whose errors shall be returned
+ * @param arch The architecture the error numbers shall be valid for
+ * @param errors_out Output parameter for the error list (may be NULL, never filled with NULL)
+ * @param num_errors_out Output parameter for the number of errors returned in `*errors_out` (may be NULL)
+ * (if `errors_out` is NULL, the number that would be returned is stored)
+ * @return LIBSYSCALLS_E_OK - On success
+ * LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
+ * the selected operating system (`os`)
+ * LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
+ * the selected architecture (`arch`) on the
+ * selected operating system (`os`)
+ * LIBSYSCALLS_E_NOERRORS - The operating system does not use named error numbers
+ */
+enum libsyscalls_error
+libsyscalls_get_syscall_errors(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_named_number **, size_t *);
+
+/**
+ * Get the system signals defined by an operating system
+ *
+ * If a signal has multiple names, it is only listed once
+ * and the listed name is arbitrary
+ *
+ * The returned listing will be sorted by the signal
+ * numbers in ascending order
+ *
+ * @param os The operating system whose errors shall be returned
+ * @param arch The architecture the error numbers shall be valid for
+ * @param signals_out Output parameter for the signal list (may be NULL, never filled with NULL)
+ * @param num_signals_out Output parameter for the number of signals returned in `*signals_out` (may be NULL)
+ * (if `signals_out` is NULL, the number that would be returned is stored)
+ * @return LIBSYSCALLS_E_OK - On success
+ * LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
+ * the selected operating system (`os`)
+ * LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
+ * the selected architecture (`arch`) on the
+ * selected operating system (`os`)
+ * LIBSYSCALLS_E_NOSIGNALS - The operating system does not use named signal numbers
+ */
+enum libsyscalls_error
+libsyscalls_get_signals(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_named_number **, size_t *);
+
+/**
+ * Get system call information tweak for the arguments passed
+ * to the system call, as well as information about how to
+ * print named values in the arguments and return
+ *
+ * @param os The operating system the system call was invoked on
+ * @param arch The architecture the system call was invoked on
+ * @param syscall The ABI of the system call (see libsyscalls_get_syscall)
+ * @param syscall_number The system call's number
+ * @param syscall_arguments The values store in register (as upon system call entry)
+ * the used for the system call, in the order the registers
+ * are used as system call arguments
+ * @param info_out Output parameter for the additional system call information
+ * @return LIBSYSCALLS_E_OK - On success
+ * LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
+ * the selected operating system (`os`)
+ * LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
+ * the selected architecture (`arch`) on the
+ * selected operating system (`os`)
+ * LIBSYSCALLS_E_NOMEM - Failed to allocate memory for `*info_out`
+ * LIBSYSCALLS_E_INVAL - One of the arguments was NULL
+ */
+LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __nonnull__)
+enum libsyscalls_error
+libsyscalls_get_syscall_display_info(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_syscall_abi *,
+ long long int, unsigned long long int *, struct libsyscalls_syscall_display_info **);
+
+/**
+ * Get information on how an instance of data type is to be parsed
+ *
+ * @param os The operating system the data type is used on
+ * @param arch The architecture the data type is used on
+ * @param datatype The datatype, `LIBSYSCALLS_TYPE_DYNAMIC` can
+ * be used to get the size of the registers used
+ * as system call parameters
+ * @param description_out Output parameter for the type description
+ * @return LIBSYSCALLS_E_OK - On success
+ * LIBSYSCALLS_E_OSNOSUP - The library is not compiled with support for
+ * the selected operating system (`os`)
+ * LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
+ * the selected architecture (`arch`) on the
+ * selected operating system (`os`)
+ * LIBSYSCALLS_E_INVAL - `datatype` is not a valid data type
+ * LIBSYSCALLS_E_NOSUCHTYPE - `datatype` does not exist on the selected
+ * operating system (`os`) or architecture (`arch`)
+ * LIBSYSCALLS_E_ISSTRUCT - `datatype` represents a structure
+ *
+ * The function may complete successfully for some data
+ * types even if it for other data types would return
+ * LIBSYSCALLS_E_OSNOSUP or LIBSYSCALLS_E_ARCHNOSUP
+ */
+LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__)
+enum libsyscalls_error
+libsyscalls_get_datatype_description(enum libsyscalls_os, enum libsyscalls_arch, enum libsyscalls_datatype,
+ struct libsyscalls_datatype_description *);
+
+
+#include "libsyscalls/internal-end.h"
+#endif
diff --git a/libsyscalls/advanced.h b/libsyscalls/advanced.h
new file mode 100644
index 0000000..22ed3d0
--- /dev/null
+++ b/libsyscalls/advanced.h
@@ -0,0 +1,13 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef LIBSYSCALLS_H
+# error Do not include this header file directly
+#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
diff --git a/libsyscalls/internal-begin.h b/libsyscalls/internal-begin.h
new file mode 100644
index 0000000..9741632
--- /dev/null
+++ b/libsyscalls/internal-begin.h
@@ -0,0 +1,76 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef LIBSYSCALLS_H
+# error Do not include this header file directly
+#endif
+
+
+#include <limits.h>
+#include <stddef.h>
+
+/* a comma possible into a macro */
+#define LIBSYSCALLS_COMMA_ ,
+
+/* used to make flexible arrays non-flexible if required for static instantiation */
+#ifndef LIBSYSCALLS_FLEXABLE_OR_NPARAMS_
+# define LIBSYSCALLS_FLEXABLE_OR_NPARAMS_
+#endif
+
+#if defined(__GNUC__)
+# define LIBSYSCALLS_GCC_ATTRIBUTES_(...) __attribute__((__VA_ARGS__))
+#else
+# define LIBSYSCALLS_GCC_ATTRIBUTES_(...)
+#endif
+
+#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_LIST_ERRORS_X_(ENUM, STR) ENUM
+
+#define LIBSYSCALLS_DATATYPE_X_(NAME, ASSIGNMENT, ...) NAME ASSIGNMENT
+
+#define LIBSYSCALLS_TYPEBITS LIBSYSCALLS_TYPEBITS_SCALAR
+
+#define LIBSYSCALLS_MAKE_SPECIAL_TYPES_()\
+ LIBSYSCALLS_LIST_SPECIAL_TYPES(LIBSYSCALLS_DATATYPE_X_,, LIBSYSCALLS_COMMA_,\
+ = LIBSYSCALLS_TYPEOFFSET_SPECIAL_TYPES)
+
+#define LIBSYSCALLS_MAKE_SPLIT_PRIMITIVES_(SUFFIX)\
+ LIBSYSCALLS_LIST_SPLIT_PRIMITIVES(LIBSYSCALLS_DATATYPE_X_, SUFFIX, LIBSYSCALLS_COMMA_,\
+ = LIBSYSCALLS_TYPEOFFSET_SPLIT_PRIMITIVES\
+ | LIBSYSCALLS_TYPEBITS##SUFFIX)
+
+#define LIBSYSCALLS_MAKE_COMPOSITE_PRIMITIVES_(SUFFIX)\
+ LIBSYSCALLS_LIST_COMPOSITE_PRIMITIVES(LIBSYSCALLS_DATATYPE_X_, SUFFIX, LIBSYSCALLS_COMMA_,\
+ = LIBSYSCALLS_TYPEOFFSET_COMPOSITE_PRIMITIVES\
+ | LIBSYSCALLS_TYPEBITS##SUFFIX)
+
+#define LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_(SUFFIX)\
+ LIBSYSCALLS_LIST_UNANNOTATED_NUMERICALS(LIBSYSCALLS_DATATYPE_X_, SUFFIX, LIBSYSCALLS_COMMA_,\
+ = LIBSYSCALLS_TYPEOFFSET_UNANNOTATED_NUMERICALS\
+ | LIBSYSCALLS_TYPEBITS##SUFFIX)
+
+#define LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(SUFFIX)\
+ LIBSYSCALLS_LIST_ANNOTATED_NUMERICALS(LIBSYSCALLS_DATATYPE_X_, SUFFIX, LIBSYSCALLS_COMMA_,\
+ = LIBSYSCALLS_TYPEOFFSET_ANNOTATED_NUMERICALS\
+ | LIBSYSCALLS_TYPEBITS##SUFFIX)
+
+#define LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(SUFFIX)\
+ LIBSYSCALLS_LIST_STRUCTS_AND_UNIONS(LIBSYSCALLS_DATATYPE_X_, SUFFIX, LIBSYSCALLS_COMMA_,\
+ = LIBSYSCALLS_TYPEOFFSET_STRUCTS_AND_UNIONS\
+ | LIBSYSCALLS_TYPEBITS##SUFFIX)
+
+#define LIBSYSCALLS_MAKE_FIXED_ARRAYS_(SUFFIX)\
+ LIBSYSCALLS_LIST_FIXED_ARRAYS(LIBSYSCALLS_DATATYPE_X_, SUFFIX, LIBSYSCALLS_COMMA_,\
+ = LIBSYSCALLS_TYPEOFFSET_FIXED_ARRAYS\
+ | LIBSYSCALLS_TYPEBITS##SUFFIX)
diff --git a/libsyscalls/internal-end.h b/libsyscalls/internal-end.h
new file mode 100644
index 0000000..ed7af58
--- /dev/null
+++ b/libsyscalls/internal-end.h
@@ -0,0 +1,21 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef LIBSYSCALLS_H
+# error Do not include this header file directly
+#endif
+
+
+#undef LIBSYSCALLS_COMMA_
+#undef LIBSYSCALLS_FLEXABLE_OR_NPARAMS_
+#undef LIBSYSCALLS_GCC_ATTRIBUTES_
+#undef LIBSYSCALLS_PAD_
+
+#undef LIBSYSCALLS_LIST_ERRORS_X_
+#undef LIBSYSCALLS_DATATYPE_X_
+#undef LIBSYSCALLS_TYPEBITS
+#undef LIBSYSCALLS_MAKE_SPECIAL_TYPES_
+#undef LIBSYSCALLS_MAKE_SPLIT_PRIMITIVES_
+#undef LIBSYSCALLS_MAKE_COMPOSITE_PRIMITIVES_
+#undef LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_
+#undef LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_
+#undef LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_
+#undef LIBSYSCALLS_MAKE_FIXED_ARRAYS_
diff --git a/libsyscalls_get_datatype_description.c b/libsyscalls_get_datatype_description.c
new file mode 100644
index 0000000..1a4cb59
--- /dev/null
+++ b/libsyscalls_get_datatype_description.c
@@ -0,0 +1,418 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#include <stdlib.h>
+#include <string.h>
+
+
+#define COUNT_(...) 1
+#define COUNT(LIST_MACRO) (LIST_MACRO(COUNT_,, +,))
+
+enum endian {
+ Big,
+ Little,
+};
+
+#define LIST_ARCH_SPECS(X, D) /* byte intptr size_t endian sign */\
+ /*
+ 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_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_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_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_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_SPARC_32, 8, 32, 32, Big, TWOS_COMPLEMENT) D\
+ /*
+ X(LIBSYSCALLS_ARCH_SPARC_64, 8, 64, 64, TODO(bi), TWOS_COMPLEMENT) D\
+ */\
+ X(LIBSYSCALLS_ARCH_I386, 8, 32, 32, Little, TWOS_COMPLEMENT) D\
+ /*
+ X(LIBSYSCALLS_ARCH_XTENSA, 8, 32, 32, TODO, TODO)
+ */
+ /* Don't forget to update SUPPORTED_ARCHES in Makefile */
+
+
+#include "generated/types.c"
+
+enum libsyscalls_error
+libsyscalls_get_datatype_description(enum libsyscalls_os os, enum libsyscalls_arch arch, enum libsyscalls_datatype datatype,
+ struct libsyscalls_datatype_description *description_out)
+{
+ struct libsyscalls_datatype_description description_discard, larger_type;
+ enum libsyscalls_error r;
+ unsigned class;
+ int half = 0;
+ enum endian endian;
+ size_t i, j, charbits;
+ int divide_array_size_with_type_size_out;
+
+ if (!description_out)
+ description_out = &description_discard;
+
+ if (datatype & ~(LIBSYSCALLS_TYPEBITSMASK | (LIBSYSCALLS_TYPEBITSMASK - 1)))
+ return LIBSYSCALLS_E_INVAL;
+
+ datatype ^= class = datatype & LIBSYSCALLS_TYPEBITSMASK;
+
+ if (class == LIBSYSCALLS_TYPEBITS_SCALAR) {
+ description_out->array_size = 1;
+ description_out->relative_position_of_array_size = 0;
+ description_out->absolute_position_of_array_size = -1;
+ description_out->fill_is_known = 1;
+ description_out->is_signed = 0;
+ description_out->is_unsigned = 0;
+ description_out->min_is_minus_max = 0;
+ description_out->padding__ = 0;
+
+ } else if (class == LIBSYSCALLS_TYPEBITS_ARRAY) {
+ description_out->array_size = 0;
+ description_out->relative_position_of_array_size = +1;
+ description_out->absolute_position_of_array_size = -1;
+ description_out->fill_is_known = 1;
+ description_out->is_signed = 0;
+ description_out->is_unsigned = 0;
+ description_out->min_is_minus_max = 0;
+ description_out->padding__ = 0;
+
+ } else if (class == LIBSYSCALLS_TYPEBITS_ARRAY_UNKNOWN_FILL) {
+ description_out->array_size = 0;
+ description_out->relative_position_of_array_size = +1;
+ description_out->absolute_position_of_array_size = -1;
+ description_out->fill_is_known = 0;
+ description_out->is_signed = 0;
+ description_out->is_unsigned = 0;
+ description_out->min_is_minus_max = 0;
+ description_out->padding__ = 0;
+
+ } else {
+ return LIBSYSCALLS_E_INVAL;
+ }
+
+ if (datatype >= LIBSYSCALLS_TYPEOFFSET_STRUCTS_AND_UNIONS)
+ return LIBSYSCALLS_E_ISSTRUCT;
+
+ memset(description_out->byteorder, ~0U, sizeof(description_out->byteorder));
+
+#define CASE(ARCH, CHARBITS, INTPTR_BITS, SIZE_BITS, ENDIAN, SIGN)\
+ case ARCH: description_out->sign_representation = LIBSYSCALLS_SIGN_##SIGN; break
+ switch ((int)arch) {
+ LIST_ARCH_SPECS(CASE, ;);
+ default:
+ return LIBSYSCALLS_E_ARCHNOSUP;
+ }
+#undef CASE
+
+ description_out->annotation = LIBSYSCALLS_ANNOTATION_NONE;
+ description_out->section = LIBSYSCALLS_SECTION_WHOLE;
+
+ switch (description_out->sign_representation) {
+ case LIBSYSCALLS_SIGN_ONES_COMPLEMENT:
+ case LIBSYSCALLS_SIGN_SIGN_MAGNITUDE:
+ description_out->min_is_minus_max = 1;
+ break;
+ case LIBSYSCALLS_SIGN_TWOS_COMPLEMENT:
+ case LIBSYSCALLS_SIGN_EXCESS_HALF:
+ break;
+ }
+
+ if (datatype >= LIBSYSCALLS_TYPEOFFSET_FIXED_ARRAYS) {
+ if (class != LIBSYSCALLS_TYPEBITS_SCALAR)
+ return LIBSYSCALLS_E_INVAL;
+ switch (datatype) {
+ case LIBSYSCALLS_TYPE_2_INTS:
+ datatype = LIBSYSCALLS_TYPE_INT;
+ description_out->array_size = 2;
+ break;
+ case LIBSYSCALLS_TYPE_2_INTS_FD:
+ datatype = LIBSYSCALLS_TYPE_INT;
+ description_out->annotation = LIBSYSCALLS_ANNOTATION_FD;
+ description_out->array_size = 2;
+ break;
+ case LIBSYSCALLS_TYPE_2_UINT32S:
+ datatype = LIBSYSCALLS_TYPE_UINT32;
+ description_out->array_size = 2;
+ break;
+ case LIBSYSCALLS_TYPE_FD_SET:
+ goto os_dependent;
+ default:
+ return LIBSYSCALLS_E_INVAL;
+ }
+ goto unannotated;
+
+ } else if (datatype >= LIBSYSCALLS_TYPEOFFSET_ANNOTATED_NUMERICALS) {
+ switch (datatype) {
+ case LIBSYSCALLS_TYPE_INT_SIGNAL:
+ datatype = LIBSYSCALLS_TYPE_INT;
+ description_out->annotation = LIBSYSCALLS_ANNOTATION_SIGNAL;
+ break;
+ case LIBSYSCALLS_TYPE_INT_FD:
+ datatype = LIBSYSCALLS_TYPE_INT;
+ description_out->annotation = LIBSYSCALLS_ANNOTATION_FD;
+ break;
+ case LIBSYSCALLS_TYPE_INT_ATFD:
+ datatype = LIBSYSCALLS_TYPE_INT;
+ description_out->annotation = LIBSYSCALLS_ANNOTATION_ATFD;
+ break;
+ case LIBSYSCALLS_TYPE_LONG_FD:
+ datatype = LIBSYSCALLS_TYPE_LONG;
+ description_out->annotation = LIBSYSCALLS_ANNOTATION_FD;
+ break;
+ case LIBSYSCALLS_TYPE_LONG_ATFD:
+ datatype = LIBSYSCALLS_TYPE_LONG;
+ description_out->annotation = LIBSYSCALLS_ANNOTATION_ATFD;
+ break;
+ default:
+ return LIBSYSCALLS_E_INVAL;
+ }
+ goto unannotated;
+
+ } else if (datatype >= LIBSYSCALLS_TYPEOFFSET_UNANNOTATED_NUMERICALS) {
+ unannotated:
+ if (datatype - LIBSYSCALLS_TYPEOFFSET_UNANNOTATED_NUMERICALS >= COUNT(LIBSYSCALLS_LIST_UNANNOTATED_NUMERICALS)) {
+ return LIBSYSCALLS_E_INVAL;
+ } else if (datatype == LIBSYSCALLS_TYPE_MEMORY_ADDRESS) {
+ datatype = LIBSYSCALLS_TYPE_INTPTR;
+ } else if (datatype == LIBSYSCALLS_TYPE_CHAR) {
+ datatype = LIBSYSCALLS_TYPE_SCHAR;
+ } else {
+ description_out->is_unsigned = (datatype - LIBSYSCALLS_TYPE_SCHAR) & 1;
+ description_out->is_signed = 1 ^ description_out->is_unsigned;
+ datatype &= ~1;
+ }
+ goto arch_or_os_dependent;
+
+ } else if (datatype >= LIBSYSCALLS_TYPEOFFSET_COMPOSITE_PRIMITIVES) {
+ if (class != LIBSYSCALLS_TYPEBITS_SCALAR)
+ return LIBSYSCALLS_E_INVAL;
+ if (datatype - LIBSYSCALLS_TYPEOFFSET_COMPOSITE_PRIMITIVES >= COUNT(LIBSYSCALLS_LIST_COMPOSITE_PRIMITIVES))
+ return LIBSYSCALLS_E_INVAL;
+ datatype = LIBSYSCALLS_TYPE_MEMORY_ADDRESS;
+ goto unannotated;
+
+ } else if (datatype >= LIBSYSCALLS_TYPEOFFSET_SPLIT_PRIMITIVES) {
+ if (class != LIBSYSCALLS_TYPEBITS_SCALAR)
+ return LIBSYSCALLS_E_INVAL;
+ enum libsyscalls_datatype t = datatype;
+ switch (datatype) {
+ case LIBSYSCALLS_TYPE_UINT64_HIGH_32:
+ case LIBSYSCALLS_TYPE_UINT64_LOW_32:
+ case LIBSYSCALLS_TYPE_UINT64_FRONT_32:
+ case LIBSYSCALLS_TYPE_UINT64_BACK_32:
+ description_out->is_unsigned = 1;
+ datatype = LIBSYSCALLS_TYPE_UINT32;
+ break;
+ case LIBSYSCALLS_TYPE_INT64_HIGH_32:
+ case LIBSYSCALLS_TYPE_INT64_LOW_32:
+ case LIBSYSCALLS_TYPE_INT64_FRONT_32:
+ case LIBSYSCALLS_TYPE_INT64_BACK_32:
+ t -= LIBSYSCALLS_TYPE_INT64_HIGH_32;
+ t += LIBSYSCALLS_TYPE_UINT64_HIGH_32;
+ description_out->is_signed = 1;
+ datatype = LIBSYSCALLS_TYPE_INT32;
+ break;
+ default:
+ return LIBSYSCALLS_E_INVAL;
+ }
+ switch (t) {
+ case LIBSYSCALLS_TYPE_UINT64_HIGH_32:
+ description_out->section = LIBSYSCALLS_SECTION_UPPER_HALF;
+ break;
+ case LIBSYSCALLS_TYPE_UINT64_LOW_32:
+ description_out->section = LIBSYSCALLS_SECTION_LOWER_HALF;
+ break;
+ case LIBSYSCALLS_TYPE_UINT64_FRONT_32:
+ case LIBSYSCALLS_TYPE_UINT64_BACK_32:
+ half = t == LIBSYSCALLS_TYPE_UINT64_FRONT_32 ? -1 : +1;
+ r = libsyscalls_get_datatype_description(os, arch, LIBSYSCALLS_TYPE_UINT64, &larger_type);
+ if (r)
+ return r;
+ break;
+ default:
+ abort();
+ }
+ goto unannotated;
+
+ } else {
+ if (class)
+ return LIBSYSCALLS_E_INVAL;
+ switch (datatype) {
+ case LIBSYSCALLS_TYPE_UNKNOWN:
+ case LIBSYSCALLS_TYPE_DYNAMIC:
+ datatype = LIBSYSCALLS_TYPE_DYNAMIC;
+ description_out->is_signed = 1;
+ description_out->is_unsigned = 1;
+ description_out->sign_representation = LIBSYSCALLS_SIGN_UNDETERMINED;
+ description_out->annotation = LIBSYSCALLS_ANNOTATION_UNDETERMINED;
+ description_out->section = LIBSYSCALLS_SECTION_UNDETERMINED;
+ goto os_dependent;
+ case LIBSYSCALLS_TYPE_NO_RETURN:
+ case LIBSYSCALLS_TYPE_VOID:
+ description_out->width_in_bits = 0;
+ break;
+ default:
+ return LIBSYSCALLS_E_INVAL;
+ }
+ }
+
+ return LIBSYSCALLS_E_OK;
+
+arch_or_os_dependent:
+ divide_array_size_with_type_size_out = 0;
+
+arch_dependent:
+ switch (datatype) {
+ /* Note that LIBSYSCALLS_TYPE_INTN does not have the same semantics
+ * as POSIX's intN_t: these are not necessarily two's complement
+ * encoded and can have any range of valid numbers as long as that
+ * type has the correct width */
+ case LIBSYSCALLS_TYPE_INT8:
+ description_out->width_in_bits = 8;
+ goto not_os_dependent;
+ case LIBSYSCALLS_TYPE_INT16:
+ description_out->width_in_bits = 16;
+ goto not_os_dependent;
+ case LIBSYSCALLS_TYPE_INT32:
+ description_out->width_in_bits = 32;
+ goto not_os_dependent;
+ case LIBSYSCALLS_TYPE_INT64:
+ description_out->width_in_bits = 64;
+ goto not_os_dependent;
+ case LIBSYSCALLS_TYPE_INTPTR:
+ case LIBSYSCALLS_TYPE_PTRDIFF:
+#define CASE(ARCH, CHARBITS, INTPTR_BITS, SIZE_BITS, ENDIAN, SIGN)\
+ case ARCH: description_out->width_in_bits = INTPTR_BITS; break
+ switch ((int)arch) {
+ LIST_ARCH_SPECS(CASE, ;);
+ default:
+ abort();
+ }
+ goto not_os_dependent;
+#undef CASE
+ case LIBSYSCALLS_TYPE_SSIZE:
+#define CASE(ARCH, CHARBITS, INTPTR_BITS, SIZE_BITS, ENDIAN, SIGN)\
+ case ARCH: description_out->width_in_bits = SIZE_BITS; break
+ switch ((int)arch) {
+ LIST_ARCH_SPECS(CASE, ;);
+ default:
+ abort();
+ }
+ goto not_os_dependent;
+#undef CASE
+ default:
+ break;
+ }
+
+os_dependent:
+#define CASE(UPPERCASE, LOWERCASE)\
+ case LIBSYSCALLS_OS_##UPPERCASE:\
+ r = get_##LOWERCASE##_datatype_description(arch, &datatype, description_out,\
+ &divide_array_size_with_type_size_out);\
+ break
+
+ switch ((int)os) {
+ LIST_OSES(CASE, ;);
+ default:
+ return LIBSYSCALLS_E_OSNOSUP;
+ }
+ if (r)
+ return r;
+#undef CASE
+
+ switch (datatype) {
+ case LIBSYSCALLS_TYPE_INT8:
+ case LIBSYSCALLS_TYPE_INT16:
+ case LIBSYSCALLS_TYPE_INT32:
+ case LIBSYSCALLS_TYPE_INT64:
+ case LIBSYSCALLS_TYPE_INTPTR:
+ case LIBSYSCALLS_TYPE_PTRDIFF:
+ case LIBSYSCALLS_TYPE_SSIZE:
+ goto arch_dependent;
+ default:
+ break;
+ }
+
+not_os_dependent:
+ if (divide_array_size_with_type_size_out)
+ description_out->array_size /= description_out->width_in_bits;
+
+#define CASE(ARCH, CHARBITS, INTPTR_BITS, SIZE_BITS, ENDIAN, SIGN)\
+ case ARCH: charbits = CHARBITS; endian = ENDIAN; break
+ switch ((int)arch) {
+ LIST_ARCH_SPECS(CASE, ;);
+ default:
+ abort();
+ }
+#undef CASE
+
+ if (description_out->width_in_bits % charbits)
+ return LIBSYSCALLS_E_NOSUCHTYPE;
+
+ if (description_out->width_in_bits > (size_t)UCHAR_MAX * sizeof(*description_out->byteorder) ||
+ description_out->width_in_bits > sizeof(description_out->byteorder) / sizeof(*description_out->byteorder) * charbits)
+ abort();
+
+ switch (endian) {
+ case Big:
+ for (i = 0, j = description_out->width_in_bits; j;)
+ description_out->byteorder[i++] = j -= charbits;
+ break;
+ case Little:
+ for (i = 0, j = 0; j < description_out->width_in_bits; j += charbits)
+ description_out->byteorder[i++] = j;
+ break;
+ default:
+ abort();
+ }
+
+ if (half) {
+ unsigned long long int bytemask, coverage = 0;
+ unsigned long long int remmask;
+ unsigned char bytebits;
+
+ for (i = 0; larger_type.byteorder[i]; i++)
+ if (!~larger_type.byteorder[i])
+ abort();
+ bytebits = larger_type.byteorder[i];
+ bytemask = (1ULL << bytebits) - 1ULL;
+ remmask = 0xFFFFFFFFULL; /* we known from the code above that we are working with 32-bit sections */
+
+ for (i = 0; larger_type.byteorder[i]; i++) {
+ coverage |= (remmask & bytemask) << larger_type.byteorder[i];
+ remmask >>= bytebits;
+ }
+
+ /* we known from the code above that we are working with split 64-bit integers */
+ if (coverage == 0xFFFFFFFF00000000ull) description_out->section = LIBSYSCALLS_SECTION_UPPER_HALF;
+ else if (coverage == 0x00000000FFFFFFFFull) description_out->section = LIBSYSCALLS_SECTION_LOWER_HALF;
+ else if (coverage == 0x0000FFFFFFFF0000ull) description_out->section = LIBSYSCALLS_SECTION_INNER_HALF;
+ else if (coverage == 0xFFFF00000000FFFFull) description_out->section = LIBSYSCALLS_SECTION_OUTER_HALF;
+ else if (coverage == 0x0000FFFF0000FFFFull) description_out->section = LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF;
+ else if (coverage == 0xFFFF0000FFFF0000ull) description_out->section = LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF;
+ else if (coverage == 0x00FF00FF00FF00FFull) description_out->section = LIBSYSCALLS_SECTION_EVEN_BYTES_AS_HALF;
+ else if (coverage == 0xFF00FF00FF00FF00ull) description_out->section = LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF;
+ else
+ abort();
+ }
+
+ return LIBSYSCALLS_E_OK;
+}
diff --git a/libsyscalls_get_signals.c b/libsyscalls_get_signals.c
new file mode 100644
index 0000000..9c49760
--- /dev/null
+++ b/libsyscalls_get_signals.c
@@ -0,0 +1,32 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+#include "generated/signals.c"
+
+enum libsyscalls_error
+libsyscalls_get_signals(enum libsyscalls_os os, enum libsyscalls_arch arch,
+ const struct libsyscalls_named_number **signals_out, size_t *num_signals_out)
+{
+ const struct libsyscalls_named_number *discard_signals;
+ size_t discard_num_signals;
+
+ if (!signals_out) signals_out = &discard_signals;
+ if (!num_signals_out) num_signals_out = &discard_num_signals;
+
+#define CASE(UPPERCASE, LOWERCASE)\
+ case LIBSYSCALLS_OS_##UPPERCASE:\
+ return get_##LOWERCASE##_signals(arch, signals_out, num_signals_out)
+
+ switch ((int)os) {
+ LIST_OSES(CASE, ;);
+
+ /* if OS is known but does not have named numerical signal,
+ * get_##LOWERCASE##_signals shall return LIBSYSCALLS_E_NOSIGNALS */
+
+ default:
+ return LIBSYSCALLS_E_OSNOSUP;
+ }
+
+#undef CASE
+}
diff --git a/libsyscalls_get_syscall.c b/libsyscalls_get_syscall.c
new file mode 100644
index 0000000..aea4d2f
--- /dev/null
+++ b/libsyscalls_get_syscall.c
@@ -0,0 +1,37 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+enum libsyscalls_error
+libsyscalls_get_syscall(enum libsyscalls_os os, enum libsyscalls_arch arch, long long int syscallnr,
+ const struct libsyscalls_syscall **syscall_out)
+{
+ const struct libsyscalls_syscall *syscalldesc;
+ static enum libsyscalls_error error;
+ long long int min, max;
+
+ error = libsyscalls_get_syscall_range(os, arch, &min, &max);
+ if (error)
+ return error;
+
+ if (syscallnr < min || syscallnr > max)
+ return LIBSYSCALLS_E_NOSUCHSYSCALL;
+
+ /* buffer access is validated by libsyscalls_get_syscall_range() */
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
+#endif
+
+ syscalldesc = libsyscalls_syscalls_tables_[os][arch][syscallnr - min];
+
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+
+ if (!syscalldesc)
+ return LIBSYSCALLS_E_NOSUCHSYSCALL;
+ if (syscall_out)
+ *syscall_out = syscalldesc;
+ return LIBSYSCALLS_E_OK;
+}
diff --git a/libsyscalls_get_syscall_display_info.c b/libsyscalls_get_syscall_display_info.c
new file mode 100644
index 0000000..5b39284
--- /dev/null
+++ b/libsyscalls_get_syscall_display_info.c
@@ -0,0 +1,148 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#include <stdalign.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define LOWEST_BIT(X) ((X) & ~((X) - 1))
+#define POST_HIGHEST_OF_CONSECUTIVELY_BITS(X) ((X) + LOWEST_BIT(X))
+
+
+static inline signed char
+trailing_zeroes(unsigned long long int x) {
+ int r = 0;
+ if (x == 0)
+ return -1;
+ for (; (x & 1) == 0; x >>= 1)
+ r += 1;
+ return (signed char)r;
+}
+
+
+static int
+signed_named_number_cmp(const void *a_, const void *b_)
+{
+ const struct libsyscalls_named_number *a = a_, *b = b_;
+ return a->number.s < b->number.s ? -1 : a->number.s > b->number.s;
+}
+
+
+static int
+unsigned_named_number_cmp(const void *a_, const void *b_)
+{
+ const struct libsyscalls_named_number *a = a_, *b = b_;
+ return a->number.u < b->number.u ? -1 : a->number.u > b->number.u;
+}
+
+
+static const char *
+extract_signal(enum libsyscalls_os os, enum libsyscalls_arch arch,
+ unsigned long long int *valuep, char *fallback_out, int is_signed)
+{
+ const struct libsyscalls_named_number *signals, *found;
+ size_t nsignals;
+ struct libsyscalls_named_number key = {.number.u = *valuep};
+
+ if (libsyscalls_get_signals(os, arch, &signals, &nsignals))
+ return NULL;
+
+ found = bsearch(&key, signals, nsignals, sizeof(key),
+ is_signed ? &signed_named_number_cmp : &unsigned_named_number_cmp);
+ if (!found)
+ return NULL;
+
+ *valuep = 0;
+ return found->name;
+}
+
+
+static struct libsyscalls_syscall_display_info *
+build_syscall_display_info(void *data, size_t data_size, size_t data_align,
+ libsyscalls_symbol_printer_function **funcs,
+ const struct libsyscalls_syscall_abi *syscall, int nargs, int nsyms)
+{
+ struct libsyscalls_syscall_display_info *ret;
+ size_t size, dataoff, paramoff;
+ int i;
+
+ size = sizeof(*ret);
+
+ if (size & (data_align - 1)) {
+ size |= data_align - 1;
+ size += 1;
+ }
+ dataoff = size;
+ size += nsyms * data_size;
+
+ if (size & (alignof(*ret->params) - 1)) {
+ size |= alignof(*ret->params) - 1;
+ size += 1;
+ }
+ paramoff = size;
+ size += (nargs + 1) * sizeof(*ret->params);
+
+ ret = calloc(1, size);
+ if (!ret)
+ return NULL;
+
+ ret->size = sizeof(*ret);
+ ret->params = (void *)&((char *)ret)[paramoff];
+ ret->retvalue = &ret->params[nargs];
+
+ nsyms = 0;
+ for (i = 0; i < nargs; i++) {
+ ret->params[i].type = syscall->parameters_types[i];
+ if (funcs[i]) {
+ ret->params[i].function = funcs[i];
+ ret->params[i].data = (void *)&((char *)ret)[dataoff + nsyms * data_size];
+ memcpy(ret->params[i].data, &((char *)data)[i * data_size], data_size);
+ nsyms++;
+ }
+ }
+ ret->retvalue->type = syscall->return_type;
+ ret->retvalue->expect_zero = syscall->expect_zero;
+ if (funcs[i]) {
+ ret->retvalue->function = funcs[i];
+ ret->retvalue->data = (void *)&((char *)ret)[dataoff + nsyms * data_size];
+ memcpy(ret->retvalue->data, &((char *)data)[i * data_size], data_size);
+ }
+
+ return ret;
+}
+
+
+#include "generated/symbols.c"
+
+
+enum libsyscalls_error
+libsyscalls_get_syscall_display_info(enum libsyscalls_os os, enum libsyscalls_arch arch,
+ const struct libsyscalls_syscall_abi *syscall,
+ long long int syscall_number,
+ unsigned long long int *syscall_arguments,
+ struct libsyscalls_syscall_display_info **info_out)
+{
+ struct libsyscalls_syscall_display_info *info;
+
+ if (!syscall || !syscall_arguments || !info_out)
+ return LIBSYSCALLS_E_INVAL;
+
+#define CASE(UPPERCASE, LOWERCASE)\
+ case LIBSYSCALLS_OS_##UPPERCASE:\
+ info = get_##LOWERCASE##_syscall_display_info(arch, syscall, syscall_number, syscall_arguments);\
+ break
+
+ switch ((int)os) {
+ LIST_OSES(CASE, ;);
+ default:
+ return LIBSYSCALLS_E_OSNOSUP;
+ }
+
+#undef CASE
+
+ if (!info)
+ return LIBSYSCALLS_E_NOMEM;
+ *info_out = info;
+ return LIBSYSCALLS_E_OK;
+}
diff --git a/libsyscalls_get_syscall_errors.c b/libsyscalls_get_syscall_errors.c
new file mode 100644
index 0000000..14b1e05
--- /dev/null
+++ b/libsyscalls_get_syscall_errors.c
@@ -0,0 +1,32 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+#include "generated/errors.c"
+
+enum libsyscalls_error
+libsyscalls_get_syscall_errors(enum libsyscalls_os os, enum libsyscalls_arch arch,
+ const struct libsyscalls_named_number **errors_out, size_t *num_errors_out)
+{
+ const struct libsyscalls_named_number *discard_errors;
+ size_t discard_num_errors;
+
+ if (!errors_out) errors_out = &discard_errors;
+ if (!num_errors_out) num_errors_out = &discard_num_errors;
+
+#define CASE(UPPERCASE, LOWERCASE)\
+ case LIBSYSCALLS_OS_##UPPERCASE:\
+ return get_##LOWERCASE##_syscall_errors(arch, errors_out, num_errors_out)
+
+ switch ((int)os) {
+ LIST_OSES(CASE, ;);
+
+ /* if OS is known but does not have named error numbers,
+ * get_##LOWERCASE##_syscall_errors shall return LIBSYSCALLS_E_NOERRORS; */
+
+ default:
+ return LIBSYSCALLS_E_OSNOSUP;
+ }
+
+#undef CASE
+}
diff --git a/libsyscalls_get_syscall_range.c b/libsyscalls_get_syscall_range.c
new file mode 100644
index 0000000..eb9b11e
--- /dev/null
+++ b/libsyscalls_get_syscall_range.c
@@ -0,0 +1,26 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+#include "generated/get_syscall_range.c"
+
+enum libsyscalls_error
+libsyscalls_get_syscall_range(enum libsyscalls_os os, enum libsyscalls_arch arch, long long int *min_out, long long int *max_out)
+{
+ long long int discarded;
+
+ if (!min_out) min_out = &discarded;
+ if (!max_out) max_out = &discarded;
+
+#define CASE(UPPERCASE, LOWERCASE)\
+ case LIBSYSCALLS_OS_##UPPERCASE:\
+ return get_##LOWERCASE##_syscall_range(arch, min_out, max_out)
+
+ switch ((int)os) {
+ LIST_OSES(CASE, ;);
+ default:
+ return LIBSYSCALLS_E_OSNOSUP;
+ }
+
+#undef CASE
+}
diff --git a/libsyscalls_perror.c b/libsyscalls_perror.c
new file mode 100644
index 0000000..4b110c7
--- /dev/null
+++ b/libsyscalls_perror.c
@@ -0,0 +1,15 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+#include <stdio.h>
+
+
+void
+libsyscalls_perror(const char *prefix, enum libsyscalls_error error)
+{
+ const char *str = libsyscalls_strerror(error);
+ if (prefix && *prefix)
+ fprintf(stderr, "%s: %s\n", prefix, str);
+ else
+ fprintf(stderr, "%s\n", str);
+}
diff --git a/libsyscalls_strerror.c b/libsyscalls_strerror.c
new file mode 100644
index 0000000..d54ed74
--- /dev/null
+++ b/libsyscalls_strerror.c
@@ -0,0 +1,18 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+const char *
+libsyscalls_strerror(enum libsyscalls_error error)
+{
+#define X(ENUM, STR)\
+ case ENUM: return STR
+
+ switch ((int)error) {
+ LIBSYSCALLS_LIST_ERRORS(X, ;);
+ default:
+ return "Unrecognised error";
+ }
+
+#undef X
+}
diff --git a/libsyscalls_syscalls_tables_.c b/libsyscalls_syscalls_tables_.c
new file mode 100644
index 0000000..403b1c7
--- /dev/null
+++ b/libsyscalls_syscalls_tables_.c
@@ -0,0 +1,10 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+const struct libsyscalls_syscall *const *const *const libsyscalls_syscalls_tables_[] = {
+#define X(UPPERCASE, LOWERCASE)\
+ [LIBSYSCALLS_OS_##UPPERCASE] = libsyscalls_##LOWERCASE##_syscalls_table_
+ LIST_OSES(X, COMMA)
+#undef X
+};
diff --git a/linux/download.mk b/linux/download.mk
new file mode 100644
index 0000000..31da0b1
--- /dev/null
+++ b/linux/download.mk
@@ -0,0 +1,33 @@
+LINUX_MIRROR = https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot
+LINUX_TAREXT = tar.gz
+LINUX_TARBALL = $(LINUX_MIRROR)/linux-$(LINUX_VERSION).$(LINUX_TAREXT)
+LINUX_UNPACK = (gunzip | tar -x)
+
+LINUX_DIR = linux-src/linux-$(LINUX_VERSION)
+LINUX_SOURCE = $(LINUX_DIR)/README
+
+
+SILENCE_LINUX_SOURCE_IF_EXISTS != test ! -f "$(LINUX_SOURCE)" || printf '@'
+SILENCE_LINUX_TARBALL_IF_EXISTS != test ! -f "$(LINUX_DIR).$(LINUX_TAREXT)" || printf '@'
+
+$(LINUX_SOURCE): $(LINUX_DIR).$(LINUX_TAREXT)
+ $(SILENCE_LINUX_SOURCE_IF_EXISTS)if test ! -f "$@"; then \
+ (cd -- linux-src && $(LINUX_UNPACK)) < $(LINUX_DIR).$(LINUX_TAREXT) && \
+ (test -d $(LINUX_DIR) || \
+ mv -- linux-src/linux-v$(LINUX_VERSION) $(LINUX_DIR) || \
+ mv -- linux-src/$(LINUX_VERSION) $(LINUX_DIR) || \
+ mv -- linux-src/v$(LINUX_VERSION) $(LINUX_DIR) \
+ ) && \
+ touch -- "$@"; \
+ fi
+
+$(LINUX_DIR).$(LINUX_TAREXT):
+ $(SILENCE_LINUX_TARBALL_IF_EXISTS)mkdir -p -- linux-src
+ $(SILENCE_LINUX_TARBALL_IF_EXISTS)test -f "$@" || $(DOWNLOAD) $(LINUX_TARBALL) > "$@" || (rm -f -- "$@"; false)
+
+
+download-linux: $(LINUX_DIR).$(LINUX_TAREXT)
+download: download-linux
+
+
+.PHONY: download-linux
diff --git a/linux/errors.c b/linux/errors.c
new file mode 100644
index 0000000..d8a0e7f
--- /dev/null
+++ b/linux/errors.c
@@ -0,0 +1,130 @@
+/* See LICENSE file for copyright and license details. */
+
+/* This file is included from ../libsyscalls_get_syscall_errors.c */
+
+
+#include "../generated/linux-errors.h"
+
+static enum libsyscalls_error
+get_linux_syscall_errors(enum libsyscalls_arch arch, const struct libsyscalls_named_number **errs_out, size_t *nerrs_out)
+{
+#define CASE(ARCH)\
+ *errs_out = linux_errors_for_##ARCH;\
+ *nerrs_out = sizeof(linux_errors_for_##ARCH) / sizeof(*linux_errors_for_##ARCH);\
+ goto out
+
+ switch ((int)arch) {
+ case LIBSYSCALLS_ARCH_ALPHA:
+#ifdef LIST_LINUX_ERRORS_FOR_ALPHA
+ CASE(alpha);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_AMD64:
+ case LIBSYSCALLS_ARCH_AMD64_X32:
+ case LIBSYSCALLS_ARCH_I386:
+#ifdef LIST_LINUX_ERRORS_FOR_X86
+ CASE(x86);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_ARM_OABI:
+ case LIBSYSCALLS_ARCH_ARM_EABI:
+#ifdef LIST_LINUX_ERRORS_FOR_ARM
+ CASE(arm);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_IA64:
+#ifdef LIST_LINUX_ERRORS_FOR_IA64
+ CASE(ia64);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_M68K:
+#ifdef LIST_LINUX_ERRORS_FOR_M68K
+ CASE(m68k);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_MICROBLAZE:
+#ifdef LIST_LINUX_ERRORS_FOR_MICROBLAZE
+ CASE(microblaze);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_MIPS_O32:
+ case LIBSYSCALLS_ARCH_MIPS_N32:
+ case LIBSYSCALLS_ARCH_MIPS_N64:
+#ifdef LIST_LINUX_ERRORS_FOR_MIPS
+ CASE(mips);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_PARISC_32:
+ case LIBSYSCALLS_ARCH_PARISC_64:
+#ifdef LIST_LINUX_ERRORS_FOR_PARISC
+ CASE(parisc);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_POWERPC_32:
+ case LIBSYSCALLS_ARCH_POWERPC_64:
+ case LIBSYSCALLS_ARCH_POWERPC_NOSPU:
+ case LIBSYSCALLS_ARCH_POWERPC_SPU:
+#ifdef LIST_LINUX_ERRORS_FOR_POWERPC
+ CASE(powerpc);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_S390_32:
+ case LIBSYSCALLS_ARCH_S390_64:
+#ifdef LIST_LINUX_ERRORS_FOR_S390
+ CASE(s390);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_SH:
+#ifdef LIST_LINUX_ERRORS_FOR_SH
+ CASE(sh);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_SPARC_32:
+ case LIBSYSCALLS_ARCH_SPARC_64:
+#ifdef LIST_LINUX_ERRORS_FOR_SPARC
+ CASE(sparc);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_XTENSA:
+#ifdef LIST_LINUX_ERRORS_FOR_XTENSA
+ CASE(xtensa);
+#else
+ break;
+#endif
+
+ default:
+ return LIBSYSCALLS_E_ARCHNOSUP;
+ }
+
+ *errs_out = linux_errors_for_generic;
+ *nerrs_out = sizeof(linux_errors_for_generic) / sizeof(*linux_errors_for_generic);
+
+out:
+ return LIBSYSCALLS_E_OK;
+
+#undef CASE
+}
diff --git a/linux/errors.mk b/linux/errors.mk
new file mode 100644
index 0000000..b6b7197
--- /dev/null
+++ b/linux/errors.mk
@@ -0,0 +1,52 @@
+libsyscalls_get_syscall_errors.o: generated/linux-errors.h linux/errors.c
+libsyscalls_get_syscall_errors.lo: generated/linux-errors.h linux/errors.c
+
+generated/linux-errors.tbl: $(LINUX_SOURCE) linux/errors.mk
+ mkdir -p -- generated
+ set -e; ( \
+ get_gcc_or_clang () { \
+ ( \
+ ( \
+ IFS=:; \
+ for dir in $$PATH; do \
+ if test ! -d "$$dir"; then continue; fi; \
+ for file in "$$dir"/*; do \
+ if test ! -x "$$file"; then continue; fi; \
+ printf '%s\n' "$$file"; \
+ done \
+ done \
+ ) | grep '/\(gcc\|clang\)\(-[0-9.]\+\)\?$$'; \
+ printf '%s\n' gcc; \
+ ) | sed 1q; \
+ }; \
+ extract="$$(get_gcc_or_clang) -E -dM"; \
+ toolsdir="linux-src/linux-$(LINUX_VERSION)/tools"; \
+ process_arch() \
+ { \
+ ($$extract "-I$$toolsdir/include/uapi" "$$2" && \
+ cat -- "linux-src/linux-$(LINUX_VERSION)/include/linux/errno.h") \
+ | sed -n 's/^\s*\x23\s*define\s\+\(E[^\s]\+\)\s\+\([0-9]\+\)\s*\(\/.*\)\?$$/'"$$1"' \2 \1/p' \
+ | sort -k 2 -nu; \
+ }; \
+ for arch in $$(printf '%s\n' "$$toolsdir/arch"/*/ | sed 's:^.*/\([^/]*\)/$$:\1:'); do \
+ if test -f "$$toolsdir/arch/$$arch/include/uapi/asm/errno.h"; then \
+ process_arch "$$arch" "$$toolsdir/arch/$$arch/include/uapi/asm/errno.h"; \
+ fi; \
+ done; \
+ process_arch generic "$$toolsdir/include/uapi/asm-generic/errno.h"; \
+ ) > $@
+
+generated/linux-errors.h: generated/linux-errors.tbl linux/errors.mk
+ set -e; \
+ for arch in $$(cut -d ' ' -f 1 < generated/linux-errors.tbl | uniq); do \
+ ARCH="$$(printf '%s\n' "$$arch" | tr '[a-z]' '[A-Z]')"; \
+ printf '#define LIST_LINUX_ERRORS_FOR_%s(X, D)\\\n' "$$ARCH"; \
+ sed -n 's/^'"$$arch"' \([0-9]\+\) \(.*\)$$/\tX(\1, "\2") D\\/p' \
+ < generated/linux-errors.tbl \
+ | sed '$$s/ D\\//'; \
+ printf 'static struct libsyscalls_named_number linux_errors_for_%s[] = {\n' "$$arch"; \
+ printf '#define X(NR, NAME) {.number.s = NR, .name = NAME}\n'; \
+ printf '\tLIST_LINUX_ERRORS_FOR_%s(X, COMMA)\n' "$$ARCH"; \
+ printf '#undef X\n'; \
+ printf '};\n'; \
+ done > $@
diff --git a/linux/linux-support.mk b/linux/linux-support.mk
new file mode 100644
index 0000000..5efeafe
--- /dev/null
+++ b/linux/linux-support.mk
@@ -0,0 +1,54 @@
+LINUX_VERSION = 6.6
+# Changing this number can potentially break the build,
+# silently or violently, so make sure everything still
+# works afterwards
+
+SUPPORTED_LINUX_ARCHES =\
+ ALPHA\
+ AMD64\
+ AMD64_X32\
+ ARM_OABI\
+ ARM_EABI\
+ IA64\
+ M68K\
+ MICROBLAZE\
+ MIPS_O32\
+ MIPS_N32\
+ MIPS_N64\
+ PARISC_32\
+ PARISC_64\
+ POWERPC_32\
+ POWERPC_64\
+ POWERPC_NOSPU\
+ POWERPC_SPU\
+ S390_32\
+ S390_64\
+ SH\
+ SPARC_32\
+ SPARC_64\
+ I386\
+ XTENSA
+
+OPERATING_SYSTEMS += linux
+NPARAMS += 8
+
+
+SUPPORTED_LINUX_ARCHES != printf '%s\n' $(SUPPORTED_LINUX_ARCHES) $(SUPPORTED_ARCHES) | sort | uniq -d
+
+
+include linux/download.mk
+include linux/errors.mk
+include linux/signals.mk
+include linux/syscalls.mk
+include linux/syscall-table.mk
+include linux/symbols.mk
+include linux/types.mk
+
+
+HDR += generated/linux-arches.h
+
+generated/linux-arches.h: linux/linux-support.mk
+ mkdir -p -- generated
+ (printf '\43define LIST_LINUX_ARCHES(X, D)\\\n' && \
+ printf '\tX(%s) D\\\n' $(SUPPORTED_LINUX_ARCHES); \
+ ) | sed '$$s/ D\\//' > $@
diff --git a/linux/no.mk b/linux/no.mk
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/linux/no.mk
diff --git a/linux/signals.c b/linux/signals.c
new file mode 100644
index 0000000..7d7f868
--- /dev/null
+++ b/linux/signals.c
@@ -0,0 +1,130 @@
+/* See LICENSE file for copyright and license details. */
+
+/* This file is included from ../libsyscalls_get_signals.c */
+
+
+#include "../generated/linux-signals.h"
+
+static enum libsyscalls_error
+get_linux_signals(enum libsyscalls_arch arch, const struct libsyscalls_named_number **sigs_out, size_t *nsigs_out)
+{
+#define CASE(ARCH)\
+ *sigs_out = linux_signals_for_##ARCH;\
+ *nsigs_out = sizeof(linux_signals_for_##ARCH) / sizeof(*linux_signals_for_##ARCH);\
+ goto out
+
+ switch ((int)arch) {
+ case LIBSYSCALLS_ARCH_ALPHA:
+#ifdef LIST_LINUX_SIGNALS_FOR_ALPHA
+ CASE(alpha);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_AMD64:
+ case LIBSYSCALLS_ARCH_AMD64_X32:
+ case LIBSYSCALLS_ARCH_I386:
+#ifdef LIST_LINUX_SIGNALS_FOR_X86
+ CASE(x86);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_ARM_OABI:
+ case LIBSYSCALLS_ARCH_ARM_EABI:
+#ifdef LIST_LINUX_SIGNALS_FOR_ARM
+ CASE(arm);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_IA64:
+#ifdef LIST_LINUX_SIGNALS_FOR_IA64
+ CASE(ia64);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_M68K:
+#ifdef LIST_LINUX_SIGNALS_FOR_M68K
+ CASE(m68k);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_MICROBLAZE:
+#ifdef LIST_LINUX_SIGNALS_FOR_MICROBLAZE
+ CASE(microblaze);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_MIPS_O32:
+ case LIBSYSCALLS_ARCH_MIPS_N32:
+ case LIBSYSCALLS_ARCH_MIPS_N64:
+#ifdef LIST_LINUX_SIGNALS_FOR_MIPS
+ CASE(mips);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_PARISC_32:
+ case LIBSYSCALLS_ARCH_PARISC_64:
+#ifdef LIST_LINUX_SIGNALS_FOR_PARISC
+ CASE(parisc);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_POWERPC_32:
+ case LIBSYSCALLS_ARCH_POWERPC_64:
+ case LIBSYSCALLS_ARCH_POWERPC_NOSPU:
+ case LIBSYSCALLS_ARCH_POWERPC_SPU:
+#ifdef LIST_LINUX_SIGNALS_FOR_POWERPC
+ CASE(powerpc);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_S390_32:
+ case LIBSYSCALLS_ARCH_S390_64:
+#ifdef LIST_LINUX_SIGNALS_FOR_S390
+ CASE(s390);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_SH:
+#ifdef LIST_LINUX_SIGNALS_FOR_SH
+ CASE(sh);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_SPARC_32:
+ case LIBSYSCALLS_ARCH_SPARC_64:
+#ifdef LIST_LINUX_SIGNALS_FOR_SPARC
+ CASE(sparc);
+#else
+ break;
+#endif
+
+ case LIBSYSCALLS_ARCH_XTENSA:
+#ifdef LIST_LINUX_SIGNALS_FOR_XTENSA
+ CASE(xtensa);
+#else
+ break;
+#endif
+
+ default:
+ return LIBSYSCALLS_E_ARCHNOSUP;
+ }
+
+ *sigs_out = linux_signals_for_generic;
+ *nsigs_out = sizeof(linux_signals_for_generic) / sizeof(*linux_signals_for_generic);
+
+out:
+ return LIBSYSCALLS_E_OK;
+
+#undef CASE
+}
diff --git a/linux/signals.mk b/linux/signals.mk
new file mode 100644
index 0000000..f7a8a45
--- /dev/null
+++ b/linux/signals.mk
@@ -0,0 +1,138 @@
+libsyscalls_get_signals.o: generated/linux-signals.h linux/signals.c
+libsyscalls_get_signals.lo: generated/linux-signals.h linux/signals.c
+
+generated/linux-signals.tbl: $(LINUX_SOURCE) linux/signals.mk
+ mkdir -p -- generated
+ set -e; ( \
+ get_gcc_or_clang () { \
+ ( \
+ ( \
+ IFS=:; \
+ for dir in $$PATH; do \
+ if test ! -d "$$dir"; then continue; fi; \
+ for file in "$$dir"/*; do \
+ if test ! -x "$$file"; then continue; fi; \
+ printf '%s\n' "$$file"; \
+ done \
+ done \
+ ) | grep '/\(gcc\|clang\)\(-[0-9.]\+\)\?$$'; \
+ printf '%s\n' gcc; \
+ ) | sed 1q; \
+ }; \
+ if test -n "$(CC_DEF_EXTRACT)"; then \
+ c="$(CC_DEF_EXTRACT)"; \
+ else \
+ c="$(CC)"; \
+ fi; \
+ c="$$($$c --version 2>&1 | sed 1q | sed 's/^.*(\(.*\)).*$$/\1/' | tr '[A-Z]' '[a-z]' | cut -d ' ' -f 1)"; \
+ if test ! "$$c" = gcc && test ! "$$c" = clang; then \
+ c="$$(get_gcc_or_clang)"; \
+ fi; \
+ extract="$$c -E -dM -D__KERNEL__"; \
+ srcdir="linux-src/linux-$(LINUX_VERSION)"; \
+ mkdir -p -- "$$srcdir/tools/include/generated/"; \
+ touch -- "$$srcdir/tools/include/generated/bounds.h"; \
+ touch -- "$$srcdir/tools/include/generated/timeconst.h"; \
+ process_arch () \
+ { \
+ set -e; \
+ signals="$$( \
+ $$extract "-I$$srcdir/tools/include" $$fixes "$$2" \
+ | sed -n 's/^\s*\x23\s*define\s\+\(SIG[^\s]\+\)\s\+\([0-9]\+\)\s*\(\/.*\)\?$$/'"$$1"' \2 \1/p' \
+ | grep -v ' SIG_' \
+ | grep -v ' SIGSTKSZ' \
+ | sort -k 2 -nu; \
+ )"; \
+ if test "$$1" = arm; then \
+ signals="$$(printf "%s\n" "$$signals" | sed 's/\bSIGSWI\b/SIGRTMIN/')"; \
+ fi; \
+ printf "%s\n" "$$signals"; \
+ sigrtmin="$$(printf "%s\n" "$$signals" | sed -n 's/^.* \([0-9]\+\) SIGRTMIN$$/\1/p')"; \
+ maxnamed="$$(printf "%s\n" "$$signals" | sed -n '$$s/^.* \([0-9]\+\) .*$$/\1/p')"; \
+ test "$$sigrtmin" = "$$maxnamed"; \
+ maxsig=_NSIG; \
+ depth=0; \
+ while test -n "$$maxsig" && test -n "$$(printf '%s\n' "$$maxsig" | tr -d '[0-9]')" ; do \
+ printf '%s: looking for %s\n' "$$1" "$$maxsig" >&2; \
+ def="$$maxsig"; \
+ maxsig="$$($$extract "-I$$srcdir/tools/include" $$fixes "$$2" \
+ | sed -n 's/^\s*\x23\s*define\s\+'"$$def"'\s\+\([A-Z0-9_]\+\)\s*\(\/.*\)\?$$/\1/p')"; \
+ if test -z "$$maxsig"; then \
+ maxsig="$$($$extract "-I$$srcdir/tools/include" \
+ "-I$$srcdir/arch/$$1/include" \
+ "-I$$srcdir/include" \
+ "-I$$srcdir" \
+ $$fixes \
+ "$$(printf '%s\n' "$$2" | sed 's:/uapi/:/:')" \
+ | sed -n 's/^\s*\x23\s*define\s\+'"$$def"'\s\+\([A-Z0-9_]\+\)\s*\(\/.*\)\?$$/\1/p')"; \
+ fi; \
+ printf '%s: found %s\n' "$$1" "$$maxsig" >&2; \
+ : $$(( depth++ )); \
+ test $$(( depth )) -lt 1000; \
+ done; \
+ test -n "$$maxsig"; \
+ i=1; \
+ while (( sigrtmin + i <= maxsig )); do \
+ printf '%s %d SIGRTMIN+%d\n' "$$1" $$(( sigrtmin + i )) $$i; \
+ : $$(( i++ )); \
+ done; \
+ }; \
+ getsigs () { \
+ process_arch "$$@" | sed 's/\bSIGRTMIN\b/_&/'; \
+ }; \
+ for arch in $$(printf '%s\n' "$$srcdir/arch"/*/ | sed 's:^.*/\([^/]*\)/$$:\1:'); do \
+ if test ! "$$arch" = s390 && test -f "$$srcdir/arch/$$arch/include/uapi/asm/signal.h"; then \
+ getsigs "$$arch" "$$srcdir/arch/$$arch/include/uapi/asm/signal.h"; \
+ fi; \
+ done; \
+ getsigs generic "$$srcdir/include/uapi/asm-generic/signal.h"; \
+ ) > $@
+ @printf '\033[1;32m%s\033[m\n' \
+ 'Compiler warnings above are not of interest, they were generated during' \
+ 'extraction of the Linux source code and are not part of this library'
+ @grep '^generic.*SIGRTMIN+.*' >/dev/null 2>/dev/null < $@
+ grep '^generic ' < $@ | cut -d ' ' -f 2 > generated/linux-signals.generic.tbl
+ @# For most architectures the signal numbers are the same,
+ @# yet they have their own signal.h listing them, so to remove
+ @# duplication in the library, we removing duplicates after
+ @# validating that they have not diverged
+ grep '^arm ' < $@ | cut -d ' ' -f 2 | diff -u generated/linux-signals.generic.tbl -
+ sed '/^arm /d' < $@ > $@.tmp && mv -- $@.tmp $@
+ grep '^arm64 ' < $@ | cut -d ' ' -f 2 | diff -u generated/linux-signals.generic.tbl -
+ sed '/^arm64 /d' < $@ > $@.tmp && mv -- $@.tmp $@
+ grep '^hexagon ' < $@ | cut -d ' ' -f 2 | diff -u generated/linux-signals.generic.tbl -
+ sed '/^hexagon /d' < $@ > $@.tmp && mv -- $@.tmp $@
+ grep '^loongarch ' < $@ | cut -d ' ' -f 2 | diff -u generated/linux-signals.generic.tbl -
+ sed '/^loongarch /d' < $@ > $@.tmp && mv -- $@.tmp $@
+ grep '^arc ' < $@ | cut -d ' ' -f 2 | diff -u generated/linux-signals.generic.tbl -
+ sed '/^arc /d' < $@ > $@.tmp && mv -- $@.tmp $@
+ grep '^nios2 ' < $@ | cut -d ' ' -f 2 | diff -u generated/linux-signals.generic.tbl -
+ sed '/^nios2 /d' < $@ > $@.tmp && mv -- $@.tmp $@
+ grep '^ia64 ' < $@ | cut -d ' ' -f 2 | diff -u generated/linux-signals.generic.tbl -
+ sed '/^ia64 /d' < $@ > $@.tmp && mv -- $@.tmp $@
+ grep '^m68k ' < $@ | cut -d ' ' -f 2 | diff -u generated/linux-signals.generic.tbl -
+ sed '/^m68k /d' < $@ > $@.tmp && mv -- $@.tmp $@
+ grep '^powerpc ' < $@ | cut -d ' ' -f 2 | diff -u generated/linux-signals.generic.tbl -
+ sed '/^powerpc /d' < $@ > $@.tmp && mv -- $@.tmp $@
+ grep '^sh ' < $@ | cut -d ' ' -f 2 | diff -u generated/linux-signals.generic.tbl -
+ sed '/^sh /d' < $@ > $@.tmp && mv -- $@.tmp $@
+ grep '^x86 ' < $@ | cut -d ' ' -f 2 | diff -u generated/linux-signals.generic.tbl -
+ sed '/^x86 /d' < $@ > $@.tmp && mv -- $@.tmp $@
+ grep '^xtensa ' < $@ | cut -d ' ' -f 2 | diff -u generated/linux-signals.generic.tbl -
+ sed '/^xtensa /d' < $@ > $@.tmp && mv -- $@.tmp $@
+ rm -f -- generated/linux-signals.*.tbl
+
+generated/linux-signals.h: generated/linux-signals.tbl linux/signals.mk
+ set -e; \
+ for arch in $$(cut -d ' ' -f 1 < generated/linux-signals.tbl | uniq); do \
+ ARCH="$$(printf '%s\n' "$$arch" | tr '[a-z]' '[A-Z]')"; \
+ printf '#define LIST_LINUX_SIGNALS_FOR_%s(X, D)\\\n' "$$ARCH"; \
+ sed -n 's/^'"$$arch"' \([0-9]\+\) \(.*\)$$/\tX(\1, "\2") D\\/p' \
+ < generated/linux-signals.tbl \
+ | sed '$$s/ D\\//'; \
+ printf 'static struct libsyscalls_named_number linux_signals_for_%s[] = {\n' "$$arch"; \
+ printf '#define X(NR, NAME) {.number.s = NR, .name = NAME}\n'; \
+ printf '\tLIST_LINUX_SIGNALS_FOR_%s(X, COMMA)\n' "$$ARCH"; \
+ printf '#undef X\n'; \
+ printf '};\n'; \
+ done > $@
diff --git a/linux/symbols.c b/linux/symbols.c
new file mode 100644
index 0000000..d91880f
--- /dev/null
+++ b/linux/symbols.c
@@ -0,0 +1,321 @@
+/* See LICENSE file for copyright and license details. */
+
+/* This file is included from ../libsyscalls_get_syscall_display_info.c */
+
+/* TODO (see syscalls.h) */
+#define extract_linux_symbol_madvise extract_linux_symbol_noflags
+#define extract_linux_symbol_msync extract_linux_symbol_noflags
+#define extract_linux_symbol_mlock extract_linux_symbol_noflags
+#define extract_linux_symbol_mcl extract_linux_symbol_noflags
+#define extract_linux_symbol_epoll extract_linux_symbol_noflags
+#define extract_linux_symbol_sock_fd extract_linux_symbol_noflags
+#define extract_linux_symbol_dup3 extract_linux_symbol_noflags
+#define extract_linux_symbol_pipe extract_linux_symbol_noflags
+#define extract_linux_symbol_inotify_fd extract_linux_symbol_noflags
+#define extract_linux_symbol_fan_event_f extract_linux_symbol_noflags
+#define extract_linux_symbol_mq_open extract_linux_symbol_noflags
+#define extract_linux_symbol_swapon extract_linux_symbol_noflags
+#define extract_linux_symbol_inotify_mask extract_linux_symbol_noflags
+#define extract_linux_symbol_shmget extract_linux_symbol_noflags
+#define extract_linux_symbol_fan_class extract_linux_symbol_noflags
+#define extract_linux_symbol_fan_mark extract_linux_symbol_noflags
+#define extract_linux_symbol_fan extract_linux_symbol_noflags
+#define extract_linux_symbol_socket extract_linux_symbol_noflags
+#define extract_linux_symbol_reboot extract_linux_symbol_noflags
+
+
+static const char *
+extract_linux_symbol_signal(struct libsyscalls_symbol_printer_data *data, unsigned long long int *valuep, char *fallback_out)
+{
+ return extract_signal(LIBSYSCALLS_OS_LINUX, data->arch, valuep, fallback_out,
+ 0 /* doesn't matter, unsigned is probably faster */);
+}
+
+
+static const char *
+extract_linux_symbol_mode(struct libsyscalls_symbol_printer_data *data, unsigned long long int *valuep, char *fallback_out)
+{
+ unsigned long long int value;
+ size_t i;
+ *fallback_out = 'o';
+ *valuep ^= value = *valuep & 07777ULL;
+ i = 0;
+ data->buf[i++] = '0';
+ if (value & 07000) goto digits4;
+ if (value & 0700) goto digits3;
+ if (value & 070) goto digits2;
+ if (value & 07) goto digits1;
+ if (0) {
+ digits4:
+ data->buf[i++] = '0' | (value & 07000);
+ digits3:
+ data->buf[i++] = '0' | (value & 0700);
+ digits2:
+ data->buf[i++] = '0' | (value & 070);
+ digits1:
+ data->buf[i++] = '0' | (value & 07);
+ }
+ data->buf[i++] = ' ';
+ data->buf[i++] = '(';
+ data->buf[i++] = (value & 0400) ? 'r' : '-';
+ data->buf[i++] = (value & 0200) ? 'w' : '-';
+ if (value & 04000)
+ data->buf[i++] = (value & 0100) ? 's' : 'S';
+ else
+ data->buf[i++] = (value & 0100) ? 'x' : '-';
+ data->buf[i++] = (value & 040) ? 'r' : '-';
+ data->buf[i++] = (value & 020) ? 'w' : '-';
+ if (value & 02000)
+ data->buf[i++] = (value & 010) ? 's' : 'S';
+ else
+ data->buf[i++] = (value & 010) ? 'x' : '-';
+ data->buf[i++] = (value & 04) ? 'r' : '-';
+ data->buf[i++] = (value & 02) ? 'w' : '-';
+ if (value & 01000)
+ data->buf[i++] = (value & 01) ? 't' : 'T';
+ else
+ data->buf[i++] = (value & 01) ? 'x' : '-';
+ data->buf[i++] = ')';
+ data->buf[i] = '\0';
+ return data->buf;
+}
+
+
+static const char *
+extract_linux_symbol_umask(struct libsyscalls_symbol_printer_data *data, unsigned long long int *valuep, char *fallback_out)
+{
+ unsigned long long int value;
+ size_t i;
+ *fallback_out = 'o';
+ *valuep ^= value = *valuep & 0777ULL;
+ i = 0;
+ data->buf[i++] = '0';
+ if (value & 0700) goto digits3;
+ if (value & 070) goto digits2;
+ if (value & 07) goto digits1;
+ if (0) {
+ digits3:
+ data->buf[i++] = '0' | (value & 0700);
+ digits2:
+ data->buf[i++] = '0' | (value & 070);
+ digits1:
+ data->buf[i++] = '0' | (value & 07);
+ }
+ data->buf[i++] = ' ';
+ data->buf[i++] = '(';
+ data->buf[i++] = 'u';
+ data->buf[i++] = ':';
+ data->buf[i++] = ':';
+ data->buf[i++] = (value & 0400) ? '-' : 'r';
+ data->buf[i++] = (value & 0200) ? '-' : 'w';
+ data->buf[i++] = (value & 0100) ? '-' : 'x';
+ data->buf[i++] = ',';
+ data->buf[i++] = 'g';
+ data->buf[i++] = ':';
+ data->buf[i++] = ':';
+ data->buf[i++] = (value & 040) ? '-' : 'r';
+ data->buf[i++] = (value & 020) ? '-' : 'w';
+ data->buf[i++] = (value & 010) ? '-' : 'x';
+ data->buf[i++] = ',';
+ data->buf[i++] = 'o';
+ data->buf[i++] = ':';
+ data->buf[i++] = ':';
+ data->buf[i++] = (value & 04) ? '-' : 'r';
+ data->buf[i++] = (value & 02) ? '-' : 'w';
+ data->buf[i++] = (value & 01) ? '-' : 'x';
+ data->buf[i++] = ')';
+ data->buf[i] = '\0';
+ return data->buf;
+}
+
+
+static const char *
+extract_linux_symbol_dev(struct libsyscalls_symbol_printer_data *data, unsigned long long int *valuep, char *fallback_out)
+{
+ unsigned long long int value;
+ unsigned long long int major, major1, major2;
+ unsigned long long int minor, minor1, minor2;
+
+ *fallback_out = 'x';
+
+ major1 = 0xFFFFF00000000000ULL;
+ minor1 = 0x00000FFFFFF00000ULL;
+ major2 = 0x00000000000FFF00ULL;
+ minor2 = 0x00000000000000FFULL;
+
+ *valuep ^= value = *valuep & (major1 | minor1 | major2 | minor2);
+
+ major1 = (value & major1) / LOWEST_BIT(major1) * POST_HIGHEST_OF_CONSECUTIVELY_BITS(major2);
+ major2 = (value & major2) / LOWEST_BIT(major2);
+
+ minor1 = (value & minor1) / LOWEST_BIT(minor1) * POST_HIGHEST_OF_CONSECUTIVELY_BITS(minor2);
+ minor2 = (value & minor2) / LOWEST_BIT(minor2);
+
+ major = major1 | major2;
+ minor = minor1 | minor1;
+
+ sprintf(data->buf, "%llu (%llu:%llu)", value, major, minor);
+ return data->buf;
+}
+
+
+static const char *
+extract_linux_symbol_clockid_t(struct libsyscalls_symbol_printer_data *data, unsigned long long int *valuep, char *fallback_out)
+{
+ if (*valuep >= 0)
+ return NULL;
+ else if ((*valuep & 7) == 2)
+ sprintf(data->buf, "%lli (pid: %llu)", (long long int)*valuep, ~*valuep / 8);
+ else if ((*valuep & 7) == 3)
+ sprintf(data->buf, "%lli (fd: %llu)", (long long int)*valuep, ~*valuep / 8);
+ else if ((*valuep & 7) == 6)
+ sprintf(data->buf, "%lli (tid: %llu)", (long long int)*valuep, ~*valuep / 8);
+ else
+ sprintf(data->buf, "%lli (~%llu*8 + %u)", (long long int)*valuep, ~*valuep / 8, *valuep & 7);
+ *valuep = 0;
+ return data->buf;
+}
+
+
+#define SYMBOL_PRINTERS_ONLY
+#include "syscalls.h"
+#undef SYMBOL_PRINTERS_ONLY
+
+#include "../generated/linux-symbol-extractors.h"
+
+
+static int
+get_linux_symbol_extractor_by_sym_nr(LIBSYSCALLS_SYMBOL_PRINTER printer, libsyscalls_symbol_printer_function **function_out,
+ enum libsyscalls_arch arch, const struct libsyscalls_syscall_abi *syscall, int nr,
+ struct libsyscalls_symbol_printer_data *data_out)
+{
+ int ret;
+
+#define CASE(E, F, N)\
+ case E:\
+ *function_out = &F;\
+ ret = N;\
+ break
+
+ switch (printer) {
+ LIST_LINUX_EXTRACTORS(CASE, ;);
+
+ case LINUX_SYMBOL_PRINTER_SIGNAL:
+ *function_out = &extract_linux_symbol_signal;
+ ret = 1;
+ break;
+
+ default:
+ abort();
+ }
+
+#undef CASE
+
+ data_out->arch = arch;
+ data_out->nr = nr;
+
+ (void) syscall;
+ return ret;
+}
+
+
+static libsyscalls_symbol_printer_function *
+get_linux_symbol_extractor_by_arg_nr(enum libsyscalls_arch arch, const struct libsyscalls_syscall_abi *syscall,
+ int arg, struct libsyscalls_symbol_printer_data *data_out)
+{
+ int nr, n;
+ unsigned mask;
+ LIBSYSCALLS_SYMBOL_PRINTER first, second;
+ libsyscalls_symbol_printer_function *function;
+
+ if (!syscall->symbol_printer || arg >= NPARAMS) {
+ return NULL;
+ } else if (arg < 0) {
+ if (syscall->symbolic_return)
+ nr = 0;
+ else
+ return NULL;
+ } else if ((syscall->symbolic_mask >> arg) & 1) {
+ mask = (unsigned)syscall->symbolic_mask;
+ nr = (int)syscall->symbolic_return;
+ for (mask &= (1U << arg) - 1; mask; mask >>= 1)
+ nr += (int)mask & 1;
+ } else {
+ return NULL;
+ }
+
+ first = (syscall->symbol_printer & 0x00FF) >> 0;
+ second = (syscall->symbol_printer & 0xFF00) >> 8;
+ if (second && !first)
+ second = syscall->symbol_printer;
+
+ if (first) {
+ n = get_linux_symbol_extractor_by_sym_nr(first, &function, arch, syscall, nr, data_out);
+ if (nr < n)
+ goto have_fun;
+ nr -= n;
+ }
+
+ if (second) {
+ n = get_linux_symbol_extractor_by_sym_nr(second, &function, arch, syscall, nr, data_out);
+ if (nr < n)
+ goto have_fun;
+ }
+
+ abort();
+
+have_fun:
+ return function;
+}
+
+
+static struct libsyscalls_syscall_display_info *
+get_linux_syscall_display_info(enum libsyscalls_arch arch, const struct libsyscalls_syscall_abi *syscall,
+ long long int syscall_number, unsigned long long int *syscall_argument)
+{
+ LIBSYSCALLS_SYMBOL_PRINTER_DATA *data;
+ libsyscalls_symbol_printer_function **funcs;
+ int i, nargs, nsyms;
+ size_t data_size = offsetof(LIBSYSCALLS_SYMBOL_PRINTER_DATA, buf);
+ size_t data_align = alignof(*data);
+ size_t bufspace, bufspace1, bufspace2;
+ LIBSYSCALLS_SYMBOL_PRINTER first, second;
+
+ nargs = (int)syscall->max_argument_count;
+ nargs = nargs < 0 ? 0 : nargs;
+
+ first = (syscall->symbol_printer & 0x00FF) >> 0;
+ second = (syscall->symbol_printer & 0xFF00) >> 8;
+ if (second && !first)
+ second = syscall->symbol_printer;
+
+ bufspace1 = LINUX_REQUIRE_SYMBOL_BUFFER(first);
+ bufspace2 = LINUX_REQUIRE_SYMBOL_BUFFER(second);
+ bufspace = bufspace1 > bufspace2 ? bufspace1 : bufspace2;
+ data_size += bufspace;
+ if (bufspace & (data_align - 1)) {
+ data_size |= data_align - 1;
+ data_size += 1;
+ }
+
+ {
+ char data_vla_buf[(nargs + 1) * data_size + data_align];
+ libsyscalls_symbol_printer_function *funcs_vla[nargs + 1];
+
+ data = (void *)ALIGN_BUF(data_vla_buf, data_align);
+ funcs = funcs_vla;
+
+ nsyms = 0;
+ for (i = 0; i < nargs; i++) {
+ funcs[i] = get_linux_symbol_extractor_by_arg_nr(arch, syscall, i, &data[i]);
+ nsyms += !!funcs[i];
+ }
+ funcs[i] = get_linux_symbol_extractor_by_arg_nr(arch, syscall, -1, &data[i]);
+ nsyms += !!funcs[i];
+
+ (void) syscall_argument;
+ (void) syscall_number;
+
+ return build_syscall_display_info(data, data_size, data_align, funcs, syscall, nargs, nsyms);
+ }
+}
diff --git a/linux/symbols.mk b/linux/symbols.mk
new file mode 100644
index 0000000..f045222
--- /dev/null
+++ b/linux/symbols.mk
@@ -0,0 +1,73 @@
+LINUX_SYMBOL_TABLES != sed -n 's/^.*LINUX_SYMBOL_PRINTER_\([A-Z0-9_]\+\)\b.*\$$\$$\$$.*\$$\$$\$$.*$$/\1/p' < linux/syscalls.h
+
+LINUX_SYMBOL_TABLE_FILES != printf 'linux-src/symbols-$(LINUX_VERSION)/%s\n' $(LINUX_SYMBOL_TABLES)
+
+LINUX_SYMBOL_TABLE_DEPS =\
+ $(LINUX_SOURCE)\
+ linux/symbols.mk\
+ linux/syscalls.h\
+ util/getdefs\
+ util/getenum
+
+LINUX_SYMBOL_EXTRACTOR_DEPS =\
+ $(LINUX_SYMBOL_TABLE_FILES)\
+ linux/symbols.mk\
+ linux/syscalls.h\
+ util/make-enum\
+ util/make-mask\
+ util/make-multiextractor\
+ util/make-sym-extractor
+
+
+libsyscalls_get_syscall_display_info.o: generated/linux-symbol-extractors.h linux/symbols.c
+libsyscalls_get_syscall_display_info.lo: generated/linux-symbol-extractors.h linux/symbols.c
+
+
+$(LINUX_SYMBOL_TABLE_FILES): $(LINUX_SYMBOL_TABLE_DEPS)
+ mkdir -p -- linux-src/symbols-$(LINUX_VERSION)
+ table="$$(printf '%s\n' "$@" | tr / '\n' | sed -n '$$p')" && \
+ command="$$(sed -n 's/^.*LINUX_SYMBOL_PRINTER_'"$$table"'\b.*\$$\$$\$$\s*\(.*\)\s*\$$\$$\$$.*$$/\1/p' < linux/syscalls.h)" && \
+ test -n "$$command" && \
+ printf '%s\n' "$$command" && \
+ (cd -- linux-src/linux-$(LINUX_VERSION) && env PATH="../../util:$${PATH}" sh -e -c "$$command") > $@
+
+generated/linux-symbol-extractors.h: $(LINUX_SYMBOL_EXTRACTOR_DEPS)
+ mkdir -p -- generated
+ set -e; \
+ for tablefile in $(LINUX_SYMBOL_TABLE_FILES); do \
+ tablename="$$(printf '%s\n' "$$tablefile" | cut -d / -f 3)"; \
+ how="$$(sed -n < linux/syscalls.h \
+ 's/^.*LINUX_SYMBOL_PRINTER_'"$$tablename"'\b.*\/\*\s*\(.*\)\s*\$$\$$\$$.*\$$\$$\$$.*$$/\1/p')"; \
+ printf '\n'; \
+ util/make-sym-extractor "$$tablename" "$$how" < "$$tablefile"; \
+ done > $@.tmp
+ set -e; \
+ pattern='\s\+LINUX_SYMBOL_PRINTER_\([A-Z0-9_]\+\)\s*'; \
+ funcprefix='extract_linux_symbol_'; \
+ sed -n 's/^\s*\x23\s*define'"$$pattern$$pattern"'\(\/.*\)\?$$/\x23define '$$funcprefix'\1 '$$funcprefix'\2/p' \
+ < linux/syscalls.h | tr '[A-Z]' '[a-z]' > $@
+ storage_and_rettype="$$(sed '/^$$/d' < $@.tmp | sed 1q | sed 's/\*/\\\*/g' | sed 's/[^\*]$$/& /')"; \
+ sed -n 's/^extract_symbol_.*/'"$${storage_and_rettype}"'&;/p' < $@.tmp | cat - $@.tmp >> $@
+ -rm -f -- $@.tmp
+ set -e; \
+ sed 's/, */ /g' < linux/syscalls.h \
+ | sed -n 's/^.*LINUX_SYMBOL_PRINTER_\([A-Z0-9_]\+\)\b.*[^$$]\$$\$$\s*SYMBOLS(\(.*\))\s*\$$\$$[^$$].*$$/\1 \2/p' \
+ | while read line; do \
+ printf '\n'; \
+ util/make-multiextractor $$line; \
+ done >> $@
+ printf '\n\43define LIST_LINUX_EXTRACTORS(X, D)\\\n' >> $@
+ set -e; \
+ phonies="$$(sed -n '/\$$\$$\$$\s*BEGIN\s\+PHONIES\s*\$$\$$\$$/,/\$$\$$\$$\s*END\s\+PHONIES\s*\$$\$$\$$/p' < linux/syscalls.h \
+ | sed -n 's/^\s*LINUX_SYMBOL_PRINTER_\([A-Z0-9_]\+\)\b.*$$/\1/p')"; \
+ sed -n 's/^extract_symbol_\([^)]*\)(.*)\s*\/\*\s*\([0-9]\+\)\s*\*\/\s*$$/\1 \2/p' < $@ \
+ | while read name n; do \
+ if ! printf '%s\n' "$$phonies" | grep -i \^"$$name"\$$ > /dev/null; then \
+ printf '\tX(LINUX_SYMBOL_PRINTER_%s, extract_symbol_%s, %i) D\\\n' \
+ "$$(printf '%s\n' "$$name" | tr '[a-z]' '[A-Z]')" \
+ "$$name" \
+ "$$n"; \
+ fi; \
+ done \
+ | sed '$$s/ \D\\$$//' >> $@
+ sed 's/extract_symbol/extract_linux_symbol/g' < $@ > $@.tmp && mv -- $@.tmp $@
diff --git a/linux/syscall-table.c b/linux/syscall-table.c
new file mode 100644
index 0000000..6bcd480
--- /dev/null
+++ b/linux/syscall-table.c
@@ -0,0 +1,58 @@
+/* See LICENSE file for copyright and license details. */
+#define REQUIRE_FLEXABLE_OR_NPARAMS
+#include "../common.h"
+
+
+#include "../generated/linux-syscall-table.h"
+#include "../generated/linux-syscalls.h"
+#include "syscalls.h"
+
+
+/* generated/linux-syscall-dedup.h removes references to duplicate symbols, then compiler optimisation removes them */
+#if defined(__clang__)
+# pragma clang diagnostic ignored "-Wunused-const-variable"
+#elif defined(__GNUC__)
+# pragma GCC diagnostic ignored "-Wunused-const-variable"
+#endif
+
+
+#define MAKE_SYSCALL_WITHOUT_COMPAT(ARCH, NR, NAME, ACTUAL)\
+ static const struct libsyscalls_syscall linux_##ARCH##_syscall_##NAME = {\
+ .name = #NAME,\
+ .actual_syscall = &linux_syscall_##ACTUAL,\
+ .actual_compat_syscall = NULL\
+ }
+
+#define MAKE_SYSCALL_WITH_COMPAT(ARCH, NR, NAME, ACTUAL, COMPAT)\
+ static const struct libsyscalls_syscall linux_##ARCH##_syscall_##NAME = {\
+ .name = #NAME,\
+ .actual_syscall = &linux_syscall_##ACTUAL,\
+ .actual_compat_syscall = &linux_syscall_##COMPAT\
+ }
+
+
+#define X(ARCH)\
+ LIST_LINUX_SYSCALLS_FOR_##ARCH(MAKE_##ARCH##_SYSCALL_WITHOUT_COMPAT, MAKE_##ARCH##_SYSCALL_WITH_COMPAT, ;)
+LIST_LINUX_ARCHES(X, ;);
+#undef X
+
+#ifndef CREATING_DEDUP_TABLE
+# include "../generated/linux-syscall-dedup.h"
+#endif
+
+#define MAKE_SYSCALL_TABLE_ENTRY(ARCH, NR, NAME, ...)\
+ [NR] = &linux_##ARCH##_syscall_##NAME
+
+#define X(ARCH)\
+ static const struct libsyscalls_syscall *const linux_##ARCH##_syscalls_table[] = {\
+ LIST_LINUX_SYSCALLS_FOR_##ARCH(MAKE_##ARCH##_SYSCALL_TABLE_ENTRY, MAKE_##ARCH##_SYSCALL_TABLE_ENTRY, COMMA)\
+ }
+LIST_LINUX_ARCHES(X, ;);
+#undef X
+
+
+const struct libsyscalls_syscall *const *const libsyscalls_linux_syscalls_table_[] = {
+#define X(ARCH) [LIBSYSCALLS_ARCH_##ARCH] = linux_##ARCH##_syscalls_table
+ LIST_LINUX_ARCHES(X, COMMA)
+#undef X
+};
diff --git a/linux/syscall-table.mk b/linux/syscall-table.mk
new file mode 100644
index 0000000..3f0d944
--- /dev/null
+++ b/linux/syscall-table.mk
@@ -0,0 +1,60 @@
+OBJ += linux/syscall-table.o
+
+
+linux/syscall-table.o: generated/linux-syscall-table.h linux/syscalls.h $(LINUX_SYSCALLS_HDR) generated/linux-syscall-dedup.h
+linux/syscall-table.lo: generated/linux-syscall-table.h linux/syscalls.h $(LINUX_SYSCALLS_HDR) generated/linux-syscall-dedup.h
+
+libsyscalls_get_syscall_range.o: $(LINUX_SYSCALLS_HDR)
+libsyscalls_get_syscall_range.lo: $(LINUX_SYSCALLS_HDR)
+
+
+generated/linux-syscall-table.h: linux/syscall-table.c common.h linux/linux-support.mk
+ set -e; \
+ macros="$$(sed -n 's/^\s*\x23\s*define\s\+MAKE_\([^(]*\)(.*$$/\1/p' < linux/syscall-table.c)"; \
+ for arch in $(SUPPORTED_LINUX_ARCHES); do \
+ for macro in $$macros; do \
+ printf '\43define MAKE_%s_%s(...) MAKE_%s(%s, __VA_ARGS__)\n' \
+ "$$arch" "$$macro" "$$macro" "$$arch"; \
+ done; \
+ done > $@
+
+
+generated/linux-syscalls.h: linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43include "%s"\n' $(LINUX_SYSCALLS_HDR) \
+ | grep -v '"$@"' \
+ | sed 's:generated/::' > $@
+
+
+generated/linux-syscall-ranges.h: $(LINUX_SYSCALLS_ARCH_HDR)
+ printf '%s\n' 'This may take some time ...'; \
+ set -e; arch=; \
+ cat -- $(LINUX_SYSCALLS_ARCH_HDR) \
+ | sed 's/^\s*X[A-Z_]*(\([^,]*\).*$$/\1/' \
+ | sed 's/\x23\s*define\s\+LIST_LINUX_SYSCALLS_FOR_\(.*\)(.*/\1/' \
+ | sed '/^\s*$$/d' \
+ | (\
+ while read line; do \
+ if test -z "$$(printf '%s\n' "$$line" | sed 's/^[A-Z].*$$//')"; then \
+ if test -n "$$arch"; then \
+ printf '\43define %s_LINUX_SYSCALL_FOR_%s %i\n' \
+ MIN "$$arch" "$$min" \
+ MAX "$$arch" "$$max"; \
+ fi; \
+ arch="$$line"; \
+ min=; \
+ max=; \
+ else \
+ val=$$(( $$line )); \
+ if test -z "$$min" || test "$$val" -lt "$$min"; then \
+ min=$$val; \
+ fi; \
+ if test -z "$$max" || test "$$val" -gt "$$max"; then \
+ max=$$val; \
+ fi; \
+ fi; \
+ done; \
+ printf '\43define %s_LINUX_SYSCALL_FOR_%s %i\n' \
+ MIN "$$arch" "$$min" \
+ MAX "$$arch" "$$max"; \
+ ) > $@
diff --git a/linux/syscalls.h b/linux/syscalls.h
new file mode 100644
index 0000000..94d714e
--- /dev/null
+++ b/linux/syscalls.h
@@ -0,0 +1,988 @@
+/* See LICENSE file for copyright and license details. */
+
+/* This file is included from syscall-table.c or symbols.c */
+
+
+#define LINUX_MODE_BUFFER_SIZE sizeof("07777 (rwsrwsrwt)")
+#define LINUX_UMASK_BUFFER_SIZE sizeof("0777 (u::rwx,g::rwx,o::rwx)")
+#define LINUX_DEV_BUFFER_SIZE sizeof("18446744073709551615 (4294967295:4294967295)")
+#define LINUX_CLOCKID_T_BUFFER_SIZE (sizeof("- (~*8 + 7)") + 2 * 3 * sizeof(long long int))
+
+#define LINUX_REQUIRE_SYMBOL_BUFFER(PRINTER)\
+ ((PRINTER) == LINUX_SYMBOL_PRINTER_ATFD_MODE ? LINUX_MODE_BUFFER_SIZE :\
+ (PRINTER) == LINUX_SYMBOL_PRINTER_MODE ? LINUX_MODE_BUFFER_SIZE :\
+ (PRINTER) == LINUX_SYMBOL_PRINTER_UMASK ? LINUX_UMASK_BUFFER_SIZE :\
+ (PRINTER) == LINUX_SYMBOL_PRINTER_DEV ? LINUX_DEV_BUFFER_SIZE :\
+ (PRINTER) == LINUX_SYMBOL_PRINTER_CLOCKID ? LINUX_CLOCKID_T_BUFFER_SIZE : 0)
+
+enum { /* LIBSYSCALLS_SYMBOL_PRINTER */
+ NO_LINUX_SYMBOL_PRINTER = 0,
+
+ /* The comments after the enum constnts are used by linux/symbols.mk, do not break them */
+
+ LINUX_SYMBOL_PRINTER_CLOCKID, /* clockid_t,enum $$$ getdefs CLOCK < include/uapi/linux/time.h $$$ */
+ LINUX_SYMBOL_PRINTER_MODE, /* mode_t (e.g. "0666 (rw-rw-rw-)") */
+ LINUX_SYMBOL_PRINTER_UMASK, /* mode_t (e.g. "022 (u::rwx,g::r-x,o::r-x)") */
+ LINUX_SYMBOL_PRINTER_DEV, /* int (major:minor) */
+ LINUX_SYMBOL_PRINTER_SIGNAL,
+
+ LINUX_SYMBOL_PRINTER_2ATFD, /* $$ SYMBOLS(ATFD, ATFD) $$ */
+ LINUX_SYMBOL_PRINTER_ATFD_MODE, /* $$ SYMBOLS(ATFD, MODE) $$ */
+ LINUX_SYMBOL_PRINTER_FACCESSAT, /* $$ SYMBOLS(ATFD, ACCESS_OK) $$ */
+ LINUX_SYMBOL_PRINTER_FANOTIFY_MARK, /* $$ SYMBOLS(FAN_MARK, FAN) $$ */
+ LINUX_SYMBOL_PRINTER_3STATX, /* $$ SYMBOLS(ATFD, AT_STATX, STATX) $$ */
+
+ LINUX_SYMBOL_PRINTER_ITIMER, /* enum $$$ getdefs ITIMER < include/uapi/linux/time.h $$$ */
+ LINUX_SYMBOL_PRINTER_SEEK, /* enum $$$ getdefs SEEK < include/uapi/linux/fs.h $$$ */
+ LINUX_SYMBOL_PRINTER_EPOLL_CTL, /* enum $$$ getdefs EPOLL_CTL < include/uapi/linux/eventpoll.h $$$ */
+ LINUX_SYMBOL_PRINTER_SCHEDULER, /* enum $$$ grep -v '0x' < include/uapi/linux/sched.h | getdefs SCHED | grep -v '^SCHED_FLAG_' $$$ */
+ LINUX_SYMBOL_PRINTER_SHUT, /* enum $$$ getenum sock_shutdown_cmd < include/linux/net.h $$$ */
+ LINUX_SYMBOL_PRINTER_FADVISE, /* enum $$$ getdefs FADV POSIX_FADV < include/uapi/linux/fadvise.h $$$ */
+ LINUX_SYMBOL_PRINTER_ADJTIMEX, /* enum $$$ getdefs TIME < include/uapi/linux/timex.h $$$ */
+ LINUX_SYMBOL_PRINTER_IPC_KEY, /* enum $$$ grep IPC_PRIVATE < include/uapi/linux/ipc.h | sed 's/(\s*\(__kernel_\)\?key_t\s*)//g' | getdefs IPC $$$ */
+ LINUX_SYMBOL_PRINTER_ATFD, /* enum $$$ getdefs AT < tools/include/uapi/linux/fcntl.h | grep '^AT_FDCWD ' $$$ */
+ LINUX_SYMBOL_PRINTER_MSGCTL, /* IPCCTL,enum $$$ sed '1,/ctl commands/d;/ctl commands/d;/^\//q' < include/uapi/linux/msg.h | getdefs MSG $$$ */
+ LINUX_SYMBOL_PRINTER_SHMCTL, /* IPCCTL,enum $$$ sed '1,/ctl commands/d;/ctl commands/d;/^\//q' < include/uapi/linux/shm.h | getdefs SHM $$$ */
+ LINUX_SYMBOL_PRINTER_SEMCTL, /* IPCCTL,IPCCTL_SEM,enum $$$ sed '1,/[cC]ommand [dD]efinitions/d;/^\//q' < include/uapi/linux/sem.h | getdefs $$$ */
+ LINUX_SYMBOL_PRINTER_NOFLAGS, /* mask $$$ true $$$ */
+ LINUX_SYMBOL_PRINTER_ACCESS_OK, /* mask $$$ printf '%s_OK %i\n' X 1 W 2 R 4 F 0 $$$ */
+ LINUX_SYMBOL_PRINTER_SPLICE_F, /* mask $$$ getdefs SPLICE < include/linux/splice.h $$$ */
+ LINUX_SYMBOL_PRINTER_XATTR, /* mask $$$ getdefs XATTR < include/uapi/linux/xattr.h $$$ */
+ LINUX_SYMBOL_PRINTER_SYNC_FILE_RANGE, /* mask $$$ getdefs SYNC_FILE_RANGE < include/uapi/linux/fs.h $$$ */
+ LINUX_SYMBOL_PRINTER_RENAME, /* mask $$$ getdefs RENAME < include/uapi/linux/fs.h $$$ */
+ LINUX_SYMBOL_PRINTER_GRND, /* mask $$$ getdefs GRND < include/uapi/linux/random.h $$$ */
+ LINUX_SYMBOL_PRINTER_CLOSE_RANGE, /* mask $$$ getdefs CLOSE_RANGE < include/uapi/linux/close_range.h $$$ */
+ LINUX_SYMBOL_PRINTER_FSOPEN, /* mask $$$ getdefs FSOPEN < include/uapi/linux/mount.h $$$ */
+ LINUX_SYMBOL_PRINTER_LOCK, /* mask $$$ getdefs LOCK < include/uapi/asm-generic/fcntl.h | grep -v '^LOCK_RW '; ! cat arch'/'*\/include/uapi/asm/fcntl.h | grep \\sLOCK_ > /dev/null $$$ */
+ LINUX_SYMBOL_PRINTER_RWF, /* mask $$$ sed 's/(\s*__force\s\+__kernel_rwf_t\s*)//' < include/uapi/linux/fs.h | getdefs RWF $$$ */
+ LINUX_SYMBOL_PRINTER_STATX, /* mask $$$ getdefs STATX < include/uapi/linux/stat.h | grep -v '^STATX_\(BASIC_STATS \|ALL \|ATTR_\)' $$$ */
+ LINUX_SYMBOL_PRINTER_FALLOC, /* mask $$$ getdefs FALLOC_FL < include/uapi/linux/falloc.h $$$ */
+ LINUX_SYMBOL_PRINTER_AT, /* mask $$$ grep '\(AT_EMPTY_PATH\|AT_SYMLINK_NOFOLLOW\)' < include/uapi/linux/fcntl.h | getdefs AT $$$ */
+ LINUX_SYMBOL_PRINTER_TIMER, /* mask $$$ getdefs TIMER < include/uapi/linux/time.h $$$ */
+ LINUX_SYMBOL_PRINTER_UMOUNT, /* mask $$$ getdefs MNT UMOUNT < include/linux/fs.h $$$ */
+ LINUX_SYMBOL_PRINTER_RECV, /* mask $$$ grep -v 'sendpage()' < include/linux/socket.h | getdefs MSG | grep -v MSG_'\(WAITFORONE\|BATCH\|TRYHARD\)' | grep -v ' 0$' $$$ */ /* TODO MSG_TRYHARD should be used instead of MSG_DONTROUT for DECnet */
+ LINUX_SYMBOL_PRINTER_IPC_NOWAIT, /* mask $$$ grep IPC_NOWAIT < include/uapi/linux/ipc.h | getdefs IPC $$$ */
+ LINUX_SYMBOL_PRINTER_IPCGET, /* mask $$$ grep '\(IPC_CREAT\|IPC_EXCL\)' < include/uapi/linux/ipc.h | getdefs IPC $$$ */
+ LINUX_SYMBOL_PRINTER_UNLINK, /* mask $$$ getdefs AT < tools/include/uapi/linux/fcntl.h | grep '^AT_REMOVEDIR ' $$$ */
+ LINUX_SYMBOL_PRINTER_SHM, /* mask $$$ sed '1,/shmat()/d;/^\//q' < include/uapi/linux/shm.h | getdefs SHM $$$ */
+ LINUX_SYMBOL_PRINTER_FACCESSAT2, /* AT|mask $$$ grep AT_EACCESS < include/uapi/linux/fcntl.h | getdefs AT $$$ */
+ LINUX_SYMBOL_PRINTER_AT_AUTOMOUNT, /* AT|mask $$$ grep AT_NO_AUTOMOUNT < include/uapi/linux/fcntl.h | getdefs AT $$$ */
+ LINUX_SYMBOL_PRINTER_AT_STATX, /* AT_AUTOMOUNT|mask $$$ getdefs AT_STATX < include/uapi/linux/fcntl.h | grep -v '^AT_STATX_SYNC_TYPE ' $$$ */
+ LINUX_SYMBOL_PRINTER_RECVM, /* RECV|mask $$$ getdefs MSG < include/linux/socket.h | grep '^MSG_WAITFORONE ' $$$ */
+ LINUX_SYMBOL_PRINTER_SENDM, /* SEND|mask $$$ getdefs MSG < include/linux/socket.h | grep '^MSG_BATCH ' $$$ */
+ LINUX_SYMBOL_PRINTER_MSGRCV, /* IPC_NOWAIT|mask $$$ grep '^.*\s0[0-9a-fA-FxulUL]*\s*\(/.*\)\?$' < include/uapi/linux/msg.h | getdefs MSG $$$ */
+ LINUX_SYMBOL_PRINTER_SCHEDULER_SET, /* SCHEDULER|mask $$$ grep '0x' < include/uapi/linux/sched.h | getdefs SCHED | grep -v '^SCHED_FLAG_' $$$ */
+
+ /* arch dependent (TODO -- don't forget to remove #define from top of symbols.c) */
+ LINUX_SYMBOL_PRINTER_MADVISE, /* MADV_{NORMAL, RANDOM, SEQUENTIAL, WILLNEED, DONTNEED, REMOVE, ...} */
+ LINUX_SYMBOL_PRINTER_MSYNC, /* MS_{ASYNC, SYNC}|MS_INVALIDATE */
+ LINUX_SYMBOL_PRINTER_MLOCK, /* MLOCK_ONFAULT, 0 */
+ LINUX_SYMBOL_PRINTER_MCL, /* MCL_CURRENT|MCL_FUTURE|MCL_ONFAULT */
+ LINUX_SYMBOL_PRINTER_EPOLL, /* EPOLL_CLOEXEC|0 */
+ LINUX_SYMBOL_PRINTER_SOCK_FD, /* SOCK_NONBLOCK|SOCK_CLOEXEC */
+ LINUX_SYMBOL_PRINTER_DUP3, /* O_CLOEXEC|0 */
+ LINUX_SYMBOL_PRINTER_PIPE, /* O_CLOEXEC|O_DIRECT|O_NONBLOCK|O_NOTIFICATION_PIPE */
+ LINUX_SYMBOL_PRINTER_INOTIFY_FD, /* IN_NONBLOCK|IN_CLOEXEC */
+ LINUX_SYMBOL_PRINTER_FAN_EVENT_F, /* O_{RDONLY, WRONLY, RDWR}|O_{LARGEFILE|CLOEXEC|APPEND|DSYNC|NOATIME|NONBLOCK|SYNC} */
+ LINUX_SYMBOL_PRINTER_MQ_OPEN, /* {O_RDONLY, O_WRONLY, O_RDWR}|O_CLOEXEC|O_CREAT|O_EXCL|O_NONBLOCK */
+
+ /* TODO -- don't forget to remove #define from top of symbols.c */
+ LINUX_SYMBOL_PRINTER_SWAPON, /* swapon(2) flags */
+ LINUX_SYMBOL_PRINTER_INOTIFY_MASK, /* inotify(7) */
+ LINUX_SYMBOL_PRINTER_SHMGET, /* IPCGET|mask $ SHM_HUGETLB|... */
+ LINUX_SYMBOL_PRINTER_FAN_CLASS, /* FAN_CLASS_{PRE_CONTENT, CONTENT, NOTIF}|FAN_{CLOEXEC|NONBLOCK|...} */
+ LINUX_SYMBOL_PRINTER_FAN_MARK, /* FAN_MARK_{{ADD, REMOVE, FLUSH}|DONT_FOLLOW|ONLYDIR|MOUNT|...} */
+ LINUX_SYMBOL_PRINTER_FAN, /* FAN_{ACCESS,MODIFY|CLOSE_WRITE|CLOSE_NOWRITE|OPEN|...} */
+ LINUX_SYMBOL_PRINTER_SOCKET, /* all three parameters of socket(2) */
+ LINUX_SYMBOL_PRINTER_REBOOT, /* all parameters of reboot(2), and used to infer whether the fourth argument is included */
+
+#define LINUX_SYMBOL_PRINTER_SEMGET LINUX_SYMBOL_PRINTER_IPCGET
+#define LINUX_SYMBOL_PRINTER_MSGGET LINUX_SYMBOL_PRINTER_IPCGET
+#define LINUX_SYMBOL_PRINTER_SEND LINUX_SYMBOL_PRINTER_RECV /* TODO */
+#define LINUX_SYMBOL_PRINTER_MSGSND LINUX_SYMBOL_PRINTER_IPC_NOWAIT
+
+ END_OF_LINUX_SYMBOL_PRINTERS
+
+#if 0 /* $$$ BEGIN PHONIES $$$ */ /* These are just for the implementation */
+ LINUX_SYMBOL_PRINTER_IPCCTL /* enum $$$ sed '/IPC_RMID/p;1,/IPC_RMID/d;/^\//q' < include/uapi/linux/ipc.h | getdefs IPC $$$ */
+ LINUX_SYMBOL_PRINTER_IPCCTL_SEM /* enum $$$ sed '1,/ctl \(commands\|cmds\)/d;/ctl \(commands\|cmds\)/d;/^\//q' < include/uapi/linux/sem.h | getdefs SEM $$$ */
+#endif /* $$$ END PHONIES $$$ */
+};
+
+_Static_assert(END_OF_LINUX_SYMBOL_PRINTERS <= 0xFF, "LINUX_SYMBOL_PRINTER enums"); /* We only have 16 bits, and SYMBOLS can back in two values */
+
+
+#ifndef SYMBOL_PRINTERS_ONLY
+
+
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wgnu-flexible-array-initializer"
+# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" /* TODO how does that make sense in C23? */
+#elif defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wpedantic"
+#endif
+
+#define SYS(...) SYSCALL_ABI(linux, __VA_ARGS__)
+
+#define SYMBOLS(A, ...) .symbol_printer = (LINUX_SYMBOL_PRINTER_##A __VA_OPT__(SYMBOLS_2(__VA_ARGS__)))
+#define SYMBOLS_2(A, ...) | (LINUX_SYMBOL_PRINTER_##A << 8) __VA_OPT__(SYMBOLS_3(__VA_ARGS__))
+
+
+#define linux_syscall_sys_exit linux_syscall_sys_exit_group
+#define linux_syscall_sys_fdatasync linux_syscall_sys_fsync
+#define linux_syscall_sys_syncfs linux_syscall_sys_fsync
+#define linux_syscall_sys_getpid linux_syscall_sys_gettid
+#define linux_syscall_sys_getpgrp linux_syscall_sys_gettid
+#define linux_syscall_sys_getgid linux_syscall_sys_getuid
+#define linux_syscall_sys_geteuid linux_syscall_sys_getuid
+#define linux_syscall_sys_getegid linux_syscall_sys_getuid
+#define linux_syscall_sys_geteuid16 linux_syscall_sys_getuid16
+#define linux_syscall_sys_getgid16 linux_syscall_sys_getuid16
+#define linux_syscall_sys_getegid16 linux_syscall_sys_getuid16
+#define linux_syscall_sys_setgid16 linux_syscall_sys_setuid16
+#define linux_syscall_sys_setfsuid16 linux_syscall_sys_setuid16
+#define linux_syscall_sys_setfsgid16 linux_syscall_sys_setuid16
+#define linux_syscall_sys_setregid16 linux_syscall_sys_setreuid16
+#define linux_syscall_sys_setresgid16 linux_syscall_sys_setresuid16
+#define linux_syscall_sys_getresgid16 linux_syscall_sys_getresuid16
+#define linux_syscall_sys_getxgid linux_syscall_sys_getxuid
+#define linux_syscall_sys_setfsgid linux_syscall_sys_setuid
+#define linux_syscall_sys_setgid linux_syscall_sys_setuid
+#define linux_syscall_sys_setregid linux_syscall_sys_setreuid
+#define linux_syscall_sys_setresgid linux_syscall_sys_setresuid
+#define linux_syscall_sys_getresgid linux_syscall_sys_getresuid
+#define linux_syscall_sys_getpgid linux_syscall_sys_getsid
+#define linux_syscall_sys_setfsuid linux_syscall_sys_setuid
+#define linux_syscall_sys_vfork linux_syscall_sys_fork
+#define linux_syscall_sys_symlink linux_syscall_sys_link
+#define linux_syscall_sys_rmdir linux_syscall_sys_unlink
+#define linux_syscall_sys_lsetxattr linux_syscall_sys_setxattr
+#define linux_syscall_sys_lgetxattr linux_syscall_sys_getxattr
+#define linux_syscall_sys_llistxattr linux_syscall_sys_listxattr
+#define linux_syscall_sys_lremovexattr linux_syscall_sys_removexattr
+#define linux_syscall_sys_lstat linux_syscall_sys_stat
+#define linux_syscall_sys_newlstat linux_syscall_sys_newstat
+#define linux_syscall_sys_lchown linux_syscall_sys_chown
+#define linux_syscall_sys_lchown16 linux_syscall_sys_chown16
+#define linux_syscall_sys_lstat64 linux_syscall_sys_stat64
+#define linux_syscall_sys_setdomainname linux_syscall_sys_sethostname
+#define linux_syscall_sys_old_shmctl linux_syscall_sys_shmctl
+#define linux_syscall_sys_old_semctl linux_syscall_sys_semctl
+#define linux_syscall_sys_old_msgctl linux_syscall_sys_msgctl
+#define linux_syscall_sys_sched_get_priority_max linux_syscall_sys_sched_get_priority_min
+#define linux_syscall_sys_tkill linux_syscall_sys_kill
+#define linux_syscall_alpha_clone linux_syscall_sys_clone
+#define linux_syscall_alpha_fork linux_syscall_sys_fork
+#define linux_syscall_alpha_vfork linux_syscall_sys_fork
+#define linux_syscall_sys_osf_brk linux_syscall_sys_brk
+#define linux_syscall_sys_ia64_pipe linux_syscall_sys_alpha_pipe
+#define linux_syscall_sys_sh_pipe linux_syscall_sys_alpha_pipe
+#define linux_syscall_compat_sys_sigreturn linux_syscall_sys_sigreturn
+#define linux_syscall_compat_sys_rt_sigreturn linux_syscall_sys_rt_sigreturn
+#define linux_syscall_compat_sys_x32_rt_sigreturn linux_syscall_sys_rt_sigreturn
+#define linux_syscall_compat_sys_arch_prctl linux_syscall_sys_arch_prctl
+
+SYS(sys_accept, NETWORK_ENABLED_IPC, ACCEPT, 3, INT_FD, PARAMS(_,INT_FD, OUT,STRUCT_SOCKADDR, OUT,UINT));
+SYS(sys_listen, NETWORK_ENABLED_IPC, LISTEN, 2, ZERO(INT), PARAMS(_,INT_FD, _,INT));
+SYS(sys_bind, NETWORK_ENABLED_IPC, BIND, 3, ZERO(INT), PARAMS(_,INT_FD, IN,STRUCT_SOCKADDR, _,INT));
+SYS(sys_connect, NETWORK_ENABLED_IPC, CONNECT, 3, ZERO(INT), PARAMS(_,INT_FD, IN,STRUCT_SOCKADDR, _,INT));
+SYS(sys_getsockname, NETWORK_ENABLED_IPC, STAT, 3, ZERO(INT), PARAMS(_,INT_FD, OUT,STRUCT_SOCKADDR, BI,INT));
+SYS(sys_getpeername, NETWORK_ENABLED_IPC, STAT, 3, ZERO(INT), PARAMS(_,INT_FD, OUT,STRUCT_SOCKADDR, BI,INT));
+SYS(sys_acct, LOGGING, PROCESSES, 1, ZERO(INT), PARAMS(_,STRING));
+SYS(sys_alarm, TIME, TIMER_RELATIVE, 1, UINT, PARAMS(_,UINT));
+SYS(sys_nanosleep, TIME, SLEEP_RELATIVE, 2, ZERO(INT), PARAMS(IN,STRUCT_TIMESPEC, OUT,STRUCT_TIMESPEC));
+SYS(sys_nanosleep_time32, TIME, SLEEP_RELATIVE, 2, ZERO(INT), PARAMS(IN,STRUCT_OLD_TIMESPEC32, OUT,STRUCT_OLD_TIMESPEC32));
+SYS(sys_close, FILE_DESCRIPTORS, DUP_OR_CLOSE, 1, ZERO(INT), PARAMS(_,INT_FD));
+SYS(sys_dup, FILE_DESCRIPTORS, DUP_OR_CLOSE, 1, INT, PARAMS(_,INT_FD));
+SYS(sys_dup2, FILE_DESCRIPTORS, DUP_OR_CLOSE, 2, INT, PARAMS(_,INT_FD, _,INT_FD));
+SYS(sys_exit, PROCESSES, EXIT, 1, ZERO(NO_RETURN), PARAMS(_,INT));
+SYS(sys_pause, SIGNALS, PAUSE, 0, ZERO(INT), PARAMS());
+SYS(sys_gettid, PROCESSES, STAT_SELF, 0, INT, PARAMS());
+SYS(sys_getppid, PROCESSES, STAT_PARENT, 0, INT, PARAMS());
+SYS(sys_getxpid, PROCESSES, STAT_PARENT, 0, 2_INTS, PARAMS());
+SYS(sys_getxuid, PROCESSES, STAT_SELF, 0, 2_UINT32S, PARAMS());
+SYS(sys_getuid, PROCESSES, STAT_SELF, 0, UINT32, PARAMS());
+SYS(sys_getuid16, PROCESSES, STAT_SELF, 0, USHORT, PARAMS());
+SYS(sys_getresuid, PROCESSES, STAT_SELF, 3, ZERO(INT), PARAMS(OUT,UINT32, OUT,UINT32, OUT,UINT32));
+SYS(sys_getresuid16, PROCESSES, STAT_SELF, 3, ZERO(INT), PARAMS(OUT,USHORT, OUT,USHORT, OUT,USHORT));
+SYS(sys_getsid, PROCESSES, STAT_SELF, 1, INT, PARAMS(_,INT));
+SYS(sys_setresuid, PROCESSES, CHANGE_PERMISSIONS, 3, ZERO(INT), PARAMS(_,UINT32, _,UINT32, _,UINT32));
+SYS(sys_setresuid16, PROCESSES, CHANGE_PERMISSIONS, 3, ZERO(INT), PARAMS(_,USHORT, _,USHORT, _,USHORT));
+SYS(sys_setreuid, PROCESSES, CHANGE_PERMISSIONS, 2, ZERO(INT), PARAMS(_,UINT32, _,UINT32));
+SYS(sys_setreuid16, PROCESSES, CHANGE_PERMISSIONS, 2, ZERO(INT), PARAMS(_,USHORT, _,USHORT));
+SYS(sys_setuid, PROCESSES, CHANGE_PERMISSIONS, 1, INT, PARAMS(_,UINT32));
+SYS(sys_setuid16, PROCESSES, CHANGE_PERMISSIONS, 1, ZERO(INT), PARAMS(_,USHORT));
+SYS(sys_sync, FILESYSTEM, SYNC, 0, ZERO(INT), PARAMS());
+SYS(sys_fsync, FILESYSTEM, SYNC, 1, ZERO(INT), PARAMS(_,INT_FD));
+SYS(sys_fork, PROCESSES, CLONE, 0, INT, PARAMS());
+SYS(sys_link, FILESYSTEM, LINK, 2, ZERO(INT), PARAMS(_,STRING, _,STRING));
+SYS(sys_unlink, FILESYSTEM, UNLINK, 1, ZERO(INT), PARAMS(_,STRING));
+SYS(sys_rename, FILESYSTEM, LINK_OR_UNLINK, 2, ZERO(INT), PARAMS(_,STRING, _,STRING));
+SYS(sys_read, FILE_DESCRIPTORS, READ, 3, SSIZE, PARAMS(_,INT_FD, OUT,BUFFER, _,SIZE));
+SYS(sys_write, FILE_DESCRIPTORS, WRITE, 3, SSIZE, PARAMS(_,INT_FD, IN,BUFFER, _,SIZE));
+SYS(sys_sendfile, FILE_DESCRIPTORS, READ_OR_PEEK_AND_WRITE, 4, SSIZE, PARAMS(_,INT_FD, _,INT_FD, BI,LONG, _,SIZE));
+SYS(sys_sendfile64, FILE_DESCRIPTORS, READ_OR_PEEK_AND_WRITE, 4, SSIZE, PARAMS(_,INT_FD, _,INT_FD, BI,LLONG, _,SIZE));
+SYS(sys_getxattr, FILESYSTEM, STAT, 4, SSIZE, PARAMS(_,STRING, _,STRING, OUT,BUFFER, _,SIZE));
+SYS(sys_fgetxattr, FILE_DESCRIPTORS, STAT, 4, SSIZE, PARAMS(_,INT_FD, _,STRING, OUT,BUFFER, _,SIZE));
+SYS(sys_listxattr, FILESYSTEM, STAT, 3, SSIZE, PARAMS(_,STRING, OUT,BUFFER, _,SIZE));
+SYS(sys_flistxattr, FILE_DESCRIPTORS, STAT, 3, SSIZE, PARAMS(,INT_FD, OUT,BUFFER, _,SIZE));
+SYS(sys_removexattr, FILESYSTEM, MODIFY, 2, ZERO(INT), PARAMS(_,STRING, _,STRING));
+SYS(sys_fremovexattr, FILE_DESCRIPTORS, MODIFY, 2, ZERO(INT), PARAMS(_,INT_FD, _,STRING));
+SYS(sys_chdir, PROCESSES, CHDIR, 1, ZERO(INT), PARAMS(_,STRING));
+SYS(sys_fchdir, PROCESSES, CHDIR, 1, ZERO(INT), PARAMS(_,INT_FD));
+SYS(sys_chroot, PROCESSES, CHROOT, 1, ZERO(INT), PARAMS(_,STRING));
+SYS(sys_pivot_root, PROCESSES, CHROOT, 2, ZERO(INT), PARAMS(_,STRING, _,STRING));
+SYS(sys_getcwd, PROCESSES, STAT_SELF, 2, LONG, PARAMS(OUT,BUFFER, _,ULONG));
+SYS(sys_readahead, FILE_DESCRIPTORS, ADVISE, 3, ZERO(INT), PARAMS(_,INT_FD, _,LLONG, _,SIZE));
+SYS(sys_chown, FILESYSTEM, MODIFY, 3, ZERO(INT), PARAMS(_,STRING, _,UINT32, _,UINT32));
+SYS(sys_chown16, FILESYSTEM, MODIFY, 3, ZERO(INT), PARAMS(_,STRING, _,USHORT, _,USHORT));
+SYS(sys_fchown, FILE_DESCRIPTORS, MODIFY, 3, ZERO(INT), PARAMS(_,INT_FD, _,UINT32, _,UINT32));
+SYS(sys_fchown16, FILE_DESCRIPTORS, MODIFY, 3, ZERO(INT), PARAMS(_,INT_FD, _,USHORT, _,USHORT));
+SYS(sys_truncate, FILESYSTEM, WRITE, 2, ZERO(INT), PARAMS(_,STRING, _,LONG));
+SYS(compat_sys_truncate, FILESYSTEM, WRITE, 2, ZERO(INT), PARAMS(_,STRING, _,INT32));
+SYS(sys_truncate64, FILESYSTEM, WRITE, 2, ZERO(INT), PARAMS(_,STRING, _,LLONG));
+SYS(sparc___compat_sys_truncate64, FILESYSTEM, WRITE, 3, ZERO(INT), PARAMS(_,STRING, _,UINT64_HIGH_32, _,UINT64_LOW_32));
+SYS(sys_ftruncate, FILE_DESCRIPTORS, WRITE, 2, ZERO(INT), PARAMS(_,INT_FD, _,ULONG));
+SYS(compat_sys_ftruncate, FILE_DESCRIPTORS, WRITE, 2, ZERO(INT), PARAMS(_,INT_FD, _,UINT32));
+SYS(sys_ftruncate64, FILE_DESCRIPTORS, WRITE, 2, ZERO(INT), PARAMS(_,INT_FD, _,LLONG));
+SYS(sparc___compat_sys_ftruncate64, FILE_DESCRIPTORS, WRITE, 3, ZERO(INT), PARAMS(_,INT_FD, _,UINT64_HIGH_32, _,UINT64_LOW_32));
+SYS(sys_brk, MEMORY, ALLOCATE, 1, MEMORY_ADDRESS, PARAMS(_,MEMORY_ADDRESS));
+SYS(sys_swapoff, SYSTEM, SWAP, 1, ZERO(INT), PARAMS(_,STRING));
+SYS(sys_oldumount, FILESYSTEM, MOUNTPOINT, 1, ZERO(INT), PARAMS(_,STRING));
+SYS(sys_execve, PROCESSES, EXEC, 3, ZERO(INT), PARAMS(_,STRING, _,STRINGS_THEN_NULL, _,STRINGS_THEN_NULL));
+SYS(sys_newstat, FILESYSTEM, STAT, 2, ZERO(INT), PARAMS(_,STRING, OUT,STRUCT_STAT));
+SYS(sys_stat64, FILESYSTEM, STAT, 2, ZERO(INT), PARAMS(_,STRING, OUT,STRUCT_STAT64));
+SYS(sys_stat, FILESYSTEM, STAT, 2, ZERO(INT), PARAMS(_,STRING, OUT,STRUCT_OLD_STAT));
+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_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));
+SYS(sys_mlock, MEMORY, LOCK, 2, ZERO(INT), PARAMS(_,MEMORY_ADDRESS, _,SIZE));
+SYS(sys_epoll_create, FILE_DESCRIPTORS, CREATE_POLL, 1, INT_FD, PARAMS(_,INT));
+SYS(sys_pread64, FILE_DESCRIPTORS, PEEK, 4, SSIZE, PARAMS(_,INT_FD, OUT,BUFFER, _,SIZE, _,LLONG));
+SYS(sys_pwrite64, FILE_DESCRIPTORS, WRITE, 4, SSIZE, PARAMS(_,INT_FD, INT,BUFFER, _,SIZE, _,LLONG));
+SYS(sys_gethostname, SYSTEM, GET_NAME, 2, ZERO(INT), PARAMS(OUT,BUFFER, _,INT));
+SYS(sys_olduname, SYSTEM, GET_NAME, 1, ZERO(INT), PARAMS(OUT,STRUCT_OLDOLD_UTSNAME));
+SYS(sys_uname, SYSTEM, GET_NAME, 1, ZERO(INT), PARAMS(OUT,STRUCT_OLD_UTSNAME));
+SYS(sys_newuname, SYSTEM, GET_NAME, 1, ZERO(INT), PARAMS(OUT,STRUCT_NEW_UTSNAME));
+SYS(sys_sethostname, SYSTEM, SET_NAME, 2, ZERO(INT), PARAMS(IN,BUFFER, _,INT));
+SYS(sys_sysinfo, SYSTEM, STAT, 1, ZERO(INT), PARAMS(OUT,STRUCT_SYSINFO));
+SYS(sys_shmdt, IPC, DETACH, 1, ZERO(INT), PARAMS(_,MEMORY_ADDRESS));
+SYS(sys_mq_unlink, IPC, CONTROL, 1, ZERO(INT), PARAMS(_,STRING));
+SYS(sys_mq_notify, IPC, CONTROL, 2, ZERO(INT), PARAMS(_,INT_FD, IN,STRUCT_SIGEVENT));
+SYS(sys_mq_getsetattr, IPC, CONTROL, 3, ZERO(INT), PARAMS(_,INT_FD, IN,STRUCT_MQ_ATTR, OUT,STRUCT_MQ_ATTR));
+SYS(sys_mq_timedsend, IPC, COMMUNICATE_WITH_ABSOLUTE_TIMEOUT, 5, ZERO(INT), PARAMS(_,INT_FD, _,BUFFER, _,SIZE, _,UINT, IN,STRUCT_TIMESPEC));
+SYS(sys_mq_timedsend_time32, IPC, COMMUNICATE_WITH_ABSOLUTE_TIMEOUT, 5, ZERO(INT), PARAMS(_,INT_FD, _,BUFFER, _,UINT, _,UINT, IN,STRUCT_OLD_TIMESPEC32));
+SYS(sys_mq_timedreceive, IPC, COMMUNICATE_WITH_ABSOLUTE_TIMEOUT, 5, SSIZE, PARAMS(_,INT_FD, OUT,BUFFER, _,SIZE, OUT,UINT, IN,STRUCT_TIMESPEC));
+SYS(sys_mq_timedreceive_time32, IPC, COMMUNICATE_WITH_ABSOLUTE_TIMEOUT, 5, SSIZE, PARAMS(_,INT_FD, OUT,BUFFER, _,UINT, OUT,UINT, IN,STRUCT_OLD_TIMESPEC32));
+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_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));
+SYS(sys_sched_rr_get_interval_time32, SCHEDULING, GET, 2, ZERO(INT), PARAMS(_,INT, OUT,STRUCT_OLD_TIMESPEC32));
+SYS(sys_inotify_init, FILESYSTEM, MONITOR, 0, INT_FD, PARAMS());
+SYS(sys_inotify_rm_watch, FILESYSTEM, MONITOR, 2, ZERO(INT), PARAMS(_,INT_FD, _,INT32));
+SYS(sys_getpagesize, SYSTEM, FUNDAMENTAL, 0, INT, PARAMS());
+SYS(sys_kill, SIGNALS, KILL, 2, ZERO(INT), PARAMS(_,INT, SYM,INT_SIGNAL), SYMBOLS(SIGNAL));
+SYS(sys_tgkill, SIGNALS, KILL, 3, ZERO(INT), PARAMS(_,INT, _,INT, SYM,INT_SIGNAL), SYMBOLS(SIGNAL));
+SYS(sys_symlinkat, FILESYSTEM, LINK, 3, ZERO(INT), PARAMS(_,STRING, SYM,INT_ATFD, _,STRING), SYMBOLS(ATFD));
+SYS(sys_renameat, FILESYSTEM, LINK_OR_UNLINK, 4, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, SYM,INT_ATFD, _,STRING), SYMBOLS(ATFD, ATFD));
+SYS(sys_readlinkat, FILESYSTEM, READLINK, 4, INT, PARAMS(SYM,INT_ATFD, _,STRING, OUT,BUFFER, _,INT), SYMBOLS(ATFD));
+SYS(sys_clock_getres, TIME, INTROSPECT, 2, ZERO(INT), PARAMS(SYM,INT, OUT,STRUCT_TIMESPEC), SYMBOLS(CLOCKID));
+SYS(sys_clock_getres_time32, TIME, INTROSPECT, 2, ZERO(INT), PARAMS(SYM,INT, OUT,STRUCT_OLD_TIMESPEC32), SYMBOLS(CLOCKID));
+SYS(sys_clock_gettime, TIME, GET, 2, ZERO(INT), PARAMS(SYM,INT, OUT,STRUCT_TIMESPEC), SYMBOLS(CLOCKID));
+SYS(sys_clock_gettime32, TIME, GET, 2, ZERO(INT), PARAMS(SYM,INT, OUT,STRUCT_OLD_TIMESPEC32), SYMBOLS(CLOCKID));
+SYS(sys_clock_settime, TIME, SET, 2, ZERO(INT), PARAMS(SYM,INT, IN,STRUCT_TIMESPEC), SYMBOLS(CLOCKID));
+SYS(sys_clock_settime32, TIME, SET, 2, ZERO(INT), PARAMS(SYM,INT, IN,STRUCT_OLD_TIMESPEC32), SYMBOLS(CLOCKID));
+SYS(sys_shutdown, FILE_DESCRIPTORS, DUP_OR_CLOSE, 2, ZERO(INT), PARAMS(_,INT_FD, SYM,UINT), SYMBOLS(SHUT));
+SYS(sys_close_range, FILE_DESCRIPTORS, CLOSE_OR_UNSHARE, 3, ZERO(INT), PARAMS(_,UINT, _,UINT, SYM,UINT), SYMBOLS(CLOSE_RANGE));
+SYS(sys_send, FILE_DESCRIPTORS, WRITE, 4, SSIZE, PARAMS(_,INT_FD, IN,BUFFER, _,SIZE, SYM,UINT), SYMBOLS(SEND));
+SYS(sys_sendto, FILE_DESCRIPTORS, WRITE, 6, SSIZE, PARAMS(_,INT_FD, IN,BUFFER, _,SIZE, SYM,UINT, IN,STRUCT_SOCKADDR, _,INT), SYMBOLS(SEND));
+SYS(sys_sendmsg, FILE_DESCRIPTORS, WRITE, 3, SSIZE, PARAMS(_,INT_FD, IN,STRUCT_MSGHDR, SYM,UINT), SYMBOLS(SEND));
+SYS(sys_sendmmsg, FILE_DESCRIPTORS, WRITE, 4, INT, PARAMS(_,INT_FD, BI,STRUCT_MMSGHDR, _,UINT, SYM,UINT), SYMBOLS(SENDM));
+SYS(sys_lseek, FILE_DESCRIPTORS, SEEK, 3, LONG, PARAMS(_,INT_FD, _,LONG, SYM,UINT), SYMBOLS(SEEK));
+SYS(sys_llseek, FILE_DESCRIPTORS, SEEK, 5, INT, PARAMS(_,INT_FD, _,INT64_HIGH_32, _,INT64_LOW_32, OUT,LLONG, SYM,UINT), SYMBOLS(SEEK));
+SYS(sys_sched_getscheduler, SCHEDULING, GET, 1, INT, PARAMS(_,INT), SYMBOLS(SCHEDULER));
+SYS(sys_sched_getattr, SCHEDULING, GET, 4, ZERO(INT), PARAMS(_,INT, OUT,STRUCT_SCHED_ATTR, _,UINT, SYM,UINT), SYMBOLS(NOFLAGS));
+SYS(sys_sched_setattr, SCHEDULING, SET, 3, INT, PARAMS(_,INT, IN,STRUCT_SCHED_ATTR, SYM,UINT), SYMBOLS(NOFLAGS));
+SYS(sys_recv, FILE_DESCRIPTORS, READ_OR_PEEK, 4, SSIZE, PARAMS(_,INT_FD, OUT,BUFFER, _,SIZE, SYM,UINT), SYMBOLS(RECV));
+SYS(sys_recvfrom, FILE_DESCRIPTORS, READ_OR_PEEK_AND_STAT, 6, SSIZE, PARAMS(_,INT_FD, OUT,BUFFER, _,SIZE, SYM,UINT, OUT,STRUCT_SOCKADDR, BI,INT), SYMBOLS(RECV));
+SYS(sys_recvmsg, FILE_DESCRIPTORS, READ_OR_PEEK_AND_STAT, 3, SSIZE, PARAMS(_,INT_FD, BI,STRUCT_MSGHDR, SYM,UINT), SYMBOLS(RECV));
+SYS(sys_recvmmsg, FILE_DESCRIPTORS, READ_OR_PEEK_AND_STAT, 5, INT, PARAMS(_,INT_FD, BI,STRUCT_MMSGHDR, _,UINT, SYM,UINT, BI,STRUCT_TIMESPEC), SYMBOLS(RECVM));
+SYS(sys_recvmmsg_time32, FILE_DESCRIPTORS, READ_OR_PEEK_AND_STAT, 5, INT, PARAMS(_,INT_FD, BI,STRUCT_MMSGHDR, _,UINT, SYM,UINT, BI,STRUCT_OLD_TIMESPEC32), SYMBOLS(RECVM));
+SYS(sys_splice, FILE_DESCRIPTORS, READ_OR_PEEK_AND_WRITE, 6, SSIZE, PARAMS(_,INT_FD, BI,LLONG, _,INT_FD, BI,LLONG, _,SIZE, SYM,UINT), SYMBOLS(SPLICE_F));
+SYS(sys_tee, FILE_DESCRIPTORS, PEEK_AND_WRITE, 4, SSIZE, PARAMS(_,INT_FD, _,INT_FD, _,SIZE, SYM,UINT), SYMBOLS(SPLICE_F));
+SYS(sys_setxattr, FILESYSTEM, MODIFY, 5, ZERO(INT), PARAMS(_,STRING, _,STRING, IN,BUFFER, _,SIZE, SYM,UINT), SYMBOLS(XATTR));
+SYS(sys_fsetxattr, FILE_DESCRIPTORS, MODIFY, 5, ZERO(INT), PARAMS(_,INT_FD, _,STRING, IN,BUFFER, _,SIZE, SYM,UINT), SYMBOLS(XATTR));
+SYS(sys_fadvise64, FILE_DESCRIPTORS, ADVISE, 4, ZERO(INT), PARAMS(_,INT_FD, _,LLONG, _,SIZE, SYM,INT), SYMBOLS(FADVISE));
+SYS(sys_fadvise64_64, FILE_DESCRIPTORS, ADVISE, 4, ZERO(INT), PARAMS(_,INT_FD, _,LLONG, _,LLONG, SYM,INT), SYMBOLS(FADVISE));
+SYS(sys_sched_get_priority_min, SCHEDULING, INTROSPECT, 1, INT, PARAMS(SYM,INT), SYMBOLS(SCHEDULER));
+SYS(sys_sched_setscheduler, SCHEDULING, SET, 3, ZERO(INT), PARAMS(_,INT, SYM,INT, OUT,STRUCT_SCHED_PARAM), SYMBOLS(SCHEDULER_SET));
+SYS(sys_adjtimex, TIME, GET_OR_SET, 1, SYMB(INT), PARAMS(BI,STRUCT_TIMEX), SYMBOLS(ADJTIMEX));
+SYS(sys_adjtimex_time32, TIME, GET_OR_SET, 1, SYMB(INT), PARAMS(BI,STRUCT_OLD_TIMEX32), SYMBOLS(ADJTIMEX));
+SYS(sys_access, FILESYSTEM, STAT, 2, ZERO(INT), PARAMS(_,STRING, SYM,UINT), SYMBOLS(ACCESS_OK));
+SYS(sys_faccessat, FILESYSTEM, STAT, 3, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, SYM,UINT), SYMBOLS(ATFD, ACCESS_OK));
+SYS(sys_clock_adjtime, TIME, GET_OR_SET, 2, SYMB(INT), PARAMS(SYMB,INT, BI,STRUCT_TIMEX), SYMBOLS(ADJTIMEX, CLOCKID));
+SYS(sys_clock_adjtime32, TIME, GET_OR_SET, 2, INT, PARAMS(SYM,INT, BI,STRUCT_OLD_TIMEX32), SYMBOLS(ADJTIMEX, CLOCKID));
+SYS(sys_getitimer, TIME, TIMER_RELATIVE_READ, 2, ZERO(INT), PARAMS(SYM,INT, OUT,STRUCT_OLD_ITIMERVAL), SYMBOLS(ITIMER));
+SYS(sys_setitimer, TIME, TIMER_RELATIVE_WITH_READ, 3, ZERO(INT), PARAMS(SYM,INT, INT,STRUCT_OLD_ITIMERVAL, OUT,STRUCT_OLD_ITIMERVAL), SYMBOLS(ITIMER));
+SYS(sys_umount, FILESYSTEM, MOUNTPOINT, 2, ZERO(INT), PARAMS(_,STRING, SYM,UINT), SYMBOLS(UMOUNT));
+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_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));
+SYS(sys_dup3, FILE_DESCRIPTORS, DUP_OR_CLOSE, 3, INT, PARAMS(_,INT_FD, _,INT_FD, SYM,UINT), SYMBOLS(DUP3));
+SYS(sys_sync_file_range, FILESYSTEM, SYNC, 4, ZERO(INT), PARAMS(_,INT_FD, _,LLONG, _,LLONG, SYM,UINT), SYMBOLS(SYNC_FILE_RANGE));
+SYS(sys_sync_file_range2, FILESYSTEM, SYNC, 4, ZERO(INT), PARAMS(_,INT_FD, SYM,UINT, _,LLONG, _,LLONG), SYMBOLS(SYNC_FILE_RANGE));
+SYS(sys_renameat2, FILESYSTEM, LINK_OR_UNLINK, 5, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, SYM,INT_ATFD, _,STRING, SYM,UINT), SYMBOLS(2ATFD, RENAME));
+SYS(sys_mknod, FILESYSTEM, LINK, 3, ZERO(INT), PARAMS(_,STRING, SYM,USHORT, SYM,UINT), SYMBOLS(MODE, DEV));
+SYS(sys_mknodat, FILESYSTEM, LINK, 4, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, SYM,USHORT, SYM,UINT), SYMBOLS(ATFD_MODE, DEV));
+SYS(sys_mkdir, FILESYSTEM, LINK, 2, ZERO(INT), PARAMS(_,STRING, SYM,USHORT), SYMBOLS(MODE));
+SYS(sys_mkdirat, FILESYSTEM, LINK, 3, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, SYM,USHORT), SYMBOLS(ATFD, MODE));
+SYS(sys_umask, FILESYSTEM, UMASK, 1, SYMB(UINT), PARAMS(SYM,UINT), SYMBOLS(UMASK, UMASK));
+SYS(sys_flock, IPC, FILE_LOCK, 2, ZERO(INT), PARAMS(_,INT_FD, SYM,UINT), SYMBOLS(LOCK));
+SYS(sys_fchmod, FILE_DESCRIPTORS, MODIFY, 2, ZERO(INT), PARAMS(_,INT_FD, SYM,USHORT), SYMBOLS(MODE));
+SYS(sys_chmod, FILESYSTEM, MODIFY, 2, ZERO(INT), PARAMS(_,STRING, SYM,USHORT), SYMBOLS(MODE));
+SYS(sys_fchmodat, FILESYSTEM, MODIFY, 3, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, SYM,USHORT), SYMBOLS(ATFD, MODE));
+SYS(sys_fchmodat2, FILESYSTEM, MODIFY, 4, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, SYM,USHORT, SYM,UINT), SYMBOLS(ATFD_MODE, AT));
+SYS(sys_fallocate, FILE_DESCRIPTORS, WRITE, 4, ZERO(INT), PARAMS(_,INT_FD, SYM,INT, _,LLONG, _,LLONG), SYMBOLS(FALLOC));
+SYS(sys_execveat, PROCESSES, EXEC, 5, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, IN,STRINGS_THEN_NULL, IN,STRINGS_THEN_NULL, SYM,UINT), SYMBOLS(ATFD, AT));
+SYS(sys_newfstatat, FILESYSTEM, STAT, 4, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, OUT,STRUCT_STAT, SYM,UINT), SYMBOLS(ATFD, AT_AUTOMOUNT));
+SYS(sys_fstatat64, FILESYSTEM, STAT, 4, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, OUT,STRUCT_STAT64, SYM,INT), SYMBOLS(ATFD, AT_AUTOMOUNT));
+SYS(sys_linkat, FILESYSTEM, LINK, 5, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, SYM,INT_ATFD, _,STRING, SYM,UINT), SYMBOLS(2ATFD, AT));
+SYS(sys_unlinkat, FILESYSTEM, UNLINK, 3, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, SYM,UINT), SYMBOLS(ATFD, UNLINK));
+SYS(sys_fchownat, FILESYSTEM, MODIFY, 5, ZERO(INT), PARAMS(SYM,INT_ATFD, _,STRING, _,UINT32, _,UINT32, SYM,UINT), SYMBOLS(ATFD, AT));
+SYS(sys_swapon, SYSTEM, SWAP, 2, ZERO(INT), PARAMS(_,STRING, SYM,INT), SYMBOLS(SWAPON));
+SYS(sys_shmctl, IPC, CONTROL, 2, INT, PARAMS(_,INT, SYM,INT, BI/* depends on command*/,DYNAMIC), SYMBOLS(SHMCTL));
+SYS(sys_msgctl, IPC, CONTROL, 2, INT, PARAMS(_,INT, SYM,INT, BI/* depends on command*/,DYNAMIC), SYMBOLS(MSGCTL));
+SYS(sys_semctl, IPC, CONTROL, 3, INT, PARAMS(_,INT, _,INT, SYM,INT, BI/* depends on command*/,DYNAMIC), SYMBOLS(SEMCTL));
+SYS(sys_mlock2, MEMORY, LOCK, 3, ZERO(INT), PARAMS(_,MEMORY_ADDRESS, _,SIZE, SYM,UINT), SYMBOLS(MLOCK));
+SYS(sys_mlockall, MEMORY, LOCK, 1, ZERO(INT), PARAMS(SYM,INT), SYMBOLS(MCL));
+SYS(sys_preadv2, FILE_DESCRIPTORS, READ_OR_PEEK, 6, SSIZE, PARAMS(_,LONG_FD, BI,STRUCT_IOVEC_ARRAY, _,ULONG, _,INT64_LOW_32, _,INT64_HIGH_32, SYM,UINT), SYMBOLS(RWF));
+SYS(sys_pwritev2, FILE_DESCRIPTORS, WRITE, 6, SSIZE, PARAMS(_,LONG_FD, IN,STRUCT_IOVEC_ARRAY, _,ULONG, _,INT64_LOW_32, _,INT64_HIGH_32, SYM,UINT), SYMBOLS(RWF));
+SYS(sys_shmat, IPC, ATTACH, 3, MEMORY_ADDRESS, PARAMS(_,INT, _,MEMORY_ADDRESS, SYM,UINT), SYMBOLS(SHM));
+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_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));
+SYS(sys_shmget, IPC, CONTROL, 3, INT, PARAMS(SYM,INT, _,SIZE, SYM,UINT), SYMBOLS(IPC_KEY, SHMGET));
+SYS(sys_msgget, IPC, CONTROL, 2, INT, PARAMS(SYM,INT, SYM,UINT), SYMBOLS(IPC_KEY, MSGGET));
+SYS(sys_semget, IPC, CONTROL, 3, INT, PARAMS(SYM,INT, _,INT, SYM,UINT), SYMBOLS(IPC_KEY, SEMGET));
+SYS(sys_msgrcv, IPC, COMMUNICATE, 5, INT, PARAMS( _,INT_FD, IN,STRUCT_MSGBUF, _,SIZE, _,LONG, SYM,UINT), SYMBOLS(MSGRCV));
+SYS(sys_msgsnd, IPC, COMMUNICATE, 4, ZERO(SSIZE), PARAMS(_,INT, OUT,STRUCT_MSGBUF, _,SIZE, SYM,UINT), SYMBOLS(MSGSND));
+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_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));
+SYS(sys_getgroups, PROCESSES, STAT_SELF, 2, INT, PARAMS(_,INT, OUT,UINT32_ARRAY));
+SYS(sys_getgroups16, PROCESSES, STAT_SELF, 2, INT, PARAMS(_,INT, OUT,USHORT_ARRAY));
+SYS(sys_setgroups, PROCESSES, CHANGE_PERMISSIONS, 2, ZERO(INT), PARAMS(_,INT, IN,UINT32_ARRAY));
+SYS(sys_setgroups16, PROCESSES, CHANGE_PERMISSIONS, 2, ZERO(INT), PARAMS(_,INT, IN,USHORT_ARRAY));
+SYS(sys_semop, IPC, COMMUNICATE, 3, ZERO(INT), PARAMS(_,INT, IN,STRUCT_SEMBUF_ARRAY, _,UINT));
+SYS(sys_semtimedop, IPC, COMMUNICATE_WITH_RELATIVE_TIMEOUT, 4, ZERO(INT), PARAMS(_,INT, IN,STRUCT_SEMBUF_ARRAY, _,UINT, IN,STRUCT_TIMESPEC));
+SYS(sys_semtimedop_time32, IPC, COMMUNICATE_WITH_RELATIVE_TIMEOUT, 4, ZERO(INT), PARAMS(_,INT, IN,STRUCT_SEMBUF_ARRAY, _,UINT, IN,STRUCT_OLD_TIMESPEC32));
+SYS(sys_mincore, MEMORY, STAT, 3, ZERO(INT), PARAMS(_,MEMORY_ADDRESS, _,SIZE, OUT,UCHAR_ARRAY_UNKNOWN_FILL /* entirely filled */));
+SYS(sys_reboot, SYSTEM, REBOOT, 3, ZERO(INT), PARAMS(SYM,UINT, SYM,UINT, SYM,UINT, _,STRING), SYMBOLS(REBOOT));
+
+#define TODO_SYS(...) SYS(__VA_ARGS__, .queer = 1)
+TODO_SYS(sys_poll, FILE_DESCRIPTORS, POLL, 3, INT, PARAMS(BI,STRUCT_POLLFD_ARRAY, _,UINT, _,INT));
+TODO_SYS(sys_ppoll, FILE_DESCRIPTORS, POLL, 5, INT, PARAMS(BI,STRUCT_POLLFD_ARRAY, _,UINT, IN,STRUCT_TIMESPEC, IN,ULONG_ARRAY, _,SIZE));
+TODO_SYS(sys_ppoll_time32, FILE_DESCRIPTORS, POLL, 5, INT, PARAMS(BI,STRUCT_POLLFD_ARRAY, _,UINT, IN,STRUCT_OLD_TIMESPEC32, IN,ULONG_ARRAY, _,SIZE));
+TODO_SYS(sys_old_select, FILE_DESCRIPTORS, POLL, 1, INT, PARAMS(BI,STRUCT_SEL_ARG_STRUCT));
+TODO_SYS(sys_select, FILE_DESCRIPTORS, POLL, 5, INT, PARAMS(_,INT, BI,FD_SET, BI,FD_SET, BI,FD_SET, BI,STRUCT_OLD_TIMEVAL)); /* unlike pselect6, select may update the timeout argument */
+TODO_SYS(sys_pselect6, FILE_DESCRIPTORS, POLL, 6, INT, PARAMS(_,INT, BI,FD_SET, BI,FD_SET, BI,FD_SET, OUT,STRUCT_TIMESPEC, IN,ULONG));
+TODO_SYS(sys_pselect6_time32, FILE_DESCRIPTORS, POLL, 6, INT, PARAMS(_,INT, BI,FD_SET, BI,FD_SET, BI,FD_SET, OUT,STRUCT_OLD_TIMESPEC32, IN,ULONG));
+TODO_SYS(sys_readv, FILE_DESCRIPTORS, READ, 3, SSIZE, PARAMS(_,LONG_FD, BI,STRUCT_IOVEC_ARRAY, _,ULONG));
+TODO_SYS(sys_writev, FILE_DESCRIPTORS, WRITE, 3, SSIZE, PARAMS(_,LONG_FD, IN,STRUCT_IOVEC_ARRAY, _,ULONG));
+TODO_SYS(sys_preadv, FILE_DESCRIPTORS, PEEK, 5, SSIZE, PARAMS(_,LONG_FD, BI,STRUCT_IOVEC_ARRAY, _,ULONG, _,INT64_LOW_32, _,INT64_HIGH_32));
+TODO_SYS(sys_pwritev, FILE_DESCRIPTORS, WRITE, 5, SSIZE, PARAMS(_,LONG_FD, IN,STRUCT_IOVEC_ARRAY, _,ULONG, _,INT64_LOW_32, _,INT64_HIGH_32));
+TODO_SYS(sys_sched_getaffinity, SCHEDULING, GET, 3, INT, PARAMS(_,INT, _,UINT, OUT,ULONG_ARRAY));
+TODO_SYS(sys_sched_setaffinity, SCHEDULING, SET, 3, ZERO(INT), PARAMS(_,INT, _,UINT, IN,ULONG_ARRAY));
+#undef TODO_SYS
+
+
+#define XXX TODO /* when none on the architectures is not support yet by libsyscalls's core */
+static struct libsyscalls_syscall_abi TODO =
+ {.category = LIBSYSCALLS_CAT_SUPPORT_PENDING,
+ .min_argument_count = -1,
+ .max_argument_count = -1};
+
+#define linux_syscall_sys_add_key TODO
+#define linux_syscall_sys_arch_prctl TODO
+#define linux_syscall_sys_bpf TODO
+#define linux_syscall_sys_cachestat TODO
+#define linux_syscall_sys_capget TODO
+#define linux_syscall_sys_capset TODO
+#define linux_syscall_sys_clone TODO
+#define linux_syscall_sys_clone3 TODO
+#define linux_syscall_sys_copy_file_range TODO
+#define linux_syscall_sys_creat TODO
+#define linux_syscall_sys_delete_module TODO
+#define linux_syscall_sys_eventfd TODO
+#define linux_syscall_sys_eventfd2 TODO
+#define linux_syscall_sys_fcntl TODO
+#define linux_syscall_sys_finit_module TODO
+#define linux_syscall_sys_fsconfig TODO
+#define linux_syscall_sys_fsmount TODO
+#define linux_syscall_sys_fspick TODO
+#define linux_syscall_sys_fstatfs TODO
+#define linux_syscall_sys_futex TODO
+#define linux_syscall_sys_futex_waitv TODO
+#define linux_syscall_sys_futimesat TODO
+#define linux_syscall_sys_getcpu TODO
+#define linux_syscall_sys_getdents TODO
+#define linux_syscall_sys_getdents64 TODO
+#define linux_syscall_sys_get_mempolicy TODO
+#define linux_syscall_sys_getpriority TODO
+#define linux_syscall_sys_getrlimit TODO
+#define linux_syscall_sys_get_robust_list TODO
+#define linux_syscall_sys_getrusage TODO
+#define linux_syscall_sys_getsockopt TODO
+#define linux_syscall_sys_gettimeofday TODO
+#define linux_syscall_sys_init_module TODO
+#define linux_syscall_sys_io_cancel TODO
+#define linux_syscall_sys_ioctl TODO
+#define linux_syscall_sys_io_destroy TODO
+#define linux_syscall_sys_io_getevents TODO
+#define linux_syscall_sys_ioperm TODO
+#define linux_syscall_sys_io_pgetevents TODO
+#define linux_syscall_sys_iopl TODO
+#define linux_syscall_sys_ioprio_get TODO
+#define linux_syscall_sys_ioprio_set TODO
+#define linux_syscall_sys_io_setup TODO
+#define linux_syscall_sys_io_submit TODO
+#define linux_syscall_sys_io_uring_enter TODO
+#define linux_syscall_sys_io_uring_register TODO
+#define linux_syscall_sys_io_uring_setup TODO
+#define linux_syscall_sys_kcmp TODO
+#define linux_syscall_sys_kexec_file_load TODO
+#define linux_syscall_sys_kexec_load TODO
+#define linux_syscall_sys_keyctl TODO
+#define linux_syscall_sys_landlock_add_rule TODO
+#define linux_syscall_sys_landlock_create_ruleset TODO
+#define linux_syscall_sys_landlock_restrict_self TODO
+#define linux_syscall_sys_lookup_dcookie TODO
+#define linux_syscall_sys_map_shadow_stack TODO
+#define linux_syscall_sys_mbind TODO
+#define linux_syscall_sys_membarrier TODO
+#define linux_syscall_sys_memfd_create TODO
+#define linux_syscall_sys_memfd_secret TODO
+#define linux_syscall_sys_migrate_pages TODO
+#define linux_syscall_sys_mmap TODO
+#define linux_syscall_sys_modify_ldt TODO
+#define linux_syscall_sys_mount TODO
+#define linux_syscall_sys_mount_setattr TODO
+#define linux_syscall_sys_move_mount TODO
+#define linux_syscall_sys_move_pages TODO
+#define linux_syscall_sys_mprotect TODO
+#define linux_syscall_sys_mremap TODO
+#define linux_syscall_sys_munmap TODO
+#define linux_syscall_sys_name_to_handle_at TODO
+#define linux_syscall_sys_ni_syscall TODO
+#define linux_syscall_sys_open TODO
+#define linux_syscall_sys_openat TODO
+#define linux_syscall_sys_openat2 TODO
+#define linux_syscall_sys_open_by_handle_at TODO
+#define linux_syscall_sys_open_tree TODO
+#define linux_syscall_sys_perf_event_open TODO
+#define linux_syscall_sys_personality TODO
+#define linux_syscall_sys_pidfd_getfd TODO
+#define linux_syscall_sys_pidfd_open TODO
+#define linux_syscall_sys_pidfd_send_signal TODO
+#define linux_syscall_sys_pkey_alloc TODO
+#define linux_syscall_sys_pkey_free TODO
+#define linux_syscall_sys_pkey_mprotect TODO
+#define linux_syscall_sys_prctl TODO
+#define linux_syscall_sys_prlimit64 TODO
+#define linux_syscall_sys_process_madvise TODO
+#define linux_syscall_sys_process_mrelease TODO
+#define linux_syscall_sys_process_vm_readv TODO
+#define linux_syscall_sys_process_vm_writev TODO
+#define linux_syscall_sys_ptrace TODO
+#define linux_syscall_sys_quotactl TODO
+#define linux_syscall_sys_quotactl_fd TODO
+#define linux_syscall_sys_remap_file_pages TODO
+#define linux_syscall_sys_request_key TODO
+#define linux_syscall_sys_restart_syscall TODO
+#define linux_syscall_sys_rseq TODO
+#define linux_syscall_sys_rt_sigaction TODO
+#define linux_syscall_sys_rt_sigpending TODO
+#define linux_syscall_sys_rt_sigprocmask TODO
+#define linux_syscall_sys_rt_sigqueueinfo TODO
+#define linux_syscall_sys_rt_sigreturn TODO
+#define linux_syscall_sys_rt_sigsuspend TODO
+#define linux_syscall_sys_rt_sigtimedwait TODO
+#define linux_syscall_sys_rt_tgsigqueueinfo TODO
+#define linux_syscall_sys_seccomp TODO
+#define linux_syscall_sys_set_mempolicy TODO
+#define linux_syscall_sys_set_mempolicy_home_node TODO
+#define linux_syscall_sys_setns TODO
+#define linux_syscall_sys_setpriority TODO
+#define linux_syscall_sys_setrlimit TODO
+#define linux_syscall_sys_set_robust_list TODO
+#define linux_syscall_sys_setsockopt TODO
+#define linux_syscall_sys_set_tid_address TODO
+#define linux_syscall_sys_settimeofday TODO
+#define linux_syscall_sys_sigaltstack TODO
+#define linux_syscall_sys_signalfd TODO
+#define linux_syscall_sys_signalfd4 TODO
+#define linux_syscall_sys_statfs TODO
+#define linux_syscall_sys_sysfs TODO
+#define linux_syscall_sys_syslog TODO
+#define linux_syscall_sys_time TODO
+#define linux_syscall_sys_timer_create TODO
+#define linux_syscall_sys_timer_delete TODO
+#define linux_syscall_sys_timerfd_create TODO
+#define linux_syscall_sys_timerfd_gettime TODO
+#define linux_syscall_sys_timerfd_settime TODO
+#define linux_syscall_sys_timer_getoverrun TODO
+#define linux_syscall_sys_timer_gettime TODO
+#define linux_syscall_sys_timer_settime TODO
+#define linux_syscall_sys_times TODO
+#define linux_syscall_sys_unshare TODO
+#define linux_syscall_sys_userfaultfd TODO
+#define linux_syscall_sys_ustat TODO
+#define linux_syscall_sys_utime TODO
+#define linux_syscall_sys_utimensat TODO
+#define linux_syscall_sys_utimes TODO
+#define linux_syscall_sys_vmsplice TODO
+#define linux_syscall_sys_wait4 TODO
+#define linux_syscall_sys_waitid TODO
+#define linux_syscall_sys_waitpid TODO
+#define linux_syscall_sys_create_module TODO
+#define linux_syscall_sys_epoll_ctl_old TODO
+#define linux_syscall_sys_epoll_wait_old TODO
+#define linux_syscall_sys_get_kernel_syms TODO
+#define linux_syscall_sys_get_thread_area TODO
+#define linux_syscall_sys_nfsservctl TODO
+#define linux_syscall_sys_query_module TODO
+#define linux_syscall_sys_set_thread_area TODO
+#define linux_syscall_sys_uselib TODO
+
+#define linux_syscall_compat_sys_recvfrom TODO /* i386 x32 mips powerpc s390 */
+#define linux_syscall_compat_sys_execve TODO /* i386 x32 mips powerpc s390 parisc */
+#define linux_syscall_compat_sys_execveat TODO /* i386 x32 mips powerpc s390 parisc */
+#define linux_syscall_compat_sys_fcntl64 TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_get_robust_list TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_io_setup TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_io_submit TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_ioctl TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_kexec_load TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_mq_notify TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_ptrace TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_recvmmsg_time64 TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_recvmsg TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_rt_sigaction TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_rt_sigpending TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_rt_sigqueueinfo TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_rt_sigtimedwait_time64 TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_rt_tgsigqueueinfo TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_sendmmsg TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_sendmsg TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_set_robust_list TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_sigaltstack TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_timer_create TODO /* i386 x32 mips powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_waitid TODO /* i386 x32 mips powerpc s390 parisc sparc */
+
+#define linux_syscall_sys_io_pgetevents_time32 TODO /* i386 arm mips microblaze parisc powerpc sparc */
+#define linux_syscall_sys_fcntl64 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc xtensa */
+#define linux_syscall_sys_rt_sigtimedwait_time32 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc xtensa */
+#define linux_syscall_sys_futex_time32 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 xtensa */
+#define linux_syscall_sys_futimesat_time32 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 xtensa */
+#define linux_syscall_sys_io_getevents_time32 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 xtensa */
+#define linux_syscall_sys_timer_gettime32 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 xtensa */
+#define linux_syscall_sys_timer_settime32 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 xtensa */
+#define linux_syscall_sys_timerfd_gettime32 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 xtensa */
+#define linux_syscall_sys_timerfd_settime32 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 xtensa */
+#define linux_syscall_sys_utime32 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 xtensa */
+#define linux_syscall_sys_utimensat_time32 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 xtensa */
+#define linux_syscall_sys_utimes_time32 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 xtensa */
+#define linux_syscall_sys_sigpending TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 alpha */
+#define linux_syscall_sys_nice TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 */
+#define linux_syscall_sys_sigprocmask TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 */
+#define linux_syscall_sys_socketcall TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 */
+#define linux_syscall_sys_stime32 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 */
+#define linux_syscall_sys_time32 TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc s390 */
+#define linux_syscall_sys_sgetmask TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc */
+#define linux_syscall_sys_ssetmask TODO /* i386 arm mips m68k microblaze parisc powerpc sh sparc */
+#define linux_syscall_sys_sigaction TODO /* i386 arm mips m68k powerpc sh s390 */
+#define linux_syscall_sys_sigsuspend TODO /* i386 arm mips m68k powerpc sh sparc s390 alpha */
+#define linux_syscall_sys_ipc TODO /* i386 arm mips m68k powerpc sh sparc */
+#define linux_syscall_sys_old_readdir TODO /* i386 arm mips m68k powerpc sh sparc */
+#define linux_syscall_sys_signal TODO /* i386 arm m68k microblaze parisc powerpc sh sparc s390 */
+#define linux_syscall_sys_old_getrlimit TODO /* i386 arm m68k powerpc sh */
+#define linux_syscall_sys_old_mmap TODO /* i386 arm m68k s390 */
+#define linux_syscall_sys_vm86 TODO /* i386 arm */
+
+#define linux_syscall_sys_fstatfs64 TODO /* i386 mips m68k ia64 microblaze parisc powerpc sh sparc s390 alpha xtensa */
+#define linux_syscall_sys_statfs64 TODO /* i386 mips m68k ia64 microblaze parisc powerpc sh sparc s390 alpha xtensa */
+#define linux_syscall_sys_sigreturn TODO /* i386 mips m68k powerpc sh sparc s390 alpha */
+#define linux_syscall_compat_sys_getitimer TODO /* i386 mips parisc powerpc sparc s390 alpha */
+#define linux_syscall_compat_sys_setitimer TODO /* i386 mips parisc powerpc sparc s390 alpha */
+#define linux_syscall_compat_sys_epoll_pwait2 TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_fstatfs TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_fstatfs64 TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_getdents TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_getrlimit TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_getrusage TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_gettimeofday TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_io_pgetevents TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_keyctl TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_lookup_dcookie TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_mq_getsetattr TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_mq_open TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_msgctl TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_msgrcv TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_msgsnd TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_newfstat TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_newlstat TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_newstat TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_open TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_open_by_handle_at TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_openat TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_ppoll_time32 TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_ppoll_time64 TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_preadv TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_preadv2 TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_pselect6_time32 TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_pselect6_time64 TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_pwritev TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_pwritev2 TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_recvmmsg_time32 TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_rt_sigprocmask TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_rt_sigsuspend TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_rt_sigtimedwait_time32 TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_sched_getaffinity TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_sched_setaffinity TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_select TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_semctl TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_sendfile TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_setrlimit TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_settimeofday TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_shmat TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_shmctl TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_signalfd TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_sigpending TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_sigprocmask TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_statfs TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_statfs64 TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_sysinfo TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_times TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_ustat TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_wait4 TODO /* i386 mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_old_readdir TODO /* i386 mips powerpc sparc s390 */
+#define linux_syscall_compat_sys_signalfd4 TODO /* i386 mips powerpc sparc s390 */
+#define linux_syscall_compat_sys_ipc TODO /* i386 mips powerpc sparc */
+#define linux_syscall_compat_sys_socketcall TODO /* i386 mips powerpc s390 */
+#define linux_syscall_sys_setaltroot TODO /* i386 mips */
+
+#define linux_syscall_compat_sys_lseek TODO /* i386 powerpc s390 parisc sparc */
+#define linux_syscall_compat_sys_sigaction TODO /* i386 powerpc s390 */
+#define linux_syscall_compat_sys_old_getrlimit TODO /* i386 powerpc s390 */
+#define linux_syscall_compat_sys_old_select TODO /* i386 powerpc */
+#define linux_syscall_sys_set_zone_reclaim TODO /* i386 microblaze */
+#define linux_syscall_sys_mmap_pgoff TODO /* i386 xtensa */
+#define linux_syscall_sys_ia32_fadvise64 TODO /* i386 */
+#define linux_syscall_sys_ia32_fadvise64_64 TODO /* i386 */
+#define linux_syscall_sys_ia32_fallocate TODO /* i386 */
+#define linux_syscall_sys_ia32_ftruncate64 TODO /* i386 */
+#define linux_syscall_sys_ia32_pread64 TODO /* i386 */
+#define linux_syscall_sys_ia32_pwrite64 TODO /* i386 */
+#define linux_syscall_sys_ia32_readahead TODO /* i386 */
+#define linux_syscall_sys_ia32_sync_file_range TODO /* i386 */
+#define linux_syscall_sys_ia32_truncate64 TODO /* i386 */
+#define linux_syscall_sys_vm86old TODO /* i386 */
+#define linux_syscall_compat_sys_ia32_clone TODO /* i386 */
+#define linux_syscall_compat_sys_ia32_fstat64 TODO /* i386 */
+#define linux_syscall_compat_sys_ia32_fstatat64 TODO /* i386 */
+#define linux_syscall_compat_sys_ia32_lstat64 TODO /* i386 */
+#define linux_syscall_compat_sys_ia32_mmap TODO /* i386 */
+#define linux_syscall_compat_sys_ia32_stat64 TODO /* i386 */
+
+#define linux_syscall_compat_sys_preadv64 TODO /* x32 */
+#define linux_syscall_compat_sys_preadv64v2 TODO /* x32 */
+#define linux_syscall_compat_sys_pwritev64 TODO /* x32 */
+#define linux_syscall_compat_sys_pwritev64v2 TODO /* x32 */
+
+#define linux_syscall_sys_idle XXX /* arm alpha */
+#define linux_syscall_sys_pciconfig_iobase XXX /* arm alpha powerpc */
+#define linux_syscall_sys_pciconfig_read TODO /* arm alpha powerpc sparc ia64 */
+#define linux_syscall_sys_pciconfig_write TODO /* arm alpha powerpc sparc ia64 */
+#define linux_syscall_sys_syscall XXX /* arm mips */
+#define linux_syscall_sys_mmap2 TODO /* arm microblaze parisc powerpc sparc ia64 m64k sh */
+#define linux_syscall_sys_rt_sigreturn_wrapper TODO /* arm microblaze parisc */
+#define linux_syscall_sys_afs_syscall XXX /* arm */
+#define linux_syscall_sys_arm_fadvise64_64 XXX /* arm */
+#define linux_syscall_sys_break XXX /* arm */
+#define linux_syscall_sys_fstatfs64_wrapper XXX /* arm */
+#define linux_syscall_sys_ftime XXX /* arm */
+#define linux_syscall_sys_gtty XXX /* arm */
+#define linux_syscall_sys_lock XXX /* arm */
+#define linux_syscall_sys_mpx XXX /* arm */
+#define linux_syscall_sys_oabi_bind XXX /* arm */
+#define linux_syscall_sys_oabi_connect XXX /* arm */
+#define linux_syscall_sys_oabi_epoll_ctl XXX /* arm */
+#define linux_syscall_sys_oabi_fcntl64 XXX /* arm */
+#define linux_syscall_sys_oabi_fstat64 XXX /* arm */
+#define linux_syscall_sys_oabi_fstatat64 XXX /* arm */
+#define linux_syscall_sys_oabi_ftruncate64 XXX /* arm */
+#define linux_syscall_sys_oabi_ipc XXX /* arm */
+#define linux_syscall_sys_oabi_lstat64 XXX /* arm */
+#define linux_syscall_sys_oabi_pread64 XXX /* arm */
+#define linux_syscall_sys_oabi_pwrite64 XXX /* arm */
+#define linux_syscall_sys_oabi_readahead XXX /* arm */
+#define linux_syscall_sys_oabi_semop XXX /* arm */
+#define linux_syscall_sys_oabi_semtimedop XXX /* arm */
+#define linux_syscall_sys_oabi_sendmsg XXX /* arm */
+#define linux_syscall_sys_oabi_sendto XXX /* arm */
+#define linux_syscall_sys_oabi_socketcall XXX /* arm */
+#define linux_syscall_sys_oabi_stat64 XXX /* arm */
+#define linux_syscall_sys_oabi_truncate64 XXX /* arm */
+#define linux_syscall_sys_prof XXX /* arm */
+#define linux_syscall_sys_profil XXX /* arm */
+#define linux_syscall_sys_sigreturn_wrapper XXX /* arm */
+#define linux_syscall_sys_statfs64_wrapper XXX /* arm */
+#define linux_syscall_sys_stty XXX /* arm */
+#define linux_syscall_sys_ulimit XXX /* arm */
+
+#define linux_syscall_compat_sys_epoll_pwait TODO /* mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_fanotify_mark TODO /* mips parisc powerpc sparc s390 */
+#define linux_syscall_compat_sys_fcntl TODO /* mips parisc powerpc sparc s390 */
+#define linux_syscall_sys_cacheflush TODO /* mips parisc m68k sh */
+#define linux_syscall_sys32_rt_sigreturn TODO /* mips sparc */
+#define linux_syscall_sys32_sigreturn TODO /* mips sparc */
+#define linux_syscall_compat_sys_recv XXX /* mips powerpc */
+#define linux_syscall___sys_clone TODO /* mips m68k */
+#define linux_syscall___sys_clone3 TODO /* mips m68k */
+#define linux_syscall___sys_fork TODO /* mips m68k */
+#define linux_syscall___sys_sysmips XXX /* mips */
+#define linux_syscall_compat_sys_old_msgctl XXX /* mips */
+#define linux_syscall_compat_sys_old_semctl XXX /* mips */
+#define linux_syscall_compat_sys_old_shmctl XXX /* mips */
+#define linux_syscall_sys32_fadvise64_64 XXX /* mips */
+#define linux_syscall_sys32_fallocate XXX /* mips */
+#define linux_syscall_sys32_readahead XXX /* mips */
+#define linux_syscall_sys32_sigsuspend XXX /* mips */
+#define linux_syscall_sys32_sync_file_range XXX /* mips */
+#define linux_syscall_sys32_syscall XXX /* mips */
+#define linux_syscall_sys_32_ftruncate64 XXX /* mips */
+#define linux_syscall_sys_32_llseek XXX /* mips */
+#define linux_syscall_sys_32_personality XXX /* mips */
+#define linux_syscall_sys_32_pread XXX /* mips */
+#define linux_syscall_sys_32_pwrite XXX /* mips */
+#define linux_syscall_sys_32_sigaction XXX /* mips */
+#define linux_syscall_sys_32_truncate64 XXX /* mips */
+#define linux_syscall_sys_cachectl XXX /* mips */
+#define linux_syscall_sys_mips_mmap XXX /* mips */
+#define linux_syscall_sys_mips_mmap2 XXX /* mips */
+#define linux_syscall_sysm_pipe XXX /* mips */
+#define linux_syscall_sysn32_rt_sigreturn XXX /* mips */
+
+#define linux_syscall_sys_stime TODO /* powerpc parisc sparc */
+#define linux_syscall_compat_sys_sendfile64 TODO /* powerpc parisc s390 */
+#define linux_syscall_compat_sys_fallocate TODO /* powerpc sparc */
+
+#define linux_syscall_alpha_syscall_zero XXX /* alpha */
+#define linux_syscall_sys_getdtablesize XXX /* alpha */
+#define linux_syscall_sys_old_adjtimex XXX /* alpha */
+#define linux_syscall_sys_osf_fstat XXX /* alpha */
+#define linux_syscall_sys_osf_fstatfs XXX /* alpha */
+#define linux_syscall_sys_osf_fstatfs64 XXX /* alpha */
+#define linux_syscall_sys_osf_getdirentries XXX /* alpha */
+#define linux_syscall_sys_osf_getdomainname XXX /* alpha */
+#define linux_syscall_sys_osf_getpriority XXX /* alpha */
+#define linux_syscall_sys_osf_getrusage XXX /* alpha */
+#define linux_syscall_sys_osf_getsysinfo XXX /* alpha */
+#define linux_syscall_sys_osf_gettimeofday XXX /* alpha */
+#define linux_syscall_sys_osf_lstat XXX /* alpha */
+#define linux_syscall_sys_osf_mmap XXX /* alpha */
+#define linux_syscall_sys_osf_mount XXX /* alpha */
+#define linux_syscall_sys_osf_proplist_syscall XXX /* alpha */
+#define linux_syscall_sys_osf_select XXX /* alpha */
+#define linux_syscall_sys_osf_set_program_attributes XXX /* alpha */
+#define linux_syscall_sys_osf_setsysinfo XXX /* alpha */
+#define linux_syscall_sys_osf_settimeofday XXX /* alpha */
+#define linux_syscall_sys_osf_sigaction XXX /* alpha */
+#define linux_syscall_sys_osf_sigprocmask XXX /* alpha */
+#define linux_syscall_sys_osf_sigstack XXX /* alpha */
+#define linux_syscall_sys_osf_stat XXX /* alpha */
+#define linux_syscall_sys_osf_statfs XXX /* alpha */
+#define linux_syscall_sys_osf_statfs64 XXX /* alpha */
+#define linux_syscall_sys_osf_sysinfo XXX /* alpha */
+#define linux_syscall_sys_osf_usleep_thread XXX /* alpha */
+#define linux_syscall_sys_osf_utimes XXX /* alpha */
+#define linux_syscall_sys_osf_utsname XXX /* alpha */
+#define linux_syscall_sys_osf_wait4 XXX /* alpha */
+#define linux_syscall_sys_sethae XXX /* alpha */ /* return 0; see syscalls(2) */
+
+#define linux_syscall_xtensa_fadvise64_64 XXX /* xtensa */
+#define linux_syscall_xtensa_rt_sigreturn XXX /* xtensa */
+#define linux_syscall_xtensa_shmat XXX /* xtensa */
+
+#define linux_syscall_ia64_brk XXX /* ia64 */
+#define linux_syscall_ia64_clock_getres XXX /* ia64 */
+#define linux_syscall_ia64_execve XXX /* ia64 */
+#define linux_syscall_ia64_getpriority XXX /* ia64 */
+#define linux_syscall_ia64_mremap XXX /* ia64 */
+#define linux_syscall_sys_clone2 XXX /* ia64 */
+#define linux_syscall_sys_getunwind XXX /* ia64 */
+
+#define linux_syscall_old_mmap XXX /* sh */
+#define linux_syscall_sys_fadvise64_64_wrapper XXX /* sh */
+#define linux_syscall_sys_pread_wrapper XXX /* sh */
+#define linux_syscall_sys_pwrite_wrapper XXX /* sh */
+
+#define linux_syscall___sys_vfork TODO /* m68k */
+#define linux_syscall_sys_atomic_barrier TODO /* m68k */
+#define linux_syscall_sys_atomic_cmpxchg_32 TODO /* m68k */
+
+#define linux_syscall_compat_sys_io_pgetevents_time64 TODO /* parisc */
+#define linux_syscall_parisc_compat_signalfd4 TODO /* parisc */
+#define linux_syscall_parisc_eventfd2 TODO /* parisc */
+#define linux_syscall_parisc_fadvise64_64 TODO /* parisc */
+#define linux_syscall_parisc_fallocate TODO /* parisc */
+#define linux_syscall_parisc_ftruncate64 TODO /* parisc */
+#define linux_syscall_parisc_inotify_init1 TODO /* parisc */
+#define linux_syscall_parisc_madvise TODO /* parisc */
+#define linux_syscall_parisc_personality TODO /* parisc */
+#define linux_syscall_parisc_pipe2 TODO /* parisc */
+#define linux_syscall_parisc_pread64 TODO /* parisc */
+#define linux_syscall_parisc_pwrite64 TODO /* parisc */
+#define linux_syscall_parisc_readahead TODO /* parisc */
+#define linux_syscall_parisc_signalfd4 TODO /* parisc */
+#define linux_syscall_parisc_sync_file_range TODO /* parisc */
+#define linux_syscall_parisc_timerfd_create TODO /* parisc */
+#define linux_syscall_parisc_truncate64 TODO /* parisc */
+#define linux_syscall_parisc_userfaultfd TODO /* parisc */
+#define linux_syscall_sys32_fanotify_mark TODO /* parisc */
+#define linux_syscall_sys32_unimplemented TODO /* parisc */
+#define linux_syscall_sys_acl_get TODO /* parisc */
+#define linux_syscall_sys_acl_set TODO /* parisc */
+#define linux_syscall_sys_alloc_hugepages TODO /* parisc */
+#define linux_syscall_sys_attrctl TODO /* parisc */
+#define linux_syscall_sys_clone3_wrapper TODO /* parisc */
+#define linux_syscall_sys_clone_wrapper TODO /* parisc */
+#define linux_syscall_sys_fork_wrapper TODO /* parisc */
+#define linux_syscall_sys_free_hugepages TODO /* parisc */
+#define linux_syscall_sys_timerfd TODO /* parisc */
+#define linux_syscall_sys_vfork_wrapper TODO /* parisc */
+
+#define linux_syscall_compat_sys_fadvise64 TODO /* sparc */
+#define linux_syscall_compat_sys_fadvise64_64 TODO /* sparc */
+#define linux_syscall_compat_sys_fstat64 TODO /* sparc */
+#define linux_syscall_compat_sys_fstatat64 TODO /* sparc */
+#define linux_syscall_compat_sys_lstat64 TODO /* sparc */
+#define linux_syscall_compat_sys_pread64 TODO /* sparc */
+#define linux_syscall_compat_sys_pwrite64 TODO /* sparc */
+#define linux_syscall_compat_sys_readahead TODO /* sparc */
+#define linux_syscall_compat_sys_sparc_sigaction TODO /* sparc */
+#define linux_syscall_compat_sys_stat64 TODO /* sparc */
+#define linux_syscall_compat_sys_sync_file_range TODO /* sparc */
+#define linux_syscall_sparc_exit TODO /* sparc */
+#define linux_syscall_sparc_exit_group TODO /* sparc */
+#define linux_syscall_sunos_execv TODO /* sparc */
+#define linux_syscall_sys32_execve TODO /* sparc */
+#define linux_syscall_sys32_execveat TODO /* sparc */
+#define linux_syscall_sys32_mmap2 TODO /* sparc */
+#define linux_syscall_sys32_socketcall TODO /* sparc */
+#define linux_syscall_sys64_execve TODO /* sparc */
+#define linux_syscall_sys64_execveat TODO /* sparc */
+#define linux_syscall_sys_64_mremap TODO /* sparc */
+#define linux_syscall_sys_64_munmap TODO /* sparc */
+#define linux_syscall_sys_getdomainname TODO /* sparc */
+#define linux_syscall_sys_kern_features TODO /* sparc */
+#define linux_syscall_sys_memory_ordering TODO /* sparc */
+#define linux_syscall_sys_nis_syscall TODO /* sparc */
+#define linux_syscall_sys_sparc64_personality TODO /* sparc */
+#define linux_syscall_sys_sparc_adjtimex TODO /* sparc */
+#define linux_syscall_sys_sparc_clock_adjtime TODO /* sparc */
+#define linux_syscall_sys_sparc_ipc TODO /* sparc */
+#define linux_syscall_sys_sparc_pipe TODO /* sparc */
+#define linux_syscall_sys_sparc_remap_file_pages TODO /* sparc */
+#define linux_syscall_sys_sparc_sigaction TODO /* sparc */
+#define linux_syscall_sys_utrap_install TODO /* sparc */
+
+#define linux_syscall_compat_sys_mmap2 XXX /* powerpc */
+#define linux_syscall_compat_sys_ppc32_fadvise64 XXX /* powerpc */
+#define linux_syscall_compat_sys_ppc64_personality XXX /* powerpc */
+#define linux_syscall_compat_sys_ppc_ftruncate64 XXX /* powerpc */
+#define linux_syscall_compat_sys_ppc_pread64 XXX /* powerpc */
+#define linux_syscall_compat_sys_ppc_pwrite64 XXX /* powerpc */
+#define linux_syscall_compat_sys_ppc_readahead XXX /* powerpc */
+#define linux_syscall_compat_sys_ppc_sync_file_range2 XXX /* powerpc */
+#define linux_syscall_compat_sys_ppc_truncate64 XXX /* powerpc */
+#define linux_syscall_compat_sys_swapcontext XXX /* powerpc */
+#define linux_syscall_sys_debug_setcontext XXX /* powerpc */
+#define linux_syscall_sys_ppc32_fadvise64 XXX /* powerpc */
+#define linux_syscall_sys_ppc64_personality XXX /* powerpc */
+#define linux_syscall_sys_ppc_fadvise64_64 XXX /* powerpc */
+#define linux_syscall_sys_ppc_fallocate XXX /* powerpc */
+#define linux_syscall_sys_ppc_ftruncate64 XXX /* powerpc */
+#define linux_syscall_sys_ppc_pread64 XXX /* powerpc */
+#define linux_syscall_sys_ppc_pwrite64 XXX /* powerpc */
+#define linux_syscall_sys_ppc_readahead XXX /* powerpc */
+#define linux_syscall_sys_ppc_sync_file_range2 XXX /* powerpc */
+#define linux_syscall_sys_ppc_truncate64 XXX /* powerpc */
+#define linux_syscall_sys_rtas XXX /* powerpc */
+#define linux_syscall_sys_spu_create XXX /* powerpc */
+#define linux_syscall_sys_spu_run XXX /* powerpc */
+#define linux_syscall_sys_subpage_prot XXX /* powerpc */
+#define linux_syscall_sys_swapcontext XXX /* powerpc */
+#define linux_syscall_sys_switch_endian XXX /* powerpc */
+
+#define linux_syscall_compat_sys_s390_fadvise64 XXX /* s390 */
+#define linux_syscall_compat_sys_s390_fadvise64_64 XXX /* s390 */
+#define linux_syscall_compat_sys_s390_fallocate XXX /* s390 */
+#define linux_syscall_compat_sys_s390_fstat64 XXX /* s390 */
+#define linux_syscall_compat_sys_s390_fstatat64 XXX /* s390 */
+#define linux_syscall_compat_sys_s390_ftruncate64 XXX /* s390 */
+#define linux_syscall_compat_sys_s390_ipc XXX /* s390 */
+#define linux_syscall_compat_sys_s390_lstat64 XXX /* s390 */
+#define linux_syscall_compat_sys_s390_mmap2 XXX /* s390 */
+#define linux_syscall_compat_sys_s390_old_mmap XXX /* s390 */
+#define linux_syscall_compat_sys_s390_pread64 XXX /* s390 */
+#define linux_syscall_compat_sys_s390_pwrite64 XXX /* s390 */
+#define linux_syscall_compat_sys_s390_read XXX /* s390 */
+#define linux_syscall_compat_sys_s390_readahead XXX /* s390 */
+#define linux_syscall_compat_sys_s390_stat64 XXX /* s390 */
+#define linux_syscall_compat_sys_s390_sync_file_range XXX /* s390 */
+#define linux_syscall_compat_sys_s390_truncate64 XXX /* s390 */
+#define linux_syscall_compat_sys_s390_write XXX /* s390 */
+#define linux_syscall_sys__sysctl XXX /* s390 */
+#define linux_syscall_sys_getpmsg XXX /* s390 */
+#define linux_syscall_sys_putpmsg XXX /* s390 */
+#define linux_syscall_sys_s390_guarded_storage XXX /* s390 */
+#define linux_syscall_sys_s390_ipc XXX /* s390 */
+#define linux_syscall_sys_s390_pci_mmio_read XXX /* s390 */
+#define linux_syscall_sys_s390_pci_mmio_write XXX /* s390 */
+#define linux_syscall_sys_s390_personality XXX /* s390 */
+#define linux_syscall_sys_s390_runtime_instr XXX /* s390 */
+#define linux_syscall_sys_s390_sthyi XXX /* s390 */
+
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#else
+# pragma GCC diagnostic pop
+#endif
+
+
+#endif /* !SYMBOL_PRINTERS_ONLY */
diff --git a/linux/syscalls.mk b/linux/syscalls.mk
new file mode 100644
index 0000000..7c13441
--- /dev/null
+++ b/linux/syscalls.mk
@@ -0,0 +1,450 @@
+LINUX_SYSCALL_DIR = linux-src/syscalls-$(LINUX_VERSION)
+
+LINUX_SYSCALLS_ARCH_TBL_SPLIT_X64 != printf '$(LINUX_SYSCALL_DIR)/%s.tbl\n' amd64 x86
+LINUX_SYSCALLS_ARCH_TBL_SPLIT_MIPS != printf '$(LINUX_SYSCALL_DIR)/%s.tbl\n' mips-n32 mips-o32 mips-n64
+
+LINUX_SYSCALLS_ARCHES_SPLIT != grep '^LINUX_SYSCALLS_ARCH_TBL_SPLIT_' < linux/syscalls.mk | cut -d \% -f 2 | cut -d ' ' -f 2-
+LINUX_SYSCALLS_ARCHES_SIMPLE != (sed -n 's/^generated\/linux-syscalls-\([a-zA-Z0-9_-]\+\)\.h\s*:.*$$/\1/p' && \
+ printf '%s\n' $(LINUX_SYSCALLS_ARCHES_SPLIT)) < linux/syscalls.mk | sort | uniq -u
+LINUX_SYSCALLS_ARCHES = $(LINUX_SYSCALLS_ARCHES_SIMPLE) $(LINUX_SYSCALLS_ARCHES_SPLIT)
+LINUX_SYSCALLS_ARCH_HDR != printf 'generated/linux-syscalls-%s.h\n' $(LINUX_SYSCALLS_ARCHES)
+LINUX_SYSCALLS_ARCH_TBL_SIMPLE != printf '$(LINUX_SYSCALL_DIR)/%s.tbl\n' $(LINUX_SYSCALLS_ARCHES_SIMPLE)
+LINUX_SYSCALLS_ARCH_TBL_SPLIT != printf '$(LINUX_SYSCALL_DIR)/%s.tbl\n' $(LINUX_SYSCALLS_ARCHES_SPLIT)
+LINUX_SYSCALLS_ARCH_TBL = $(LINUX_SYSCALLS_ARCH_TBL_SIMPLE) $(LINUX_SYSCALLS_ARCH_TBL_SPLIT)
+
+LINUX_SYSCALLS_HDR =\
+ generated/linux-syscalls.h\
+ generated/linux-syscall-ranges.h\
+ $(LINUX_SYSCALLS_ARCH_HDR)
+
+
+generated/linux-syscalls-alpha.h: $(LINUX_SYSCALL_DIR)/alpha.tbl linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_ALPHA(X, _X_COMPAT, D)\\\n' > $@
+ printf '%i common %s %s\n' \
+ 320 idle sys_idle \
+ | cat -- $(LINUX_SYSCALL_DIR)/alpha.tbl - \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\"}' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/alpha.tbl | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/alpha.tbl | awk '{ print $$2 }' | grep '^common$$')"
+
+
+$(LINUX_SYSCALL_DIR)/amd64.tbl.fixed: $(LINUX_SYSCALL_DIR)/amd64.tbl linux/syscalls.mk
+ cat -- $(LINUX_SYSCALL_DIR)/amd64.tbl \
+ | sed 's/\s\+\(getpmsg\|putpmsg\|afs_syscall\|tuxcall\|security\|vserver\)\s*$$/& sys_ni_syscall/' \
+ | sed 's/^\s*[0-9]\+\s\+[a-z0-9]\+\s\+\([A-Za-z0-9_]\+\)\s*$$/& sys_\1/' \
+ > $@
+
+generated/linux-syscalls-amd64.h: $(LINUX_SYSCALL_DIR)/amd64.tbl.fixed linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_AMD64(X, _X_COMPAT, D)\\\n' > $@
+ cat -- $(LINUX_SYSCALL_DIR)/amd64.tbl.fixed \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|64\)$$/\\/p' \
+ | sed '$$s/ D\\$$//' >> $@
+ printf '\n\43define LIST_LINUX_SYSCALLS_FOR_AMD64_X32(X, _X_COMPAT, D)\\\n' >> $@
+ cat -- $(LINUX_SYSCALL_DIR)/amd64.tbl.fixed \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|x32\)$$/\\/p' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/amd64.tbl.fixed | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/amd64.tbl.fixed | awk '{ print $$2 }' | \
+ grep '^\(common\|64\|x32\)$$')"
+
+
+$(LINUX_SYSCALL_DIR)/arm.tbl.fixed: $(LINUX_SYSCALL_DIR)/arm.tbl linux/syscalls.mk
+ printf '%i common %s %s\n' \
+ 7 waitpid sys_waitpid \
+ 17 break sys_break \
+ 18 old_stat sys_stat \
+ 28 old_fstat sys_fstat \
+ 31 stty sys_stty \
+ 32 gtty sys_gtty \
+ 35 ftime sys_ftime \
+ 44 prof sys_prof \
+ 48 signal sys_signal \
+ 53 lock sys_lock \
+ 56 mpx sys_mpx \
+ 58 ulimit sys_ulimit \
+ 59 oldolduname sys_olduname \
+ 68 sgetmask sys_sgetmask \
+ 69 ssetmask sys_ssetmask \
+ 84 old_lstat sys_lstat \
+ 98 profil sys_profil \
+ 101 ioperm sys_ioperm \
+ 109 olduname sys_uname \
+ 110 iopl sys_iopl \
+ 112 idle sys_idle \
+ 123 modify_ldt sys_modify_ldt \
+ 127 create_module sys_create_module \
+ 130 get_kernel_syms sys_get_kernel_syms \
+ 137 afs_syscall sys_afs_syscall \
+ 166 vm86 sys_vm86 \
+ 167 query_module sys_query_module \
+ | cat -- $(LINUX_SYSCALL_DIR)/arm.tbl - \
+ | sed 's/\svserver\s*$$/& sys_ni_syscall/' \
+ | sed 's/\snfsservctl\s*$$/& sys_nfsservctl/' \
+ > $@
+
+generated/linux-syscalls-arm.h: $(LINUX_SYSCALL_DIR)/arm.tbl.fixed linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_ARM_EABI(X, _X_COMPAT, D)\\\n' > $@
+ cat -- $(LINUX_SYSCALL_DIR)/arm.tbl.fixed \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|eabi\)$$/\\/p' \
+ | sed '$$s/ D\\$$//' >> $@
+ printf '\n\43define LIST_LINUX_SYSCALLS_FOR_ARM_OABI(X, X_COMPAT, D)\\\n' >> $@
+ cat -- $(LINUX_SYSCALL_DIR)/arm.tbl.fixed \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX_COMPAT(" $$1 ", " $$3 ", " $$4 ", " $$5 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|oabi\)$$/\\/p' \
+ | sed 's/X_COMPAT(\(.*\), ) D\\$$/X(\1) D\\/' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/arm.tbl.fixed | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/arm.tbl.fixed | awk '{ print $$2 }' | \
+ grep '^\(common\|oabi\|eabi\)$$')"
+
+
+generated/linux-syscalls-ia64.h: $(LINUX_SYSCALL_DIR)/ia64.tbl linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_IA64(X, _X_COMPAT, D)\\\n' > $@
+ printf '%i common %s %s\n' \
+ $$(( 1120 - 1024 )) old_stat sys_stat \
+ $$(( 1121 - 1024 )) old_lstat sys_lstat \
+ $$(( 1122 - 1024 )) old_fstat sys_fstat \
+ $$(( 1132 - 1024 )) create_module sys_create_module \
+ $$(( 1135 - 1024 )) get_kernel_syms sys_get_kernel_syms \
+ $$(( 1136 - 1024 )) query_module sys_query_module \
+ | cat -- $(LINUX_SYSCALL_DIR)/ia64.tbl - \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX((" $$1 " + 1024), " $$3 ", " $$4 ") D\\"}' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/ia64.tbl | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/ia64.tbl | awk '{ print $$2 }' | grep '^common$$')"
+
+
+generated/linux-syscalls-m68k.h: $(LINUX_SYSCALL_DIR)/m68k.tbl linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_M68K(X, _X_COMPAT, D)\\\n' > $@
+ printf '%i common %s %s\n' \
+ 17 break sys_ni_syscall \
+ 31 stty sys_ni_syscall \
+ 32 gtty sys_ni_syscall \
+ 35 ftime sys_ni_syscall \
+ 44 prof sys_ni_syscall \
+ 53 lock sys_ni_syscall \
+ 56 mpx sys_ni_syscall \
+ 58 ulimit sys_ni_syscall \
+ 59 oldolduname sys_olduname \
+ 98 profil sys_ni_syscall \
+ 101 ioperm sys_ioperm \
+ 109 olduname sys_uname \
+ 110 iopl sys_iopl \
+ 112 idle sys_idle \
+ 113 vm86 sys_vm86 \
+ 137 afs_syscall sys_ni_syscall \
+ 278 vserver sys_ni_syscall \
+ | cat -- $(LINUX_SYSCALL_DIR)/m68k.tbl - \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\"}' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/m68k.tbl | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/m68k.tbl | awk '{ print $$2 }' | grep '^common$$')"
+
+
+generated/linux-syscalls-microblaze.h: $(LINUX_SYSCALL_DIR)/microblaze.tbl linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_MICROBLAZE(X, _X_COMPAT, D)\\\n' > $@
+ printf '%i common %s %s\n' \
+ 251 set_zone_reclaim sys_set_zone_reclaim \
+ 285 setaltroot sys_setaltroot \
+ | cat -- $(LINUX_SYSCALL_DIR)/microblaze.tbl - \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\"}' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/microblaze.tbl | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/microblaze.tbl | awk '{ print $$2 }' | grep '^common$$')"
+
+
+generated/linux-syscalls-mips-n32.h: $(LINUX_SYSCALL_DIR)/mips-n32.tbl linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_MIPS_N32(X, _X_COMPAT, D)\\\n' > $@
+ printf '%i common %s %s\n' \
+ 242 setaltroot sys_setaltroot \
+ | cat -- $(LINUX_SYSCALL_DIR)/mips-n32.tbl - \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\"}' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/mips-n32.tbl | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/mips-n32.tbl | awk '{ print $$2 }' | grep '^n32$$')"
+
+
+generated/linux-syscalls-mips-n64.h: $(LINUX_SYSCALL_DIR)/mips-n64.tbl linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_MIPS_N64(X, _X_COMPAT, D)\\\n' > $@
+ printf '%i common %s %s\n' \
+ 238 setaltroot sys_setaltroot \
+ | cat -- $(LINUX_SYSCALL_DIR)/mips-n64.tbl - \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\"}' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/mips-n64.tbl | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/mips-n64.tbl | awk '{ print $$2 }' | \
+ grep '^\(n64\|common\)$$')"
+
+
+generated/linux-syscalls-mips-o32.h: $(LINUX_SYSCALL_DIR)/mips-o32.tbl linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_MIPS_O32(X, X_COMPAT, D)\\\n' > $@
+ printf '%i common %s %s\n' \
+ 18 old_stat sys_stat \
+ 28 old_fstat sys_fstat \
+ 82 select sys_old_select \
+ 84 old_lstat sys_lstat \
+ 279 setaltroot sys_setaltroot \
+ | cat -- $(LINUX_SYSCALL_DIR)/mips-o32.tbl - \
+ | sed '/^\s*\(18\|28\|82\|84\)\s\+o32.*$$/d' \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX_COMPAT(" $$1 ", " $$3 ", " $$4 ", " $$5 ") D\\"}' \
+ | sed 's/X_COMPAT(\(.*\), ) D\\$$/X(\1) D\\/' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/mips-o32.tbl | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/mips-o32.tbl | awk '{ print $$2 }' | grep '^o32$$')"
+
+
+$(LINUX_SYSCALL_DIR)/parisc.tbl.fixed: $(LINUX_SYSCALL_DIR)/parisc.tbl linux/syscalls.mk
+ printf '%i common %s %s\n' \
+ 102 socketcall sys_socketcall \
+ 127 create_module sys_create_module \
+ 130 get_kernel_syms sys_get_kernel_syms \
+ 137 afs_syscall sys_ni_syscall \
+ 167 query_module sys_query_module \
+ 169 nfsservctl sys_nfsservctl \
+ 196 getpmsg sys_ni_syscall \
+ 197 putpmsg sys_ni_syscall \
+ 203 attrctl sys_attrctl \
+ 204 acl_get sys_acl_get \
+ 205 acl_set sys_acl_set \
+ 213 set_thread_area sys_set_thread_area \
+ 214 get_thread_area sys_get_thread_area \
+ 220 alloc_hugepages sys_alloc_hugepages \
+ 221 free_hugepages sys_free_hugepages \
+ 263 vserver sys_ni_syscall \
+ 303 timerfd sys_timerfd \
+ | cat -- $(LINUX_SYSCALL_DIR)/parisc.tbl - > $@
+
+generated/linux-syscalls-parisc.h: $(LINUX_SYSCALL_DIR)/parisc.tbl.fixed linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_PARISC_64(X, _X_COMPAT, D)\\\n' > $@
+ cat -- $(LINUX_SYSCALL_DIR)/parisc.tbl.fixed \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|64\)$$/\\/p' \
+ | sed '$$s/ D\\$$//' >> $@
+ printf '\n\43define LIST_LINUX_SYSCALLS_FOR_PARISC_32(X, X_COMPAT, D)\\\n' >> $@
+ cat -- $(LINUX_SYSCALL_DIR)/parisc.tbl.fixed \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX_COMPAT(" $$1 ", " $$3 ", " $$4 ", " $$5 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|32\)$$/\\/p' \
+ | sed 's/X_COMPAT(\(.*\), ) D\\$$/X(\1) D\\/' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/parisc.tbl.fixed | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/parisc.tbl.fixed | awk '{ print $$2 }' | \
+ grep '^\(common\|64\|32\)$$')"
+
+
+generated/linux-syscalls-powerpc.h: $(LINUX_SYSCALL_DIR)/powerpc.tbl linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_POWERPC_32(X, X_COMPAT, D)\\\n' > $@
+ cat -- $(LINUX_SYSCALL_DIR)/powerpc.tbl \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX_COMPAT(" $$1 ", " $$3 ", " $$4 ", " $$5 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|32\)$$/\\/p' \
+ | sed 's/X_COMPAT(\(.*\), ) D\\$$/X(\1) D\\/' \
+ | sed '$$s/ D\\$$//' >> $@
+ printf '\n\43define LIST_LINUX_SYSCALLS_FOR_POWERPC_NOSPU(X, X_COMPAT, D)\\\n' >> $@
+ cat -- $(LINUX_SYSCALL_DIR)/powerpc.tbl \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX_COMPAT(" $$1 ", " $$3 ", " $$4 ", " $$5 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|nospu\)$$/\\/p' \
+ | sed 's/X_COMPAT(\(.*\), ) D\\$$/X(\1) D\\/' \
+ | sed '$$s/ D\\$$//' >> $@
+ printf '\n\43define LIST_LINUX_SYSCALLS_FOR_POWERPC_64(X, _X_COMPAT, D)\\\n' >> $@
+ cat -- $(LINUX_SYSCALL_DIR)/powerpc.tbl \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|64\)$$/\\/p' \
+ | sed '$$s/ D\\$$//' >> $@
+ printf '\n\43define LIST_LINUX_SYSCALLS_FOR_POWERPC_SPU(X, _X_COMPAT, D)\\\n' >> $@
+ cat -- $(LINUX_SYSCALL_DIR)/powerpc.tbl \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|spu\)$$/\\/p' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/powerpc.tbl | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/powerpc.tbl | awk '{ print $$2 }' | \
+ grep '^\(common\|spu\|nospu\|64\|32\)$$')"
+
+
+generated/linux-syscalls-s390.h: $(LINUX_SYSCALL_DIR)/s390.tbl linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_S390_32(X, _X_COMPAT, D)\\\n' > $@
+ cat -- $(LINUX_SYSCALL_DIR)/s390.tbl \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | sed 's/^\s*\([0-9]\+\)\s\+\([A-Za-z0-9_]\+\)\s\+\([A-Za-z0-9_]\+\)\s\+-\s\+-\s*$$/\1 \2 \3 sys_\3 sys_\3/' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$5 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|32\)$$/\\/p' \
+ | sed '$$s/ D\\$$//' >> $@
+ printf '\n\43define LIST_LINUX_SYSCALLS_FOR_S390_64(X, _X_COMPAT, D)\\\n' >> $@
+ cat -- $(LINUX_SYSCALL_DIR)/s390.tbl \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | sed 's/^\s*\([0-9]\+\)\s\+\([A-Za-z0-9_]\+\)\s\+\([A-Za-z0-9_]\+\)\s\+-\s\+-\s*$$/\1 \2 \3 sys_\3 sys_\3/' \
+ | sed 's/^\s*\(89\)\s\+\(common\)\s\+\(readdir\)\s\+-\s\+/\1 \2 \3 sys_old_readdir /' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|64\)$$/\\/p' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/s390.tbl | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/s390.tbl | awk '{ print $$2 }' | \
+ grep '^\(common\|32\|64\)$$')"
+
+
+generated/linux-syscalls-sh.h: $(LINUX_SYSCALL_DIR)/sh.tbl linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_SH(X, _X_COMPAT, D)\\\n' > $@
+ printf '%i common %s %s\n' \
+ 17 break sys_ni_syscall \
+ 31 stty sys_ni_syscall \
+ 32 gtty sys_ni_syscall \
+ 35 ftime sys_ni_syscall \
+ 44 prof sys_ni_syscall \
+ 53 lock sys_ni_syscall \
+ 56 mpx sys_ni_syscall \
+ 58 ulimit sys_ni_syscall \
+ 59 oldolduname sys_olduname \
+ 82 select sys_old_select \
+ 98 profil sys_ni_syscall \
+ 101 ioperm sys_ioperm \
+ 110 iopl sys_iopl \
+ 112 idle sys_idle \
+ 113 vm86old sys_vm86old \
+ 127 create_module sys_create_module \
+ 130 get_kernel_syms sys_get_kernel_syms \
+ 137 afs_syscall sys_ni_syscall \
+ 166 vm86 sys_vm86 \
+ 167 query_module sys_query_module \
+ | cat -- $(LINUX_SYSCALL_DIR)/sh.tbl - \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\"}' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/sh.tbl | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/sh.tbl | awk '{ print $$2 }' | grep '^common$$')"
+
+
+generated/linux-syscalls-sparc.h: $(LINUX_SYSCALL_DIR)/sparc.tbl linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_SPARC_32(X, X_COMPAT, D)\\\n' > $@
+ printf '%i common %s %s\n' \
+ 267 vserver sys_vserver \
+ | cat -- $(LINUX_SYSCALL_DIR)/sparc.tbl - \
+ | sed 's/compat_sys_\(truncate64\|ftruncate64\)/sparc___&/g' \
+ | sed '/^\s*267\s\+common\s\+vserver\s\+.*$$/d' \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX_COMPAT(" $$1 ", " $$3 ", " $$4 ", " $$5 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|32\)$$/\\/p' \
+ | sed 's/X_COMPAT(\(.*\), ) D\\$$/X(\1) D\\/' \
+ | sed '$$s/ D\\$$//' >> $@
+ printf '\n\43define LIST_LINUX_SYSCALLS_FOR_SPARC_64(X, _X_COMPAT, D)\\\n' >> $@
+ printf '%i common %s %s\n' \
+ 267 vserver sys_vserver \
+ | cat -- $(LINUX_SYSCALL_DIR)/sparc.tbl - \
+ | sed '/^\s*267\s\+common\s\+vserver\s\+.*$$/d' \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\" $$2}' \
+ | sed -n 's/\\\(common\|64\)$$/\\/p' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/sparc.tbl | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/sparc.tbl | awk '{ print $$2 }' | \
+ grep '^\(common\|32\|64\)$$')"
+
+
+generated/linux-syscalls-x86.h: $(LINUX_SYSCALL_DIR)/x86.tbl linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_I386(X, X_COMPAT, D)\\\n' > $@
+ printf '%i common %s %s\n' \
+ 251 set_zone_reclaim sys_set_zone_reclaim \
+ 285 setaltroot sys_setaltroot \
+ | cat -- $(LINUX_SYSCALL_DIR)/x86.tbl - \
+ | sed 's/\s\+\(break\|stty\|gtty\|ftime\|prof\|lock\|mpx\|ulimit\|profil\|idle\|afs_syscall\|getpmsg\|putpmsg\|vserver\)\s*$$/& sys_ni_syscall/' \
+ | sed 's/^\s*[0-9]\+\s\+[a-z0-9]\+\s\+\([A-Za-z0-9_]\+\)\s*$$/& sys_\1/' \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX_COMPAT(" $$1 ", " $$3 ", " $$4 ", " $$5 ") D\\"}' \
+ | sed 's/X_COMPAT(\(.*\), ) D\\$$/X(\1) D\\/' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/x86.tbl | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/x86.tbl | awk '{ print $$2 }' | grep '^i386$$')"
+
+
+generated/linux-syscalls-xtensa.h: $(LINUX_SYSCALL_DIR)/xtensa.tbl linux/syscalls.mk
+ mkdir -p -- generated
+ printf '\43define LIST_LINUX_SYSCALLS_FOR_XTENSA(X, _X_COMPAT, D)\\\n' > $@
+ printf '%i common %s %s\n' \
+ 305 timerfd sys_timerfd \
+ | cat -- $(LINUX_SYSCALL_DIR)/xtensa.tbl - \
+ | sed 's/reserved152\s\+sys_ni_syscall/set_thread_area sys_set_thread_area/' \
+ | sed 's/reserved153\s\+sys_ni_syscall/get_thread_area sys_get_thread_area/' \
+ | sed 's/nfsservctl\s\+sys_ni_syscall/nfsservctl sys_nfsservctl/' \
+ | sed '/^\s*\(\x23.*\)\?$$/d' \
+ | awk '{ print "\tX(" $$1 ", " $$3 ", " $$4 ") D\\"}' \
+ | sed '$$s/ D\\$$//' >> $@
+ test "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/xtensa.tbl | awk '{ print $$2 }')" = \
+ "$$(sed '/^\s*\(\x23.*\)\?$$/d' < $(LINUX_SYSCALL_DIR)/xtensa.tbl | awk '{ print $$2 }' | grep '^common$$')"
+
+
+$(LINUX_SYSCALLS_ARCH_TBL_SIMPLE): $(LINUX_SOURCE) linux/syscalls.mk
+ mkdir -p -- $(LINUX_SYSCALL_DIR)
+ arch="$$(printf '%s\n' "$(@F)" | cut -d . -f 1)"; \
+ if test "$$arch" = arm; then \
+ printf '%s\n' "ln -sf -- ../tools $(LINUX_DIR)/arch/$$arch/kernel/syscalls" && \
+ ln -sf -- ../tools $(LINUX_DIR)/arch/$$arch/kernel/syscalls || exit 1; \
+ fi && \
+ printf '%s\n' "cp -- $(LINUX_DIR)/arch/$$arch/kernel/syscalls/syscall.tbl $@" && \
+ cp -- $(LINUX_DIR)/arch/$$arch/kernel/syscalls/syscall.tbl $@
+
+$(LINUX_SYSCALLS_ARCH_TBL_SPLIT_X64): $(LINUX_SOURCE) linux/syscalls.mk
+ mkdir -p -- $(LINUX_SYSCALL_DIR)
+ test -e $(LINUX_DIR)/arch/x86/kernel/syscalls || \
+ ln -sf -- ../entry/syscalls $(LINUX_DIR)/arch/x86/kernel/syscalls
+ cp -- $(LINUX_DIR)/arch/x86/kernel/syscalls/syscall_32.tbl $(LINUX_SYSCALL_DIR)/x86.tbl
+ cp -- $(LINUX_DIR)/arch/x86/kernel/syscalls/syscall_64.tbl $(LINUX_SYSCALL_DIR)/amd64.tbl
+
+$(LINUX_SYSCALLS_ARCH_TBL_SPLIT_MIPS): $(LINUX_SOURCE) linux/syscalls.mk
+ mkdir -p -- $(LINUX_SYSCALL_DIR)
+ cp -- $(LINUX_DIR)/arch/mips/kernel/syscalls/syscall_n32.tbl $(LINUX_SYSCALL_DIR)/mips-n32.tbl
+ cp -- $(LINUX_DIR)/arch/mips/kernel/syscalls/syscall_o32.tbl $(LINUX_SYSCALL_DIR)/mips-o32.tbl
+ cp -- $(LINUX_DIR)/arch/mips/kernel/syscalls/syscall_n64.tbl $(LINUX_SYSCALL_DIR)/mips-n64.tbl
+
+
+generated/linux-syscall-dedup.h: $(HDR) $(LINUX_SYSCALLS_HDR) linux/syscalls.h linux/syscall-table.c linux/syscalls.mk
+ mkdir -p -- generated
+ cpp -DCREATING_DEDUP_TABLE linux/syscall-table.c \
+ | grep -v '^#' \
+ | tr '\n;\t' ' \n ' \
+ | sed -n 's/^.* libsyscalls_syscall \+\(linux_[A-Z0-9a-z_]\+_syscall_[A-Z0-9a-z_]\+.*\)$$/\1/p' \
+ | tr -d ' ' \
+ | sed 's/=/ /' \
+ | sort -k 2 \
+ | (set -e; master=; mastertext=; \
+ while read slave slavetext; do \
+ if test "$$slavetext" = "$$mastertext"; then \
+ printf '#define %s %s\n' "$$slave" "$$master"; \
+ else \
+ master="$$slave"; \
+ mastertext="$$slavetext"; \
+ fi; \
+ done \
+ ) > $@
diff --git a/linux/types.c b/linux/types.c
new file mode 100644
index 0000000..fee69fe
--- /dev/null
+++ b/linux/types.c
@@ -0,0 +1,54 @@
+/* See LICENSE file for copyright and license details. */
+
+/* This file is included from ../libsyscalls_get_datatype_description.c */
+
+
+/* If new architectures are added, the table at the top of
+ * ../libsyscalls_get_datatype_description.c must be updated */
+
+
+static enum libsyscalls_error
+get_linux_datatype_description(enum libsyscalls_arch arch, enum libsyscalls_datatype *datatype,
+ struct libsyscalls_datatype_description *description_out,
+ int *divide_array_size_with_type_size_out)
+{
+ /*
+ * Generally Linux has char as 8 bit, short int as 16, int as 32 bit,
+ * and long long int as 64 bit (it's code even make such assumptions),
+ * however that's is not necessarily the case for more exotic
+ * architectures, for example, some specialised processors have 16 bit
+ * chars and run Linux (although not mainline). Linux also used
+ * long int for addresses (intptr_t), which is normally how it should
+ * be done but Windows always set long int to 32 bit (at least on x86/amd64)
+ * for backwards compatibility, and of course it cannot be assumed that
+ * Linux does something similar this for some architecture in the future
+ * (although that looks very unlikely, at least 32+-bit architecture,
+ * it is of course possible that if Linux is ported to a 16-bit architecture,
+ * intptr_t would be 16 bits, and thus long int must be something else
+ * as it must be at least 32 bits). It's probably safe to assume,
+ * system calls use intptr_t/uintptr_t.
+ */
+
+ switch ((int)*datatype) {
+ case LIBSYSCALLS_TYPE_SCHAR: description_out->width_in_bits = 8; break;
+ case LIBSYSCALLS_TYPE_SHORT: description_out->width_in_bits = 16; break;
+ case LIBSYSCALLS_TYPE_INT: description_out->width_in_bits = 32; break;
+ case LIBSYSCALLS_TYPE_LLONG: description_out->width_in_bits = 64; break;
+
+ case LIBSYSCALLS_TYPE_LONG:
+ case LIBSYSCALLS_TYPE_DYNAMIC: /* syscall */
+ *datatype = LIBSYSCALLS_TYPE_INTPTR;
+ break;
+
+ case LIBSYSCALLS_TYPE_FD_SET:
+ *datatype = LIBSYSCALLS_TYPE_INTPTR;
+ description_out->array_size = 1024;
+ *divide_array_size_with_type_size_out = 1;
+ break;
+
+ default:
+ /* something only defined on some other operating system */
+ return LIBSYSCALLS_E_NOSUCHTYPE;
+ }
+ return LIBSYSCALLS_E_OK;
+}
diff --git a/linux/types.mk b/linux/types.mk
new file mode 100644
index 0000000..0e27c13
--- /dev/null
+++ b/linux/types.mk
@@ -0,0 +1,2 @@
+libsyscalls_get_datatype_description.o: linux/types.c
+libsyscalls_get_datatype_description.lo: linux/types.c
diff --git a/linux/what-architecture-am-i-using b/linux/what-architecture-am-i-using
new file mode 100755
index 0000000..1c7a9ba
--- /dev/null
+++ b/linux/what-architecture-am-i-using
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+set -e
+
+# TODO complete this list
+
+if uname -s | grep -i linux > /dev/null; then
+ arch="$(uname -m)"
+ if test "$arch" = x86_64; then
+ printf '%s\n' AMD64
+ if test $# = 0 || "$@"; then
+ if test $# = 0 || gunzip < /proc/config.gz | grep '^CONFIG_X86_X32_ABI=y$' > /dev/null; then
+ printf '%s\n' AMD64_X32
+ fi
+ if test $# = 0 || gunzip < /proc/config.gz | grep '^CONFIG_X86=y$' > /dev/null; then
+ printf '%s\n' I386
+ fi
+ fi
+ elif test "$arch" = i686 || test "$arch" = i386; then
+ printf '%s\n' I386
+ else
+ exit 1
+ fi
+else
+ exit 2
+fi
diff --git a/linux/yes.mk b/linux/yes.mk
new file mode 120000
index 0000000..7b78b0b
--- /dev/null
+++ b/linux/yes.mk
@@ -0,0 +1 @@
+linux-support.mk \ No newline at end of file
diff --git a/mk/generate.mk b/mk/generate.mk
new file mode 100644
index 0000000..ec33cdc
--- /dev/null
+++ b/mk/generate.mk
@@ -0,0 +1,127 @@
+NPARAMS != printf '%d\n' 1 $(NPARAMS) | sort -n | sed -n '$$p'
+
+IMPORTANT_CPPFLAGS += -DNPARAMS="$(NPARAMS)"
+
+GET_SYSCALL_RANGE_GEN != printf 'generated/get_syscall_range.%s.c\n' $(OPERATING_SYSTEMS)
+
+
+libsyscalls_get_syscall_range.o: $(GET_SYSCALL_RANGE_GEN) generated/get_syscall_range.c
+libsyscalls_get_syscall_range.lo: $(GET_SYSCALL_RANGE_GEN) generated/get_syscall_range.c
+
+libsyscalls_get_syscall_display_info.o: generated/symbols.c
+libsyscalls_get_syscall_display_info.lo: generated/symbols.c
+
+libsyscalls_get_signals.o: generated/signals.c
+libsyscalls_get_signals.lo: generated/signals.c
+
+libsyscalls_get_syscall_errors.o: generated/errors.c
+libsyscalls_get_syscall_errors.lo: generated/errors.c
+
+libsyscalls_get_datatype_description.o: generated/types.c
+libsyscalls_get_datatype_description.lo: generated/types.c
+
+
+$(GET_SYSCALL_RANGE_GEN): get_syscall_range.template.c mk/generate.mk
+ mkdir -p -- generated
+ set -e; \
+ lowercase="$$(printf '%s\n' "$@" | cut -d . -f 2)"; \
+ uppercase="$$(printf '%s\n' "$$lowercase" | tr '[a-z]' '[A-Z]')"; \
+ sed -e "s/zzz/$$lowercase/g" -e "s/ZZZ/$$uppercase/g" < get_syscall_range.template.c > $@
+
+generated/get_syscall_range.c: Makefile mk/generate.mk
+ printf '\43include "get_syscall_range.%s.c"\n' $(OPERATING_SYSTEMS) > $@
+
+generated/symbols.c: Makefile mk/generate.mk
+ mkdir -p -- generated
+ printf '\43include "../%s/symbols.c"\n' $(OPERATING_SYSTEMS) > $@
+
+generated/signals.c: Makefile mk/generate.mk
+ mkdir -p -- generated
+ printf '\43include "../%s/signals.c"\n' $(OPERATING_SYSTEMS) > $@
+
+generated/errors.c: Makefile mk/generate.mk
+ mkdir -p -- generated
+ printf '\43include "../%s/errors.c"\n' $(OPERATING_SYSTEMS) > $@
+
+generated/types.c: Makefile mk/generate.mk
+ mkdir -p -- generated
+ printf '\43include "../%s/types.c"\n' $(OPERATING_SYSTEMS) > $@
+
+generated/arches.h: Makefile mk/generate.mk
+ mkdir -p -- generated
+ printf '\43include "%s-arches.h"\n' $(OPERATING_SYSTEMS) > $@
+
+generated/oses.h: Makefile mk/generate.mk
+ mkdir -p -- generated
+ set -e;\
+ for os in $(OPERATING_SYSTEMS); do\
+ printf '%s\n' "$$(printf '%s\n' "$$os" | tr '[a-z]' '[A-Z]')" "$$os";\
+ done |\
+ (printf '\43define LIST_OSES(X, D)\\\n' &&\
+ xargs printf '\tX(%s, %s) D\\\n';\
+ ) | sed '$$s/ D\\//' > $@
+
+generated/lowercase.h: libsyscalls.h mk/generate.mk
+ mkdir -p -- generated
+ sed -n 's/^\s*LIBSYSCALLS_CAT_\([A-Z0-9_]\+\).*$$/\1/p' < libsyscalls.h \
+ | grep -v '^\(SUPPORT_PENDING\|NOT_IMPLEMENTED\)$$' \
+ | while read uppercase; do \
+ printf '\43define LOWERCASE_%s %s\n' \
+ "$$uppercase" \
+ "$$(printf '%s\n' "$$uppercase" | tr '[A-Z]' '[a-z]')"; \
+ done > $@
+
+libsyscalls/short-enums.h: libsyscalls.h mk/generate.mk
+ rm -f -- $@
+ printf '\43%s\n' > $@ \
+ 'ifndef LIBSYSCALLS_H' \
+ ' error Do not include this header file directly' \
+ 'endif'
+ sed -n 's/^.*\b\(enum_libsyscalls_[A-Za-z0-9_]\+\)\([^A-Za-z0-9_].*\|\)$$/\1/p' < libsyscalls.h \
+ | sort -u \
+ | xargs printf 'typedef unsigned short int %s;\n' \
+ >> $@
+ chmod -- a-w $@
+
+generated/macros.h: common.h mk/generate.mk
+ set -e;\
+ for find in COUNT_ARG_PAIRS PARAMS_BUILD_TYPES; do \
+ text="$$(sed -n 's/^\s*\x23\s*define\s\+'"$$find"'_1(/&/p' < common.h)"; \
+ i=1; while (( i <= $(NPARAMS) )); do \
+ j=$$(( i + 1 )); \
+ printf '%s\n' "$$text" | sed -e "s/_2/_$$j/g" -e "s/_1/_$$i/g"; \
+ i=$$j; \
+ done; \
+ done > $@;
+ (set -e; \
+ nparamspairs="$$(i=1; while (( i <= $(NPARAMS) )); do printf '%s\n' $$i $$i; : $$(( i++ )); done)"; \
+ printf '\43define PARAMS_BUILD_MASK(MASK, ...)\\\n'; \
+ printf '\t0 PARAMS_BUILD_MASK_(MASK, _, 0'; \
+ printf ', _, %s%s' $$nparamspairs; \
+ printf ')\n'; \
+ printf '\43define PARAMS_BUILD_MASK_(MASK'; \
+ printf ', A%s, x%s' $$nparamspairs; \
+ printf ', ...)'; \
+ printf '\\\n\tMASK\43\43_\43\43A%s(1U << %s)' $$nparamspairs; \
+ printf '\n'; \
+ ) >> $@
+ (set -e; \
+ for a in IN OUT SYM; do b=; \
+ for b in "$$b" "$$b"_IN; do \
+ for b in "$$b" "$$b"_OUT; do \
+ for b in "$$b" "$$b"_SYM; do \
+ c=; if printf '%s\n' "$$b" | grep "$$a" >/dev/null; then \
+ c=' |X'; \
+ fi; \
+ printf '\43define %s%s(X)%s\n' "$$a" "$$b" "$$c"; \
+ done; done; done; \
+ done) | sed 's/_IN_OUT/_BI/' | sed 's/\(\s[A-Z]\+\)(/\1__(/' >> $@
+
+
+SELF_CHECK_COMMAND = test "$(NPARAMS)" -le 16
+SELF_CHECK_RULE != if ! $(SELF_CHECK_COMMAND); then printf 'self-check\n'; fi
+libsyscalls.a: $(SELF_CHECK_RULE)
+libsyscalls.$(LIBEXT): $(SELF_CHECK_RULE)
+self-check:; $(SELF_CHECK_COMMAND)
+
+.PHONY: self-check
diff --git a/mk/linux.mk b/mk/linux.mk
new file mode 100644
index 0000000..ad58f69
--- /dev/null
+++ b/mk/linux.mk
@@ -0,0 +1,6 @@
+LIBEXT = so
+LIBFLAGS = -shared -Wl,-soname,lib$(LIB_NAME).$(LIBEXT).$(LIB_MAJOR)
+LIBMAJOREXT = $(LIBEXT).$(LIB_MAJOR)
+LIBMINOREXT = $(LIBEXT).$(LIB_VERSION)
+
+FIX_INSTALL_NAME = :
diff --git a/mk/macos.mk b/mk/macos.mk
new file mode 100644
index 0000000..e222491
--- /dev/null
+++ b/mk/macos.mk
@@ -0,0 +1,6 @@
+LIBEXT = dylib
+LIBFLAGS = -dynamiclib -Wl,-compatibility_version,$(LIB_MAJOR) -Wl,-current_version,$(LIB_VERSION)
+LIBMAJOREXT = $(LIB_MAJOR).$(LIBEXT)
+LIBMINOREXT = $(LIB_VERSION).$(LIBEXT)
+
+FIX_INSTALL_NAME = install_name_tool -id "$(PREFIX)/lib/libsyscalls.$(LIBMAJOREXT)"
diff --git a/mk/windows.mk b/mk/windows.mk
new file mode 100644
index 0000000..ed5ec8d
--- /dev/null
+++ b/mk/windows.mk
@@ -0,0 +1,6 @@
+LIBEXT = dll
+LIBFLAGS = -shared
+LIBMAJOREXT = $(LIB_MAJOR).$(LIBEXT)
+LIBMINOREXT = $(LIB_VERSION).$(LIBEXT)
+
+FIX_INSTALL_NAME = :
diff --git a/util/getdefs b/util/getdefs
new file mode 100755
index 0000000..869dff6
--- /dev/null
+++ b/util/getdefs
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+set -e
+
+text="$(cat)"
+
+expr='\(0x[0-9a-fA-F]\+\|[0-9]\+\)[Ll]*[Uu]*[Ll]*'
+expr='\(\*\|\/\|[+~-]\|<<\|>>\)\?\s*'"$expr"
+expr='\('"$expr"'\|(\|)\)'
+expr='\s*\('"$expr"'\s*\)\+'
+
+filter () {
+ sed -n 's/^\s*#\s*define\s\+\('"$1"'\)\s\+\('"$expr"'\)\s*\(\/.*\)\?$/\1 \2/p'
+}
+
+if test $# = 0; then
+ printf '%s\n' "$text" | filter '[A-Z0-9_]\+'
+else
+ for prefix; do
+ printf '%s\n' "$text" | filter "$prefix"'_[A-Z0-9_]\+'
+ done
+fi | \
+while read name value; do
+ value="$(printf '%s\n' "$value" | tr -d ULul)"
+ value=$(printf '%s\n' "$(( $value ))" | cut -d . -f 1)
+ printf '%s %s\n' "$name" "$value"
+done
diff --git a/util/getenum b/util/getenum
new file mode 100755
index 0000000..84cb73e
--- /dev/null
+++ b/util/getenum
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+set -e
+
+sed '1,/^\s*enum\s\+'"$1"'\b/d' | \
+tr '\n' '\0' | cut -d \; -f 1 | tr '\0' '\n' | \
+sed -n 's/^\s*\([A-Z0-9_]\+\)\(\s*=[^,]*\)\?\s*,\?\s*\(\/.*\)\?/\1\2/p' | \
+sed 's/=/ /g' | \
+(
+ prev=-1
+ while read name value; do
+ if test -z "$value"; then
+ value=$(( prev + 1 ))
+ else
+ value="$(printf '%s\n' "$value" | tr -d ULul)"
+ value=$(printf '%s\n' "$(( $value ))" | cut -d . -f 1)
+ fi
+ printf '%s %s\n' "$name" "$value"
+ prev=$value
+ done
+)
diff --git a/util/make-enum b/util/make-enum
new file mode 100755
index 0000000..7b63e3c
--- /dev/null
+++ b/util/make-enum
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+set -e
+
+test $# -ge 1
+
+lowercase () { printf '%s\n' "$*" | tr '[A-Z]' '[a-z]'; }
+
+symbols="$(lowercase "$1")"
+shift 1
+
+validate () {
+ if (( -$1 > 0x7FFF )) || (( +$1 > 0x7FFF )); then
+ printf 'Invalid enum value: %s = %x (beyond 16-bit signed integer)\n' $2 $1 >&2
+ return 1
+ else
+ return 0
+ fi
+}
+
+printf 'static const char *\n'
+printf 'extract_symbol_%s(struct libsyscalls_symbol_printer_data *data, ' "$symbols"
+printf 'unsigned long long int *valuep, char *fallback_out) /* 1 */\n'
+printf '{\n'
+printf ' const char *ret;\n'
+printf ' switch ((signed long long int)*valuep) {\n'
+while read name value; do
+validate $value $name
+printf ' case %i: ret = "%s"; break;\n' $value $name
+done
+printf ' default:\n'
+if test $# -ge 1; then
+ for use; do
+printf ' if ((ret = extract_symbol_%s(data, valuep, fallback_out))) return ret;\n' "$(lowercase "$use")"
+ done
+fi
+printf ' return NULL;\n'
+printf ' }\n'
+printf ' *valuep = 0;\n'
+if test $# = 0; then
+printf ' (void) data;\n'
+printf ' (void) fallback_out;\n'
+fi
+printf ' return ret;\n'
+printf '}\n'
diff --git a/util/make-mask b/util/make-mask
new file mode 100755
index 0000000..1285f52
--- /dev/null
+++ b/util/make-mask
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+set -e
+
+test $# -ge 1
+
+lowercase () { printf '%s\n' "$*" | tr '[A-Z]' '[a-z]'; }
+
+symbols="$(lowercase "$1")"
+shift 1
+
+trailing_zeroes () {
+ r=0
+ x=$1
+ while (( (x & 1) == 0 )); do
+ : $(( r++ ))
+ x=$(( x >> 1 ))
+ done
+ if (( x > 1 )); then
+ printf 'Invalid bitmask value: %s = %#x: multiple bits set\n' $2 $1 >&2
+ exit 1
+ fi
+ printf '%i\n' $r
+}
+
+ifzero=
+printf 'static const char *\n'
+printf 'extract_symbol_%s(struct libsyscalls_symbol_printer_data *data, ' "$symbols"
+printf 'unsigned long long int *valuep, char *fallback_out) /* 1 */\n'
+printf '{\n'
+printf ' const char *ret;\n'
+printf ' signed char bit = trailing_zeroes(*valuep);\n'
+printf ' *fallback_out = %s;\n' "'x'"
+printf ' switch (bit) {\n'
+while read name value; do
+ if test $value = 0; then ifzero="$name"; continue; fi
+printf ' case %i: ret = "%s"; break;\n' $(trailing_zeroes $value $name) $name
+done
+if test -n "$ifzero"; then
+printf ' case -1: return "%s";\n' $ifzero
+fi
+printf ' default:\n'
+if test $# -ge 1; then
+ for use; do
+printf ' if ((ret = extract_symbol_%s(data, valuep, fallback_out))) return ret;\n' "$(lowercase "$use")"
+ done
+fi
+printf ' return NULL;\n'
+printf ' }\n'
+printf ' *valuep ^= 1ULL << (unsigned)bit;\n'
+if test $# = 0; then
+printf ' (void) data;\n'
+fi
+printf ' return ret;\n'
+printf '}\n'
diff --git a/util/make-multiextractor b/util/make-multiextractor
new file mode 100755
index 0000000..487162e
--- /dev/null
+++ b/util/make-multiextractor
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+set -e
+
+test $# -ge 3
+
+lowercase () { printf '%s\n' "$*" | tr '[A-Z]' '[a-z]'; }
+
+symbols="$(lowercase "$1")"
+shift 1
+
+printf 'static const char *\n'
+printf 'extract_symbol_%s(struct libsyscalls_symbol_printer_data *data, ' "$symbols"
+printf 'unsigned long long int *valuep, char *fallback_out) /* %i */\n' $#
+printf '{\n'
+printf ' switch (data->nr) {\n'
+i=0
+for use; do
+printf ' case %i:\n' $(( i++ ))
+printf ' return extract_symbol_%s(data, valuep, fallback_out);\n' "$(lowercase "$use")"
+done
+printf ' default:\n'
+printf ' abort();\n'
+printf ' }\n'
+printf '}\n'
diff --git a/util/make-sym-extractor b/util/make-sym-extractor
new file mode 100755
index 0000000..7fec6b8
--- /dev/null
+++ b/util/make-sym-extractor
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+set -e
+
+test $# = 2
+
+symbols="$1"
+how=""
+deps=""
+set $(printf '%s\n' "$2" | tr ',|' ' ')
+
+for dep; do
+ if test "$dep" = mask || test "$dep" = enum; then
+ test -z "$how"
+ how="$dep"
+ else
+ deps="$deps $dep"
+ fi
+done
+
+test -n "$how"
+
+dir="$(dirname -- "$0")"
+
+$dir/make-$how "$symbols" $deps
diff --git a/util/what-architecture-am-i-using b/util/what-architecture-am-i-using
new file mode 100755
index 0000000..e64d255
--- /dev/null
+++ b/util/what-architecture-am-i-using
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+dir="$(dirname -- "$0")"
+
+for cmd in "$dir"/../*/what-architecture-am-i-using; do
+ if printf '%s\n' "$cmd" | grep '/util/what-architecture-am-i-using$' > /dev/null; then
+ continue
+ fi
+ "$cmd" "$@"
+ status=$?
+ if test $status = 0; then
+ exit 0
+ elif test $status = 1; then
+ printf '%s\n' 'Architecture not recognised' >&2
+ printf 'UNRECOGNISED\n'
+ exit 1
+ fi
+done
+
+printf '%s\n' 'Operating system not recognised' >&2
+printf 'UNRECOGNISED\n'
+exit 2