Example #1
0
 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)
Example #3
0
 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,
     )
Example #4
0
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)
Example #5
0
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)
Example #6
0
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)
Example #7
0
 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
     )
Example #8
0
 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']
     )
Example #9
0
 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,
     )
Example #10
0
 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"],
     )
Example #11
0
 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
Example #12
0
 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
Example #13
0
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)
Example #14
0
    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)