def resolve_frame_symbols(data): debug_meta = data['debug_meta'] debug_images = debug_meta['images'] sdk_info = get_sdk_from_event(data) stacktraces = find_all_stacktraces(data) if not stacktraces: return project = Project.objects.get_from_cache( id=data['project'], ) errors = [] referenced_images = find_stacktrace_referenced_images( debug_images, stacktraces) sym = Symbolizer(project, debug_images, referenced_images=referenced_images) frame = None idx = -1 def report_error(e): errors.append({ 'type': EventError.NATIVE_INTERNAL_FAILURE, 'frame': frame, 'error': 'frame #%d: %s: %s' % ( idx, e.__class__.__name__, six.text_type(e), ) }) longest_addr = 0 processed_frames = [] with sym: for stacktrace in stacktraces: for idx, frame in enumerate(stacktrace['frames']): if 'image_addr' not in frame or \ 'instruction_addr' not in frame or \ 'symbol_addr' not in frame: continue try: sfrm = sym.symbolize_frame({ 'object_name': frame.get('package'), 'object_addr': frame['image_addr'], 'instruction_addr': frame['instruction_addr'], 'symbol_addr': frame['symbol_addr'], }, sdk_info, report_error=report_error) if not sfrm: continue # XXX: log here if symbol could not be found? frame['function'] = sfrm.get('symbol_name') or \ frame.get('function') or '<unknown>' frame['abs_path'] = sfrm.get('filename') or None if frame['abs_path']: frame['filename'] = posixpath.basename(frame['abs_path']) if sfrm.get('line') is not None: frame['lineno'] = sfrm['line'] else: frame['instruction_offset'] = \ parse_addr(sfrm['instruction_addr']) - \ parse_addr(sfrm['symbol_addr']) if sfrm.get('column') is not None: frame['colno'] = sfrm['column'] frame['package'] = sfrm['object_name'] or frame.get('package') frame['symbol_addr'] = '0x%x' % parse_addr(sfrm['symbol_addr']) frame['instruction_addr'] = '0x%x' % parse_addr( sfrm['instruction_addr']) frame['in_app'] = is_in_app(frame) longest_addr = max(longest_addr, len(frame['symbol_addr']), len(frame['instruction_addr'])) processed_frames.append(frame) except Exception: logger.exception('Failed to symbolicate') errors.append({ 'type': EventError.NATIVE_INTERNAL_FAILURE, 'error': 'The symbolicator encountered an internal failure', }) # Pad out addresses to be of the same length for frame in processed_frames: for key in 'symbol_addr', 'instruction_addr': frame[key] = '0x' + frame[key][2:].rjust(longest_addr - 2, '0') if errors: data.setdefault('errors', []).extend(errors) return data
def resolve_frame_symbols(data): debug_meta = data['debug_meta'] debug_images = debug_meta['images'] sdk_info = get_sdk_from_event(data) stacktraces = find_all_stacktraces(data) if not stacktraces: return project = Project.objects.get_from_cache( id=data['project'], ) errors = [] referenced_images = find_stacktrace_referenced_images( debug_images, [x[0] for x in stacktraces]) sym = Symbolizer(project, debug_images, referenced_images=referenced_images) frame = None idx = -1 def report_error(exc_type, exc_value, tb): if exc_value.is_user_fixable or exc_value.is_sdk_failure: errors.append({ 'type': EventError.NATIVE_INTERNAL_FAILURE, 'frame': frame, 'error': u'frame #%d: %s' % (idx, exc_value) }) if not exc_value.is_user_fixable: logger.debug('Failed to symbolicate', exc_info=(exc_type, exc_value, tb)) with sym: for stacktrace, container in stacktraces: store_raw = False new_frames = list(stacktrace['frames']) for idx, frame in enumerate(stacktrace['frames']): if 'image_addr' not in frame or \ 'instruction_addr' not in frame or \ 'symbol_addr' not in frame: continue try: # Construct a raw frame that is used by the symbolizer # backend. raw_frame = { 'object_name': frame.get('package'), 'object_addr': frame['image_addr'], 'instruction_addr': frame['instruction_addr'], 'symbol_addr': frame['symbol_addr'], } new_frame = dict(frame) try: sfrm = sym.symbolize_frame(raw_frame, sdk_info) except SymbolicationFailed: report_error(*sys.exc_info()) else: symbol = sfrm.get('symbol_name') or \ new_frame.get('function') or '<unknown>' function = demangle_symbol(symbol, simplified=True) new_frame['function'] = function # If we demangled something, store the original in the # symbol portion of the frame if function != symbol: new_frame['symbol'] = symbol new_frame['abs_path'] = sfrm.get('filename') or None if new_frame['abs_path']: new_frame['filename'] = posixpath.basename( new_frame['abs_path']) if sfrm.get('line') is not None: new_frame['lineno'] = sfrm['line'] else: new_frame['instruction_offset'] = \ parse_addr(sfrm['instruction_addr']) - \ parse_addr(sfrm['symbol_addr']) if sfrm.get('column') is not None: new_frame['colno'] = sfrm['column'] new_frame['package'] = sfrm['object_name'] \ or new_frame.get('package') new_frame['symbol_addr'] = '0x%x' % \ parse_addr(sfrm['symbol_addr']) new_frame['instruction_addr'] = '0x%x' % parse_addr( sfrm['instruction_addr']) new_frame['in_app'] = sym.is_in_app(raw_frame) if new_frame != frame: new_frames[idx] = new_frame store_raw = True except Exception: logger.exception('Failed to symbolicate') errors.append({ 'type': EventError.NATIVE_INTERNAL_FAILURE, 'error': 'The symbolicator encountered an internal failure', }) # Remember the raw stacktrace. if store_raw and container is not None: container['raw_stacktrace'] = { 'frames': stacktrace['frames'], } # Put the new frames in stacktrace['frames'] = new_frames if errors: data.setdefault('errors', []).extend(errors) return data
def preprocess_apple_crash_event(data): """This processes the "legacy" AppleCrashReport.""" crash_report = data['sentry.interfaces.AppleCrashReport'] if os.environ.get('SENTRY_DUMP_APPLE_CRASH_REPORT') == '1': dump_crash_report(crash_report) project = Project.objects.get_from_cache( id=data['project'], ) system = None errors = [] threads = [] crash = crash_report['crash'] crashed_thread = None threads = {} raw_threads = {} for raw_thread in crash['threads']: if raw_thread['crashed'] and raw_thread.get('backtrace'): crashed_thread = raw_thread raw_threads[raw_thread['index']] = raw_thread threads[raw_thread['index']] = { 'id': raw_thread['index'], 'name': raw_thread.get('name'), 'current': raw_thread.get('current_thread', False), 'crashed': raw_thread.get('crashed', False), } sdk_info = get_sdk_from_apple_system_info(system) referenced_images = find_apple_crash_report_referenced_images( crash_report['binary_images'], raw_threads.values()) sym = Symbolizer(project, crash_report['binary_images'], referenced_images=referenced_images) with sym: if crashed_thread is None: append_error(data, { 'type': EventError.NATIVE_NO_CRASHED_THREAD, }) else: system = crash_report.get('system') try: bt, errors = sym.symbolize_backtrace( crashed_thread['backtrace']['contents'], sdk_info) for error in errors: append_error(data, error) if inject_apple_backtrace(data, bt, crash.get('diagnosis'), crash.get('error'), system, crashed_thread.get('notable_addresses'), crashed_thread['index']): # We recorded an exception, so in this case we can # skip having the stacktrace. threads[crashed_thread['index']]['stacktrace'] = None except Exception: logger.exception('Failed to symbolicate') errors.append({ 'type': EventError.NATIVE_INTERNAL_FAILURE, 'error': 'The symbolicator encountered an internal failure', }) for thread in six.itervalues(threads): # If we were told to skip the stacktrace, skip it indeed if thread.get('stacktrace', Ellipsis) is None: continue raw_thread = raw_threads.get(thread['id']) if raw_thread is None or not raw_thread.get('backtrace'): continue bt, errors = sym.symbolize_backtrace( raw_thread['backtrace']['contents'], sdk_info) for error in errors: append_error(data, error) thread['stacktrace'] = convert_stacktrace( bt, system, raw_thread.get('notable_addresses')) if threads: data['threads'] = { 'values': sorted(threads.values(), key=lambda x: x['id']), } if system: inject_apple_device_data(data, system) return data
def resolve_frame_symbols(data): debug_meta = data['debug_meta'] debug_images = debug_meta['images'] sdk_info = get_sdk_from_event(data) stacktraces = find_all_stacktraces(data) if not stacktraces: return project = Project.objects.get_from_cache(id=data['project'], ) errors = [] referenced_images = find_stacktrace_referenced_images( debug_images, [x[0] for x in stacktraces]) sym = Symbolizer(project, debug_images, referenced_images=referenced_images) frame = None idx = -1 def report_error(e): errors.append({ 'type': EventError.NATIVE_INTERNAL_FAILURE, 'frame': frame, 'error': 'frame #%d: %s: %s' % ( idx, e.__class__.__name__, six.text_type(e), ) }) with sym: for stacktrace, container in stacktraces: store_raw = False new_frames = list(stacktrace['frames']) for idx, frame in enumerate(stacktrace['frames']): if 'image_addr' not in frame or \ 'instruction_addr' not in frame or \ 'symbol_addr' not in frame: continue try: sfrm = sym.symbolize_frame( { 'object_name': frame.get('package'), 'object_addr': frame['image_addr'], 'instruction_addr': frame['instruction_addr'], 'symbol_addr': frame['symbol_addr'], }, sdk_info, report_error=report_error) if not sfrm: continue new_frame = dict(frame) # XXX: log here if symbol could not be found? new_frame['function'] = sfrm.get('symbol_name') or \ new_frame.get('function') or '<unknown>' new_frame['abs_path'] = sfrm.get('filename') or None if new_frame['abs_path']: new_frame['filename'] = posixpath.basename( new_frame['abs_path']) if sfrm.get('line') is not None: new_frame['lineno'] = sfrm['line'] else: new_frame['instruction_offset'] = \ parse_addr(sfrm['instruction_addr']) - \ parse_addr(sfrm['symbol_addr']) if sfrm.get('column') is not None: new_frame['colno'] = sfrm['column'] new_frame['package'] = sfrm[ 'object_name'] or new_frame.get('package') new_frame['symbol_addr'] = '0x%x' % parse_addr( sfrm['symbol_addr']) new_frame['instruction_addr'] = '0x%x' % parse_addr( sfrm['instruction_addr']) new_frame['in_app'] = is_in_app(new_frame) if new_frame != frame: new_frames[idx] = new_frame store_raw = True except Exception: logger.exception('Failed to symbolicate') errors.append({ 'type': EventError.NATIVE_INTERNAL_FAILURE, 'error': 'The symbolicator encountered an internal failure', }) # Remember the raw stacktrace. if store_raw and container is not None: container['raw_stacktrace'] = { 'frames': stacktrace['frames'], } # Put the new frames in stacktrace['frames'] = new_frames if errors: data.setdefault('errors', []).extend(errors) return data