Exemple #1
0
    def _SymbolizeLinuxAndAndroid(self, symfile, unsymbolized_name):
        def _SymbolizerCallback(sym_info, frames):
            # Unwind inline chain to the top.
            while sym_info.inlined_by:
                sym_info = sym_info.inlined_by

            symbolized_name = sym_info.name if sym_info.name else unsymbolized_name
            for frame in frames:
                frame.name = symbolized_name

        symbolizer = elf_symbolizer.ELFSymbolizer(symfile.symbolizable_path,
                                                  self.symbolizer_path,
                                                  _SymbolizerCallback,
                                                  inlines=True)

        for address, frames in symfile.frames_by_address.iteritems():
            # SymbolizeAsync() asserts that the type of address is int. We operate
            # on longs (since they are raw pointers possibly from 64-bit processes).
            # It's OK to cast here because we're passing relative PC, which should
            # always fit into int.
            symbolizer.SymbolizeAsync(int(address), frames)

        symbolizer.Join()
def RunElfSymbolizer(outfile, library, addr2line_binary, nm_binary, jobs,
                     disambiguate, src_path):
    nm_output = RunNm(library, nm_binary)
    nm_output_lines = nm_output.splitlines()
    nm_output_lines_len = len(nm_output_lines)
    address_symbol = {}
    progress = Progress()

    def map_address_symbol(symbol, addr):
        progress.count += 1
        if addr in address_symbol:
            # 'Collision between %s and %s.' % (str(symbol.name),
            #                                   str(address_symbol[addr].name))
            progress.collisions += 1
        else:
            if symbol.disambiguated:
                progress.disambiguations += 1
            if symbol.was_ambiguous:
                progress.was_ambiguous += 1

            address_symbol[addr] = symbol

        progress_output()

    def progress_output():
        progress_chunk = 100
        if progress.count % progress_chunk == 0:
            time_now = time.time()
            time_spent = time_now - progress.time_last_output
            if time_spent > 1.0:
                # Only output at most once per second.
                progress.time_last_output = time_now
                chunk_size = progress.count - progress.count_last_output
                progress.count_last_output = progress.count
                if time_spent > 0:
                    speed = chunk_size / time_spent
                else:
                    speed = 0
                progress_percent = (100.0 *
                                    (progress.count + progress.skip_count) /
                                    nm_output_lines_len)
                disambiguation_percent = 0
                if progress.disambiguations != 0:
                    disambiguation_percent = (100.0 *
                                              progress.disambiguations /
                                              progress.was_ambiguous)

                sys.stdout.write(
                    '\r%.1f%%: Looked up %d symbols (%d collisions, '
                    '%d disambiguations where %.1f%% succeeded)'
                    ' - %.1f lookups/s.' %
                    (progress_percent, progress.count, progress.collisions,
                     progress.disambiguations, disambiguation_percent, speed))

    # In case disambiguation was disabled, we remove the source path (which upon
    # being set signals the symbolizer to enable disambiguation)
    if not disambiguate:
        src_path = None
    symbolizer = elf_symbolizer.ELFSymbolizer(library,
                                              addr2line_binary,
                                              map_address_symbol,
                                              max_concurrent_jobs=jobs,
                                              source_root_path=src_path)
    user_interrupted = False
    try:
        for line in nm_output_lines:
            match = sNmPattern.match(line)
            if match:
                location = match.group(5)
                if not location:
                    addr = int(match.group(1), 16)
                    size = int(match.group(2), 16)
                    if addr in address_symbol:  # Already looked up, shortcut
                        # ELFSymbolizer.
                        map_address_symbol(address_symbol[addr], addr)
                        continue
                    elif size == 0:
                        # Save time by not looking up empty symbols (do they even exist?)
                        print('Empty symbol: ' + line)
                    else:
                        symbolizer.SymbolizeAsync(addr, addr)
                        continue

            progress.skip_count += 1
    except KeyboardInterrupt:
        user_interrupted = True
        print('Interrupting - killing subprocesses. Please wait.')

    try:
        symbolizer.Join()
    except KeyboardInterrupt:
        # Don't want to abort here since we will be finished in a few seconds.
        user_interrupted = True
        print('Patience you must have my young padawan.')

    print ''

    if user_interrupted:
        print(
            'Skipping the rest of the file mapping. '
            'Output will not be fully classified.')

    symbol_path_origin_dir = os.path.dirname(os.path.abspath(library))

    with open(outfile, 'w') as out:
        for line in nm_output_lines:
            match = sNmPattern.match(line)
            if match:
                location = match.group(5)
                if not location:
                    addr = int(match.group(1), 16)
                    symbol = address_symbol.get(addr)
                    if symbol is not None:
                        path = '??'
                        if symbol.source_path is not None:
                            path = os.path.abspath(
                                os.path.join(symbol_path_origin_dir,
                                             symbol.source_path))
                        line_number = 0
                        if symbol.source_line is not None:
                            line_number = symbol.source_line
                        out.write('%s\t%s:%d\n' % (line, path, line_number))
                        continue

            out.write('%s\n' % line)

    print('%d symbols in the results.' % len(address_symbol))