Esempio n. 1
0
    def symbolize_frame(self, frame, system_info=None,
                        report_error=None):
        error = None
        img = self.images.get(frame['object_addr'])

        # Step one: try to symbolize with cached dsym files.
        try:
            new_frame = self.symsynd_symbolizer.symbolize_frame(
                frame, silent=False)
            if new_frame is not None:
                return self._process_frame(new_frame, img)
        except SymbolicationError as e:
            error = e

        # If that does not work, look up system symbols.
        if img is not None:
            symbol = find_system_symbol(img, frame['instruction_addr'],
                                        system_info)
            if symbol is not None:
                symbol = demangle_symbol(symbol) or symbol
                rv = dict(frame, symbol_name=symbol, filename=None,
                          line=0, column=0, uuid=img['uuid'],
                          object_name=img['name'])
                return self._process_frame(rv, img)

        if report_error is not None and error is not None:
            report_error(error)
        return self._process_frame(frame, img)
Esempio n. 2
0
    def symbolize_frame(self, frame, system_info=None, report_error=None):
        error = None
        img = self.images.get(frame['object_addr'])

        # Step one: try to symbolize with cached dsym files.
        try:
            new_frame = self.symsynd_symbolizer.symbolize_frame(frame,
                                                                silent=False)
            if new_frame is not None:
                return self._process_frame(new_frame, img)
        except SymbolicationError as e:
            error = e

        # If that does not work, look up system symbols.
        if img is not None:
            symbol = find_system_symbol(img, frame['instruction_addr'],
                                        system_info)
            if symbol is not None:
                symbol = demangle_symbol(symbol) or symbol
                rv = dict(frame,
                          symbol_name=symbol,
                          filename=None,
                          line=0,
                          column=0,
                          uuid=img['uuid'],
                          object_name=img['name'])
                return self._process_frame(rv, img)

        if report_error is not None and error is not None:
            report_error(error)
        return self._process_frame(frame, img)
Esempio n. 3
0
 def _process_symbol(sym):
     too_long = trim_symbols and len(sym) > MAX_SYM
     if demangle or too_long:
         new_sym = demangle_symbol(sym)
         if new_sym is not None and (len(new_sym) < sym or too_long):
             sym = new_sym
     if trim_symbols:
         sym = sym[:MAX_SYM]
     return sym
Esempio n. 4
0
    def symbolize_system_frame(self, frame, sdk_info):
        img = self.images.get(frame['object_addr'])
        if img is None:
            return

        symbol = find_system_symbol(img, frame['instruction_addr'],
                                    sdk_info)
        if symbol is None:
            return

        symbol = demangle_symbol(symbol) or symbol
        rv = dict(frame, symbol_name=symbol, filename=None,
                  line=0, column=0, uuid=img['uuid'],
                  object_name=img['name'])
        return self._process_frame(rv, img)
Esempio n. 5
0
    def symbolize_frame(self, frame, system_info=None):
        # Step one: try to symbolize with cached dsym files.
        new_frame = self.symsynd_symbolizer.symbolize_frame(frame)
        if new_frame is not None:
            return trim_frame(new_frame)

        # If that does not work, look up system symbols.
        img = self.images.get(frame['object_addr'])
        if img is not None:
            symbol = find_system_symbol(img, frame['instruction_addr'],
                                        system_info)
            if symbol is not None:
                symbol = demangle_symbol(symbol) or symbol
                rv = dict(frame, symbol_name=symbol, filename=None,
                          line=0, column=0, uuid=img['uuid'])
                return trim_frame(rv)
Esempio n. 6
0
    def symbolize(self,
                  dsym_path,
                  image_vmaddr,
                  image_addr,
                  instruction_addr,
                  cpu_name,
                  uuid=None,
                  silent=True,
                  demangle=True):
        if self._closed:
            raise RuntimeError('Symbolizer is closed')
        if not is_valid_cpu_name(cpu_name):
            raise ValueError('"%s" is not a valid cpu name' % cpu_name)
        dsym_path = normalize_dsym_path(dsym_path)

        image_vmaddr = parse_addr(image_vmaddr)
        if not image_vmaddr:
            image_vmaddr = get_macho_vmaddr(dsym_path, cpu_name) or 0

        image_addr = parse_addr(image_addr)
        instruction_addr = parse_addr(instruction_addr)

        addr = image_vmaddr + instruction_addr - image_addr

        try:
            with self._lock:
                with timedsection('symbolize'):
                    sym = self.symbolizer.symbolize(dsym_path, addr, cpu_name)
            if sym[0] is None:
                raise SymbolicationError('Symbolizer could not find symbol')
        except SymbolicationError:
            if not silent:
                raise
            sym = (None, None, 0, 0)

        symbol_name = sym[0]
        if demangle:
            symbol_name = demangle_symbol(symbol_name)

        return {
            'symbol_name': symbol_name,
            'filename': sym[1],
            'line': sym[2],
            'column': sym[3],
            'uuid': uuid,
        }
Esempio n. 7
0
    def symbolize_frame(self, frame, system_info=None):
        # Step one: try to symbolize with cached dsym files.
        new_frame = self.symsynd_symbolizer.symbolize_frame(frame)
        if new_frame is not None:
            return trim_frame(new_frame)

        # If that does not work, look up system symbols.
        img = self.images.get(frame['object_addr'])
        if img is not None:
            symbol = find_system_symbol(img, frame['instruction_addr'],
                                        system_info)
            if symbol is not None:
                symbol = demangle_symbol(symbol) or symbol
                rv = dict(frame,
                          symbol_name=symbol,
                          filename=None,
                          line=0,
                          column=0,
                          uuid=img['uuid'])
                return trim_frame(rv)
Esempio n. 8
0
    def symbolize(self,
                  dsym_path,
                  image_vmaddr,
                  image_addr,
                  instruction_addr,
                  cpu_name,
                  uuid=None,
                  silent=True):
        if self._closed:
            raise RuntimeError('Symbolizer is closed')
        if not is_valid_cpu_name(cpu_name):
            raise ValueError('"%s" is not a valid cpu name' % cpu_name)
        dsym_path = normalize_dsym_path(dsym_path)

        image_vmaddr = parse_addr(image_vmaddr)
        if not image_vmaddr:
            image_vmaddr = get_macho_vmaddr(dsym_path, cpu_name) or 0

        image_addr = parse_addr(image_addr)
        instruction_addr = parse_addr(instruction_addr)

        addr = image_vmaddr + instruction_addr - image_addr

        try:
            with self._lock:
                with timedsection('symbolize'):
                    sym = self.symbolizer.symbolize(dsym_path, addr, cpu_name)
            if sym[0] is None:
                raise SymbolicationError('Symbolizer could not find symbol')
        except SymbolicationError:
            if not silent:
                raise
            sym = (None, None, 0, 0)

        return {
            'symbol_name': demangle_symbol(sym[0]),
            'filename': sym[1],
            'line': sym[2],
            'column': sym[3],
            'uuid': uuid,
        }
Esempio n. 9
0
    def process_frame(self, frame):
        # XXX: warn on missing availability?

        # Only process frames here that are of supported platforms and
        # have the mandatory requirements for
        if not self.available or \
           self.get_effective_platform(frame) != 'cocoa' or \
           'image_addr' not in frame or \
           'instruction_addr' not in frame or \
           'symbol_addr' not in frame:
            return None

        errors = []

        # Construct a raw frame that is used by the symbolizer
        # backend.
        sym_frame = {
            'object_name': frame.get('package'),
            'object_addr': frame['image_addr'],
            'instruction_addr': frame['instruction_addr'],
            'symbol_name': frame.get('function'),
            'symbol_addr': frame['symbol_addr'],
        }
        new_frame = dict(frame)
        raw_frame = dict(frame)

        try:
            sfrm = self.sym.symbolize_frame(sym_frame, self.sdk_info)
        except SymbolicationFailed as e:
            if e.is_user_fixable or e.is_sdk_failure:
                errors.append({
                    'type': EventError.NATIVE_INTERNAL_FAILURE,
                    'image_uuid': e.image_uuid,
                    'image_path': e.image_path,
                    'image_arch': e.image_arch,
                    'message': e.message,
                })
            else:
                logger.debug('Failed to symbolicate with native backend',
                             exc_info=True)
        else:
            symbol = sfrm.get('symbol_name') or \
                new_frame.get('function') or '<unknown>'
            function = demangle_symbol(symbol, simplified=True)

            new_frame['function'] = function

            # If we demangled something, store the original in the
            # symbol portion of the frame
            if function != symbol:
                new_frame['symbol'] = symbol

            new_frame['abs_path'] = sfrm.get('filename') or None
            if new_frame['abs_path']:
                new_frame['filename'] = posixpath.basename(
                    new_frame['abs_path'])
            if sfrm.get('line') is not None:
                new_frame['lineno'] = sfrm['line']
            else:
                new_frame['instruction_offset'] = \
                    parse_addr(sfrm['instruction_addr']) - \
                    parse_addr(sfrm['symbol_addr'])
            if sfrm.get('column') is not None:
                new_frame['colno'] = sfrm['column']
            new_frame['package'] = sfrm['object_name'] \
                or new_frame.get('package')
            new_frame['symbol_addr'] = '0x%x' % \
                parse_addr(sfrm['symbol_addr'])
            new_frame['instruction_addr'] = '0x%x' % parse_addr(
                sfrm['instruction_addr'])

        in_app = self.sym.is_in_app(sym_frame)
        new_frame['in_app'] = raw_frame['in_app'] = in_app
        return [new_frame], [raw_frame], errors
Esempio n. 10
0
    def process_frame(self, frame, stacktrace_info, idx):
        # XXX: warn on missing availability?

        # Only process frames here that are of supported platforms and
        # have the mandatory requirements for
        if not self.available or \
           self.get_effective_platform(frame) != 'cocoa' or \
           'instruction_addr' not in frame:
            return None

        errors = []

        # Construct a raw frame that is used by the symbolizer
        # backend.  We only assemble the bare minimum we need here.
        sym_input_frame = {
            'object_name':
            frame.get('package'),
            'instruction_addr':
            self.find_best_instruction(frame, stacktrace_info, idx),
            'symbol_name':
            frame.get('function'),
            'symbol_addr':
            frame.get('symbol_addr'),
        }
        in_app = self.sym.is_in_app(sym_input_frame)

        new_frames = []
        raw_frame = dict(frame)
        raw_frame['in_app'] = in_app

        try:
            symbolicated_frames = self.sym.symbolize_frame(
                sym_input_frame, self.sdk_info, symbolize_inlined=True)
            if not symbolicated_frames:
                return None, [raw_frame], []
        except SymbolicationFailed as e:
            errors = []
            if e.is_user_fixable or e.is_sdk_failure:
                errors.append({
                    'type': e.type,
                    'image_uuid': e.image_uuid,
                    'image_path': e.image_path,
                    'image_arch': e.image_arch,
                    'message': e.message,
                })
            else:
                logger.debug('Failed to symbolicate with native backend',
                             exc_info=True)
            return None, [raw_frame], errors

        for sfrm in symbolicated_frames:
            symbol = sfrm.get('symbol_name') or \
                frame.get('function') or '<unknown>'
            function = demangle_symbol(symbol, simplified=True)

            new_frame = dict(frame)
            new_frame['function'] = function

            # If we demangled something, store the original in the
            # symbol portion of the frame
            if function != symbol:
                new_frame['symbol'] = symbol

            new_frame['abs_path'] = sfrm.get('filename') or None
            if new_frame['abs_path']:
                new_frame['filename'] = posixpath.basename(
                    new_frame['abs_path'])
            if sfrm.get('line') is not None:
                new_frame['lineno'] = sfrm['line']
            if sfrm.get('column') is not None:
                new_frame['colno'] = sfrm['column']
            new_frame['package'] = sfrm['object_name'] \
                or new_frame.get('package')

            new_frame['in_app'] = in_app
            new_frames.append(new_frame)

        return new_frames, [raw_frame], []
Esempio n. 11
0
def resolve_frame_symbols(data):
    debug_meta = data['debug_meta']
    debug_images = debug_meta['images']
    sdk_info = get_sdk_from_event(data)

    stacktraces = find_all_stacktraces(data)
    if not stacktraces:
        return

    project = Project.objects.get_from_cache(
        id=data['project'],
    )

    errors = []
    referenced_images = find_stacktrace_referenced_images(
        debug_images, [x[0] for x in stacktraces])
    sym = Symbolizer(project, debug_images,
                     referenced_images=referenced_images)

    frame = None
    idx = -1

    def report_error(e):
        errors.append({
            'type': EventError.NATIVE_INTERNAL_FAILURE,
            'frame': frame,
            'error': 'frame #%d: %s: %s' % (
                idx,
                e.__class__.__name__,
                six.text_type(e),
            )
        })

    with sym:
        for stacktrace, container in stacktraces:
            store_raw = False

            new_frames = list(stacktrace['frames'])
            for idx, frame in enumerate(stacktrace['frames']):
                if 'image_addr' not in frame or \
                   'instruction_addr' not in frame or \
                   'symbol_addr' not in frame:
                    continue
                try:
                    sfrm = sym.symbolize_frame({
                        'object_name': frame.get('package'),
                        'object_addr': frame['image_addr'],
                        'instruction_addr': frame['instruction_addr'],
                        'symbol_addr': frame['symbol_addr'],
                    }, sdk_info, report_error=report_error)
                    if not sfrm:
                        continue
                    new_frame = dict(frame)
                    # XXX: log here if symbol could not be found?
                    symbol = sfrm.get('symbol_name') or \
                        new_frame.get('function') or '<unknown>'
                    function = demangle_symbol(symbol, simplified=True)

                    new_frame['function'] = function

                    # If we demangled something, store the original in the
                    # symbol portion of the frame
                    if function != symbol:
                        new_frame['symbol'] = symbol

                    new_frame['abs_path'] = sfrm.get('filename') or None
                    if new_frame['abs_path']:
                        new_frame['filename'] = posixpath.basename(new_frame['abs_path'])
                    if sfrm.get('line') is not None:
                        new_frame['lineno'] = sfrm['line']
                    else:
                        new_frame['instruction_offset'] = \
                            parse_addr(sfrm['instruction_addr']) - \
                            parse_addr(sfrm['symbol_addr'])
                    if sfrm.get('column') is not None:
                        new_frame['colno'] = sfrm['column']
                    new_frame['package'] = sfrm['object_name'] or new_frame.get('package')
                    new_frame['symbol_addr'] = '0x%x' % parse_addr(sfrm['symbol_addr'])
                    new_frame['instruction_addr'] = '0x%x' % parse_addr(
                        sfrm['instruction_addr'])
                    new_frame['in_app'] = is_in_app(new_frame)

                    if new_frame != frame:
                        new_frames[idx] = new_frame
                        store_raw = True
                except Exception:
                    logger.exception('Failed to symbolicate')
                    errors.append({
                        'type': EventError.NATIVE_INTERNAL_FAILURE,
                        'error': 'The symbolicator encountered an internal failure',
                    })

            # Remember the raw stacktrace.
            if store_raw and container is not None:
                container['raw_stacktrace'] = {
                    'frames': stacktrace['frames'],
                }

            # Put the new frames in
            stacktrace['frames'] = new_frames

    if errors:
        data.setdefault('errors', []).extend(errors)

    return data
Esempio n. 12
0
    def process_frame(self, processable_frame, processing_task):
        frame = processable_frame.frame
        errors = []

        new_frames = []
        raw_frame = dict(frame)
        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.
            sym_input_frame = {
                'object_name': frame.get('package'),
                'instruction_addr': processable_frame.data['instruction_addr'],
                'symbol_name': frame.get('function'),
            }
            in_app = self.sym.is_in_app(sym_input_frame)
            raw_frame['in_app'] = in_app
            try:
                symbolicated_frames = self.sym.symbolize_frame(
                    sym_input_frame, self.sdk_info,
                    symbolserver_match=processable_frame.data['symbolserver_match'],
                    symbolize_inlined=True)
                if not symbolicated_frames:
                    return None, [raw_frame], []
            except SymbolicationFailed as e:
                reprocessing_active = False
                if self.project:
                    reprocessing_active = bool(
                        self.project.get_option('sentry:reprocessing_active', False)
                    )
                # User fixable but fatal errors are reported as processing
                # issues but only if the feature is activated.
                if reprocessing_active and e.is_user_fixable and e.is_fatal:
                    report_processing_issue(self.data,
                        scope='native',
                        object='dsym:%s' % e.image_uuid,
                        type=e.type,
                        data={
                            'image_path': e.image_path,
                            'image_uuid': e.image_uuid,
                            'image_arch': e.image_arch,
                            'message': e.message,
                        }
                    )

                # This in many ways currently does not really do anything.
                # The reason is that once a processing issue is reported
                # the event will only be stored as a raw event and no
                # group will be generated.  As a result it also means that
                # we will not have any user facing event or error showing
                # up at all.  We want to keep this here though in case we
                # do not want to report some processing issues (eg:
                # optional dsyms)
                errors = []
                if e.is_user_fixable or e.is_sdk_failure:
                    errors.append({
                        'type': e.type,
                        'image_uuid': e.image_uuid,
                        'image_path': e.image_path,
                        'image_arch': e.image_arch,
                        'message': e.message,
                    })
                else:
                    logger.debug('Failed to symbolicate with native backend',
                                 exc_info=True)
                return [raw_frame], [raw_frame], errors

            processable_frame.set_cache_value([in_app, symbolicated_frames])
        else:
            in_app, symbolicated_frames = processable_frame.cache_value
            raw_frame['in_app'] = in_app

        for sfrm in symbolicated_frames:
            symbol = sfrm.get('symbol_name') or \
                frame.get('function') or NATIVE_UNKNOWN_STRING
            function = demangle_symbol(symbol, simplified=True)

            new_frame = dict(frame)
            new_frame['function'] = function

            # If we demangled something, store the original in the
            # symbol portion of the frame
            if function != symbol:
                new_frame['symbol'] = symbol

            new_frame['abs_path'] = sfrm.get('filename') or None
            if new_frame['abs_path']:
                new_frame['filename'] = posixpath.basename(
                    new_frame['abs_path'])
            if sfrm.get('line') is not None:
                new_frame['lineno'] = sfrm['line']
            if sfrm.get('column') is not None:
                new_frame['colno'] = sfrm['column']
            new_frame['package'] = sfrm['object_name'] \
                or new_frame.get('package')
            new_frame['in_app'] = in_app
            new_frames.append(new_frame)

        return new_frames, [raw_frame], []
Esempio n. 13
0
    def process_frame(self, processable_frame, processing_task):
        frame = processable_frame.frame
        errors = []

        new_frames = []
        raw_frame = dict(frame)
        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.
            sym_input_frame = {
                'object_name': frame.get('package'),
                'instruction_addr': processable_frame.data['instruction_addr'],
                'symbol_name': frame.get('function'),
            }
            in_app = self.sym.is_in_app(sym_input_frame)
            raw_frame['in_app'] = in_app
            img_uuid = processable_frame.data['image_uuid']
            if img_uuid is not None:
                self.dsyms_referenced.add(img_uuid)
            try:
                symbolicated_frames = self.sym.symbolize_frame(
                    sym_input_frame,
                    self.sdk_info,
                    symbolserver_match=processable_frame.
                    data['symbolserver_match'],
                    symbolize_inlined=True)
                if not symbolicated_frames:
                    return None, [raw_frame], []
            except SymbolicationFailed as e:
                reprocessing_active = False
                if self.project:
                    reprocessing_active = bool(
                        self.project.get_option('sentry:reprocessing_active',
                                                False))
                # User fixable but fatal errors are reported as processing
                # issues but only if the feature is activated.
                if reprocessing_active and e.is_user_fixable and e.is_fatal:
                    report_processing_issue(self.data,
                                            scope='native',
                                            object='dsym:%s' % e.image_uuid,
                                            type=e.type,
                                            data={
                                                'image_path': e.image_path,
                                                'image_uuid': e.image_uuid,
                                                'image_arch': e.image_arch,
                                                'message': e.message,
                                            })

                # This in many ways currently does not really do anything.
                # The reason is that once a processing issue is reported
                # the event will only be stored as a raw event and no
                # group will be generated.  As a result it also means that
                # we will not have any user facing event or error showing
                # up at all.  We want to keep this here though in case we
                # do not want to report some processing issues (eg:
                # optional dsyms)
                errors = []
                if e.is_user_fixable or e.is_sdk_failure:
                    errors.append({
                        'type': e.type,
                        'image_uuid': e.image_uuid,
                        'image_path': e.image_path,
                        'image_arch': e.image_arch,
                        'message': e.message,
                    })
                else:
                    logger.debug('Failed to symbolicate with native backend',
                                 exc_info=True)
                return [raw_frame], [raw_frame], errors

            processable_frame.set_cache_value([in_app, symbolicated_frames])
        else:
            in_app, symbolicated_frames = processable_frame.cache_value
            raw_frame['in_app'] = in_app

        for sfrm in symbolicated_frames:
            symbol = sfrm.get('symbol_name') or \
                frame.get('function') or NATIVE_UNKNOWN_STRING
            function = demangle_symbol(symbol, simplified=True)

            new_frame = dict(frame)
            new_frame['function'] = function

            # If we demangled something, store the original in the
            # symbol portion of the frame
            if function != symbol:
                new_frame['symbol'] = symbol

            new_frame['abs_path'] = sfrm.get('filename') or None
            if new_frame['abs_path']:
                new_frame['filename'] = posixpath.basename(
                    new_frame['abs_path'])
            if sfrm.get('line') is not None:
                new_frame['lineno'] = sfrm['line']
            if sfrm.get('column') is not None:
                new_frame['colno'] = sfrm['column']
            new_frame['package'] = sfrm['object_name'] \
                or new_frame.get('package')
            new_frame['in_app'] = in_app
            new_frames.append(new_frame)

        return new_frames, [raw_frame], []
Esempio n. 14
0
def resolve_frame_symbols(data):
    debug_meta = data['debug_meta']
    debug_images = debug_meta['images']
    sdk_info = get_sdk_from_event(data)

    stacktraces = find_all_stacktraces(data)
    if not stacktraces:
        return

    project = Project.objects.get_from_cache(
        id=data['project'],
    )

    errors = []
    referenced_images = find_stacktrace_referenced_images(
        debug_images, [x[0] for x in stacktraces])
    sym = Symbolizer(project, debug_images,
                     referenced_images=referenced_images)

    frame = None
    idx = -1

    def report_error(exc_type, exc_value, tb):
        if exc_value.is_user_fixable or exc_value.is_sdk_failure:
            errors.append({
                'type': EventError.NATIVE_INTERNAL_FAILURE,
                'frame': frame,
                'error': u'frame #%d: %s' % (idx, exc_value)
            })
        if not exc_value.is_user_fixable:
            logger.debug('Failed to symbolicate',
                         exc_info=(exc_type, exc_value, tb))

    with sym:
        for stacktrace, container in stacktraces:
            store_raw = False

            new_frames = list(stacktrace['frames'])
            for idx, frame in enumerate(stacktrace['frames']):
                if 'image_addr' not in frame or \
                   'instruction_addr' not in frame or \
                   'symbol_addr' not in frame:
                    continue
                try:
                    # Construct a raw frame that is used by the symbolizer
                    # backend.
                    raw_frame = {
                        'object_name': frame.get('package'),
                        'object_addr': frame['image_addr'],
                        'instruction_addr': frame['instruction_addr'],
                        'symbol_addr': frame['symbol_addr'],
                    }
                    new_frame = dict(frame)

                    try:
                        sfrm = sym.symbolize_frame(raw_frame, sdk_info)
                    except SymbolicationFailed:
                        report_error(*sys.exc_info())
                    else:
                        symbol = sfrm.get('symbol_name') or \
                            new_frame.get('function') or '<unknown>'
                        function = demangle_symbol(symbol, simplified=True)

                        new_frame['function'] = function

                        # If we demangled something, store the original in the
                        # symbol portion of the frame
                        if function != symbol:
                            new_frame['symbol'] = symbol

                        new_frame['abs_path'] = sfrm.get('filename') or None
                        if new_frame['abs_path']:
                            new_frame['filename'] = posixpath.basename(
                                new_frame['abs_path'])
                        if sfrm.get('line') is not None:
                            new_frame['lineno'] = sfrm['line']
                        else:
                            new_frame['instruction_offset'] = \
                                parse_addr(sfrm['instruction_addr']) - \
                                parse_addr(sfrm['symbol_addr'])
                        if sfrm.get('column') is not None:
                            new_frame['colno'] = sfrm['column']
                        new_frame['package'] = sfrm['object_name'] \
                            or new_frame.get('package')
                        new_frame['symbol_addr'] = '0x%x' % \
                            parse_addr(sfrm['symbol_addr'])
                        new_frame['instruction_addr'] = '0x%x' % parse_addr(
                            sfrm['instruction_addr'])

                    new_frame['in_app'] = sym.is_in_app(raw_frame)
                    if new_frame != frame:
                        new_frames[idx] = new_frame
                        store_raw = True
                except Exception:
                    logger.exception('Failed to symbolicate')
                    errors.append({
                        'type': EventError.NATIVE_INTERNAL_FAILURE,
                        'error': 'The symbolicator encountered an internal failure',
                    })

            # Remember the raw stacktrace.
            if store_raw and container is not None:
                container['raw_stacktrace'] = {
                    'frames': stacktrace['frames'],
                }

            # Put the new frames in
            stacktrace['frames'] = new_frames

    if errors:
        data.setdefault('errors', []).extend(errors)

    return data
Esempio n. 15
0
    def process_frame(self, processable_frame, processing_task):
        frame = processable_frame.frame
        errors = []

        new_frames = []
        raw_frame = dict(frame)

        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.
            sym_input_frame = {
                'object_name': frame.get('package'),
                'instruction_addr': processable_frame.data['instruction_addr'],
                'symbol_name': frame.get('function'),
            }
            in_app = self.sym.is_in_app(sym_input_frame)
            raw_frame['in_app'] = in_app
            try:
                symbolicated_frames = self.sym.symbolize_frame(
                    sym_input_frame, self.sdk_info, symbolize_inlined=True)
                if not symbolicated_frames:
                    return None, [raw_frame], []
            except SymbolicationFailed as e:
                errors = []
                if e.is_user_fixable or e.is_sdk_failure:
                    errors.append({
                        'type': e.type,
                        'image_uuid': e.image_uuid,
                        'image_path': e.image_path,
                        'image_arch': e.image_arch,
                        'message': e.message,
                    })
                else:
                    logger.debug('Failed to symbolicate with native backend',
                                 exc_info=True)
                return None, [raw_frame], errors

            processable_frame.set_cache_value([in_app, symbolicated_frames])
        else:
            in_app, symbolicated_frames = processable_frame.cache_value
            raw_frame['in_app'] = in_app

        for sfrm in symbolicated_frames:
            symbol = sfrm.get('symbol_name') or \
                frame.get('function') or NATIVE_UNKNOWN_STRING
            function = demangle_symbol(symbol, simplified=True)

            new_frame = dict(frame)
            new_frame['function'] = function

            # If we demangled something, store the original in the
            # symbol portion of the frame
            if function != symbol:
                new_frame['symbol'] = symbol

            new_frame['abs_path'] = sfrm.get('filename') or None
            if new_frame['abs_path']:
                new_frame['filename'] = posixpath.basename(
                    new_frame['abs_path'])
            if sfrm.get('line') is not None:
                new_frame['lineno'] = sfrm['line']
            if sfrm.get('column') is not None:
                new_frame['colno'] = sfrm['column']
            new_frame['package'] = sfrm['object_name'] \
                or new_frame.get('package')

            new_frame['in_app'] = in_app
            new_frames.append(new_frame)

        return new_frames, [raw_frame], []