Esempio n. 1
0
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
Esempio n. 2
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)
Esempio n. 3
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)
Esempio n. 4
0
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
Esempio n. 5
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)
Esempio n. 6
0
    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
Esempio n. 7
0
    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
Esempio n. 8
0
    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
Esempio n. 9
0
    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
Esempio n. 10
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)