OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 | |
3 # Copyright (c) 2011 The Native Client Authors. All rights reserved. | |
4 # Use of this source code is governed by a BSD-style license that can be | |
5 # found in the LICENSE file. | |
6 | |
7 # Annotates the output of ncval with line numbers, taken from debugging | |
8 # information using binutils' addr2line. | |
9 | |
10 # TODO(mseaborn): Merge this with validator_arm/validation-report.py, | |
11 # the Python wrapper script for the ARM validator. | |
12 | |
13 import linecache | |
14 import re | |
15 import subprocess | |
16 import sys | |
17 | |
18 | |
19 objdump_regexp = re.compile(r"\s*([0-9a-f]+):\s+") | |
20 ncval_regexp = re.compile("VALIDATOR: ([0-9a-f]+):") | |
21 addr2line_regexp = re.compile(r"(.*):(\d+)$") | |
22 | |
23 | |
24 def check(obj_file, output_fh): | |
25 def disassemble_address(addr): | |
26 proc = subprocess.Popen( | |
27 ["x86_64-nacl-objdump", "-d", obj_file, | |
28 "--start-address", "0x" + addr, | |
29 "--stop-address", "0x%x" % (int(addr, 16) + 16)], | |
30 stdout=subprocess.PIPE) | |
31 for line in proc.stdout: | |
32 match = objdump_regexp.match(line) | |
33 if match is not None: | |
34 output_fh.write(" code: %s\n" % line[match.end():].strip()) | |
35 break | |
36 | |
37 def decode_address(addr): | |
38 # We have to do one invocation of addr2line per address when | |
39 # getting inline context. If we pipe addresses in, addr2line | |
40 # does not tell us when the output ends for each input | |
41 # address. | |
42 proc = subprocess.Popen( | |
43 ["x86_64-nacl-addr2line", "--functions", "--inlines", | |
44 "-e", obj_file, addr], | |
45 stdout=subprocess.PIPE) | |
46 for info in proc.stdout: | |
47 match = addr2line_regexp.match(info.rstrip()) | |
48 if match is not None: | |
49 filename = match.group(1) | |
50 lineno = int(match.group(2)) | |
51 output_fh.write(" file: %s" % info) | |
52 src_line = linecache.getline(filename, lineno) | |
53 if src_line != "": | |
54 output_fh.write(" " + src_line.lstrip()) | |
55 else: | |
56 output_fh.write(" func: %s" % info) | |
57 | |
58 # Pass --max_errors=-1 to get all validation errors. This works | |
59 # around ncval's default of truncating the number of results to 100. | |
60 # Pass --cpuid-all because we are only interested in instructions | |
61 # that are always rejected by the validator. | |
62 proc = subprocess.Popen(["ncval", "--max_errors=-1", "--cpuid-all", | |
63 "--annotate", obj_file], | |
64 stdout=subprocess.PIPE) | |
65 for line in proc.stdout: | |
66 match = ncval_regexp.match(line) | |
67 if match is not None: | |
68 output_fh.write("\n") | |
69 output_fh.write(line) | |
70 addr = match.group(1) | |
71 disassemble_address(addr) | |
72 decode_address(addr) | |
73 return proc.wait() | |
74 | |
75 | |
76 def main(args): | |
77 result = 0 | |
78 for obj_file in args: | |
79 if check(obj_file, sys.stdout) != 0: | |
80 result = 1 | |
81 return result | |
82 | |
83 | |
84 if __name__ == "__main__": | |
85 sys.exit(main(sys.argv[1:])) | |
OLD | NEW |