summaryrefslogtreecommitdiff
path: root/chromium/tools/cygprofile/check_orderfile.py
blob: e8a01bb15127010ffbd52db82b6b44aacb2e3cec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#!/usr/bin/env vpython
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Check that symbols are ordered into a binary as they appear in the orderfile.
"""

import logging
import optparse
import sys

import symbol_extractor


def _VerifySymbolOrder(orderfile_symbols, symbol_infos, threshold):
  """Verify symbol ordering.

  Checks that the non-section symbols in |orderfile_filename| are consistent
  with the offsets |symbol_infos|.

  Args:
    orderfile_symbols: ([str]) list of symbols from orderfile.
    symbol_infos: ([SymbolInfo]) symbol infos from binary.
    threshold: (int) The number of misordered symbols beyond which we error.

  Returns:
    True iff the ordering is consistent within |threshold|.
  """
  last_offset = 0
  name_to_offset = {si.name: si.offset for si in symbol_infos}
  missing_count = 0
  misorder_count = 0
  misordered_syms = []
  for sym in orderfile_symbols:
    if '.' in sym:
      continue  # sym is a section name.
    if sym not in name_to_offset:
      missing_count += 1
      continue
    next_offset = name_to_offset[sym]
    if next_offset < last_offset:
      misorder_count += 1
      misordered_syms.append((sym, next_offset, last_offset))
    last_offset = next_offset
  logging.warning('Missing symbols in verification: %d', missing_count)
  if misorder_count:
    logging.warning('%d misordered symbols:\n %s', misorder_count,
                    '\n '.join(str(x) for x in misordered_syms[:10]))
    if misorder_count > threshold:
      logging.error('%d misordered symbols over threshold %d, failing',
                    misorder_count, threshold)
      return False
  return True


def main():
  parser = optparse.OptionParser(usage=
      'usage: %prog [options] <binary> <orderfile>')
  parser.add_option('--target-arch', action='store', dest='arch', default='arm',
                    choices=['arm', 'arm64', 'x86', 'x86_64', 'x64', 'mips'],
                    help='The target architecture for the binary.')
  parser.add_option('--threshold', action='store', dest='threshold',
                    default=20, type=int,
                    help='The maximum allowed number of out-of-order symbols.')
  options, argv = parser.parse_args(sys.argv)
  if len(argv) != 3:
    parser.print_help()
    return 1
  (binary_filename, orderfile_filename) = argv[1:]

  symbol_extractor.SetArchitecture(options.arch)
  symbol_infos = symbol_extractor.SymbolInfosFromBinary(binary_filename)

  if not _VerifySymbolOrder([sym.strip() for sym in file(orderfile_filename)],
                            symbol_infos, options.threshold):
    return 1


if __name__ == '__main__':
  logging.basicConfig(level=logging.INFO)
  sys.exit(main())