#!/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] ') 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())