Roll src/third_party/WebKit 9d2dfea:3aea697 (svn 201972:201973)
[chromium-blink-merge.git] / tools / cygprofile / check_orderfile.py
blob0c34d8807b7fdc08679b8c8c365070d83e48cd00
1 #!/usr/bin/python
2 # Copyright 2015 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Check that symbols are ordered into a binary as they appear in the orderfile.
7 """
9 import logging
10 import optparse
11 import sys
13 import cyglog_to_orderfile
14 import cygprofile_utils
15 import patch_orderfile
16 import symbol_extractor
19 _MAX_WARNINGS_TO_PRINT = 200
22 def _IsSameMethod(name1, name2):
23 """Returns true if name1 or name2 are split method forms of the other."""
24 return patch_orderfile.RemoveSuffixes(name1) == \
25 patch_orderfile.RemoveSuffixes(name2)
28 def _CountMisorderedSymbols(symbols, symbol_infos):
29 """Count the number of misordered symbols, and log them.
31 Args:
32 symbols: ordered sequence of symbols from the orderfile
33 symbol_infos: ordered list of SymbolInfo from the binary
35 Returns:
36 (misordered_pairs_count, matched_symbols_count, unmatched_symbols_count)
37 """
38 name_to_symbol_info = symbol_extractor.CreateNameToSymbolInfo(symbol_infos)
39 matched_symbol_infos = []
40 missing_count = 0
41 misordered_count = 0
43 # Find the SymbolInfo matching the orderfile symbols in the binary.
44 for symbol in symbols:
45 if symbol in name_to_symbol_info:
46 matched_symbol_infos.append(name_to_symbol_info[symbol])
47 else:
48 missing_count += 1
49 if missing_count < _MAX_WARNINGS_TO_PRINT:
50 logging.warning('Symbol "%s" is in the orderfile, not in the binary' %
51 symbol)
52 logging.info('%d matched symbols, %d un-matched (Only the first %d unmatched'
53 ' symbols are shown)' % (
54 len(matched_symbol_infos), missing_count,
55 _MAX_WARNINGS_TO_PRINT))
57 # In the order of the orderfile, find all the symbols that are at an offset
58 # smaller than their immediate predecessor, and record the pair.
59 previous_symbol_info = symbol_extractor.SymbolInfo(
60 name='', offset=-1, size=0, section='')
61 for symbol_info in matched_symbol_infos:
62 if symbol_info.offset < previous_symbol_info.offset and not (
63 _IsSameMethod(symbol_info.name, previous_symbol_info.name)):
64 logging.warning('Misordered pair: %s - %s' % (
65 str(previous_symbol_info), str(symbol_info)))
66 misordered_count += 1
67 previous_symbol_info = symbol_info
68 return (misordered_count, len(matched_symbol_infos), missing_count)
71 def main():
72 parser = optparse.OptionParser(usage=
73 'usage: %prog [options] <binary> <orderfile>')
74 parser.add_option('--target-arch', action='store', dest='arch',
75 choices=['arm', 'arm64', 'x86', 'x86_64', 'x64', 'mips'],
76 help='The target architecture for the binary.')
77 parser.add_option('--threshold', action='store', dest='threshold', default=0,
78 help='The maximum allowed number of out-of-order symbols.')
79 options, argv = parser.parse_args(sys.argv)
80 if not options.arch:
81 options.arch = cygprofile_utils.DetectArchitecture()
82 if len(argv) != 3:
83 parser.print_help()
84 return 1
85 (binary_filename, orderfile_filename) = argv[1:]
87 symbol_extractor.SetArchitecture(options.arch)
88 obj_dir = cygprofile_utils.GetObjDir(binary_filename)
89 symbol_to_sections_map = \
90 cyglog_to_orderfile.GetSymbolToSectionsMapFromObjectFiles(obj_dir)
91 section_to_symbols_map = cygprofile_utils.InvertMapping(
92 symbol_to_sections_map)
93 symbols = patch_orderfile.GetSymbolsFromOrderfile(orderfile_filename,
94 section_to_symbols_map)
95 symbol_infos = symbol_extractor.SymbolInfosFromBinary(binary_filename)
96 # Missing symbols is not an error since some of them can be eliminated through
97 # inlining.
98 (misordered_pairs_count, matched_symbols, _) = _CountMisorderedSymbols(
99 symbols, symbol_infos)
100 return (misordered_pairs_count > options.threshold) or (matched_symbols == 0)
103 if __name__ == '__main__':
104 logging.basicConfig(level=logging.INFO)
105 sys.exit(main())