| #!/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', |
| '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}') |