| 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 |