The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 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: |
David 'Digit' Turner | fc26931 | 2010-10-11 22:11:06 +0200 | [diff] [blame] | 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>'" |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 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]*)" ) |
Raghu Gandham | 1fa0d84 | 2012-01-27 17:51:42 -0800 | [diff] [blame] | 73 | re_mips_line = re.compile( r"#define __NR_(\w*)\s*\(__NR_Linux\s*\+\s*([0-9]*)\)" ) |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 74 | |
| 75 | # now read the Linux arm header |
| 76 | def process_nr_line(line,dict): |
| 77 | |
Raghu Gandham | 1fa0d84 | 2012-01-27 17:51:42 -0800 | [diff] [blame] | 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 | |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 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: |
JP Abgrall | 22b1377 | 2011-04-05 19:52:26 -0700 | [diff] [blame] | 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 |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 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 | |
| 117 | def 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 | |
| 126 | arm_dict = {} |
| 127 | x86_dict = {} |
Raghu Gandham | 1fa0d84 | 2012-01-27 17:51:42 -0800 | [diff] [blame] | 128 | mips_dict = {} |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 129 | |
David 'Digit' Turner | fc26931 | 2010-10-11 22:11:06 +0200 | [diff] [blame] | 130 | # remove trailing slash from the linux_root, if any |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 131 | if linux_root[-1] == '/': |
| 132 | linux_root = linux_root[:-1] |
| 133 | |
David 'Digit' Turner | fc26931 | 2010-10-11 22:11:06 +0200 | [diff] [blame] | 134 | arm_unistd = find_arch_header(linux_root, "arm", "unistd.h") |
| 135 | if 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." |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 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 | # |
David 'Digit' Turner | fc26931 | 2010-10-11 22:11:06 +0200 | [diff] [blame] | 144 | x86_unistd = find_arch_header(linux_root, "i386", "unistd.h") |
| 145 | if 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." |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 150 | sys.exit(1) |
| 151 | |
Raghu Gandham | 1fa0d84 | 2012-01-27 17:51:42 -0800 | [diff] [blame] | 152 | mips_unistd = find_arch_header(linux_root, "mips", "unistd.h") |
| 153 | if 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 | |
David 'Digit' Turner | fc26931 | 2010-10-11 22:11:06 +0200 | [diff] [blame] | 158 | process_header( arm_unistd, arm_dict ) |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 159 | process_header( x86_unistd, x86_dict ) |
Raghu Gandham | 1fa0d84 | 2012-01-27 17:51:42 -0800 | [diff] [blame] | 160 | process_header( mips_unistd, mips_dict ) |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 161 | |
| 162 | # now perform the comparison |
| 163 | errors = 0 |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 164 | |
David 'Digit' Turner | fc26931 | 2010-10-11 22:11:06 +0200 | [diff] [blame] | 165 | def 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): |
Raghu Gandham | 1fa0d84 | 2012-01-27 17:51:42 -0800 | [diff] [blame] | 172 | print "error: %s syscall %s not defined, should be %d" % (archname, sc_name, sc_id) |
David 'Digit' Turner | fc26931 | 2010-10-11 22:11:06 +0200 | [diff] [blame] | 173 | errors += 1 |
| 174 | elif not arch_dict.has_key(sc_name): |
Raghu Gandham | 1fa0d84 | 2012-01-27 17:51:42 -0800 | [diff] [blame] | 175 | print "error: %s syscall %s is not implemented" % (archname, sc_name) |
David 'Digit' Turner | fc26931 | 2010-10-11 22:11:06 +0200 | [diff] [blame] | 176 | errors += 1 |
| 177 | elif arch_dict[sc_name] != sc_id: |
Raghu Gandham | 1fa0d84 | 2012-01-27 17:51:42 -0800 | [diff] [blame] | 178 | print "error: %s syscall %s should be %d instead of %d" % (archname, sc_name, arch_dict[sc_name], sc_id) |
David 'Digit' Turner | fc26931 | 2010-10-11 22:11:06 +0200 | [diff] [blame] | 179 | errors += 1 |
| 180 | return errors |
| 181 | |
Raghu Gandham | 1fa0d84 | 2012-01-27 17:51:42 -0800 | [diff] [blame] | 182 | errors += check_syscalls("arm", "armid", arm_dict) |
| 183 | errors += check_syscalls("x86", "x86id", x86_dict) |
| 184 | errors += check_syscalls("mips", "mipsid", mips_dict) |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 185 | |
| 186 | if errors == 0: |
| 187 | print "congratulations, everything's fine !!" |
| 188 | else: |
| 189 | print "correct %d errors !!" % errors |