• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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
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]*)" )
73
74# now read the Linux arm header
75def 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
104def 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
113arm_dict = {}
114x86_dict = {}
115
116
117# remove trailing slash and '/include' from the linux_root, if any
118if linux_root[-1] == '/':
119    linux_root = linux_root[:-1]
120
121if len(linux_root) > 8 and linux_root[-8:] == '/include':
122    linux_root = linux_root[:-8]
123
124arm_unistd = linux_root + "/include/asm-arm/unistd.h"
125if 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#
135x86_unistd = linux_root + "/include/asm-i386/unistd.h"
136if 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
145process_header( linux_root+"/include/asm-arm/unistd.h", arm_dict )
146process_header( x86_unistd, x86_dict )
147
148# now perform the comparison
149errors = 0
150for 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
161for 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
172if errors == 0:
173    print "congratulations, everything's fine !!"
174else:
175    print "correct %d errors !!" % errors
176