OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/python | |
2 # | |
3 # Copyright (c) 2012 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 | |
8 import sys | |
9 import os | |
10 import textwrap | |
11 from subprocess import Popen, PIPE | |
12 | |
13 _OBJDUMP = 'mips-linux-gnu-objdump' | |
14 | |
15 | |
16 def _objdump(binary, vaddr, ctx_before, ctx_after): | |
17 args = [ | |
18 _OBJDUMP, | |
19 '-d', | |
20 '-G', | |
21 binary, | |
22 '--start-address=0x%08X' % (vaddr - (4 * ctx_before)), | |
23 '--stop-address=0x%08X' % (vaddr + 4 + (4 * ctx_after))] | |
24 highlight = ctx_before | |
25 lines = 0 | |
26 for line in Popen(args, stdout=PIPE).stdout.read().split('\n'): | |
27 if line.startswith(' '): | |
28 if highlight == 0: | |
29 print '--> ', line | |
30 else: | |
31 print ' ', line | |
32 highlight -= 1 | |
33 lines += 1 | |
34 if not lines: | |
35 print ' (not found)' | |
36 | |
37 | |
38 def _problem_info(code): | |
39 return { | |
40 'kProblemUnsafe': ['Instruction is unsafe', 0, 0], | |
41 'kProblemBranchSplitsPattern': ['The destination of this branch is ' | |
42 'at middle of an pseudo-instruction that must be executed in full', | |
43 0, 0], | |
44 'kProblemPatternCrossesBundle': ['This instruction is part of a ' | |
45 'sequence that must execute in full, but it spans a bundle edge ' | |
46 '-- so an indirect branch may target it', | |
47 1, 1], | |
48 'kProblemBranchInvalidDest': ['This branch targets a location that is ' | |
49 'outside of the application\'s executable code, over 256 MB', | |
50 0, 0], | |
51 'kProblemUnsafeLoadStore': ['This load/store instruction is not ' | |
52 'preceded by a valid store mask instruction', | |
53 1, 0], | |
54 'kProblemUnsafeJumpRegister': ['This indirect jump instruction is not ' | |
55 'preceded by a valid jump mask instruction', | |
56 1, 0], | |
57 'kProblemUnsafeDataWrite': ['This instruction affects a register that ' | |
58 'must contain a valid data-region address (sp), but is not ' | |
59 'followed by a valid store mask instruction', | |
60 0, 1], | |
61 'kProblemReadOnlyRegister': ['This instruction changes the contents of' | |
62 ' read-only register', | |
63 0, 0], | |
64 'kProblemMisalignedCall': ['This linking branch/jump instruction is ' | |
65 'not at the bundle offset +8, so when its RA result is masked, the' | |
66 ' caller will not return to the next instruction (start of next ' | |
67 'bundle)', | |
68 0, 0], | |
69 'kProblemUnalignedJumpToTrampoline':['The destination of this ' | |
70 'jump/branch instruction is in trampoline code section but ' | |
71 'address is not bundle aligned', | |
72 0, 0], | |
73 'kProblemDataRegInDelaySlot':['This instruction changes value of a ' | |
74 'stack pointer but is located in the delay slot of jump/branch', | |
75 1, 0], | |
76 }[code] | |
77 | |
78 | |
79 def _safety_msg(val): | |
80 return { | |
81 0: 'UNKNOWN', # Should not appear | |
82 1: 'is undefined', | |
83 2: 'has unpredictable effects', | |
84 3: 'is deprecated', | |
85 4: 'is forbidden', | |
86 5: 'uses forbidden operands', | |
87 }[val] | |
88 | |
89 | |
90 def _explain_problem(binary, vaddr, safety, code, ref_vaddr): | |
91 msg, ctx_before, ctx_after = _problem_info(code) | |
92 if safety == 6: | |
93 msg = "At %08X: %s:" % (vaddr, msg) | |
94 else: | |
95 msg = ("At %08X: %s (%s):" | |
96 % (vaddr, msg, _safety_msg(safety))) | |
97 print '\n'.join(textwrap.wrap(msg, 70, subsequent_indent=' ')) | |
98 _objdump(binary, vaddr, ctx_before, ctx_after) | |
99 if ref_vaddr: | |
100 print "Destination address %08X:" % ref_vaddr | |
101 _objdump(binary, ref_vaddr, 1, 1) | |
102 | |
103 | |
104 def _parse_report(line): | |
105 vaddr_hex, safety, code, ref_vaddr_hex = line.split() | |
106 return (int(vaddr_hex, 16), int(safety), code, int(ref_vaddr_hex, 16)) | |
107 | |
108 | |
109 def main(argv): | |
110 if len(argv) != 2: | |
111 print >>sys.stderr, ('Error, provide one parameter to the script') | |
Nick Bray
2012/05/01 17:34:07
">>" syntax is discouraged. (Nonstandard for our
petarj
2012/05/08 14:54:19
Sure, it will be changed. This seemed to me like a
| |
112 return 1 | |
113 if not os.path.exists(sys.argv[1]): | |
114 print >>sys.stderr, ('Error, input file does not exist') | |
115 return 1 | |
116 for line in sys.stdin: | |
117 if line.startswith('ncval: '): | |
118 line = line[7:].strip() | |
119 _explain_problem(sys.argv[1], *_parse_report(line)) | |
120 return 0 | |
121 | |
122 | |
123 if __name__ == '__main__': | |
124 sys.exit(main(sys.argv)) | |
OLD | NEW |