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))