Execute a hooked function. Args: func: function hook proto: function's parameters types list params: a mapping of parameter names to their values hook_onenter: a hook to call before entering function hook hook_onexit: a hook to ca
(self, func: CallHook, proto: Mapping[str, Any], params: Mapping[str, Any], hook_onenter: Optional[OnEnterHook], hook_onexit: Optional[OnExitHook], passthru: bool)
| 132 | return tuple(zip(types, names, values)) |
| 133 | |
| 134 | def call(self, func: CallHook, proto: Mapping[str, Any], params: Mapping[str, Any], hook_onenter: Optional[OnEnterHook], hook_onexit: Optional[OnExitHook], passthru: bool) -> Tuple[Iterable[TypedArg], int, int]: |
| 135 | """Execute a hooked function. |
| 136 | |
| 137 | Args: |
| 138 | func: function hook |
| 139 | proto: function's parameters types list |
| 140 | params: a mapping of parameter names to their values |
| 141 | hook_onenter: a hook to call before entering function hook |
| 142 | hook_onexit: a hook to call after returning from function hook |
| 143 | passthru: whether to skip stack frame unwinding |
| 144 | |
| 145 | Returns: resolved params mapping, return value, return address |
| 146 | """ |
| 147 | |
| 148 | ql = self.ql |
| 149 | pc = ql.arch.regs.arch_pc |
| 150 | |
| 151 | # if set, fire up the on-enter hook and let it override original args set |
| 152 | if hook_onenter: |
| 153 | overrides = hook_onenter(ql, pc, params) |
| 154 | |
| 155 | if overrides is not None: |
| 156 | pc, params = overrides |
| 157 | |
| 158 | # call function |
| 159 | retval = func(ql, pc, params) |
| 160 | |
| 161 | # if set, fire up the on-exit hook and let it override the return value |
| 162 | if hook_onexit: |
| 163 | override = hook_onexit(ql, pc, params, retval) |
| 164 | |
| 165 | if override is not None: |
| 166 | retval = override |
| 167 | |
| 168 | # set return value |
| 169 | if retval is not None: |
| 170 | self.cc.setReturnValue(retval) |
| 171 | |
| 172 | targs = QlFunctionCall.__get_typed_args(proto, params) |
| 173 | |
| 174 | # TODO: resolve return value |
| 175 | |
| 176 | # unwind stack frame; note that function prototype sometimes does not |
| 177 | # reflect the actual number of arguments passed to the function, like |
| 178 | # in variadic functions (e.g. printf-like functions). in such case the |
| 179 | # function frame would not be unwinded entirely and cause the program |
| 180 | # to fail or produce funny results. |
| 181 | # |
| 182 | # nevertheless this type of functions never unwind their own frame, |
| 183 | # exactly for the reason they are not aware of the actual number of |
| 184 | # arguments they got. since the caller is responsible for unwinding |
| 185 | # we should be good. |
| 186 | |
| 187 | nslots = self.__count_slots(proto.values()) |
| 188 | retaddr = -1 if passthru else self.cc.unwind(nslots) |
| 189 | |
| 190 | return targs, retval, retaddr |
| 191 |
nothing calls this directly
no test coverage detected