Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / validator_x86 / discmp.py
1 #!/usr/bin/python
2 # Copyright 2008, Google Inc.
3 # All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
8 #
9 #     * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 #     * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following disclaimer
13 # in the documentation and/or other materials provided with the
14 # distribution.
15 #     * Neither the name of Google Inc. nor the names of its
16 # contributors may be used to endorse or promote products derived from
17 # this software without specific prior written permission.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 #
32 """discmp.py - compare disassembler output
33
34 This script compares output from the Native Client decoder to output
35 from GNU objdump to make sure they agree on instruction lengths. It
36 returns a zero status on success and non-zero on failure.
37
38
39 Usage:
40   discmp.py <ncdis-exe> <test-binary>*
41 """
42
43 import logging
44 import os
45 import re
46 import sys
47
48
49 def Usage():
50   print("USAGE:  discmp.py <ncdis-exe>  <test-binary>*\n")
51   sys.exit(-1)
52
53 class DisFile(object):
54   """Processes variants of disassembler output from various sources,
55    providing a list of instruction lengths, based on addresses."""
56
57   def __init__(self, stream):
58     self.fd = stream
59     self.lastline = None
60     self.lastaddr = None
61     self.thisaddr = None
62     self.thisline = None
63     # note we ignore lines that have only continuation bytes;
64     # no opcode
65     self.dislinefmt = re.compile("\s*([0-9a-f]+):\t(.*\t+.*)")
66     self.data16fmt = re.compile("\s*([0-9a-f]+):\s+66\s+data16")
67     self.waitfmt = re.compile("\s*([0-9a-f]+):\s+9b\s+[f]?wait")
68
69   def NextDisInst(self):
70     while (True):
71       line = self.fd.readline()
72       if line == "": return 0, None
73       match = self.data16fmt.match(line)
74       if (match):
75         addr = match.group(1)
76         line = self.fd.readline()
77         match = self.dislinefmt.match(line)
78         return (int(addr, 16),
79                 " " + addr + ":\t60 " + match.group(2) + "\n")
80       match = self.waitfmt.match(line)
81       if (match):
82         addr = match.group(1)
83         line = self.fd.readline()
84         match = self.dislinefmt.match(line)
85         return (int(addr, 16),
86                 " " + addr + ":\t9b " + match.group(2) + "\n")
87       match = self.dislinefmt.match(line)
88       if (match):
89         return int(match.group(1), 16), line
90
91   def NextInst(self):
92     if self.lastaddr is None:
93       self.lastaddr, self.lastline = self.NextDisInst()
94     else:
95       self.lastaddr = self.thisaddr
96       self.lastline = self.thisline
97     self.thisaddr, self.thisline = self.NextDisInst()
98     if self.thisline is None:
99       # don't know how long the last line was, so just return 1
100       return (1, self.lastline)
101     if self.lastline is None:
102       return 0, None
103     else:
104       return (self.thisaddr - self.lastaddr, self.lastline)
105
106
107 def IsElfBinary(fname):
108   fd = open(fname)
109   iselfbinary = fd.readline().startswith("\x7fELF")
110   fd.close()
111   return iselfbinary
112
113
114 def CheckOneFile(fname, ncdis, objdump):
115   logging.info("processing %s", fname)
116   if not IsElfBinary(fname):
117     print("Error:", fname, "is not an ELF binary\nContinuing...")
118     return
119   df1 = DisFile(os.popen(objdump + " -dz " + fname))
120   df2 = DisFile(os.popen(ncdis + " " + fname))
121   instcount = 0
122   while (1):
123     instcount += 1
124     len1, line1 = df1.NextInst()
125     len2, line2 = df2.NextInst()
126     if line1 is None: break
127     if line2 is None: break
128     if (len1 != len2):
129       logging.error("inst length mistmatch %d != %d\n", len1, len2)
130       logging.error(line1)
131       logging.error(line2)
132       sys.exit(-1)
133   if line1 or line2:
134     logging.error("disasm output is different lengths\n")
135     sys.exit(-1)
136   logging.info("%s: %d instructions; 0 errors!\n", fname, instcount)
137
138
139 def main(argv):
140   logging.basicConfig(level=logging.DEBUG,
141                       stream=sys.stdout)
142   ncdis = argv[1]
143   logging.info("using ncdis at: %s", ncdis)
144   objdump="objdump"
145   logging.info("using objdump at: %s", objdump)
146   for filename in argv[2:]:
147     if os.path.isdir(filename):
148       logging.info("traversing dir: %s", filename)
149       for dirpath, dirlist, filelist in os.walk(filename):
150         for fname in filelist:
151           CheckOneFile(os.path.join(dirpath, fname), ncdis, objdump)
152     else:
153       CheckOneFile(filename, ncdis, objdump)
154   return 0
155
156 if '__main__' == __name__:
157   sys.exit(main(sys.argv))