76 lines
1.9 KiB
C++
76 lines
1.9 KiB
C++
#ifndef ELFSPY_LAMBDA_H
|
|
#define ELFSPY_LAMBDA_H
|
|
|
|
namespace spy
|
|
{
|
|
|
|
/**
|
|
* @namespace spy
|
|
* @class Lambda
|
|
* This replaces an existing function with a lambda, so that all calls to
|
|
* the program are made to the lambda.
|
|
* The constructor installs the lambda in place of the function, the destructor
|
|
* uninstalls it
|
|
*/
|
|
|
|
template <typename H, typename L, typename ReturnType, typename... ArgTypes>
|
|
class Lambda
|
|
{
|
|
public:
|
|
Lambda(H& hook, L& lambda);
|
|
~Lambda();
|
|
|
|
private:
|
|
static ReturnType function(ArgTypes... argtypes);
|
|
H& hook_;
|
|
L lambda_;
|
|
static Lambda* instance_;
|
|
ReturnType (*func_)(ArgTypes...);
|
|
};
|
|
|
|
template <typename H, typename L, typename ReturnType, typename... ArgTypes>
|
|
Lambda<H, L, ReturnType, ArgTypes...>*
|
|
Lambda<H, L, ReturnType, ArgTypes...>::instance_ = nullptr;
|
|
|
|
template <typename H, typename L, typename ReturnType, typename... ArgTypes>
|
|
inline Lambda<H, L, ReturnType, ArgTypes...>::Lambda(H& hook, L& lambda)
|
|
:hook_(hook)
|
|
,lambda_(lambda)
|
|
{
|
|
instance_ = this;
|
|
func_ = hook.patch(&Lambda<H, L, ReturnType, ArgTypes...>::function);
|
|
}
|
|
|
|
template <typename H, typename L, typename ReturnType, typename... ArgTypes>
|
|
inline Lambda<H, L, ReturnType, ArgTypes...>::~Lambda()
|
|
{
|
|
hook_.patch(func_);
|
|
instance_ = nullptr;
|
|
}
|
|
|
|
template <typename H, typename L, typename ReturnType, typename... ArgTypes>
|
|
ReturnType Lambda<H, L, ReturnType, ArgTypes...>::function(ArgTypes... argtypes)
|
|
{
|
|
return instance_->lambda_(std::forward<ArgTypes>(argtypes)...);
|
|
}
|
|
|
|
template <typename H, typename L>
|
|
inline auto fake(H& hook, L& lambda)
|
|
-> typename H::template Export<Lambda, H, L, typename H::Result>::Type
|
|
{
|
|
return { hook, lambda };
|
|
}
|
|
|
|
template <typename H, typename L>
|
|
inline auto new_fake(H& hook, L& lambda)
|
|
-> typename H::template Export<Lambda, H, L, typename H::Result>::Type*
|
|
{
|
|
using Install =
|
|
typename H::template Export<Lambda, H, L, typename H::Result>::Type;
|
|
return new Install(hook, lambda);
|
|
}
|
|
|
|
} // namespace elfspy
|
|
|
|
#endif
|