diff options
Diffstat (limited to 'src/basic/missing_syscalls.py')
-rw-r--r-- | src/basic/missing_syscalls.py | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/src/basic/missing_syscalls.py b/src/basic/missing_syscalls.py new file mode 100644 index 0000000..642d4d9 --- /dev/null +++ b/src/basic/missing_syscalls.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1-or-later + +import sys +import functools + +# We only generate numbers for a dozen or so syscalls +SYSCALLS = [ + 'bpf', + 'close_range', + 'copy_file_range', + 'epoll_pwait2', + 'getrandom', + 'memfd_create', + 'mount_setattr', + 'move_mount', + 'name_to_handle_at', + 'open_tree', + 'openat2', + 'pidfd_open', + 'pidfd_send_signal', + 'pkey_mprotect', + 'renameat2', + 'setns', + 'statx', +] + +def dictify(f): + def wrap(*args, **kwargs): + return dict(f(*args, **kwargs)) + return functools.update_wrapper(wrap, f) + +@dictify +def parse_syscall_table(filename): + print(f'Reading {filename}…') + for line in open(filename): + items = line.split() + if len(items) >= 2: + yield items[0], int(items[1]) + +def parse_syscall_tables(filenames): + return {filename.split('-')[-1][:-4]: parse_syscall_table(filename) + for filename in filenames} + +DEF_TEMPLATE_A = '''\ + +#ifndef __IGNORE_{syscall} +''' + +DEF_TEMPLATE_B = '''\ +# if defined(__aarch64__) +# define systemd_NR_{syscall} {nr_arm64} +# elif defined(__alpha__) +# define systemd_NR_{syscall} {nr_alpha} +# elif defined(__arc__) || defined(__tilegx__) +# define systemd_NR_{syscall} {nr_arc} +# elif defined(__arm__) +# define systemd_NR_{syscall} {nr_arm} +# elif defined(__i386__) +# define systemd_NR_{syscall} {nr_i386} +# elif defined(__ia64__) +# define systemd_NR_{syscall} {nr_ia64} +# elif defined(__loongarch64) +# define systemd_NR_{syscall} {nr_loongarch64} +# elif defined(__m68k__) +# define systemd_NR_{syscall} {nr_m68k} +# elif defined(_MIPS_SIM) +# if _MIPS_SIM == _MIPS_SIM_ABI32 +# define systemd_NR_{syscall} {nr_mipso32} +# elif _MIPS_SIM == _MIPS_SIM_NABI32 +# define systemd_NR_{syscall} {nr_mips64n32} +# elif _MIPS_SIM == _MIPS_SIM_ABI64 +# define systemd_NR_{syscall} {nr_mips64} +# else +# error "Unknown MIPS ABI" +# endif +# elif defined(__hppa__) +# define systemd_NR_{syscall} {nr_parisc} +# elif defined(__powerpc__) +# define systemd_NR_{syscall} {nr_powerpc} +# elif defined(__riscv) +# if __riscv_xlen == 32 +# define systemd_NR_{syscall} {nr_riscv32} +# elif __riscv_xlen == 64 +# define systemd_NR_{syscall} {nr_riscv64} +# else +# error "Unknown RISC-V ABI" +# endif +# elif defined(__s390__) +# define systemd_NR_{syscall} {nr_s390} +# elif defined(__sparc__) +# define systemd_NR_{syscall} {nr_sparc} +# elif defined(__x86_64__) +# if defined(__ILP32__) +# define systemd_NR_{syscall} ({nr_x86_64} | /* __X32_SYSCALL_BIT */ 0x40000000) +# else +# define systemd_NR_{syscall} {nr_x86_64} +# endif +# elif !defined(missing_arch_template) +%s +# endif +''' + +DEF_TEMPLATE_C = '''\ + +/* may be an (invalid) negative number due to libseccomp, see PR 13319 */ +# if defined __NR_{syscall} && __NR_{syscall} >= 0 +# if defined systemd_NR_{syscall} +assert_cc(__NR_{syscall} == systemd_NR_{syscall}); +# endif +# else +# if defined __NR_{syscall} +# undef __NR_{syscall} +# endif +# if defined systemd_NR_{syscall} && systemd_NR_{syscall} >= 0 +# define __NR_{syscall} systemd_NR_{syscall} +# endif +# endif +#endif''' + +DEF_TEMPLATE = (DEF_TEMPLATE_A + + DEF_TEMPLATE_B % '# warning "{syscall}() syscall number is unknown for your architecture"' + + DEF_TEMPLATE_C) + +ARCH_CHECK = '''\ +/* Note: if this code looks strange, this is because it is derived from the same + * template as the per-syscall blocks below. */ +''' + '\n'.join(line for line in DEF_TEMPLATE_B.splitlines() + if ' define ' not in line) % '''\ +# warning "Current architecture is missing from the template" +# define missing_arch_template 1''' + +def print_syscall_def(syscall, tables, out): + mappings = {f'nr_{arch}':t.get(syscall, -1) + for arch, t in tables.items()} + print(DEF_TEMPLATE.format(syscall=syscall, **mappings), + file=out) + +def print_syscall_defs(syscalls, tables, out): + print('''\ +/* SPDX-License-Identifier: LGPL-2.1-or-later + * This file is generated by src/basic/missing_syscalls.py. Do not edit! + * + * Use 'ninja -C build update-syscall-tables' to download new syscall tables, + * and 'ninja -C build update-syscall-header' to regenerate this file. + */ +#pragma once +''', + file=out) + print(ARCH_CHECK, file=out) + for syscall in syscalls: + print_syscall_def(syscall, tables, out) + +if __name__ == '__main__': + output_file = sys.argv[1] + arch_files = sys.argv[2:] + out = open(output_file, 'wt') + + tables = parse_syscall_tables(arch_files) + print_syscall_defs(SYSCALLS, tables, out) + + print(f'Wrote {output_file}') |