Example #1
0
def massage_input_and_call(
        cmd: Command, objs: Iterable[drgn.Object]) -> Iterable[drgn.Object]:
    """
    Commands can declare that they accept input of type "foo_t*" by
    setting their input_type. They can be passed input of type "void *"
    or "foo_t" and this method will automatically convert the input
    objects to the expected type (foo_t*).
    """

    # If this Command doesn't expect any particular type, just call().
    if cmd.input_type is None:
        yield from cmd.call(objs)
        return

    # If this Command doesn't expect a pointer, just call().
    expected_type = target.get_type(cmd.input_type)
    if expected_type.kind is not drgn.TypeKind.POINTER:
        yield from cmd.call(objs)
        return

    first_obj_type, objs = get_first_type(objs)
    if first_obj_type is not None:

        # If we are passed a void*, cast it to the expected type.
        if (first_obj_type.kind is drgn.TypeKind.POINTER and
                first_obj_type.type.primitive is drgn.PrimitiveType.C_VOID):
            yield from execute_pipeline(objs, [Cast([cmd.input_type]), cmd])
            return

        # If we are passed a foo_t when we expect a foo_t*, use its address.
        if target.get_pointer_type(first_obj_type) == expected_type:
            yield from execute_pipeline(objs, [Address(), cmd])
            return

    yield from cmd.call(objs)
Example #2
0
    def __init__(self, args: str = "", name: str = "_") -> None:
        super().__init__(args, name)
        if not self.args.type:
            self.parser.error("the following arguments are required: <type>")

        tname = " ".join(self.args.type)
        try:
            self.type = target.get_type(tname)
        except LookupError:
            raise CommandError(self.name, f"could not find type '{tname}'")
Example #3
0
    def caller(self, objs: Iterable[drgn.Object]) -> Iterable[drgn.Object]:
        """
        This method will dispatch to the appropriate instance function
        based on the type of the input we receive.
        """

        out_type = None
        if self.output_type is not None:
            out_type = target.get_type(self.output_type)
        baked = dict()
        for (_, method) in inspect.getmembers(self, inspect.ismethod):
            if not hasattr(method, "input_typename_handled"):
                continue
            baked[type_canonicalize_name(
                method.input_typename_handled)] = method

        if self.isfirst:
            assert not objs
            yield from self.no_input()
            return

        for i in objs:
            obj_type_name = type_canonical_name(i.type_)

            # try subclass-specified input types first, so that they can
            # override any other behavior
            if obj_type_name in baked:
                yield from baked[obj_type_name](i)
                continue

            # try passthrough of output type
            # note, this may also be handled by subclass-specified input types
            if obj_type_name == type_canonical_name(out_type):
                yield i
                continue

            # try walkers
            if out_type is not None:
                try:
                    # pylint: disable=protected-access
                    for obj in Walk()._call([i]):
                        yield drgn.cast(out_type, obj)
                    continue
                except CommandError:
                    pass

            # error
            raise CommandError(
                self.name, 'no handler for input of type {}'.format(i.type_))
Example #4
0
    def _call(self, objs: Iterable[drgn.Object]) -> Iterable[drgn.Object]:
        """
        This function will call walk() on each input object, verifying
        the types as we go.
        """
        assert self.input_type is not None
        type_ = target.get_type(self.input_type)
        for obj in objs:
            if obj.type_ != type_:
                raise CommandError(
                    self.name,
                    'expected input of type {}, but received {}'.format(
                        type_, obj.type_))

            yield from self.walk(obj)