11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#!/usr/bin/python
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# this tool is used to check that the syscall numbers that are in
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# SYSCALLS.TXT correspond to those found in the Linux kernel sources
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# for the arm and i386 architectures
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectimport sys, re, string, os, commands
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfrom   bionic_utils import *
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# change this if necessary
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsyscalls_txt = "SYSCALLS.TXT"
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef usage():
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    print "usage: checksyscalls [options] [kernel_headers_rootdir]"
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    print "    options:    -v   enable verbose mode"
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    sys.exit(1)
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlinux_root    = None
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsyscalls_file = None
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef parse_command_line(args):
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    global linux_root, syscalls_file, verbose
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    program = args[0]
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    args    = args[1:]
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    while len(args) > 0 and args[0][0] == "-":
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        option = args[0][1:]
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        args   = args[1:]
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if option == "v":
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            D_setlevel(1)
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            usage()
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if len(args) > 2:
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        usage()
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if len(args) == 0:
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        linux_root = find_kernel_headers()
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if linux_root == None:
43fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            print "Could not locate original or system kernel headers root directory."
44fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            print "Please specify one when calling this program, i.e. 'checksyscalls <headers-directory>'"
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            sys.exit(1)
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print "using the following kernel headers root: '%s'" % linux_root
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    else:
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        linux_root = args[0]
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if not os.path.isdir(linux_root):
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            print "the directory '%s' does not exist. aborting\n" % headers_root
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            sys.exit(1)
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectparse_command_line(sys.argv)
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsyscalls_file = find_file_from_upwards(None, syscalls_txt)
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectif not syscalls_file:
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    print "could not locate the %s file. Aborting" % syscalls_txt
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    sys.exit(1)
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectprint "parsing %s" % syscalls_file
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# read the syscalls description file
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectparser = SysCallsTxtParser()
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectparser.parse_file(syscalls_file)
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsyscalls = parser.syscalls
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectre_nr_line       = re.compile( r"#define __NR_(\w*)\s*\(__NR_SYSCALL_BASE\+\s*(\w*)\)" )
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectre_nr_clock_line = re.compile( r"#define __NR_(\w*)\s*\(__NR_timer_create\+(\w*)\)" )
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectre_arm_nr_line   = re.compile( r"#define __ARM_NR_(\w*)\s*\(__ARM_NR_BASE\+\s*(\w*)\)" )
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectre_x86_line      = re.compile( r"#define __NR_(\w*)\s*([0-9]*)" )
731fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandhamre_mips_line     = re.compile( r"#define __NR_(\w*)\s*\(__NR_Linux\s*\+\s*([0-9]*)\)" )
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# now read the Linux arm header
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef process_nr_line(line,dict):
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
781fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandham    m = re_mips_line.match(line)
791fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandham    if m:
801fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandham        if dict["Linux"]==4000:
811fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandham            dict[m.group(1)] = int(m.group(2))
821fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandham        return
831fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandham
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    m = re_nr_line.match(line)
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if m:
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        dict[m.group(1)] = int(m.group(2))
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    m = re_nr_clock_line.match(line)
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if m:
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        dict[m.group(1)] = int(m.group(2)) + 259
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    m = re_arm_nr_line.match(line)
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if m:
9622b137711a2f262af78611ac57d53ddc1b0e6ff9JP Abgrall        offset_str = m.group(2)
9722b137711a2f262af78611ac57d53ddc1b0e6ff9JP Abgrall        #print "%s = %s" % (m.group(1), offset_str)
9822b137711a2f262af78611ac57d53ddc1b0e6ff9JP Abgrall        base = 10
9922b137711a2f262af78611ac57d53ddc1b0e6ff9JP Abgrall        if offset_str.lower().startswith("0x"):
10022b137711a2f262af78611ac57d53ddc1b0e6ff9JP Abgrall          # Processing something similar to
10122b137711a2f262af78611ac57d53ddc1b0e6ff9JP Abgrall          #   #define __ARM_NR_cmpxchg  (__ARM_NR_BASE+0x00fff0)
10222b137711a2f262af78611ac57d53ddc1b0e6ff9JP Abgrall          base = 16
10322b137711a2f262af78611ac57d53ddc1b0e6ff9JP Abgrall        dict["ARM_"+m.group(1)] = int(offset_str, base) + 0x0f0000
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    m = re_x86_line.match(line)
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if m:
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # try block because the ARM header has some #define _NR_XXXXX  /* nothing */
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        try:
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            #print "%s = %s" % (m.group(1), m.group(2))
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            dict[m.group(1)] = int(m.group(2))
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        except:
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            pass
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef process_header(header_file,dict):
1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    fp = open(header_file)
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    D("reading "+header_file)
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    for line in fp.xreadlines():
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        line = line.strip()
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if not line: continue
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        process_nr_line(line,dict)
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    fp.close()
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectarm_dict = {}
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectx86_dict = {}
1281fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandhammips_dict = {}
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
130fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner# remove trailing slash from the linux_root, if any
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectif linux_root[-1] == '/':
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    linux_root = linux_root[:-1]
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
134fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turnerarm_unistd = find_arch_header(linux_root, "arm", "unistd.h")
135fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turnerif not arm_unistd:
136fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner    print "WEIRD: Could not locate the ARM unistd.h kernel header file,"
137fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner    print "maybe using a different set of kernel headers might help."
1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    sys.exit(1)
1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# on recent kernels, asm-i386 and asm-x64_64 have been merged into asm-x86
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# with two distinct unistd_32.h and unistd_64.h definition files.
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# take care of this here
1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#
144fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turnerx86_unistd = find_arch_header(linux_root, "i386", "unistd.h")
145fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turnerif not x86_unistd:
146fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner    x86_unistd = find_arch_header(linux_root, "x86", "unistd_32.h")
147fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner    if not x86_unistd:
148fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        print "WEIRD: Could not locate the i386/x86 unistd.h header file,"
149fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        print "maybe using a different set of kernel headers might help."
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        sys.exit(1)
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1521fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandhammips_unistd = find_arch_header(linux_root, "mips", "unistd.h")
1531fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandhamif not mips_unistd:
1541fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandham    print "WEIRD: Could not locate the Mips unistd.h kernel header file,"
1551fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandham    print "maybe using a different set of kernel headers might help."
1561fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandham    sys.exit(1)
1571fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandham
158fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turnerprocess_header( arm_unistd, arm_dict )
1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectprocess_header( x86_unistd, x86_dict )
1601fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandhamprocess_header( mips_unistd, mips_dict )
1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# now perform the comparison
1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecterrors = 0
164fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
165fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turnerdef check_syscalls(archname, idname, arch_dict):
166fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner    errors = 0
167fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner    for sc in syscalls:
168fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        sc_name = sc["name"]
169fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        sc_id   = sc[idname]
170fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        if sc_id >= 0:
171fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            if not arch_dict.has_key(sc_name):
1721fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandham                print "error: %s syscall %s not defined, should be %d" % (archname, sc_name, sc_id)
173fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                errors += 1
174fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            elif not arch_dict.has_key(sc_name):
1751fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandham                print "error: %s syscall %s is not implemented" % (archname, sc_name)
176fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                errors += 1
177fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            elif arch_dict[sc_name] != sc_id:
1781fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandham                print "error: %s syscall %s should be %d instead of %d" % (archname, sc_name, arch_dict[sc_name], sc_id)
179fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                errors += 1
180fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner    return errors
181fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1821fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandhamerrors += check_syscalls("arm", "armid", arm_dict)
1831fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandhamerrors += check_syscalls("x86", "x86id", x86_dict)
1841fa0d849576555577ffd9675677a3c95f21b754eRaghu Gandhamerrors += check_syscalls("mips", "mipsid", mips_dict)
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectif errors == 0:
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    print "congratulations, everything's fine !!"
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectelse:
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    print "correct %d errors !!" % errors
190