1#!/usr/bin/python3 2# Regenerate <arch-syscall.h> and update syscall-names.list. 3# Copyright (C) 2020-2021 Free Software Foundation, Inc. 4# This file is part of the GNU C Library. 5# 6# The GNU C Library is free software; you can redistribute it and/or 7# modify it under the terms of the GNU Lesser General Public 8# License as published by the Free Software Foundation; either 9# version 2.1 of the License, or (at your option) any later version. 10# 11# The GNU C Library is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14# Lesser General Public License for more details. 15# 16# You should have received a copy of the GNU Lesser General Public 17# License along with the GNU C Library; if not, see 18# <http://www.gnu.org/licenses/>. 19 20import argparse 21import io 22import os 23import sys 24 25import glibcextract 26import glibcsyscalls 27 28def atomic_replace(path, contents): 29 """Atomically replace PATH with CONTENTS, via a temporary file. 30 31 The name of the temporary file is predictable, so locking is 32 required to avoid corruption. 33 34 """ 35 path_tmp = path + 'T' 36 with open(path_tmp, 'w') as tmp: 37 tmp.write(contents) 38 ok = False 39 try: 40 os.rename(path_tmp, path) 41 ok = True 42 finally: 43 # On error, try to delete the temporary file. 44 if not ok: 45 try: 46 os.unlink(path_tmp) 47 except: 48 pass 49 50def main(): 51 """The main entry point.""" 52 parser = argparse.ArgumentParser( 53 description='System call list consistency checks') 54 parser.add_argument('--cc', metavar='CC', required=True, 55 help='C compiler (including options) to use') 56 parser.add_argument('--lock', metavar='PATH', required=True, 57 help='file to lock during the updates') 58 parser.add_argument('arch_syscall', metavar='ARCH-SYSCALL-H', 59 help='The <arch-syscall.h> file to update') 60 parser.add_argument('names_list', metavar='SYSCALL-NAMES-LIST', 61 help='The syscall name list to update ') 62 63 args = parser.parse_args() 64 65 kernel_constants = glibcsyscalls.kernel_constants(args.cc) 66 67 with open(args.lock, 'r+') as lockfile: 68 os.lockf(lockfile.fileno(), os.F_LOCK, 0) 69 70 # Replace <arch-syscall.h> with data derived from kernel headers. 71 # No merging is necessary here. Arch-specific changes should go 72 # into <fixup-unistd-asm.h>. 73 out = io.StringIO() 74 out.write('/* AUTOGENERATED by update-syscall-lists.py. */\n') 75 for name, value in sorted(kernel_constants.items()): 76 out.write('#define __NR_{} {}\n'.format(name, value)) 77 atomic_replace(args.arch_syscall, out.getvalue()) 78 79 # Merge the architecture-specific system call names into the 80 # global names list, syscall-names.list. This file contains names 81 # from other architectures (and comments), so it is necessary to 82 # merge the existing files with the names obtained from the 83 # kernel. 84 with open(args.names_list, 'r') as list_file: 85 names_list = glibcsyscalls.SyscallNamesList(list_file) 86 merged = names_list.merge(kernel_constants.keys()) 87 out = io.StringIO() 88 for line in merged: 89 out.write(line) 90 atomic_replace(args.names_list, out.getvalue()) 91 92if __name__ == '__main__': 93 main() 94