Example #1
0
    def __init__(self,
                 project,
                 binary_images,
                 referenced_images=None,
                 cpu_name=None):
        self.symsynd_symbolizer = make_symbolizer(
            project, binary_images, referenced_images=referenced_images)

        # This is a duplication from symsynd.  The reason is that symsynd
        # will only load images that it can find dsyms for but we also
        # have system symbols which there are no dsyms for.
        self._image_addresses = []
        self.images = {}
        for img in binary_images:
            img_addr = parse_addr(img['image_addr'])
            self._image_addresses.append(img_addr)
            self.images[img_addr] = img
        self._image_addresses.sort()

        # This should always succeed but you never quite know.
        self.cpu_name = cpu_name
        if self.cpu_name is None:
            for img in six.itervalues(self.images):
                cpu_name = get_cpu_name(img['cpu_type'], img['cpu_subtype'])
                if self.cpu_name is None:
                    self.cpu_name = cpu_name
                elif self.cpu_name != cpu_name:
                    self.cpu_name = None
                    break
Example #2
0
def find_system_symbol(img, instruction_addr, system_info=None):
    """Finds a system symbol."""
    return DSymSymbol.objects.lookup_symbol(instruction_addr=instruction_addr,
                                            image_addr=img['image_addr'],
                                            uuid=img['uuid'],
                                            cpu_name=get_cpu_name(
                                                img['cpu_type'],
                                                img['cpu_subtype']),
                                            object_path=img['name'],
                                            system_info=system_info)
Example #3
0
    def symbolize_system_frame(self,
                               frame,
                               img,
                               sdk_info,
                               symbolize_inlined=False):
        """Symbolizes a frame with system symbols only."""
        # This is most likely a good enough cache match even though we are
        # ignoring the image here since we cache by instruction address.
        #
        # In some cases old clients might not send an sdk_info with it
        # in which case the caching won't work.
        if sdk_info is not None:
            cache_key = 'ssym:%s:%s:%s:%s:%s:%s:%s' % (
                frame['instruction_addr'],
                get_cpu_name(img['cpu_type'], img['cpu_subtype']),
                sdk_info['sdk_name'],
                sdk_info['dsym_type'],
                sdk_info['version_major'],
                sdk_info['version_minor'],
                sdk_info['version_patchlevel'],
            )
            symbol = cache.get(cache_key)
        else:
            cache_key = None
            symbol = None

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

        if symbol is None:
            # Simulator frames cannot be symbolicated
            if self._is_simulator_frame(frame, img):
                type = EventError.NATIVE_SIMULATOR_FRAME
            else:
                type = EventError.NATIVE_MISSING_SYSTEM_DSYM
            raise SymbolicationFailed(type=type, image=img)
        elif cache_key is not None:
            cache.set(cache_key, symbol, 3600)

        rv = self._process_frame(
            dict(frame,
                 symbol_name=symbol,
                 filename=None,
                 line=0,
                 column=0,
                 uuid=img['uuid'],
                 object_name=img['name']), img)

        # We actually do not support inline symbolication for system
        # frames, so we just only ever return a single frame here.  Maybe
        # we can improve this in the future.
        if symbolize_inlined:
            return [rv]
        return rv
Example #4
0
def find_system_symbol(img, instruction_addr, system_info=None):
    """Finds a system symbol."""
    return DSymSymbol.objects.lookup_symbol(
        instruction_addr=instruction_addr,
        image_addr=img['image_addr'],
        uuid=img['uuid'],
        cpu_name=get_cpu_name(img['cpu_type'],
                              img['cpu_subtype']),
        object_path=img['name'],
        system_info=system_info
    )
Example #5
0
    def symbolize_system_frame(self, frame, img, sdk_info,
                               symbolize_inlined=False):
        """Symbolizes a frame with system symbols only."""
        # This is most likely a good enough cache match even though we are
        # ignoring the image here since we cache by instruction address.
        #
        # In some cases old clients might not send an sdk_info with it
        # in which case the caching won't work.
        if sdk_info is not None:
            cache_key = 'ssym:%s:%s:%s:%s:%s:%s:%s' % (
                frame['instruction_addr'],
                get_cpu_name(img['cpu_type'], img['cpu_subtype']),
                sdk_info['sdk_name'],
                sdk_info['dsym_type'],
                sdk_info['version_major'],
                sdk_info['version_minor'],
                sdk_info['version_patchlevel'],
            )
            symbol = cache.get(cache_key)
        else:
            cache_key = None
            symbol = None

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

        if symbol is None:
            # Simulator frames cannot be symbolicated
            if self._is_simulator_frame(frame, img):
                type = EventError.NATIVE_SIMULATOR_FRAME
            else:
                type = EventError.NATIVE_MISSING_SYSTEM_DSYM
            raise SymbolicationFailed(
                type=type,
                image=img
            )
        elif cache_key is not None:
            cache.set(cache_key, symbol, 3600)

        rv = self._process_frame(dict(frame,
            symbol_name=symbol, filename=None, line=0, column=0,
            object_name=img['name']), img)

        # We actually do not support inline symbolication for system
        # frames, so we just only ever return a single frame here.  Maybe
        # we can improve this in the future.
        if symbolize_inlined:
            return [rv]
        return rv
Example #6
0
 def __init__(self, message=None, type=None, image=None):
     Exception.__init__(self)
     self.message = six.text_type(message)
     self.type = type
     if image is not None:
         self.image_uuid = image['uuid'].lower()
         self.image_path = image['name']
         self.image_name = image['name'].rsplit('/', 1)[-1]
         self.image_arch = get_cpu_name(image['cpu_type'],
                                        image['cpu_subtype'])
     else:
         self.image_uuid = None
         self.image_name = None
         self.image_path = None
         self.image_arch = None
Example #7
0
 def __init__(self, message=None, type=None, image=None):
     Exception.__init__(self)
     self.message = six.text_type(message)
     self.type = type
     if image is not None:
         self.image_uuid = image['uuid'].lower()
         self.image_path = image['name']
         self.image_name = image['name'].rsplit('/', 1)[-1]
         self.image_arch = get_cpu_name(image['cpu_type'],
                                        image['cpu_subtype'])
     else:
         self.image_uuid = None
         self.image_name = None
         self.image_path = None
         self.image_arch = None
Example #8
0
def cpu_name_from_data(data):
    """Returns the CPU name from the given data if it exists."""
    device = DeviceContextType.primary_value_for_data(data)
    if device:
        arch = device.get('arch')
        if isinstance(arch, six.string_types):
            return arch

    # TODO: kill this here.  we want to not support that going forward
    unique_cpu_name = None
    images = (data.get('debug_meta') or {}).get('images') or []
    for img in images:
        cpu_name = get_cpu_name(img['cpu_type'], img['cpu_subtype'])
        if unique_cpu_name is None:
            unique_cpu_name = cpu_name
        elif unique_cpu_name != cpu_name:
            unique_cpu_name = None
            break

    return unique_cpu_name
Example #9
0
def cpu_name_from_data(data):
    """Returns the CPU name from the given data if it exists."""
    device = DeviceContextType.primary_value_for_data(data)
    if device:
        arch = device.get('arch')
        if isinstance(arch, six.string_types):
            return arch

    # TODO: kill this here.  we want to not support that going forward
    unique_cpu_name = None
    images = (data.get('debug_meta') or {}).get('images') or []
    for img in images:
        cpu_name = get_cpu_name(img['cpu_type'],
                                img['cpu_subtype'])
        if unique_cpu_name is None:
            unique_cpu_name = cpu_name
        elif unique_cpu_name != cpu_name:
            unique_cpu_name = None
            break

    return unique_cpu_name
Example #10
0
def find_debug_images(dsym_paths, binary_images):
    images_to_load = set()

    with timedsection('iterimages0'):
        for image in binary_images:
            cpu_name = get_cpu_name(image['cpu_type'], image['cpu_subtype'])
            if cpu_name is not None:
                images_to_load.add(image['uuid'].lower())

    images = {}

    # Step one: load images that are named by their UUID
    with timedsection('loadimages-fast'):
        for uuid in list(images_to_load):
            for dsym_path in dsym_paths:
                fn = os.path.join(dsym_path, uuid)
                if os.path.isfile(fn):
                    images[uuid] = fn
                    images_to_load.discard(uuid)
                    break

    # Otherwise fall back to loading images from the dsym bundle.  Because
    # this loading strategy is pretty slow we do't actually want to use it
    # unless we have a path that looks like a bundle.  As a result we
    # find all the paths which are bundles and then only process those.
    if images_to_load:
        slow_paths = []
        for dsym_path in dsym_paths:
            if os.path.isdir(os.path.join(dsym_path, 'Contents')):
                slow_paths.append(dsym_path)

        with timedsection('loadimages-slow'):
            for dsym_path in slow_paths:
                dwarf_base = os.path.join(dsym_path, 'Contents', 'Resources',
                                          'DWARF')
                if os.path.isdir(dwarf_base):
                    for fn in os.listdir(dwarf_base):
                        # Looks like a UUID we loaded, skip it
                        if fn in images:
                            continue
                        full_fn = os.path.join(dwarf_base, fn)
                        uuids = get_macho_uuids(full_fn)
                        for _, uuid in uuids:
                            if uuid in images_to_load:
                                images[uuid] = full_fn
                                images_to_load.discard(uuid)

    rv = {}

    # Now resolve all the images.
    with timedsection('resolveimages'):
        for image in binary_images:
            cpu_name = get_cpu_name(image['cpu_type'], image['cpu_subtype'])
            if cpu_name is None:
                continue
            uid = image['uuid'].lower()
            if uid not in images:
                continue
            rv[image['image_addr']] = {
                'uuid': uid,
                'image_addr': image['image_addr'],
                'dsym_path': images[uid],
                'image_vmaddr': image['image_vmaddr'],
                'cpu_name': cpu_name,
            }

    return rv
Example #11
0
def test_cpu_names():
    assert arch.get_cpu_name(12, 9) == 'armv7'
Example #12
0
def find_debug_images(dsym_paths, binary_images):
    images_to_load = set()

    with timedsection('iterimages0'):
        for image in binary_images:
            cpu_name = get_cpu_name(image['cpu_type'],
                                    image['cpu_subtype'])
            if cpu_name is not None:
                images_to_load.add(image['uuid'].lower())

    images = {}

    # Step one: load images that are named by their UUID
    with timedsection('loadimages-fast'):
        for uuid in list(images_to_load):
            for dsym_path in dsym_paths:
                fn = os.path.join(dsym_path, uuid)
                if os.path.isfile(fn):
                    images[uuid] = fn
                    images_to_load.discard(uuid)
                    break

    # Otherwise fall back to loading images from the dsym bundle.  Because
    # this loading strategy is pretty slow we do't actually want to use it
    # unless we have a path that looks like a bundle.  As a result we
    # find all the paths which are bundles and then only process those.
    if images_to_load:
        slow_paths = []
        for dsym_path in dsym_paths:
            if os.path.isdir(os.path.join(dsym_path, 'Contents')):
                slow_paths.append(dsym_path)

        with timedsection('loadimages-slow'):
            for dsym_path in slow_paths:
                dwarf_base = os.path.join(dsym_path, 'Contents',
                                          'Resources', 'DWARF')
                if os.path.isdir(dwarf_base):
                    for fn in os.listdir(dwarf_base):
                        # Looks like a UUID we loaded, skip it
                        if fn in images:
                            continue
                        full_fn = os.path.join(dwarf_base, fn)
                        uuids = get_macho_uuids(full_fn)
                        for _, uuid in uuids:
                            if uuid in images_to_load:
                                images[uuid] = full_fn
                                images_to_load.discard(uuid)

    rv = {}

    # Now resolve all the images.
    with timedsection('resolveimages'):
        for image in binary_images:
            cpu_name = get_cpu_name(image['cpu_type'],
                                    image['cpu_subtype'])
            if cpu_name is None:
                continue
            uid = image['uuid'].lower()
            if uid not in images:
                continue
            rv[image['image_addr']] = {
                'uuid': uid,
                'image_addr': image['image_addr'],
                'dsym_path': images[uid],
                'image_vmaddr': image['image_vmaddr'],
                'cpu_name': cpu_name,
            }

    return rv