mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
src/basic: generate missing syscall headers programatically
Getting the numbers right for all architectures has proven to be a constant chore. Let's autogenerate the header from the tables that were imported in one of the previous commits. Fixes #18074. (Hopefully. I cannot verify this on all architectures.) To update the lists, or to update the header after template changes: ninja -C build update-syscall-tables update-syscall-header Note: the generated file is saved in git. Initially I wanted to only store the tables in git, and generate the header during each build. Generation is quick enough, but the header is used in many many places (wherever missing_syscall.h is included, directly or indirectly), which means that we would need to declare the dependency in meson, so the header would be generated early enough. This turned out to be very noisy. Storing the generated header in version control avoids the hassle.
This commit is contained in:
@@ -262,6 +262,9 @@ missing_audit_h = files('missing_audit.h')
|
||||
missing_capability_h = files('missing_capability.h')
|
||||
missing_socket_h = files('missing_socket.h')
|
||||
|
||||
missing_syscall_def_h = files('missing_syscall_def.h')
|
||||
basic_sources += missing_syscall_def_h
|
||||
|
||||
generate_af_list = find_program('generate-af-list.sh')
|
||||
af_list_txt = custom_target(
|
||||
'af-list.txt',
|
||||
@@ -330,32 +333,6 @@ foreach item : [['af', af_list_txt, 'af', ''],
|
||||
endforeach
|
||||
|
||||
basic_sources += generated_gperf_headers
|
||||
basic_gcrypt_sources = files(
|
||||
'gcrypt-util.c',
|
||||
'gcrypt-util.h')
|
||||
|
||||
libbasic = static_library(
|
||||
'basic',
|
||||
basic_sources,
|
||||
include_directories : includes,
|
||||
dependencies : [versiondep,
|
||||
threads,
|
||||
libcap,
|
||||
libseccomp,
|
||||
libselinux,
|
||||
libm,
|
||||
libdl],
|
||||
c_args : ['-fvisibility=default'],
|
||||
install : false)
|
||||
|
||||
# A convenience library that is separate from libbasic to avoid
|
||||
# unnecessary linking to libgcrypt.
|
||||
libbasic_gcrypt = static_library(
|
||||
'basic-gcrypt',
|
||||
basic_gcrypt_sources,
|
||||
include_directories : includes,
|
||||
dependencies : [libgcrypt],
|
||||
c_args : ['-fvisibility=default'])
|
||||
|
||||
############################################################
|
||||
|
||||
@@ -382,3 +359,47 @@ run_target(
|
||||
command : [syscall_table_update_sh, meson.current_source_dir()] + arch_list)
|
||||
|
||||
syscall_names_text = files('syscall-names.text')
|
||||
|
||||
syscall_lists = []
|
||||
foreach arch: arch_list
|
||||
syscall_lists += files('syscalls-@0@'.format(arch))
|
||||
endforeach
|
||||
|
||||
missing_syscalls_py = find_program('missing_syscalls.py')
|
||||
|
||||
run_target(
|
||||
'update-syscall-header',
|
||||
command : [missing_syscalls_py,
|
||||
missing_syscall_def_h,
|
||||
syscall_lists])
|
||||
|
||||
############################################################
|
||||
|
||||
libbasic = static_library(
|
||||
'basic',
|
||||
basic_sources,
|
||||
include_directories : includes,
|
||||
dependencies : [versiondep,
|
||||
threads,
|
||||
libcap,
|
||||
libseccomp,
|
||||
libselinux,
|
||||
libm,
|
||||
libdl],
|
||||
c_args : ['-fvisibility=default'],
|
||||
install : false)
|
||||
|
||||
############################################################
|
||||
|
||||
basic_gcrypt_sources = files(
|
||||
'gcrypt-util.c',
|
||||
'gcrypt-util.h')
|
||||
|
||||
# A convenience library that is separate from libbasic to avoid
|
||||
# unnecessary linking to libgcrypt.
|
||||
libbasic_gcrypt = static_library(
|
||||
'basic-gcrypt',
|
||||
basic_gcrypt_sources,
|
||||
include_directories : includes,
|
||||
dependencies : [libgcrypt],
|
||||
c_args : ['-fvisibility=default'])
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
674
src/basic/missing_syscall_def.h
Normal file
674
src/basic/missing_syscall_def.h
Normal file
File diff suppressed because it is too large
Load Diff
115
src/basic/missing_syscalls.py
Normal file
115
src/basic/missing_syscalls.py
Normal file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import os
|
||||
import functools
|
||||
|
||||
# We only generate numbers for a dozen or so syscalls
|
||||
SYSCALLS = [
|
||||
'bpf',
|
||||
'close_range',
|
||||
'copy_file_range',
|
||||
'getrandom',
|
||||
'memfd_create',
|
||||
'name_to_handle_at',
|
||||
'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]: parse_syscall_table(filename)
|
||||
for filename in filenames}
|
||||
|
||||
DEF_TEMPLATE = '''\
|
||||
#ifndef __IGNORE_{syscall}
|
||||
# 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(__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(__powerpc__)
|
||||
# define systemd_NR_{syscall} {nr_powerpc}
|
||||
# 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
|
||||
# else
|
||||
# warning "{syscall}() syscall number is unknown for your architecture"
|
||||
# endif
|
||||
|
||||
/* may be (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 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('/* This file is generated. Do not edit! */\n', 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}')
|
||||
Reference in New Issue
Block a user