1#!/usr/bin/python 2# 3# this tool is used to check that the syscall numbers that are in 4# SYSCALLS.TXT correspond to those found in the Linux kernel sources 5# for the arm and i386 architectures 6# 7 8import sys, re, string, os, commands 9from bionic_utils import * 10 11# change this if necessary 12syscalls_txt = "SYSCALLS.TXT" 13 14def usage(): 15 print "usage: checksyscalls [options] [kernel_headers_rootdir]" 16 print " options: -v enable verbose mode" 17 sys.exit(1) 18 19 20linux_root = None 21syscalls_file = None 22 23def parse_command_line(args): 24 global linux_root, syscalls_file, verbose 25 26 program = args[0] 27 args = args[1:] 28 while len(args) > 0 and args[0][0] == "-": 29 option = args[0][1:] 30 args = args[1:] 31 32 if option == "v": 33 D_setlevel(1) 34 else: 35 usage() 36 37 if len(args) > 2: 38 usage() 39 40 if len(args) == 0: 41 linux_root = find_kernel_headers() 42 if linux_root == None: 43 print "Could not locate original or system kernel headers root directory." 44 print "Please specify one when calling this program, i.e. 'checksyscalls <headers-directory>'" 45 sys.exit(1) 46 print "using the following kernel headers root: '%s'" % linux_root 47 else: 48 linux_root = args[0] 49 if not os.path.isdir(linux_root): 50 print "the directory '%s' does not exist. aborting\n" % headers_root 51 sys.exit(1) 52 53parse_command_line(sys.argv) 54 55syscalls_file = find_file_from_upwards(None, syscalls_txt) 56if not syscalls_file: 57 print "could not locate the %s file. Aborting" % syscalls_txt 58 sys.exit(1) 59 60print "parsing %s" % syscalls_file 61 62# read the syscalls description file 63# 64 65parser = SysCallsTxtParser() 66parser.parse_file(syscalls_file) 67syscalls = parser.syscalls 68 69re_nr_line = re.compile( r"#define __NR_(\w*)\s*\(__NR_SYSCALL_BASE\+\s*(\w*)\)" ) 70re_nr_clock_line = re.compile( r"#define __NR_(\w*)\s*\(__NR_timer_create\+(\w*)\)" ) 71re_arm_nr_line = re.compile( r"#define __ARM_NR_(\w*)\s*\(__ARM_NR_BASE\+\s*(\w*)\)" ) 72re_x86_line = re.compile( r"#define __NR_(\w*)\s*([0-9]*)" ) 73re_mips_line = re.compile( r"#define __NR_(\w*)\s*\(__NR_Linux\s*\+\s*([0-9]*)\)" ) 74 75# now read the Linux arm header 76def process_nr_line(line,dict): 77 78 m = re_mips_line.match(line) 79 if m: 80 if dict["Linux"]==4000: 81 dict[m.group(1)] = int(m.group(2)) 82 return 83 84 m = re_nr_line.match(line) 85 if m: 86 dict[m.group(1)] = int(m.group(2)) 87 return 88 89 m = re_nr_clock_line.match(line) 90 if m: 91 dict[m.group(1)] = int(m.group(2)) + 259 92 return 93 94 m = re_arm_nr_line.match(line) 95 if m: 96 offset_str = m.group(2) 97 #print "%s = %s" % (m.group(1), offset_str) 98 base = 10 99 if offset_str.lower().startswith("0x"): 100 # Processing something similar to 101 # #define __ARM_NR_cmpxchg (__ARM_NR_BASE+0x00fff0) 102 base = 16 103 dict["ARM_"+m.group(1)] = int(offset_str, base) + 0x0f0000 104 return 105 106 m = re_x86_line.match(line) 107 if m: 108 # try block because the ARM header has some #define _NR_XXXXX /* nothing */ 109 try: 110 #print "%s = %s" % (m.group(1), m.group(2)) 111 dict[m.group(1)] = int(m.group(2)) 112 except: 113 pass 114 return 115 116 117def process_header(header_file,dict): 118 fp = open(header_file) 119 D("reading "+header_file) 120 for line in fp.xreadlines(): 121 line = line.strip() 122 if not line: continue 123 process_nr_line(line,dict) 124 fp.close() 125 126arm_dict = {} 127x86_dict = {} 128mips_dict = {} 129 130# remove trailing slash from the linux_root, if any 131if linux_root[-1] == '/': 132 linux_root = linux_root[:-1] 133 134arm_unistd = find_arch_header(linux_root, "arm", "unistd.h") 135if not arm_unistd: 136 print "WEIRD: Could not locate the ARM unistd.h kernel header file," 137 print "maybe using a different set of kernel headers might help." 138 sys.exit(1) 139 140# on recent kernels, asm-i386 and asm-x64_64 have been merged into asm-x86 141# with two distinct unistd_32.h and unistd_64.h definition files. 142# take care of this here 143# 144x86_unistd = find_arch_header(linux_root, "i386", "unistd.h") 145if not x86_unistd: 146 x86_unistd = find_arch_header(linux_root, "x86", "unistd_32.h") 147 if not x86_unistd: 148 print "WEIRD: Could not locate the i386/x86 unistd.h header file," 149 print "maybe using a different set of kernel headers might help." 150 sys.exit(1) 151 152mips_unistd = find_arch_header(linux_root, "mips", "unistd.h") 153if not mips_unistd: 154 print "WEIRD: Could not locate the Mips unistd.h kernel header file," 155 print "maybe using a different set of kernel headers might help." 156 sys.exit(1) 157 158process_header( arm_unistd, arm_dict ) 159process_header( x86_unistd, x86_dict ) 160process_header( mips_unistd, mips_dict ) 161 162# now perform the comparison 163errors = 0 164 165def check_syscalls(archname, idname, arch_dict): 166 errors = 0 167 for sc in syscalls: 168 sc_name = sc["name"] 169 sc_id = sc[idname] 170 if sc_id >= 0: 171 if not arch_dict.has_key(sc_name): 172 print "error: %s syscall %s not defined, should be %d" % (archname, sc_name, sc_id) 173 errors += 1 174 elif not arch_dict.has_key(sc_name): 175 print "error: %s syscall %s is not implemented" % (archname, sc_name) 176 errors += 1 177 elif arch_dict[sc_name] != sc_id: 178 print "error: %s syscall %s should be %d instead of %d" % (archname, sc_name, arch_dict[sc_name], sc_id) 179 errors += 1 180 return errors 181 182errors += check_syscalls("arm", "armid", arm_dict) 183errors += check_syscalls("x86", "x86id", x86_dict) 184errors += check_syscalls("mips", "mipsid", mips_dict) 185 186if errors == 0: 187 print "congratulations, everything's fine !!" 188else: 189 print "correct %d errors !!" % errors 190