83 lines
2.2 KiB
C++
83 lines
2.2 KiB
C++
#ifndef ELFSPY_HOOKIMPL_H
|
|
#define ELFSPY_HOOKIMPL_H
|
|
|
|
#include "elfspy/HookBase.h"
|
|
|
|
namespace spy
|
|
{
|
|
|
|
/**
|
|
* @namespace spy
|
|
* @class HookImpl
|
|
* Part of the Hook implementation to distinguish between void and non-void
|
|
* return values.
|
|
*/
|
|
|
|
template <typename CRTP, typename ReturnType, typename... ArgTypes>
|
|
class HookImpl : public HookBase<CRTP, ReturnType, ArgTypes...>
|
|
{
|
|
public:
|
|
/// @return collection to register thunks that process return value
|
|
static std::vector<Thunk<ReturnType&&>*>& return_thunks();
|
|
|
|
protected:
|
|
static std::vector<Thunk<ReturnType&&>*> return_thunks_;
|
|
static ReturnType&& use_return(ReturnType&& result);
|
|
static ReturnType thunk(ArgTypes... args);
|
|
using Base = HookBase<CRTP, ReturnType, ArgTypes...>;
|
|
};
|
|
|
|
template <typename CRTP, typename ReturnType, typename... ArgTypes>
|
|
std::vector<Thunk<ReturnType&&>*>
|
|
HookImpl<CRTP, ReturnType, ArgTypes...>::return_thunks_;
|
|
|
|
template <typename CRTP, typename ReturnType, typename... ArgTypes>
|
|
inline std::vector<Thunk<ReturnType&&>*>&
|
|
HookImpl<CRTP, ReturnType, ArgTypes...>::return_thunks()
|
|
{
|
|
return return_thunks_;
|
|
}
|
|
|
|
template <typename CRTP, typename ReturnType, typename... ArgTypes>
|
|
ReturnType&&
|
|
HookImpl<CRTP, ReturnType, ArgTypes...>::use_return(ReturnType&& result)
|
|
{
|
|
for (auto trap : return_thunks_)
|
|
{
|
|
trap->invoke(std::forward<ReturnType>(result));
|
|
}
|
|
return std::forward<ReturnType>(result);
|
|
}
|
|
|
|
template <typename CRTP, typename ReturnType, typename... ArgTypes>
|
|
ReturnType HookImpl<CRTP, ReturnType, ArgTypes...>::thunk(ArgTypes... args)
|
|
{
|
|
Base::run_thunks(std::forward<ArgTypes>(args)...);
|
|
return use_return(
|
|
std::forward<ReturnType>((*Base::patch_)(std::forward<ArgTypes>(args)...)));
|
|
}
|
|
|
|
/// specialisation for void return
|
|
template <typename CRTP, typename... ArgTypes>
|
|
class HookImpl<CRTP, void, ArgTypes...>
|
|
: public HookBase<CRTP, void, ArgTypes...>
|
|
{
|
|
protected:
|
|
static void thunk(ArgTypes... args);
|
|
|
|
private:
|
|
using Base = HookBase<CRTP, void, ArgTypes...>;
|
|
};
|
|
|
|
template <typename CRTP, typename... ArgTypes>
|
|
void HookImpl<CRTP, void, ArgTypes...>::thunk(ArgTypes... args)
|
|
{
|
|
Base::run_thunks(std::forward<ArgTypes>(args)...);
|
|
(*Base::patch_)(std::forward<ArgTypes>(args)...);
|
|
}
|
|
|
|
|
|
} // namespace spy
|
|
|
|
#endif
|