Пример #1
0
    def _symbolize_app_frame(self, instruction_addr, obj, sdk_info=None):
        symcache = self.symcaches.get(obj.uuid)
        if symcache is None:
            if self._is_optional_dsym(obj, sdk_info=sdk_info):
                type = EventError.NATIVE_MISSING_OPTIONALLY_BUNDLED_DSYM
            else:
                type = EventError.NATIVE_MISSING_DSYM
            raise SymbolicationFailed(type=type, obj=obj)

        try:
            rv = symcache.lookup(rebase_addr(instruction_addr, obj))
        except SymbolicError as e:
            raise SymbolicationFailed(type=EventError.NATIVE_BAD_DSYM,
                                      message=six.text_type(e),
                                      obj=obj)

        if not rv:
            # For some frameworks we are willing to ignore missing symbol
            # errors.
            if self._is_optional_dsym(obj, sdk_info=sdk_info):
                return []
            raise SymbolicationFailed(type=EventError.NATIVE_MISSING_SYMBOL,
                                      obj=obj)
        return [
            self._process_frame(s, obj, addr_off=obj.addr)
            for s in reversed(rv)
        ]
Пример #2
0
    def preprocess_frame(self, processable_frame):
        instr_addr = self.find_best_instruction(processable_frame)
        obj = self.object_lookup.find_object(instr_addr)

        processable_frame.data = {
            'instruction_addr': instr_addr,
            'obj': obj,
            'debug_id': obj.debug_id if obj is not None else None,
            'symbolserver_match': None,

            # `[]` is used to indicate to the symbolizer that the symbolicator
            # deliberately discarded this frame, while `None` means the
            # symbolicator didn't run (because `self.use_symbolicator` is
            # false).
            # If the symbolicator did run and was not able to symbolize the
            # frame, this value will be a list with the raw frame as only item.
            'symbolicator_match': [] if self.use_symbolicator else None,
        }

        if obj is not None:
            processable_frame.set_cache_key_from_values(
                (
                    FRAME_CACHE_VERSION,
                    # Because the images can move around, we want to rebase
                    # the address for the cache key to be within the image
                    # the same way as we do it in the symbolizer.
                    rebase_addr(instr_addr, obj),
                    obj.debug_id,
                    obj.arch,
                    obj.size,
                )
            )
Пример #3
0
    def _symbolize_app_frame(self, instruction_addr, obj, sdk_info=None, trust=None):
        symcache = self.symcaches.get(obj.debug_id)
        if symcache is None:
            # In case we know what error happened on symcache conversion
            # we can report it to the user now.
            if obj.debug_id in self.symcaches_conversion_errors:
                raise SymbolicationFailed(
                    message=self.symcaches_conversion_errors[obj.debug_id],
                    type=EventError.NATIVE_BAD_DSYM,
                    obj=obj
                )

            if is_optional_package(obj.code_file, sdk_info=sdk_info):
                type = EventError.NATIVE_MISSING_OPTIONALLY_BUNDLED_DSYM
            else:
                type = EventError.NATIVE_MISSING_DSYM

            raise SymbolicationFailed(type=type, obj=obj)

        try:
            rv = symcache.lookup(rebase_addr(instruction_addr, obj))
        except SymbolicError as e:
            raise SymbolicationFailed(
                type=EventError.NATIVE_BAD_DSYM, message=six.text_type(e), obj=obj
            )

        if not rv:
            # For some frameworks we are willing to ignore missing symbol
            # errors. Also, ignore scanned stack frames when symbols are
            # available to complete breakpad's stack scanning heuristics.
            if trust == 'scan' or is_optional_package(obj.code_file, sdk_info=sdk_info):
                return []
            raise SymbolicationFailed(
                type=EventError.NATIVE_MISSING_SYMBOL, obj=obj)
        return [self._process_frame(s, addr_off=obj.addr) for s in reversed(rv)]
Пример #4
0
    def fetch_system_symbols(self, processing_task):
        to_lookup = []
        pf_list = []
        for pf in processing_task.iter_processable_frames(self):
            obj = pf.data['obj']
            if pf.cache_value is not None or obj is None or \
               self.sym.is_image_from_app_bundle(obj):
                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.name 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
Пример #5
0
    def _symbolize_app_frame(self, instruction_addr, obj, sdk_info=None, trust=None):
        symcache = self.symcaches.get(obj.id)
        if symcache is None:
            # In case we know what error happened on symcache conversion
            # we can report it to the user now.
            if obj.id in self.symcaches_conversion_errors:
                raise SymbolicationFailed(
                    message=self.symcaches_conversion_errors[obj.id],
                    type=EventError.NATIVE_BAD_DSYM,
                    obj=obj
                )
            if self._is_optional_dif(obj, sdk_info=sdk_info):
                type = EventError.NATIVE_MISSING_OPTIONALLY_BUNDLED_DSYM
            else:
                type = EventError.NATIVE_MISSING_DSYM
            raise SymbolicationFailed(type=type, obj=obj)

        try:
            rv = symcache.lookup(rebase_addr(instruction_addr, obj))
        except SymbolicError as e:
            raise SymbolicationFailed(
                type=EventError.NATIVE_BAD_DSYM, message=six.text_type(e), obj=obj
            )

        if not rv:
            # For some frameworks we are willing to ignore missing symbol
            # errors. Also, ignore scanned stack frames when symbols are
            # available to complete breakpad's stack scanning heuristics.
            if trust == 'scan' or self._is_optional_dif(obj, sdk_info=sdk_info):
                return []
            raise SymbolicationFailed(
                type=EventError.NATIVE_MISSING_SYMBOL, obj=obj)
        return [self._process_frame(s, obj, addr_off=obj.addr) for s in reversed(rv)]
Пример #6
0
    def fetch_system_symbols(self, processing_task):
        to_lookup = []
        pf_list = []
        for pf in processing_task.iter_processable_frames(self):
            obj = pf.data['obj']
            if pf.cache_value is not None or obj is None or \
               self.sym.is_image_from_app_bundle(obj):
                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.id)
            except (ValueError, TypeError):
                continue

            to_lookup.append(
                {
                    'object_uuid': obj.id,
                    'object_name': obj.name 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
Пример #7
0
    def fetch_system_symbols(self, processing_task):
        to_lookup = []
        pf_list = []
        for pf in processing_task.iter_processable_frames(self):
            obj = pf.data['obj']
            if pf.cache_value is not None or obj is None or \
               self.sym.is_image_from_app_bundle(obj):
                continue
            to_lookup.append(
                {
                    'object_uuid': six.text_type(obj.uuid),
                    'object_name': obj.name 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
Пример #8
0
    def preprocess_frame(self, processable_frame):
        instr_addr = self.find_best_instruction(processable_frame)
        obj = self.object_lookup.find_object(instr_addr)

        processable_frame.data = {
            'instruction_addr': instr_addr,
            'obj': obj,
            'debug_id': obj.debug_id if obj is not None else None,
            'symbolserver_match': None,

            # `[]` is used to indicate to the symbolizer that the symbolicator
            # deliberately discarded this frame, while `None` means the
            # symbolicator didn't run (because `self.use_symbolicator` is
            # false).
            # If the symbolicator did run and was not able to symbolize the
            # frame, this value will be a list with the raw frame as only item.
            'symbolicator_match': [] if self.use_symbolicator else None,
        }

        if obj is not None:
            processable_frame.set_cache_key_from_values((
                FRAME_CACHE_VERSION,
                # Because the images can move around, we want to rebase
                # the address for the cache key to be within the image
                # the same way as we do it in the symbolizer.
                rebase_addr(instr_addr, obj),
                obj.debug_id,
                obj.arch,
                obj.size,
            ))
Пример #9
0
    def _symbolize_app_frame(self, instruction_addr, obj, sdk_info=None):
        symcache = self.symcaches.get(obj.id)
        if symcache is None:
            # In case we know what error happened on symcache conversion
            # we can report it to the user now.
            if obj.id in self.symcaches_conversion_errors:
                raise SymbolicationFailed(
                    message=self.symcaches_conversion_errors[obj.id],
                    type=EventError.NATIVE_BAD_DSYM,
                    obj=obj)
            if self._is_optional_dif(obj, sdk_info=sdk_info):
                type = EventError.NATIVE_MISSING_OPTIONALLY_BUNDLED_DSYM
            else:
                type = EventError.NATIVE_MISSING_DSYM
            raise SymbolicationFailed(type=type, obj=obj)

        try:
            rv = symcache.lookup(rebase_addr(instruction_addr, obj))
        except SymbolicError as e:
            raise SymbolicationFailed(type=EventError.NATIVE_BAD_DSYM,
                                      message=six.text_type(e),
                                      obj=obj)

        if not rv:
            # For some frameworks we are willing to ignore missing symbol
            # errors.
            if self._is_optional_dif(obj, sdk_info=sdk_info):
                return []
            raise SymbolicationFailed(type=EventError.NATIVE_MISSING_SYMBOL,
                                      obj=obj)
        return [
            self._process_frame(s, obj, addr_off=obj.addr)
            for s in reversed(rv)
        ]
Пример #10
0
    def fetch_system_symbols(self, processing_task):
        to_lookup = []
        pf_list = []
        for pf in processing_task.iter_processable_frames(self):
            img = pf.data['image']
            if pf.cache_value is not None or img is None or \
               self.sym.is_image_from_app_bundle(img):
                continue
            to_lookup.append({
                'object_uuid':
                img['uuid'],
                'object_name':
                img['name'],
                'addr':
                '0x%x' % rebase_addr(pf.data['instruction_addr'], img)
            })
            pf_list.append(pf)

        if not to_lookup:
            return

        rv = lookup_system_symbols(to_lookup, self.sdk_info, self.sym.cpu_name)
        if rv is not None:
            for symrv, pf in zip(rv, pf_list):
                if symrv is None:
                    continue
                pf.data['symbolserver_match'] = symrv
Пример #11
0
    def fetch_system_symbols(self, processing_task):
        to_lookup = []
        pf_list = []
        for pf in processing_task.iter_processable_frames(self):
            obj = pf.data['obj']
            if pf.cache_value is not None or obj is None or \
               self.sym.is_image_from_app_bundle(obj):
                continue
            to_lookup.append({
                'object_uuid':
                six.text_type(obj.uuid),
                'object_name':
                obj.name 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
Пример #12
0
    def fetch_system_symbols(self, processing_task):
        to_lookup = []
        pf_list = []
        for pf in processing_task.iter_processable_frames(self):
            img = pf.data['image']
            if pf.cache_value is not None or img is None or \
               self.sym.is_frame_from_app_bundle(pf.frame, img):
                continue
            to_lookup.append({
                'object_uuid': img['uuid'],
                'object_name': img['name'],
                'addr': '0x%x' % rebase_addr(pf.data['instruction_addr'], img)
            })
            pf_list.append(pf)

        if not to_lookup:
            return

        rv = lookup_system_symbols(to_lookup, self.sdk_info,
                                   self.sym.cpu_name)
        if rv is not None:
            for symrv, pf in zip(rv, pf_list):
                if symrv is None:
                    continue
                pf.data['symbolserver_match'] = symrv
Пример #13
0
    def _get_frame_key(self, frame):
        module = self.modules.find_object(frame['instruction_addr'])

        # If we cannot resolve a module for this frame, this means we're dealing
        # with an absolute address here. Since this address changes with every
        # crash and would poison our cache, we skip it for the key calculation.
        if not module:
            return None

        return (module.id, rebase_addr(frame['instruction_addr'], module))
Пример #14
0
    def _get_frame_key(self, frame):
        module = self.modules.find_object(frame['instruction_addr'])

        # If we cannot resolve a module for this frame, this means we're dealing
        # with an absolute address here. Since this address changes with every
        # crash and would poison our cache, we skip it for the key calculation.
        if not module:
            return None

        return (
            module.debug_id,
            rebase_addr(frame['instruction_addr'], module)
        )
Пример #15
0
    def save_to_cache(self):
        """Stores the reprocessed stack trace to the cache. For frames with
        known code modules only relative offsets are stored, otherwise the
        absolute address as fallback."""
        if self.resolved_frames is None:
            raise RuntimeError('save_to_cache called before resolving frames')

        if self.resolved_frames == NO_CFI_PLACEHOLDER:
            cache.set(self._cache_key, NO_CFI_PLACEHOLDER)
            return

        values = []
        for module, frame in self.resolved_frames:
            module_id = module and module.debug_id
            addr = frame['instruction_addr']
            if module:
                addr = '0x%x' % rebase_addr(addr, module)
            values.append((module_id, addr, frame['trust']))

        cache.set(self._cache_key, values)
Пример #16
0
    def save_to_cache(self):
        """Stores the reprocessed stack trace to the cache. For frames with
        known code modules only relative offsets are stored, otherwise the
        absolute address as fallback."""
        if self.resolved_frames is None:
            raise RuntimeError('save_to_cache called before resolving frames')

        if self.resolved_frames == NO_CFI_PLACEHOLDER:
            cache.set(self._cache_key, NO_CFI_PLACEHOLDER)
            return

        values = []
        for module, frame in self.resolved_frames:
            module_id = module and module.id
            addr = frame['instruction_addr']
            if module:
                addr = '0x%x' % rebase_addr(addr, module)
            values.append((module_id, addr, frame['trust']))

        cache.set(self._cache_key, values)
Пример #17
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
Пример #18
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
Пример #19
0
    def preprocess_frame(self, processable_frame):
        instr_addr = self.find_best_instruction(processable_frame)
        obj = self.object_lookup.find_object(instr_addr)

        processable_frame.data = {
            'instruction_addr': instr_addr,
            'obj': obj,
            'debug_id': obj.id if obj is not None else None,
            'symbolserver_match': None,
        }

        if obj is not None:
            processable_frame.set_cache_key_from_values((
                FRAME_CACHE_VERSION,
                # Because the images can move around, we want to rebase
                # the address for the cache key to be within the image
                # the same way as we do it in the symbolizer.
                rebase_addr(instr_addr, obj),
                obj.id,
                obj.arch,
                obj.size,
            ))
Пример #20
0
    def preprocess_frame(self, processable_frame):
        instr_addr = self.find_best_instruction(processable_frame)
        img = self.image_lookup.find_image(instr_addr)

        processable_frame.data = {
            'instruction_addr': instr_addr,
            'image': img,
            'image_uuid': img['uuid'] if img is not None else None,
            'symbolserver_match': None,
        }

        if img is not None:
            processable_frame.set_cache_key_from_values((
                FRAME_CACHE_VERSION,
                # Because the images can move around, we want to rebase
                # the address for the cache key to be within the image
                # the same way as we do it in the symbolizer.
                rebase_addr(instr_addr, img),
                img['uuid'].lower(),
                img['cpu_type'],
                img['cpu_subtype'],
                img['image_size'],
            ))
Пример #21
0
    def preprocess_frame(self, processable_frame):
        instr_addr = self.find_best_instruction(processable_frame)
        img = self.image_lookup.find_image(instr_addr)

        processable_frame.data = {
            'instruction_addr': instr_addr,
            'image': img,
            'image_uuid': img['uuid'] if img is not None else None,
            'symbolserver_match': None,
        }

        if img is not None:
            processable_frame.set_cache_key_from_values((
                FRAME_CACHE_VERSION,
                # Because the images can move around, we want to rebase
                # the address for the cache key to be within the image
                # the same way as we do it in the symbolizer.
                rebase_addr(instr_addr, img),
                img['uuid'].lower(),
                img['cpu_type'],
                img['cpu_subtype'],
                img['image_size'],
            ))
Пример #22
0
    def _symbolize_app_frame(self, instruction_addr, obj, sdk_info=None):
        symcache = self.symcaches.get(obj.uuid)
        if symcache is None:
            if self._is_optional_dsym(obj, sdk_info=sdk_info):
                type = EventError.NATIVE_MISSING_OPTIONALLY_BUNDLED_DSYM
            else:
                type = EventError.NATIVE_MISSING_DSYM
            raise SymbolicationFailed(type=type, obj=obj)

        try:
            rv = symcache.lookup(rebase_addr(instruction_addr, obj))
        except SymbolicError as e:
            raise SymbolicationFailed(
                type=EventError.NATIVE_BAD_DSYM, message=six.text_type(e), obj=obj
            )

        if not rv:
            # For some frameworks we are willing to ignore missing symbol
            # errors.
            if self._is_optional_dsym(obj, sdk_info=sdk_info):
                return []
            raise SymbolicationFailed(
                type=EventError.NATIVE_MISSING_SYMBOL, obj=obj)
        return [self._process_frame(s, obj, addr_off=obj.addr) for s in reversed(rv)]
Пример #23
0
    def preprocess_frame(self, processable_frame):
        instr_addr = self.find_best_instruction(processable_frame)
        obj = self.object_lookup.find_object(instr_addr)

        processable_frame.data = {
            'instruction_addr': instr_addr,
            'obj': obj,
            'obj_uuid': obj.id if obj is not None else None,
            'symbolserver_match': None,
        }

        if obj is not None:
            processable_frame.set_cache_key_from_values(
                (
                    FRAME_CACHE_VERSION,
                    # Because the images can move around, we want to rebase
                    # the address for the cache key to be within the image
                    # the same way as we do it in the symbolizer.
                    rebase_addr(instr_addr, obj),
                    obj.id,
                    obj.arch,
                    obj.size,
                )
            )