1#!/usr/bin/env python3 2# SPDX-License-Identifier: LGPL-2.1-or-later 3 4import sys 5import functools 6 7# We only generate numbers for a dozen or so syscalls 8SYSCALLS = [ 9 'bpf', 10 'close_range', 11 'copy_file_range', 12 'epoll_pwait2', 13 'getrandom', 14 'memfd_create', 15 'mount_setattr', 16 'move_mount', 17 'name_to_handle_at', 18 'open_tree', 19 'openat2', 20 'pidfd_open', 21 'pidfd_send_signal', 22 'pkey_mprotect', 23 'renameat2', 24 'setns', 25 'statx', 26] 27 28def dictify(f): 29 def wrap(*args, **kwargs): 30 return dict(f(*args, **kwargs)) 31 return functools.update_wrapper(wrap, f) 32 33@dictify 34def parse_syscall_table(filename): 35 print(f'Reading {filename}…') 36 for line in open(filename): 37 items = line.split() 38 if len(items) >= 2: 39 yield items[0], int(items[1]) 40 41def parse_syscall_tables(filenames): 42 return {filename.split('-')[-1][:-4]: parse_syscall_table(filename) 43 for filename in filenames} 44 45DEF_TEMPLATE_A = '''\ 46 47#ifndef __IGNORE_{syscall} 48''' 49 50DEF_TEMPLATE_B = '''\ 51# if defined(__aarch64__) 52# define systemd_NR_{syscall} {nr_arm64} 53# elif defined(__alpha__) 54# define systemd_NR_{syscall} {nr_alpha} 55# elif defined(__arc__) || defined(__tilegx__) 56# define systemd_NR_{syscall} {nr_arc} 57# elif defined(__arm__) 58# define systemd_NR_{syscall} {nr_arm} 59# elif defined(__i386__) 60# define systemd_NR_{syscall} {nr_i386} 61# elif defined(__ia64__) 62# define systemd_NR_{syscall} {nr_ia64} 63# elif defined(__loongarch64) 64# define systemd_NR_{syscall} {nr_loongarch64} 65# elif defined(__m68k__) 66# define systemd_NR_{syscall} {nr_m68k} 67# elif defined(_MIPS_SIM) 68# if _MIPS_SIM == _MIPS_SIM_ABI32 69# define systemd_NR_{syscall} {nr_mipso32} 70# elif _MIPS_SIM == _MIPS_SIM_NABI32 71# define systemd_NR_{syscall} {nr_mips64n32} 72# elif _MIPS_SIM == _MIPS_SIM_ABI64 73# define systemd_NR_{syscall} {nr_mips64} 74# else 75# error "Unknown MIPS ABI" 76# endif 77# elif defined(__powerpc__) 78# define systemd_NR_{syscall} {nr_powerpc} 79# elif defined(__riscv) 80# if __riscv_xlen == 32 81# define systemd_NR_{syscall} {nr_riscv32} 82# elif __riscv_xlen == 64 83# define systemd_NR_{syscall} {nr_riscv64} 84# else 85# error "Unknown RISC-V ABI" 86# endif 87# elif defined(__s390__) 88# define systemd_NR_{syscall} {nr_s390} 89# elif defined(__sparc__) 90# define systemd_NR_{syscall} {nr_sparc} 91# elif defined(__x86_64__) 92# if defined(__ILP32__) 93# define systemd_NR_{syscall} ({nr_x86_64} | /* __X32_SYSCALL_BIT */ 0x40000000) 94# else 95# define systemd_NR_{syscall} {nr_x86_64} 96# endif 97# elif !defined(missing_arch_template) 98%s 99# endif 100''' 101 102DEF_TEMPLATE_C = '''\ 103 104/* may be an (invalid) negative number due to libseccomp, see PR 13319 */ 105# if defined __NR_{syscall} && __NR_{syscall} >= 0 106# if defined systemd_NR_{syscall} 107assert_cc(__NR_{syscall} == systemd_NR_{syscall}); 108# endif 109# else 110# if defined __NR_{syscall} 111# undef __NR_{syscall} 112# endif 113# if defined systemd_NR_{syscall} && systemd_NR_{syscall} >= 0 114# define __NR_{syscall} systemd_NR_{syscall} 115# endif 116# endif 117#endif''' 118 119DEF_TEMPLATE = (DEF_TEMPLATE_A + 120 DEF_TEMPLATE_B % '# warning "{syscall}() syscall number is unknown for your architecture"' + 121 DEF_TEMPLATE_C) 122 123ARCH_CHECK = '''\ 124/* Note: if this code looks strange, this is because it is derived from the same 125 * template as the per-syscall blocks below. */ 126''' + '\n'.join(line for line in DEF_TEMPLATE_B.splitlines() 127 if ' define ' not in line) % '''\ 128# warning "Current architecture is missing from the template" 129# define missing_arch_template 1''' 130 131def print_syscall_def(syscall, tables, out): 132 mappings = {f'nr_{arch}':t.get(syscall, -1) 133 for arch, t in tables.items()} 134 print(DEF_TEMPLATE.format(syscall=syscall, **mappings), 135 file=out) 136 137def print_syscall_defs(syscalls, tables, out): 138 print('''\ 139/* SPDX-License-Identifier: LGPL-2.1-or-later 140 * This file is generated by src/basic/missing_syscalls.py. Do not edit! 141 * 142 * Use 'ninja -C build update-syscall-tables' to download new syscall tables, 143 * and 'ninja -C build update-syscall-header' to regenerate this file. 144 */ 145#pragma once 146''', 147 file=out) 148 print(ARCH_CHECK, file=out) 149 for syscall in syscalls: 150 print_syscall_def(syscall, tables, out) 151 152if __name__ == '__main__': 153 output_file = sys.argv[1] 154 arch_files = sys.argv[2:] 155 out = open(output_file, 'wt') 156 157 tables = parse_syscall_tables(arch_files) 158 print_syscall_defs(SYSCALLS, tables, out) 159 160 print(f'Wrote {output_file}') 161