def _load_nm(prepared_data_dir, maps_filename, nm_json_filename): with open(os.path.join(prepared_data_dir, maps_filename), mode='r') as f: maps = parse_proc_maps(f) with open(os.path.join(prepared_data_dir, nm_json_filename), mode='r') as f: nm_files = json.load(f) symbol_tables = {} for entry in maps.iter(executable_condition): if nm_files.has_key(entry.name): if nm_files[entry.name]['format'] == 'bsd': with open(os.path.join(prepared_data_dir, nm_files[entry.name]['file']), mode='r') as f: symbol_tables[entry.name] = _get_static_symbols_from_nm_bsd( f, nm_files[entry.name]['mangled']) return StaticSymbols(maps, symbol_tables)
def _find_runtime_symbols(prepared_data_dir, addresses, outputter, loglevel=logging.WARN): log = logging.getLogger("find_runtime_symbols") log.setLevel(loglevel) handler = logging.StreamHandler() handler.setLevel(loglevel) formatter = logging.Formatter("%(message)s") handler.setFormatter(formatter) log.addHandler(handler) if not os.path.exists(prepared_data_dir): log.warn("Nothing found: %s" % prepared_data_dir) return 1 if not os.path.isdir(prepared_data_dir): log.warn("Not a directory: %s" % prepared_data_dir) return 1 with open(os.path.join(prepared_data_dir, "maps"), mode="r") as f: maps = parse_proc_maps(f) with open(os.path.join(prepared_data_dir, "nm.json"), mode="r") as f: nm_files = json.load(f) symbol_table = {} for entry in maps.iter(executable_condition): if nm_files.has_key(entry.name): if nm_files[entry.name]["format"] == "bsd": with open(os.path.join(prepared_data_dir, nm_files[entry.name]["file"]), mode="r") as f: symbol_table[entry.name] = get_procedure_boundaries_from_nm_bsd(f, nm_files[entry.name]["mangled"]) for address in addresses: if isinstance(address, str): address = int(address, 16) is_found = False for entry in maps.iter(executable_condition): if entry.begin <= address < entry.end: if entry.name in symbol_table: found = symbol_table[entry.name].find_procedure(address - (entry.begin - entry.offset)) outputter.output(address, found) else: outputter.output(address) is_found = True break if not is_found: outputter.output(address) return 0
def _load_files(prepared_data_dir, maps_filename, files_filename): with open(os.path.join(prepared_data_dir, maps_filename), mode='r') as f: maps = parse_proc_maps(f) with open(os.path.join(prepared_data_dir, files_filename), mode='r') as f: files = json.load(f) symbol_tables = {} for entry in maps.iter(executable_condition): if entry.name in files: if 'nm' in files[entry.name]: nm_entry = files[entry.name]['nm'] if nm_entry['format'] == 'bsd': with open(os.path.join(prepared_data_dir, nm_entry['file']), mode='r') as f: symbol_tables[entry.name] = _get_static_symbols_from_nm_bsd( f, nm_entry['mangled']) if 'readelf-e' in files: readelf_entry = files[entry.name]['readelf-e'] # TODO(dmikurube) Implement it. return StaticSymbols(maps, symbol_tables)
def prepare_symbol_info(maps_path, output_dir_path=None, loglevel=logging.WARN): log = logging.getLogger('prepare_symbol_info') log.setLevel(loglevel) handler = logging.StreamHandler() handler.setLevel(loglevel) formatter = logging.Formatter('%(message)s') handler.setFormatter(formatter) log.addHandler(handler) if not output_dir_path: matched = re.match('^(.*)\.maps$', os.path.basename(maps_path)) if matched: output_dir_path = matched.group(1) + '.pre' if not output_dir_path: matched = re.match('^/proc/(.*)/maps$', os.path.realpath(maps_path)) if matched: output_dir_path = matched.group(1) + '.pre' if not output_dir_path: output_dir_prefix = os.path.basename(maps_path) + '.pre' # TODO(dmikurube): Find another candidate for output_dir_path. log.info('Data for profiling will be collected in "%s".' % output_dir_path) output_dir_path_exists = False if os.path.exists(output_dir_path): if os.path.isdir(output_dir_path) and not os.listdir(output_dir_path): log.warn('Using an empty directory existing at "%s".' % output_dir_path) else: log.warn('A file or a directory exists at "%s".' % output_dir_path) output_dir_path_exists = True else: log.info('Creating a new directory at "%s".' % output_dir_path) os.mkdir(output_dir_path) if output_dir_path_exists: return 1 shutil.copyfile(maps_path, os.path.join(output_dir_path, 'maps')) with open(maps_path, mode='r') as f: maps = parse_proc_maps(f) log.debug('Listing up symbols.') nm_files = {} for entry in maps.iter(executable_condition): log.debug(' %016x-%016x +%06x %s' % ( entry.begin, entry.end, entry.offset, entry.name)) with tempfile.NamedTemporaryFile( prefix=os.path.basename(entry.name) + '.', suffix='.nm', delete=False, mode='w', dir=output_dir_path) as f: nm_filename = os.path.realpath(f.name) nm_succeeded = False cppfilt_succeeded = False p_nm = subprocess.Popen( 'nm -n --format bsd %s' % entry.name, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p_cppfilt = subprocess.Popen( 'c++filt', shell=True, stdin=p_nm.stdout, stdout=f, stderr=subprocess.PIPE) if p_nm.wait() == 0: nm_succeeded = True for line in p_nm.stderr: log.debug(line.rstrip()) if p_cppfilt.wait() == 0: cppfilt_succeeded = True for line in p_cppfilt.stderr: log.debug(line.rstrip()) if nm_succeeded and cppfilt_succeeded: nm_files[entry.name] = { 'file': os.path.basename(nm_filename), 'format': 'bsd', 'mangled': False} else: os.remove(nm_filename) with open(os.path.join(output_dir_path, 'nm.json'), 'w') as f: json.dump(nm_files, f, indent=2, sort_keys=True) log.info('Collected symbol information at "%s".' % output_dir_path) return 0
def prepare_symbol_info(maps_path, output_dir_path=None, loglevel=logging.WARN): log = logging.getLogger('prepare_symbol_info') log.setLevel(loglevel) handler = logging.StreamHandler() handler.setLevel(loglevel) formatter = logging.Formatter('%(message)s') handler.setFormatter(formatter) log.addHandler(handler) if not output_dir_path: matched = re.match('^(.*)\.maps$', os.path.basename(maps_path)) if matched: output_dir_path = matched.group(1) + '.pre' if not output_dir_path: matched = re.match('^/proc/(.*)/maps$', os.path.realpath(maps_path)) if matched: output_dir_path = matched.group(1) + '.pre' if not output_dir_path: output_dir_prefix = os.path.basename(maps_path) + '.pre' # TODO(dmikurube): Find another candidate for output_dir_path. log.info('Data for profiling will be collected in "%s".' % output_dir_path) output_dir_path_exists = False if os.path.exists(output_dir_path): if os.path.isdir(output_dir_path) and not os.listdir(output_dir_path): log.warn('Using an empty directory existing at "%s".' % output_dir_path) else: log.warn('A file or a directory exists at "%s".' % output_dir_path) output_dir_path_exists = True else: log.info('Creating a new directory at "%s".' % output_dir_path) os.mkdir(output_dir_path) if output_dir_path_exists: return 1 shutil.copyfile(maps_path, os.path.join(output_dir_path, 'maps')) with open(maps_path, mode='r') as f: maps = parse_proc_maps(f) log.debug('Listing up symbols.') files = {} for entry in maps.iter(executable_condition): log.debug(' %016x-%016x +%06x %s' % ( entry.begin, entry.end, entry.offset, entry.name)) nm_filename = _dump_command_result( 'nm -n --format bsd %s | c++filt' % entry.name, output_dir_path, os.path.basename(entry.name), '.nm', log) if not nm_filename: continue readelf_e_filename = _dump_command_result( 'readelf -e %s' % entry.name, output_dir_path, os.path.basename(entry.name), '.readelf-e', log) if not readelf_e_filename: continue files[entry.name] = {} files[entry.name]['nm'] = { 'file': os.path.basename(nm_filename), 'format': 'bsd', 'mangled': False} files[entry.name]['readelf-e'] = { 'file': os.path.basename(readelf_e_filename)} with open(os.path.join(output_dir_path, 'files.json'), 'w') as f: json.dump(files, f, indent=2, sort_keys=True) log.info('Collected symbol information at "%s".' % output_dir_path) return 0