Home | History | Annotate | Download | only in tools
      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 
      8 import sys, re, string, os, commands
      9 from   bionic_utils import *
     10 
     11 # change this if necessary
     12 syscalls_txt = "SYSCALLS.TXT"
     13 
     14 def usage():
     15     print "usage: checksyscalls [options] [kernel_headers_rootdir]"
     16     print "    options:    -v   enable verbose mode"
     17     sys.exit(1)
     18 
     19 
     20 linux_root    = None
     21 syscalls_file = None
     22 
     23 def 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 this system kernel headers root directory, please"
     44             print "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 
     53 parse_command_line(sys.argv)
     54 
     55 syscalls_file = find_file_from_upwards(None, syscalls_txt)
     56 if not syscalls_file:
     57     print "could not locate the %s file. Aborting" % syscalls_txt
     58     sys.exit(1)
     59 
     60 print "parsing %s" % syscalls_file
     61 
     62 # read the syscalls description file
     63 #
     64 
     65 parser = SysCallsTxtParser()
     66 parser.parse_file(syscalls_file)
     67 syscalls = parser.syscalls
     68 
     69 re_nr_line       = re.compile( r"#define __NR_(\w*)\s*\(__NR_SYSCALL_BASE\+\s*(\w*)\)" )
     70 re_nr_clock_line = re.compile( r"#define __NR_(\w*)\s*\(__NR_timer_create\+(\w*)\)" )
     71 re_arm_nr_line   = re.compile( r"#define __ARM_NR_(\w*)\s*\(__ARM_NR_BASE\+\s*(\w*)\)" )
     72 re_x86_line      = re.compile( r"#define __NR_(\w*)\s*([0-9]*)" )
     73 
     74 # now read the Linux arm header
     75 def process_nr_line(line,dict):
     76 
     77     m = re_nr_line.match(line)
     78     if m:
     79         dict[m.group(1)] = int(m.group(2))
     80         return
     81 
     82     m = re_nr_clock_line.match(line)
     83     if m:
     84         dict[m.group(1)] = int(m.group(2)) + 259
     85         return
     86 
     87     m = re_arm_nr_line.match(line)
     88     if m:
     89         #print "%s = %s" % (m.group(1), m.group(2))
     90         dict["ARM_"+m.group(1)] = int(m.group(2)) + 0x0f0000
     91         return
     92 
     93     m = re_x86_line.match(line)
     94     if m:
     95         # try block because the ARM header has some #define _NR_XXXXX  /* nothing */
     96         try:
     97             #print "%s = %s" % (m.group(1), m.group(2))
     98             dict[m.group(1)] = int(m.group(2))
     99         except:
    100             pass
    101         return
    102 
    103 
    104 def process_header(header_file,dict):
    105     fp = open(header_file)
    106     D("reading "+header_file)
    107     for line in fp.xreadlines():
    108         line = line.strip()
    109         if not line: continue
    110         process_nr_line(line,dict)
    111     fp.close()
    112 
    113 arm_dict = {}
    114 x86_dict = {}
    115 
    116 
    117 # remove trailing slash and '/include' from the linux_root, if any
    118 if linux_root[-1] == '/':
    119     linux_root = linux_root[:-1]
    120 
    121 if len(linux_root) > 8 and linux_root[-8:] == '/include':
    122     linux_root = linux_root[:-8]
    123 
    124 arm_unistd = linux_root + "/include/asm-arm/unistd.h"
    125 if not os.path.exists(arm_unistd):
    126     print "WEIRD: could not locate the ARM unistd.h header file"
    127     print "tried searching in '%s'" % arm_unistd
    128     print "maybe using a different set of kernel headers might help"
    129     sys.exit(1)
    130 
    131 # on recent kernels, asm-i386 and asm-x64_64 have been merged into asm-x86
    132 # with two distinct unistd_32.h and unistd_64.h definition files.
    133 # take care of this here
    134 #
    135 x86_unistd = linux_root + "/include/asm-i386/unistd.h"
    136 if not os.path.exists(x86_unistd):
    137     x86_unistd1 = x86_unistd
    138     x86_unistd = linux_root + "/include/asm-x86/unistd_32.h"
    139     if not os.path.exists(x86_unistd):
    140         print "WEIRD: could not locate the i386/x86 unistd.h header file"
    141         print "tried searching in '%s' and '%s'" % (x86_unistd1, x86_unistd)
    142         print "maybe using a different set of kernel headers might help"
    143         sys.exit(1)
    144 
    145 process_header( linux_root+"/include/asm-arm/unistd.h", arm_dict )
    146 process_header( x86_unistd, x86_dict )
    147 
    148 # now perform the comparison
    149 errors = 0
    150 for sc in syscalls:
    151     sc_name = sc["name"]
    152     sc_id   = sc["id"]
    153     if sc_id >= 0:
    154         if not arm_dict.has_key(sc_name):
    155             print "arm syscall %s not defined !!" % sc_name
    156             errors += 1
    157         elif arm_dict[sc_name] != sc_id:
    158             print "arm syscall %s should be %d instead of %d !!" % (sc_name, arm_dict[sc_name], sc_id)
    159             errors += 1
    160 
    161 for sc in syscalls:
    162     sc_name = sc["name"]
    163     sc_id2  = sc["id2"]
    164     if sc_id2 >= 0:
    165         if not x86_dict.has_key(sc_name):
    166             print "x86 syscall %s not defined !!" % sc_name
    167             errors += 1
    168         elif x86_dict[sc_name] != sc_id2:
    169             print "x86 syscall %s should be %d instead of %d !!" % (sc_name, x86_dict[sc_name], sc_id2)
    170             errors += 1
    171 
    172 if errors == 0:
    173     print "congratulations, everything's fine !!"
    174 else:
    175     print "correct %d errors !!" % errors
    176