def _normalize_in_app(stacktrace, platform=None, sdk_info=None): """ Ensures consistent values of in_app across a stacktrace. """ # Native frames have special rules regarding in_app. Apply them before other # normalization, just like grouping enhancers. # TODO(ja): Clean up those rules and put them in enhancers instead for frame in stacktrace: if frame.get('in_app') is not None: continue family = get_grouping_family_for_platform(frame.get('platform') or platform) if family == 'native': frame_package = frame.get('package') frame['in_app'] = bool(frame_package) and \ not is_known_third_party(frame_package, sdk_info=sdk_info) has_system_frames = _has_system_frames(stacktrace) for frame in stacktrace: # If all frames are in_app, flip all of them. This is expected by the UI if not has_system_frames: frame['in_app'] = False # Default to false in all cases where processors or grouping enhancers # have not yet set in_app. elif frame.get('in_app') is None: frame['in_app'] = False
def _handle_image_status(status, image, sdk_info, data): if status in ("found", "unused"): return elif status == "missing": package = image.get("code_file") # TODO(mitsuhiko): This check seems wrong? This call seems to # mirror the one in the ios symbol server support. If we change # one we need to change the other. if not package or is_known_third_party(package, sdk_info=sdk_info): return if is_optional_package(package, sdk_info=sdk_info): error = SymbolicationFailed( type=EventError.NATIVE_MISSING_OPTIONALLY_BUNDLED_DSYM) else: error = SymbolicationFailed(type=EventError.NATIVE_MISSING_DSYM) elif status == "malformed": error = SymbolicationFailed(type=EventError.NATIVE_BAD_DSYM) elif status == "too_large": error = SymbolicationFailed(type=EventError.FETCH_TOO_LARGE) elif status == "fetching_failed": error = SymbolicationFailed(type=EventError.FETCH_GENERIC_ERROR) elif status == "other": error = SymbolicationFailed(type=EventError.UNKNOWN_ERROR) else: logger.error("Unknown status: %s", status) return error.image_arch = image.get("arch") error.image_path = image.get("code_file") error.image_name = image_name(image.get("code_file")) error.image_uuid = image.get("debug_id") write_error(error, data)
def handle_symbolicator_status(status, image, sdk_info, handle_symbolication_failed): if status in ('found', 'unused'): return elif status in ( 'missing_debug_file', # TODO(markus): Legacy key. Remove after next deploy 'missing'): package = image.get('code_file') if not package or is_known_third_party(package, sdk_info=sdk_info): return if is_optional_package(package, sdk_info=sdk_info): error = SymbolicationFailed( type=EventError.NATIVE_MISSING_OPTIONALLY_BUNDLED_DSYM) else: error = SymbolicationFailed(type=EventError.NATIVE_MISSING_DSYM) elif status in ( 'malformed_debug_file', # TODO(markus): Legacy key. Remove after next deploy 'malformed'): error = SymbolicationFailed(type=EventError.NATIVE_BAD_DSYM) elif status == 'too_large': error = SymbolicationFailed(type=EventError.FETCH_TOO_LARGE) elif status == 'fetching_failed': error = SymbolicationFailed(type=EventError.FETCH_GENERIC_ERROR) elif status == 'other': error = SymbolicationFailed(type=EventError.UNKNOWN_ERROR) else: logger.error("Unknown status: %s", status) return error.image_arch = image.get('arch') error.image_path = image.get('code_file') error.image_name = image_name(image.get('code_file')) error.image_uuid = image.get('debug_id') handle_symbolication_failed(error)
def _normalize_in_app(stacktrace, platform=None, sdk_info=None): """ Ensures consistent values of in_app across a stacktrace. """ # Native frames have special rules regarding in_app. Apply them before other # normalization, just like grouping enhancers. # TODO(ja): Clean up those rules and put them in enhancers instead for frame in stacktrace: if frame.get('in_app') is not None: continue family = get_behavior_family_for_platform(frame.get('platform') or platform) if family == 'native': frame_package = frame.get('package') frame['in_app'] = bool(frame_package) and \ not is_known_third_party(frame_package, sdk_info=sdk_info) has_system_frames = _has_system_frames(stacktrace) for frame in stacktrace: # If all frames are in_app, flip all of them. This is expected by the UI if not has_system_frames: frame['in_app'] = False # Default to false in all cases where processors or grouping enhancers # have not yet set in_app. elif frame.get('in_app') is None: frame['in_app'] = False
def _handle_image_status(status, image, sdk_info, handle_symbolication_failed): if status in ('found', 'unused'): return elif status == 'missing': package = image.get('code_file') # TODO(mitsuhiko): This check seems wrong? This call seems to # mirror the one in the ios symbol server support. If we change # one we need to change the other. if not package or is_known_third_party(package, sdk_info=sdk_info): return if is_optional_package(package, sdk_info=sdk_info): error = SymbolicationFailed( type=EventError.NATIVE_MISSING_OPTIONALLY_BUNDLED_DSYM) else: error = SymbolicationFailed(type=EventError.NATIVE_MISSING_DSYM) elif status == 'malformed': error = SymbolicationFailed(type=EventError.NATIVE_BAD_DSYM) elif status == 'too_large': error = SymbolicationFailed(type=EventError.FETCH_TOO_LARGE) elif status == 'fetching_failed': error = SymbolicationFailed(type=EventError.FETCH_GENERIC_ERROR) elif status == 'other': error = SymbolicationFailed(type=EventError.UNKNOWN_ERROR) else: logger.error("Unknown status: %s", status) return error.image_arch = image.get('arch') error.image_path = image.get('code_file') error.image_name = image_name(image.get('code_file')) error.image_uuid = image.get('debug_id') handle_symbolication_failed(error)
def symbolize_frame(self, instruction_addr, sdk_info=None, symbolserver_match=None, symbolicator_match=None, trust=None): app_err = None # A missing symbolicator match indicates that the symbolicator was not # active for this event. Symbolize the app frame directly using # symbolic. # TODO: Remove this after fully switching to symbolicator if symbolicator_match is None: obj = self.object_lookup.find_object(instruction_addr) if obj is None: if trust == 'scan': return [] raise SymbolicationFailed(type=EventError.NATIVE_UNKNOWN_IMAGE) # Try to always prefer the images from the application storage. # If the symbolication fails we keep the error for later try: match = self._symbolize_app_frame( instruction_addr, obj, sdk_info=sdk_info, trust=trust) if match: return match except SymbolicationFailed as err: app_err = err # If the symbolicator was used, trust its result. Errors that were # generated during symbolication are merged into the event's error # array separately and do not need to be handled here. The match # returned can either be: # - empty: Symbolicator has explicitly discarded this # frame as a false positive. This happens especially when # stackwalking without CFI. # - all unsymbolicated frames: # Symbolicator was unable to resolve symbols for this frame, so we # fall back to (iOS) symbolserver (see below). # - some unsymbolicated frames: # Symbolicator was able to resolve e.g. # an inline frame but then failed to symbolicate. This is not really # that useful either. # # TODO: Remove this fallback once symbolicator supports iOS system # symbols and fully trust the symbolicator response. elif all(x["status"] == "symbolicated" for x in symbolicator_match) or symbolicator_match == []: return symbolicator_match # Then we check the symbolserver for a match. match = self._convert_symbolserver_match(instruction_addr, symbolserver_match) # If we do not get a match and the image was from an app bundle # and we got an error first, we now fail with the original error # as we did indeed encounter a symbolication error. If however # the match was empty we just accept it as a valid symbolication # that just did not return any results but without error. if app_err is not None \ and not match \ and (not obj.code_file or not is_known_third_party(obj.code_file, sdk_info=sdk_info)): raise app_err return match
def fetch_ios_system_symbols(self, processing_task): to_lookup = [] pf_list = [] for pf in processing_task.iter_processable_frames(self): if pf.cache_value is not None: continue obj = pf.data['obj'] package = obj and obj.code_file # TODO(ja): This should check for iOS specifically if not package or not is_known_third_party(package): continue # We can only look up objects in the symbol server that have a # uuid. If we encounter things with an age appended or # similar we need to skip. try: uuid.UUID(obj.debug_id) except (ValueError, TypeError): continue to_lookup.append({ 'object_uuid': obj.debug_id, 'object_name': obj.code_file or '<unknown>', 'addr': '0x%x' % rebase_addr(pf.data['instruction_addr'], obj) }) pf_list.append(pf) if not to_lookup: return rv = lookup_system_symbols(to_lookup, self.sdk_info, self.arch) if rv is not None: for symrv, pf in zip(rv, pf_list): if symrv is None: continue pf.data['symbolserver_match'] = symrv
def fetch_ios_system_symbols(self, processing_task): to_lookup = [] pf_list = [] for pf in processing_task.iter_processable_frames(self): if pf.cache_value is not None: continue obj = pf.data['obj'] package = obj and obj.code_file # TODO(ja): This should check for iOS specifically if not package or not is_known_third_party(package): continue # We can only look up objects in the symbol server that have a # uuid. If we encounter things with an age appended or # similar we need to skip. try: uuid.UUID(obj.debug_id) except (ValueError, TypeError): continue to_lookup.append( { 'object_uuid': obj.debug_id, 'object_name': obj.code_file or '<unknown>', 'addr': '0x%x' % rebase_addr(pf.data['instruction_addr'], obj) } ) pf_list.append(pf) if not to_lookup: return rv = lookup_system_symbols(to_lookup, self.sdk_info, self.arch) if rv is not None: for symrv, pf in zip(rv, pf_list): if symrv is None: continue pf.data['symbolserver_match'] = symrv
def handle_symbolicator_status(status, image, sdk_info, handle_symbolication_failed): if status in ('found', 'unused'): return elif status in ( 'missing_debug_file', # TODO(markus): Legacy key. Remove after next deploy 'missing' ): package = image.get('code_file') if not package or is_known_third_party(package, sdk_info=sdk_info): return if is_optional_package(package, sdk_info=sdk_info): error = SymbolicationFailed( type=EventError.NATIVE_MISSING_OPTIONALLY_BUNDLED_DSYM) else: error = SymbolicationFailed(type=EventError.NATIVE_MISSING_DSYM) elif status in ( 'malformed_debug_file', # TODO(markus): Legacy key. Remove after next deploy 'malformed' ): error = SymbolicationFailed(type=EventError.NATIVE_BAD_DSYM) elif status == 'too_large': error = SymbolicationFailed(type=EventError.FETCH_TOO_LARGE) elif status == 'fetching_failed': error = SymbolicationFailed(type=EventError.FETCH_GENERIC_ERROR) elif status == 'other': error = SymbolicationFailed(type=EventError.UNKNOWN_ERROR) else: logger.error("Unknown status: %s", status) return error.image_arch = image.get('arch') error.image_path = image.get('code_file') error.image_name = image_name(image.get('code_file')) error.image_uuid = image.get('debug_id') handle_symbolication_failed(error)