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 8from __future__ import print_function 9 10import sys 11import textwrap 12from subprocess import Popen, PIPE 13 14_OBJDUMP = 'arm-linux-gnueabi-objdump' 15 16def _objdump(binary, vaddr, ctx_before, ctx_after): 17 args = [ 18 _OBJDUMP, '-d', '-G', binary, 19 '--start-address=0x%08X' % (vaddr - (4 * ctx_before)), 20 '--stop-address=0x%08X' % (vaddr + 4 + (4 * ctx_after)) 21 ] 22 highlight = ctx_before 23 lines = 0 24 for line in Popen(args, stdout=PIPE).stdout.read().split('\n'): 25 if line.startswith(' '): 26 if highlight == 0: 27 print('--> ', line) 28 else: 29 print(' ', line) 30 highlight -= 1 31 lines += 1 32 if not lines: 33 print(' (not found)') 34 35 36def _problem_info(code): 37 return { 38 'kProblemUnsafe': ['Instruction is unsafe', 0, 0], 39 'kProblemBranchSplitsPattern': [ 40 'The destination of this branch is ' 41 'part of an instruction sequence that must be executed in full, ' 42 'or is inline data', 0, 0 43 ], 44 'kProblemPatternCrossesBundle': [ 45 'This instruction is part of a ' 46 'sequence that must execute in full, but it spans a bundle edge ' 47 '-- so an indirect branch may target it', 1, 1 48 ], 49 'kProblemBranchInvalidDest': [ 50 'This branch targets a location that is ' 51 'outside of the application\'s executable code, and is not a valid ' 52 'trampoline entry point', 0, 0 53 ], 54 'kProblemUnsafeLoadStore': [ 55 'This store instruction is not preceded by ' 56 'a valid address mask instruction', 1, 0 57 ], 58 'kProblemUnsafeBranch': [ 59 'This indirect branch instruction is not ' 60 'preceded by a valid address mask instruction', 1, 0 61 ], 62 'kProblemUnsafeDataWrite': [ 63 'This instruction affects a register that ' 64 'must contain a valid data-region address, but is not followed by ' 65 'a valid address mask instruction', 0, 1 66 ], 67 'kProblemReadOnlyRegister': [ 68 'This instruction changes the contents of ' 69 'a read-only register', 0, 0 70 ], 71 'kProblemMisalignedCall': [ 72 'This linking branch instruction is not in ' 73 'the last slot of its bundle, so when its LR result is masked, the ' 74 'caller will not return to the next instruction', 0, 0 75 ], 76 }[code] 77 78 79def _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 90def _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):" % (vaddr, msg, _safety_msg(safety))) 96 print('\n'.join(textwrap.wrap(msg, 70, subsequent_indent=' '))) 97 _objdump(binary, vaddr, ctx_before, ctx_after) 98 if ref_vaddr: 99 print("Destination address %08X:" % ref_vaddr) 100 _objdump(binary, ref_vaddr, 1, 1) 101 102 103def _parse_report(line): 104 vaddr_hex, safety, code, ref_vaddr_hex = line.split() 105 return (int(vaddr_hex, 16), int(safety), code, int(ref_vaddr_hex, 16)) 106 107 108for line in sys.stdin: 109 if line.startswith('ncval: '): 110 line = line[7:].strip() 111 _explain_problem(sys.argv[1], *_parse_report(line)) 112