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

  symbol_extractor.SetArchitecture(options.arch)
  obj_dir = cygprofile_utils.GetObjDir(binary_filename)
  symbol_to_sections_map = \
      cyglog_to_orderfile.GetSymbolToSectionsMapFromObjectFiles(obj_dir)
  section_to_symbols_map = cygprofile_utils.InvertMapping(
      symbol_to_sections_map)
  symbols = patch_orderfile.GetSymbolsFromOrderfile(orderfile_filename,
                                                    section_to_symbols_map)
  symbol_infos = symbol_extractor.SymbolInfosFromBinary(binary_filename)
  # Missing symbols is not an error since some of them can be eliminated through
  # inlining.
  (misordered_pairs_count, matched_symbols, _) = _CountMisorderedSymbols(
      symbols, symbol_infos)
  return (misordered_pairs_count > options.threshold) or (matched_symbols == 0)
예제 #2
0
def GeneratePatchedOrderfile(unpatched_orderfile, native_lib_filename,
                             output_filename):
  """Writes a patched orderfile.

  Args:
    unpatched_orderfile: (str) Path to the unpatched orderfile.
    native_lib_filename: (str) Path to the native library.
    output_filename: (str) Path to the patched orderfile.
  """
  (offset_to_symbol_infos, name_to_symbol_infos) = _GroupSymbolInfosFromBinary(
      native_lib_filename)
  obj_dir = cygprofile_utils.GetObjDir(native_lib_filename)
  raw_symbol_map = cyglog_to_orderfile.ObjectFileProcessor(
      obj_dir).GetSymbolToSectionsMap()
  suffixed = _SectionsWithSuffixes(raw_symbol_map)
  symbol_to_sections_map = _CombineSectionListsByPrimaryName(raw_symbol_map)
  section_to_symbols_map = cygprofile_utils.InvertMapping(
      symbol_to_sections_map)
  profiled_sections = _StripSuffixes(
      GetSectionsFromOrderfile(unpatched_orderfile))
  expanded_sections = _ExpandSections(
      profiled_sections, name_to_symbol_infos, offset_to_symbol_infos,
      section_to_symbols_map, symbol_to_sections_map, suffixed)

  with open(output_filename, 'w') as f:
    # Make sure the anchor functions are located in the right place, here and
    # after everything else.
    # See the comment in //base/android/library_loader/anchor_functions.cc.
    #
    # __cxx_global_var_init is one of the largest symbols (~38kB as of May
    # 2018), called extremely early, and not instrumented.
    first_sections = ('dummy_function_start_of_ordered_text',
                      '__cxx_global_var_init')
    for section in first_sections:
      for prefix in _PREFIXES:
        f.write(prefix + section + '\n')

    for section in expanded_sections:
      f.write(section + '\n')

    for prefix in _PREFIXES:
      f.write(prefix + 'dummy_function_end_of_ordered_text\n')

    # The following is needed otherwise Gold only applies a partial sort.
    f.write('.text\n')  # gets methods not in a section, such as assembly
    f.write('.text.*\n')  # gets everything else

    # Since wildcards are not supported by lld, the "end of text" anchor symbol
    # is not emitted, a different mechanism is used instead. See comments in the
    # file above.
    for prefix in _PREFIXES:
      if prefix:
        f.write(prefix + 'dummy_function_at_the_end_of_text\n')
예제 #3
0
def main(argv):
    parser = optparse.OptionParser(
        usage='usage: %prog [options] <unpatched_orderfile> <library>')
    parser.add_option('--target-arch',
                      action='store',
                      dest='arch',
                      choices=['arm', 'arm64', 'x86', 'x86_64', 'x64', 'mips'],
                      help='The target architecture for the library.')
    options, argv = parser.parse_args(argv)
    if not options.arch:
        options.arch = cygprofile_utils.DetectArchitecture()
    if len(argv) != 3:
        parser.print_help()
        return 1
    orderfile_filename = argv[1]
    binary_filename = argv[2]
    symbol_extractor.SetArchitecture(options.arch)
    (offset_to_symbol_infos,
     name_to_symbol_infos) = _GroupSymbolInfosFromBinary(binary_filename)
    obj_dir = cygprofile_utils.GetObjDir(binary_filename)
    raw_symbol_map = cyglog_to_orderfile.GetSymbolToSectionsMapFromObjectFiles(
        obj_dir)
    suffixed = _SectionsWithSuffixes(raw_symbol_map)
    symbol_to_sections_map = _CombineSectionListsByPrimaryName(raw_symbol_map)
    section_to_symbols_map = cygprofile_utils.InvertMapping(
        symbol_to_sections_map)
    profiled_sections = _StripSuffixes(
        GetSectionsFromOrderfile(orderfile_filename))
    expanded_sections = _ExpandSections(profiled_sections,
                                        name_to_symbol_infos,
                                        offset_to_symbol_infos,
                                        section_to_symbols_map,
                                        symbol_to_sections_map, suffixed)

    # Make sure the anchor functions are located in the right place, here and
    # after everything else.
    # See the comment in //tools/cygprofile/lightweight_cyrprofile.cc.
    # The linker ignores sections it doesn't see, so this can stay for all builds.
    for prefix in _PREFIXES:
        print prefix + 'dummy_function_to_anchor_text'

    for section in expanded_sections:
        print section
    # The following is needed otherwise Gold only applies a partial sort.
    print '.text'  # gets methods not in a section, such as assembly
    for prefix in _PREFIXES:
        print prefix + '*'  # gets everything else

    for prefix in _PREFIXES:
        print prefix + 'dummy_function_at_the_end_of_text'

    return 0
예제 #4
0
def main():
    parser = _CreateArgumentParser()
    args = parser.parse_args()

    assert bool(args.merged_cyglog) ^ bool(args.reached_offsets)

    if not args.target_arch:
        args.arch = cygprofile_utils.DetectArchitecture()
    symbol_extractor.SetArchitecture(args.target_arch)

    obj_dir = cygprofile_utils.GetObjDir(args.native_library)

    offsets = []
    if args.merged_cyglog:
        log_file_lines = map(string.rstrip,
                             open(args.merged_cyglog).readlines())
        offsets = _ParseLogLines(log_file_lines)
    else:
        offsets = _ReadReachedOffsets(args.reached_offsets)
    assert offsets
    _WarnAboutDuplicates(offsets)

    generator = OffsetOrderfileGenerator(
        process_profiles.SymbolOffsetProcessor(args.native_library),
        ObjectFileProcessor(obj_dir))

    ordered_sections = generator.GetOrderedSections(offsets)
    if ordered_sections is None:
        return 1

    success = False
    temp_filename = None
    output_file = None
    try:
        (fd,
         temp_filename) = tempfile.mkstemp(dir=os.path.dirname(args.output))
        output_file = os.fdopen(fd, 'w')
        output_file.write('\n'.join(ordered_sections))
        output_file.close()
        os.rename(temp_filename, args.output)
        temp_filename = None
        success = True
    finally:
        if output_file:
            output_file.close()
        if temp_filename:
            os.remove(temp_filename)

    return 0 if success else 1
예제 #5
0
def main():
    parser = optparse.OptionParser(
        usage=
        'usage: %prog [options] <merged_cyglog> <library> <output_filename>')
    parser.add_option('--target-arch',
                      action='store',
                      dest='arch',
                      choices=['arm', 'arm64', 'x86', 'x86_64', 'x64', 'mips'],
                      help='The target architecture for libchrome.so')
    options, argv = parser.parse_args(sys.argv)
    if not options.arch:
        options.arch = cygprofile_utils.DetectArchitecture()
    if len(argv) != 4:
        parser.print_help()
        return 1
    (log_filename, lib_filename, output_filename) = argv[1:]
    symbol_extractor.SetArchitecture(options.arch)

    obj_dir = cygprofile_utils.GetObjDir(lib_filename)

    log_file_lines = map(string.rstrip, open(log_filename).readlines())
    offsets = _ParseLogLines(log_file_lines)
    _WarnAboutDuplicates(offsets)

    offset_to_symbol_infos = _GroupLibrarySymbolInfosByOffset(lib_filename)
    symbol_to_sections_map = GetSymbolToSectionsMapFromObjectFiles(obj_dir)

    success = False
    temp_filename = None
    output_file = None
    try:
        (fd, temp_filename) = tempfile.mkstemp(
            dir=os.path.dirname(output_filename))
        output_file = os.fdopen(fd, 'w')
        ok = _OutputOrderfile(offsets, offset_to_symbol_infos,
                              symbol_to_sections_map, output_file)
        output_file.close()
        os.rename(temp_filename, output_filename)
        temp_filename = None
        success = ok
    finally:
        if output_file:
            output_file.close()
        if temp_filename:
            os.remove(temp_filename)

    return 0 if success else 1
예제 #6
0
def main():
    parser = CreateArgumentParser()
    args = parser.parse_args()

    assert bool(args.merged_cyglog) ^ bool(args.reached_offsets)

    if not args.target_arch:
        args.arch = cygprofile_utils.DetectArchitecture()
    symbol_extractor.SetArchitecture(args.target_arch)

    obj_dir = cygprofile_utils.GetObjDir(args.native_library)

    offsets = []
    if args.merged_cyglog:
        log_file_lines = map(string.rstrip,
                             open(args.merged_cyglog).readlines())
        offsets = _ParseLogLines(log_file_lines)
    else:
        offsets = ReadReachedOffsets(args.reached_offsets)
    assert offsets
    _WarnAboutDuplicates(offsets)

    offset_to_symbol_infos = _GroupLibrarySymbolInfosByOffset(
        args.native_library)
    symbol_to_sections_map = GetSymbolToSectionsMapFromObjectFiles(obj_dir)

    success = False
    temp_filename = None
    output_file = None
    try:
        (fd,
         temp_filename) = tempfile.mkstemp(dir=os.path.dirname(args.output))
        output_file = os.fdopen(fd, 'w')
        ok = _OutputOrderfile(offsets, offset_to_symbol_infos,
                              symbol_to_sections_map, output_file)
        output_file.close()
        os.rename(temp_filename, args.output)
        temp_filename = None
        success = ok
    finally:
        if output_file:
            output_file.close()
        if temp_filename:
            os.remove(temp_filename)

    return 0 if success else 1