def _convert_debug_meta_to_binary_image_row(self, debug_image): slide_value = parse_addr(debug_image['image_vmaddr']) image_addr = parse_addr(debug_image['image_addr']) + slide_value return '%s - %s %s %s <%s> %s' % ( hex(image_addr), hex(image_addr + debug_image['image_size'] - 1), image_name(debug_image['name']), self.context['device']['arch'], debug_image['uuid'].replace('-', '').lower(), debug_image['name'])
def _convert_frame_to_apple_string(self, frame, next=None, number=0): if frame.get('instruction_addr') is None: return None slide_value = self._get_slide_value(frame.get('image_addr')) instruction_addr = slide_value + \ parse_addr(frame.get('instruction_addr')) image_addr = slide_value + parse_addr(frame.get('image_addr')) offset = '' if frame.get('image_addr') is not None and \ (not self.symbolicated or ( frame.get('function') or NATIVE_UNKNOWN_STRING) == NATIVE_UNKNOWN_STRING): offset = ' + %s' % (instruction_addr - slide_value - parse_addr(frame.get('symbol_addr'))) symbol = hex(image_addr) if self.symbolicated: file = '' if frame.get('filename') and frame.get('lineno'): file = ' (%s:%s)' % (posixpath.basename( frame.get('filename') or NATIVE_UNKNOWN_STRING), frame['lineno']) symbol = '%s%s' % (frame.get('function') or NATIVE_UNKNOWN_STRING, file) if next and parse_addr(frame.get('instruction_addr')) == \ parse_addr(next.get('instruction_addr')): symbol = '[inlined] ' + symbol return '%s%s%s%s%s' % ( str(number).ljust(4, ' '), image_name(frame.get('package') or NATIVE_UNKNOWN_STRING).ljust( 32, ' '), hex(instruction_addr).ljust(20, ' '), symbol, offset)
def _convert_frame_to_apple_string(self, frame, next=None, number=0): if frame.get("instruction_addr") is None: return None slide_value = self._get_slide_value(frame.get("image_addr")) instruction_addr = slide_value + parse_addr(frame.get("instruction_addr")) image_addr = slide_value + parse_addr(frame.get("image_addr")) offset = "" if frame.get("image_addr") is not None and ( not self.symbolicated or (frame.get("function") or NATIVE_UNKNOWN_STRING) == NATIVE_UNKNOWN_STRING ): offset = " + %s" % ( instruction_addr - slide_value - parse_addr(frame.get("symbol_addr")) ) symbol = hex(image_addr) if self.symbolicated: file = "" if frame.get("filename") and frame.get("lineno"): file = " (%s:%s)" % ( posixpath.basename(frame.get("filename") or NATIVE_UNKNOWN_STRING), frame["lineno"], ) symbol = "%s%s" % (frame.get("function") or NATIVE_UNKNOWN_STRING, file) if next and parse_addr(frame.get("instruction_addr")) == parse_addr( next.get("instruction_addr") ): symbol = "[inlined] " + symbol return "%s%s%s%s%s" % ( str(number).ljust(4, " "), image_name(frame.get("package") or NATIVE_UNKNOWN_STRING).ljust(32, " "), hex(instruction_addr).ljust(20, " "), symbol, offset, )
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 _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 _convert_frame_to_apple_string(self, frame, next=None, number=0): if frame.get('instruction_addr') is None: return None slide_value = self._get_slide_value(frame.get('image_addr')) instruction_addr = slide_value + \ parse_addr(frame.get('instruction_addr')) image_addr = slide_value + parse_addr(frame.get('image_addr')) offset = '' if frame.get('image_addr') is not None and \ (not self.symbolicated or ( frame.get('function') or NATIVE_UNKNOWN_STRING) == NATIVE_UNKNOWN_STRING): offset = ' + %s' % ( instruction_addr - slide_value - parse_addr(frame.get('symbol_addr')) ) symbol = hex(image_addr) if self.symbolicated: file = '' if frame.get('filename') and frame.get('lineno'): file = ' (%s:%s)' % ( posixpath.basename(frame.get('filename') or NATIVE_UNKNOWN_STRING), frame['lineno'] ) symbol = '%s%s' % (frame.get('function') or NATIVE_UNKNOWN_STRING, file) if next and parse_addr(frame['instruction_addr']) == \ parse_addr(next['instruction_addr']): symbol = '[inlined] ' + symbol return '%s%s%s%s%s' % ( str(number).ljust(4, ' '), image_name(frame.get('package') or NATIVE_UNKNOWN_STRING).ljust(32, ' '), hex(instruction_addr).ljust(20, ' '), symbol, offset )
def _convert_debug_meta_to_binary_image_row(self, debug_image): slide_value = parse_addr(debug_image['image_vmaddr']) image_addr = parse_addr(debug_image['image_addr']) + slide_value return '%s - %s %s %s <%s> %s' % ( hex(image_addr), hex(image_addr + debug_image['image_size'] - 1), image_name(debug_image['name']), self.context['device']['arch'], debug_image['uuid'].replace('-', '').lower(), debug_image['name'] )
def _convert_debug_meta_to_binary_image_row(self, debug_image): slide_value = parse_addr(debug_image.get("image_vmaddr", 0)) image_addr = parse_addr(debug_image["image_addr"]) + slide_value return "%s - %s %s %s <%s> %s" % ( hex(image_addr), hex(image_addr + debug_image["image_size"] - 1), image_name(debug_image.get("code_file") or NATIVE_UNKNOWN_STRING), get_path(self.context, "device", "arch") or NATIVE_UNKNOWN_STRING, debug_image.get("debug_id").replace("-", "").lower(), debug_image.get("code_file") or NATIVE_UNKNOWN_STRING, )
def _convert_debug_meta_to_binary_image_row(self, debug_image): slide_value = parse_addr(debug_image["image_vmaddr"]) image_addr = parse_addr(debug_image["image_addr"]) + slide_value return "%s - %s %s %s <%s> %s" % ( hex(image_addr), hex(image_addr + debug_image["image_size"] - 1), image_name(debug_image["name"]), self.context["device"]["arch"], (debug_image.get("id") or debug_image.get("uuid")).replace( "-", "").lower(), debug_image["name"], )
def __init__(self, message=None, type=None, obj=None): Exception.__init__(self) self.message = six.text_type(message) self.type = type self.image_name = None self.image_path = None if obj is not None: self.image_uuid = six.text_type(obj.id) if obj.name: self.image_path = obj.name self.image_name = image_name(obj.name) self.image_arch = obj.arch else: self.image_uuid = None self.image_arch = None
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 run_symbolicator(self, processing_task): # TODO(markus): Make this work with minidumps. An unprocessed minidump # event will not contain unsymbolicated frames, because the minidump # upload already happened in store. # It will also presumably not contain images, so `self.available` will # already be `False`. if not self.available: return request_id_cache_key = request_id_cache_key_for_event(self.data) stacktraces = [] processable_stacktraces = [] for stacktrace_info, pf_list in processing_task.iter_processable_stacktraces( ): registers = stacktrace_info.stacktrace.get('registers') or {} # The filtering condition of this list comprehension is copied # from `iter_processable_frames`. # # We cannot reuse `iter_processable_frames` because the # symbolicator currently expects a list of stacktraces, not # flat frames. # # Right now we can't even filter out frames (e.g. using a frame # cache locally). The stacktraces have to be as complete as # possible because the symbolicator assumes the first frame of # a stacktrace to be the crashing frame. This assumption is # already violated because the SDK might chop off frames though # (which is less likely to be the case though). pf_list = [pf for pf in reversed(pf_list) if pf.processor == self] frames = [] for pf in pf_list: frame = {'instruction_addr': pf['instruction_addr']} if pf.get('trust') is not None: frame['trust'] = pf['trust'] frames.append(frame) stacktraces.append({'registers': registers, 'frames': frames}) processable_stacktraces.append(pf_list) rv = run_symbolicator(stacktraces=stacktraces, modules=self.images, project=self.project, arch=self.arch, signal=self.signal, request_id_cache_key=request_id_cache_key) if not rv: self.data \ .setdefault('errors', []) \ .extend(self._handle_symbolication_failed( SymbolicationFailed(type=EventError.NATIVE_SYMBOLICATOR_FAILED) )) return # TODO(markus): Set signal and os context from symbolicator response, # for minidumps assert len(self.images) == len(rv['modules']), (self.images, rv) for image, fetched_debug_file in zip(self.images, rv['modules']): status = fetched_debug_file.pop('status') # Set image data from symbolicator as symbolicator might know more # than the SDK, especially for minidumps if fetched_debug_file.get('arch') == 'unknown': fetched_debug_file.pop('arch') image.update(fetched_debug_file) if status in ('found', 'unused'): continue elif status == 'missing_debug_file': error = SymbolicationFailed( type=EventError.NATIVE_MISSING_DSYM) elif status == 'malformed_debug_file': 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) continue error.image_arch = image['arch'] error.image_path = image['code_file'] error.image_name = image_name(image['code_file']) error.image_uuid = image['debug_id'] self.data.setdefault('errors', []) \ .extend(self._handle_symbolication_failed(error)) assert len(stacktraces) == len(rv['stacktraces']) for pf_list, symbolicated_stacktrace in zip(processable_stacktraces, rv['stacktraces']): for symbolicated_frame in symbolicated_stacktrace.get( 'frames') or (): pf = pf_list[symbolicated_frame['original_index']] pf.data['symbolicator_match'].append(symbolicated_frame)