diff options
Diffstat (limited to '')
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 @@ -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 @@ -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,\ + ÷_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 |