Beispiel #1
0
    def process_frame(self, processable_frame, processing_task):
        frame = processable_frame.frame
        raw_frame = dict(frame)

        # Ensure that package is set in the raw frame, mapped from the
        # debug_images array in the payload. Grouping and UI can use this path
        # to infer in_app and exclude frames from grouping.
        if raw_frame.get('package') is None:
            obj = processable_frame.data['obj']
            raw_frame['package'] = obj and obj.code_file or None

        symbolicated_frames = convert_ios_symbolserver_match(
            processable_frame.data['instruction_addr'],
            processable_frame.data['symbolserver_match']
        )

        if not symbolicated_frames:
            if raw_frame.get('trust') == 'scan':
                return [], [raw_frame], []
            else:
                return None, [raw_frame], []

        new_frames = []
        for sfrm in symbolicated_frames:
            new_frame = dict(raw_frame)
            merge_symbolicated_frame(new_frame, sfrm)
            new_frames.append(new_frame)

        return new_frames, [raw_frame], []
Beispiel #2
0
    def process_frame(self, processable_frame, processing_task):
        frame = processable_frame.frame
        raw_frame = dict(frame)
        errors = []

        # Ensure that package is set in the raw frame, mapped from the
        # debug_images array in the payload. Grouping and UI can use this path
        # to infer in_app and exclude frames from grouping.
        if raw_frame.get('package') is None:
            obj = processable_frame.data['obj']
            raw_frame['package'] = obj and obj.code_file or None

        if processable_frame.cache_value is None:
            # Construct a raw frame that is used by the symbolizer
            # backend.  We only assemble the bare minimum we need here.
            instruction_addr = processable_frame.data['instruction_addr']

            debug_id = processable_frame.data['debug_id']
            if debug_id is not None:
                self.difs_referenced.add(debug_id)

            try:
                symbolicated_frames = self.sym.symbolize_frame(
                    instruction_addr,
                    self.sdk_info,
                    symbolserver_match=processable_frame.
                    data['symbolserver_match'],
                    symbolicator_match=processable_frame.data.get(
                        'symbolicator_match'),
                    trust=raw_frame.get('trust'),
                )
                if not symbolicated_frames:
                    if raw_frame.get('trust') == 'scan':
                        return [], [raw_frame], []
                    else:
                        return None, [raw_frame], []
            except SymbolicationFailed as e:
                errors = []
                handle_symbolication_failed(e, data=self.data, errors=errors)
                return [raw_frame], [raw_frame], errors

            _ignored = None  # Used to be in_app
            processable_frame.set_cache_value([_ignored, symbolicated_frames])

        else:  # processable_frame.cache_value is present
            _ignored, symbolicated_frames = processable_frame.cache_value

        platform = raw_frame.get('platform') or self.data.get('platform')
        new_frames = []
        for sfrm in symbolicated_frames:
            new_frame = dict(raw_frame)
            merge_symbolicated_frame(new_frame, sfrm, platform=platform)
            new_frames.append(new_frame)

        return new_frames, [raw_frame], []
Beispiel #3
0
def merge_symbolicator_minidump_response(data, response):
    sdk_info = get_sdk_from_event(data)

    # TODO(markus): Add OS context here when `merge_process_state_event` is no
    # longer called for symbolicator projects

    images = []
    set_path(data, 'debug_meta', 'images', value=images)

    for complete_image in response['modules']:
        image = {}
        merge_symbolicator_image(
            image, complete_image, sdk_info,
            lambda e: handle_symbolication_failed(e, data=data)
        )
        images.append(image)

    data_threads = []
    data['threads'] = {'values': data_threads}

    data_exception = get_path(data, 'exception', 'values', 0)

    for complete_stacktrace in response['stacktraces']:
        is_requesting = complete_stacktrace.get('is_requesting')
        thread_id = complete_stacktrace.get('thread_id')

        data_thread = {
            'id': thread_id,
            'crashed': is_requesting,
        }
        data_threads.append(data_thread)

        if is_requesting:
            data_stacktrace = get_path(data_exception, 'stacktrace')
            assert isinstance(data_stacktrace, dict), data_stacktrace
            # Make exemption specifically for unreal portable callstacks
            # TODO(markus): Allow overriding stacktrace more generically
            # (without looking into unreal context) once we no longer parse
            # minidump in the endpoint (right now we can't distinguish that
            # from user json).
            if data_stacktrace['frames'] and is_unreal_exception_stacktrace(data):
                continue
            del data_stacktrace['frames'][:]
        else:
            data_thread['stacktrace'] = data_stacktrace = {'frames': []}

        if complete_stacktrace.get('registers'):
            data_stacktrace['registers'] = complete_stacktrace['registers']

        for complete_frame in reversed(complete_stacktrace['frames']):
            new_frame = {}
            merge_symbolicated_frame(new_frame, complete_frame)
            data_stacktrace['frames'].append(new_frame)
Beispiel #4
0
def merge_symbolicator_minidump_response(data, response):
    sdk_info = get_sdk_from_event(data)

    # TODO(markus): Add OS context here when `merge_process_state_event` is no
    # longer called for symbolicator projects

    images = []
    set_path(data, 'debug_meta', 'images', value=images)

    for complete_image in response['modules']:
        image = {}
        merge_symbolicator_image(
            image, complete_image, sdk_info,
            lambda e: handle_symbolication_failed(e, data=data))
        images.append(image)

    data_threads = []
    data['threads'] = {'values': data_threads}

    data_exception = get_path(data, 'exception', 'values', 0)

    for complete_stacktrace in response['stacktraces']:
        is_requesting = complete_stacktrace.get('is_requesting')
        thread_id = complete_stacktrace.get('thread_id')

        data_thread = {
            'id': thread_id,
            'crashed': is_requesting,
        }
        data_threads.append(data_thread)

        if is_requesting:
            data_stacktrace = get_path(data_exception, 'stacktrace')
            assert isinstance(data_stacktrace, dict), data_stacktrace
            # Make exemption specifically for unreal portable callstacks
            # TODO(markus): Allow overriding stacktrace more generically
            # (without looking into unreal context) once we no longer parse
            # minidump in the endpoint (right now we can't distinguish that
            # from user json).
            if data_stacktrace['frames'] and is_unreal_exception_stacktrace(
                    data):
                continue
            data_stacktrace['frames'] = []
        else:
            data_thread['stacktrace'] = data_stacktrace = {'frames': []}

        if complete_stacktrace.get('registers'):
            data_stacktrace['registers'] = complete_stacktrace['registers']

        for complete_frame in reversed(complete_stacktrace['frames']):
            new_frame = {}
            merge_symbolicated_frame(new_frame, complete_frame)
            data_stacktrace['frames'].append(new_frame)
Beispiel #5
0
    def process_frame(self, processable_frame, processing_task):
        frame = processable_frame.frame
        raw_frame = dict(frame)
        errors = []

        # Ensure that package is set in the raw frame, mapped from the
        # debug_images array in the payload. Grouping and UI can use this path
        # to infer in_app and exclude frames from grouping.
        if raw_frame.get('package') is None:
            obj = processable_frame.data['obj']
            raw_frame['package'] = obj and obj.code_file or None

        if processable_frame.cache_value is None:
            # Construct a raw frame that is used by the symbolizer
            # backend.  We only assemble the bare minimum we need here.
            instruction_addr = processable_frame.data['instruction_addr']

            debug_id = processable_frame.data['debug_id']
            if debug_id is not None:
                self.difs_referenced.add(debug_id)

            try:
                symbolicated_frames = self.sym.symbolize_frame(
                    instruction_addr,
                    self.sdk_info,
                    symbolserver_match=processable_frame.data['symbolserver_match'],
                    symbolicator_match=processable_frame.data.get('symbolicator_match'),
                    trust=raw_frame.get('trust'),
                )
                if not symbolicated_frames:
                    if raw_frame.get('trust') == 'scan':
                        return [], [raw_frame], []
                    else:
                        return None, [raw_frame], []
            except SymbolicationFailed as e:
                errors = []
                handle_symbolication_failed(e, data=self.data, errors=errors)
                return [raw_frame], [raw_frame], errors

            _ignored = None  # Used to be in_app
            processable_frame.set_cache_value([_ignored, symbolicated_frames])

        else:  # processable_frame.cache_value is present
            _ignored, symbolicated_frames = processable_frame.cache_value

        platform = raw_frame.get('platform') or self.data.get('platform')
        new_frames = []
        for sfrm in symbolicated_frames:
            new_frame = dict(raw_frame)
            merge_symbolicated_frame(new_frame, sfrm, platform=platform)
            new_frames.append(new_frame)

        return new_frames, [raw_frame], []
Beispiel #6
0
    def process_frame(self, processable_frame, processing_task):
        frame = processable_frame.frame
        raw_frame = dict(frame)

        # Ensure that package is set in the raw frame, mapped from the
        # debug_images array in the payload. Grouping and UI can use this path
        # to infer in_app and exclude frames from grouping.
        if raw_frame.get('package') is None:
            obj = processable_frame.data['obj']
            raw_frame['package'] = obj and obj.code_file or None

        if processable_frame.cache_value is None:
            symbolicator_match = processable_frame.data['symbolicator_match']

            if not any(x["status"] != "symbolicated" for x in symbolicator_match):
                symbolicated_frames = symbolicator_match
            else:
                symbolicated_frames = convert_ios_symbolserver_match(
                    processable_frame.data['instruction_addr'],
                    processable_frame.data['symbolserver_match']
                )

            if not symbolicated_frames:
                if raw_frame.get('trust') == 'scan':
                    return [], [raw_frame], []
                else:
                    return None, [raw_frame], []

            _ignored = None  # Used to be in_app
            processable_frame.set_cache_value([_ignored, symbolicated_frames])

        else:  # processable_frame.cache_value is present
            _ignored, symbolicated_frames = processable_frame.cache_value

        new_frames = []
        for sfrm in symbolicated_frames:
            new_frame = dict(raw_frame)
            merge_symbolicated_frame(new_frame, sfrm)
            new_frames.append(new_frame)

        return new_frames, [raw_frame], []
Beispiel #7
0
def merge_symbolicator_minidump_response(data, response):
    sdk_info = get_sdk_from_event(data)

    data['platform'] = 'native'
    if response.get('crashed') is not None:
        data['level'] = 'fatal' if response['crashed'] else 'info'

    if response.get('timestamp'):
        data['timestamp'] = float(response['timestamp'])

    if response.get('system_info'):
        merge_symbolicator_minidump_system_info(data, response['system_info'])

    images = []
    set_path(data, 'debug_meta', 'images', value=images)

    for complete_image in response['modules']:
        image = {}
        merge_symbolicator_image(
            image, complete_image, sdk_info,
            lambda e: handle_symbolication_failed(e, data=data))
        images.append(image)

    # Extract the crash reason and infos
    data_exception = get_path(data, 'exception', 'values', 0)
    exc_value = ('Assertion Error: %s' % response.get('assertion')
                 if response.get('assertion') else 'Fatal Error: %s' %
                 response.get('crash_reason'))
    data_exception['value'] = exc_value
    data_exception['type'] = response.get('crash_reason')

    data_threads = []
    if response['stacktraces']:
        data['threads'] = {'values': data_threads}
    else:
        error = SymbolicationFailed(message='minidump has no thread list',
                                    type=EventError.NATIVE_SYMBOLICATOR_FAILED)
        handle_symbolication_failed(error, data=data)

    for complete_stacktrace in response['stacktraces']:
        is_requesting = complete_stacktrace.get('is_requesting')
        thread_id = complete_stacktrace.get('thread_id')

        data_thread = {
            'id': thread_id,
            'crashed': is_requesting,
        }
        data_threads.append(data_thread)

        if is_requesting:
            data_exception['thread_id'] = thread_id
            data_stacktrace = data_exception.setdefault('stacktrace', {})
            # Make exemption specifically for unreal portable callstacks
            # TODO(markus): Allow overriding stacktrace more generically
            # (without looking into unreal context) once we no longer parse
            # minidump in the endpoint (right now we can't distinguish that
            # from user json).
            if data_stacktrace.get(
                    'frames') and is_unreal_exception_stacktrace(data):
                continue
            data_stacktrace['frames'] = []
        else:
            data_thread['stacktrace'] = data_stacktrace = {'frames': []}

        if complete_stacktrace.get('registers'):
            data_stacktrace['registers'] = complete_stacktrace['registers']

        for complete_frame in reversed(complete_stacktrace['frames']):
            new_frame = {}
            merge_symbolicated_frame(new_frame, complete_frame)
            data_stacktrace['frames'].append(new_frame)
Beispiel #8
0
def merge_symbolicator_minidump_response(data, response):
    data['platform'] = 'native'
    if response.get('crashed') is not None:
        data['level'] = 'fatal' if response['crashed'] else 'info'

    validate_and_set_timestamp(data, response.get('timestamp'))

    if response.get('system_info'):
        merge_symbolicator_minidump_system_info(data, response['system_info'])

    sdk_info = get_sdk_from_event(data)

    images = []
    set_path(data, 'debug_meta', 'images', value=images)

    for complete_image in response['modules']:
        image = {}
        merge_symbolicator_image(
            image, complete_image, sdk_info,
            lambda e: write_error(e, data)
        )
        images.append(image)

    # Extract the crash reason and infos
    data_exception = get_path(data, 'exception', 'values', 0)
    exc_value = (
        'Assertion Error: %s' % response.get('assertion')
        if response.get('assertion')
        else 'Fatal Error: %s' % response.get('crash_reason')
    )
    data_exception['value'] = exc_value
    data_exception['type'] = response.get('crash_reason')

    data_threads = []
    if response['stacktraces']:
        data['threads'] = {'values': data_threads}
    else:
        error = SymbolicationFailed(message='minidump has no thread list',
                                    type=EventError.NATIVE_SYMBOLICATOR_FAILED)
        write_error(error, data)

    for complete_stacktrace in response['stacktraces']:
        is_requesting = complete_stacktrace.get('is_requesting')
        thread_id = complete_stacktrace.get('thread_id')

        data_thread = {
            'id': thread_id,
            'crashed': is_requesting,
        }
        data_threads.append(data_thread)

        if is_requesting:
            data_exception['thread_id'] = thread_id
            data_stacktrace = data_exception.setdefault('stacktrace', {})
            data_stacktrace['frames'] = []
        else:
            data_thread['stacktrace'] = data_stacktrace = {'frames': []}

        if complete_stacktrace.get('registers'):
            data_stacktrace['registers'] = complete_stacktrace['registers']

        for complete_frame in reversed(complete_stacktrace['frames']):
            new_frame = {}
            merge_symbolicated_frame(new_frame, complete_frame)
            data_stacktrace['frames'].append(new_frame)
Beispiel #9
0
def process_payload(data):
    project = Project.objects.get_from_cache(id=data['project'])
    task_id_cache_key = task_id_cache_key_for_event(data)

    symbolicator = Symbolicator(
        project=project,
        task_id_cache_key=task_id_cache_key
    )

    stacktrace_infos = [
        stacktrace
        for stacktrace in find_stacktraces_in_data(data)
        if any(is_native_platform(x) for x in stacktrace.platforms)
    ]

    stacktraces = [
        {
            'registers': sinfo.stacktrace.get('registers') or {},
            'frames': [
                f for f in reversed(sinfo.stacktrace.get('frames') or ())
                if _handles_frame(data, f)
            ]
        }
        for sinfo in stacktrace_infos
    ]

    if not any(stacktrace['frames'] for stacktrace in stacktraces):
        return

    modules = native_images_from_data(data)

    response = symbolicator.process_payload(stacktraces=stacktraces, modules=modules)

    assert len(modules) == len(response['modules']), (modules, response)

    sdk_info = get_sdk_from_event(data)

    for raw_image, complete_image in zip(modules, response['modules']):
        merge_symbolicator_image(
            raw_image,
            complete_image,
            sdk_info,
            lambda e: write_error(
                e,
                data))

    assert len(stacktraces) == len(response['stacktraces']), (stacktraces, response)

    for sinfo, complete_stacktrace in zip(stacktrace_infos, response['stacktraces']):
        complete_frames_by_idx = {}
        for complete_frame in complete_stacktrace.get('frames') or ():
            complete_frames_by_idx \
                .setdefault(complete_frame['original_index'], []) \
                .append(complete_frame)

        new_frames = []
        native_frames_idx = 0

        for raw_frame in reversed(sinfo.stacktrace['frames']):
            if not _handles_frame(data, raw_frame):
                new_frames.append(raw_frame)
                continue

            for complete_frame in complete_frames_by_idx.get(native_frames_idx) or ():
                merged_frame = dict(raw_frame)
                merge_symbolicated_frame(merged_frame, complete_frame)
                if merged_frame.get('package'):
                    raw_frame['package'] = merged_frame['package']
                new_frames.append(merged_frame)

            native_frames_idx += 1

        if sinfo.container is not None and native_frames_idx > 0:
            sinfo.container['raw_stacktrace'] = {
                'frames': list(sinfo.stacktrace['frames']),
                'registers': sinfo.stacktrace.get('registers')
            }

        new_frames.reverse()
        sinfo.stacktrace['frames'] = new_frames

    return data