1#!/usr/bin/python3 2# Consistency checks for glibc system call lists. 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 sys 22 23import glibcextract 24import glibcsyscalls 25 26def main(): 27 """The main entry point.""" 28 parser = argparse.ArgumentParser( 29 description="System call list consistency checks") 30 parser.add_argument('--cc', metavar='CC', required=True, 31 help='C compiler (including options) to use') 32 parser.add_argument('syscall_numbers_list', metavar='PATH', 33 help='Path to the list of system call numbers') 34 parser.add_argument('syscall_names_list', metavar='PATH', 35 help='Path to the list of system call names') 36 37 args = parser.parse_args() 38 39 glibc_constants = glibcsyscalls.load_arch_syscall_header( 40 args.syscall_numbers_list) 41 with open(args.syscall_names_list) as inp: 42 glibc_names = glibcsyscalls.SyscallNamesList(inp) 43 kernel_constants = glibcsyscalls.kernel_constants(args.cc) 44 kernel_version = glibcsyscalls.linux_kernel_version(args.cc) 45 46 errors = 0 47 warnings = False 48 for name in glibc_constants.keys() & kernel_constants.keys(): 49 if glibc_constants[name] != kernel_constants[name]: 50 print("error: syscall {!r} number mismatch: glibc={!r} kernel={!r}" 51 .format(name, glibc_constants[name], kernel_constants[name])) 52 errors = 1 53 54 # The architecture-specific list in the glibc tree must be a 55 # subset of the global list of system call names. 56 for name in glibc_constants.keys() - set(glibc_names.syscalls): 57 print("error: architecture syscall {!r} missing from global names list" 58 .format(name)) 59 errors = 1 60 61 for name in glibc_constants.keys() - kernel_constants.keys(): 62 print("info: glibc syscall {!r} not known to kernel".format(name)) 63 warnings = True 64 65 # If the glibc-recorded kernel version is not older than the 66 # installed kernel headers, the glibc system call set must be a 67 # superset of the kernel system call set. 68 if glibc_names.kernel_version >= kernel_version: 69 for name in kernel_constants.keys() - glibc_constants.keys(): 70 print("error: kernel syscall {!r} ({}) not known to glibc" 71 .format(name, kernel_constants[name])) 72 errors = 1 73 else: 74 for name in kernel_constants.keys() - glibc_constants.keys(): 75 print("warning: kernel syscall {!r} ({}) not known to glibc" 76 .format(name, kernel_constants[name])) 77 warnings = True 78 79 if errors > 0 or warnings: 80 print("info: glibc tables are based on kernel version {}".format( 81 ".".join(map(str, glibc_names.kernel_version)))) 82 print("info: installed kernel headers are version {}".format( 83 ".".join(map(str, kernel_version)))) 84 85 sys.exit(errors) 86 87if __name__ == '__main__': 88 main() 89