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.
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.
32 symbols: ordered sequence of symbols from the orderfile
33 symbol_infos: ordered list of SymbolInfo from the binary
36 (misordered_pairs_count, matched_symbols_count, unmatched_symbols_count)
38 name_to_symbol_info
= symbol_extractor
.CreateNameToSymbolInfo(symbol_infos
)
39 matched_symbol_infos
= []
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
])
49 if missing_count
< _MAX_WARNINGS_TO_PRINT
:
50 logging
.warning('Symbol "%s" is in the orderfile, not in the binary' %
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
)))
67 previous_symbol_info
= symbol_info
68 return (misordered_count
, len(matched_symbol_infos
), missing_count
)
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
)
81 options
.arch
= cygprofile_utils
.DetectArchitecture()
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
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
)