#ifndef ELFSPY_METHOD_H #define ELFSPY_METHOD_H #include #include "elfspy/GOTEntry.h" #include "elfspy/MethodPointer.h" #include "elfspy/MethodInfo.h" namespace spy { /** * @namespace spy * @union Method * Conversion union for all different method signatures */ template union Method { R (T::*method_)(Args...); R (T::*const_method_)(Args...) const; R (T::*volatile_method_)(Args...) volatile; R (T::*cv_method_)(Args...) const volatile; Method(R (T::*method)(Args...)); Method(R (T::*const_method)(Args...) const); Method(R (T::*volatile_method)(Args...) volatile); Method(R (T::*cv_method)(Args...) const volatile); R (*function_)(T*, Args...); void* address_; MethodPointer impl_; MethodInfo resolve(); }; template inline Method::Method(R (T::*method)(Args...)) { method_ = method; } template inline Method::Method(R (T::*const_method)(Args...) const) { const_method_ = const_method; } template inline Method::Method(R (T::*volatile_method)(Args...) volatile) { volatile_method_ = volatile_method; } template inline Method::Method(R (T::*cv_method)(Args...) const volatile) { cv_method_ = cv_method; } template MethodInfo Method::resolve() { MethodInfo info; if (impl_.is_virtual()) { info.vtable_entry_ = GOTEntry::get_vtable_entry(typeid(T), impl_); info.address_ = *info.vtable_entry_; } else { info.vtable_entry_ = nullptr; info.address_ = address_; } return info; } } // namespace spy #endif