#ifndef ELFSPY_HOOKBASE_H #define ELFSPY_HOOKBASE_H #include #include "elfspy/Thunk.h" namespace spy { /** * @namespace spy * @class HookBase * Contains the common part of HookImpl for void and non-void return values */ template class HookBase { public: /// @return collection to register thunks that process function arguments static std::vector*>& thunks(); /// @return collection to register thunks not using function arguments static std::vector*>& no_arg_thunks(); typedef ReturnType (*Signature)(ArgTypes...); /** * replace the original function with a different one * @param function to replace original with * @return previous function being called (typically the original) */ static Signature patch(Signature function); protected: static Signature real_; static Signature patch_; static std::vector*> thunks_; static std::vector*> no_arg_thunks_; static void run_thunks(ArgTypes&&... args); }; template typename HookBase::Signature HookBase::real_ = nullptr; template typename HookBase::Signature HookBase::patch_ = nullptr; template std::vector*> HookBase::thunks_; template std::vector*> HookBase::no_arg_thunks_; template inline std::vector*>& HookBase::thunks() { return thunks_; } template inline std::vector*>& HookBase::no_arg_thunks() { return no_arg_thunks_; } template void HookBase::run_thunks(ArgTypes&&... args) { for (auto thunk : thunks_) { thunk->invoke(std::forward(args)...); } for (auto stub : no_arg_thunks_) { stub->invoke(); } } template typename HookBase::Signature HookBase:: patch(typename HookBase::Signature function) { auto copy = patch_; patch_ = function; return copy; } } // namespace spy #endif