From f53076ad681cbfa450c543421b578b3f1c514201 Mon Sep 17 00:00:00 2001 From: mollismerx Date: Sat, 17 Sep 2016 22:46:34 +0200 Subject: [PATCH] Started testing virtual inheritance --- GOTEntry.cpp | 4 +-- GOTEntry.h | 3 +- Hook.h | 18 +++++++---- SPY.h | 27 ++++++++++++---- demo.cpp | 63 ++++++++++++++++++++++++++++++++++++ demo.h | 41 +++++++++++++++++++++++ example7.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 232 insertions(+), 15 deletions(-) diff --git a/GOTEntry.cpp b/GOTEntry.cpp index 2c1cfff..1e8841d 100644 --- a/GOTEntry.cpp +++ b/GOTEntry.cpp @@ -107,7 +107,7 @@ void GOTEntry::initialise(int argc, char** argv) // base + rela.plt if symbol is found and defined // base + rela.dyn if symbol is found and undefined -void* GOTEntry::set(void* function) +void* GOTEntry::set(void* function, const char* name) { if (entries_.empty()) { auto address = reinterpret_cast(function); @@ -153,7 +153,7 @@ void* GOTEntry::set(void* function) } } if (!defined) { - Report() << "cannot find definition of function " << function; + Report() << "cannot find definition of function " << name; return nullptr; } // find entries where the symbol is used in other ELF functions diff --git a/GOTEntry.h b/GOTEntry.h index 56137f1..d6ebf71 100644 --- a/GOTEntry.h +++ b/GOTEntry.h @@ -22,9 +22,10 @@ public: GOTEntry() = default; /** * @param function address of function + * @param name name of function * @return original unaltered address of function */ - void* set(void* function); + void* set(void* function, const char* name); /** * replace function with other function and reference count * @param function to enter in Global Offset Tables instead of original diff --git a/Hook.h b/Hook.h index fb3b3e5..368383d 100644 --- a/Hook.h +++ b/Hook.h @@ -42,11 +42,11 @@ public: /** * construct from function pointer */ - Hook(ReturnType (*function)(ArgTypes...)); + Hook(const char* name, ReturnType (*function)(ArgTypes...)); /** * construct from method pointer */ - Hook(MethodInfo method); + Hook(const char* name, MethodInfo method); /// restore original function ~Hook(); /** @@ -60,19 +60,24 @@ public: private: static GOTEntry got_entry_; + static const char* name_; using Base = HookImpl; }; template GOTEntry Hook::got_entry_; +template +const char* Hook::name_ = "no name"; template -Hook::Hook(ReturnType (*function)(ArgTypes...)) +Hook::Hook(const char* name, + ReturnType (*function)(ArgTypes...)) { + name_ = name; // use union to get and convert address of function Function converter; converter.address_ = function; - got_entry_.set(converter.pointer_); + got_entry_.set(converter.pointer_, name); converter.address_ = &Base::thunk; converter.pointer_ = got_entry_.spy_with(converter.pointer_); Base::patch_ = Base::real_ = converter.address_; @@ -80,9 +85,10 @@ Hook::Hook(ReturnType (*function)(ArgTypes...)) template inline Hook:: -Hook(MethodInfo method) +Hook(const char* name, MethodInfo method) { - got_entry_.set(method.address_); + name_ = name; + got_entry_.set(method.address_, name); if (method.vtable_entry_) { got_entry_.make_entry(method.vtable_entry_); } diff --git a/SPY.h b/SPY.h index 52b8b11..e4b681d 100644 --- a/SPY.h +++ b/SPY.h @@ -27,7 +27,10 @@ struct Function struct Instance : public Hook, R, Args...> { using Base = Hook, R, Args...>; - Instance() : Base(FUNC) { } + Instance(const char* name) + :Base(name, FUNC) + { + } }; }; @@ -46,7 +49,10 @@ struct MutableMethod struct Instance : public Hook, R, T*, Args...> { using Base = Hook, R, T*, Args...>; - Instance() : Base(Method(METHOD).resolve()) { } + Instance(const char* name) + :Base(name, Method(METHOD).resolve()) + { + } }; }; @@ -65,7 +71,10 @@ struct ConstMethod struct Instance : public Hook, R, T*, Args...> { using Base = Hook, R, T*, Args...>; - Instance() : Base(Method(METHOD).resolve()) { } + Instance(const char* name) + :Base(name, Method(METHOD).resolve()) + { + } }; }; @@ -84,7 +93,10 @@ struct VolatileMethod struct Instance : public Hook, R, T*, Args...> { using Base = Hook, R, T*, Args...>; - Instance() : Base(Method(METHOD).resolve()) { } + Instance(const char* name) + :Base(name, Method(METHOD).resolve()) + { + } }; }; @@ -103,7 +115,10 @@ struct ConstVolatileMethod struct Instance : public Hook, R, T*, Args...> { using Base = Hook, R, T*, Args...>; - Instance() : Base(Method(METHOD).resolve()) { } + Instance(const char* name) + :Base(name, Method(METHOD).resolve()) + { + } }; }; @@ -136,6 +151,6 @@ auto create(R (T::*)(Args...) const volatile) * SPY returns a (derived) instance of Hook that can be used to add Hooks to. */ -#define SPY(F) decltype(spy::impl::create(F))::Instance() +#define SPY(F) decltype(spy::impl::create(F))::Instance(#F) #endif diff --git a/demo.cpp b/demo.cpp index 69e4f78..71f4576 100644 --- a/demo.cpp +++ b/demo.cpp @@ -1,6 +1,7 @@ #include "elfspy/demo.h" #include +#include int f() { @@ -51,3 +52,65 @@ void MyDerivedClass::virtual_method() method(2); std::cout << "MyDerivedClass::virtual_method" << std::endl; } + +void One::one_method() +{ + std::cout << "One::one" << std::endl; + assert(check1_ == 0xe110e110); +} + +void Two::one_method() +{ + std::cout << "Two::one" << std::endl; + assert(check1_ == 0xe110e110); + assert(check2_ == 0xdeafa1de); +} + +void Two::two_method() +{ + std::cout << "Two::two" << std::endl; + assert(check1_ == 0xe110e110); + assert(check2_ == 0xdeafa1de); +} + +void Three::one_method() +{ + std::cout << "Three::one" << std::endl; + assert(check1_ == 0xe110e110); + assert(check3_ == 0xdeadbeef); +} + +void Three::three_method() +{ + std::cout << "Three::three" << std::endl; + assert(check1_ == 0xe110e110); + assert(check3_ == 0xdeadbeef); +} + +void Four::one_method() +{ + std::cout << "Four::one" << std::endl; + assert(check1_ == 0xe110e110); + assert(check2_ == 0xdeafa1de); + assert(check3_ == 0xdeadbeef); + assert(check4_ == 0xbadfeed); +} + +void Four::two_method() +{ + std::cout << "Four::two" << std::endl; + assert(check1_ == 0xe110e110); + assert(check2_ == 0xdeafa1de); + assert(check3_ == 0xdeadbeef); + assert(check4_ == 0xbadfeed); +} + +void Four::three_method() +{ + std::cout << "Four::three" << std::endl; + assert(check1_ == 0xe110e110); + assert(check2_ == 0xdeafa1de); + assert(check3_ == 0xdeadbeef); + assert(check4_ == 0xbadfeed); +} + diff --git a/demo.h b/demo.h index 0df98f2..d4844bb 100644 --- a/demo.h +++ b/demo.h @@ -23,4 +23,45 @@ public: virtual void virtual_method(); }; +class One +{ +public: + virtual ~One() = default; + virtual void one_method(); + +protected: + long check1_ = 0xe110e110; +}; + +class Two : virtual public One +{ +public: + virtual void one_method() override; + virtual void two_method(); + +protected: + long check2_ = 0xdeafa1de; +}; + +class Three : virtual public One +{ +public: + virtual void one_method() override; + virtual void three_method(); + +protected: + long check3_ = 0xdeadbeef; +}; + +class Four : public Two, public Three +{ +public: + virtual void one_method() override; + virtual void two_method() override; + virtual void three_method() override; + +protected: + long check4_ = 0xbadfeed; +}; + #endif diff --git a/example7.cpp b/example7.cpp index a018d4a..99c8d82 100644 --- a/example7.cpp +++ b/example7.cpp @@ -5,6 +5,8 @@ #include "elfspy/Arg.h" #include "elfspy/Fake.h" +#define private public +#define protected public #include "elfspy/demo.h" void func(MyClass*) @@ -12,6 +14,67 @@ void func(MyClass*) std::cout << "func()" << std::endl; } +void one_method1(One* one) +{ + std::cout << "1::1" << std::endl; + assert(one->check1_ == 0xe110e110); +} + +void one_method2(Two* two) +{ + std::cout << "2::1" << std::endl; + assert(two->check1_ == 0xe110e110); + assert(two->check2_ == 0xdeafa1de); +} + +void two_method2(Two* two) +{ + std::cout << "2::2" << std::endl; + assert(two->check1_ == 0xe110e110); + assert(two->check2_ == 0xdeafa1de); +} + +void one_method3(Three* three) +{ + std::cout << "3::1" << std::endl; + assert(three->check1_ == 0xe110e110); + assert(three->check3_ == 0xdeadbeef); +} + +void three_method3(Three* three) +{ + std::cout << "3::3" << std::endl; + assert(three->check1_ == 0xe110e110); + assert(three->check3_ == 0xdeadbeef); +} + +void one_method4(Four* four) +{ + std::cout << "4::1" << std::endl; + assert(four->check1_ == 0xe110e110); + assert(four->check2_ == 0xdeafa1de); + assert(four->check3_ == 0xdeadbeef); + assert(four->check4_ == 0xbadfeed); +} + +void two_method4(Four* four) +{ + std::cout << "4::2" << std::endl; + assert(four->check1_ == 0xe110e110); + assert(four->check2_ == 0xdeafa1de); + assert(four->check3_ == 0xdeadbeef); + assert(four->check4_ == 0xbadfeed); +} + +void three_method4(Four* four) +{ + std::cout << "4::3" << std::endl; + assert(four->check1_ == 0xe110e110); + assert(four->check2_ == 0xdeafa1de); + assert(four->check3_ == 0xdeadbeef); + assert(four->check4_ == 0xbadfeed); +} + int main(int argc, char** argv) { spy::initialise(argc, argv); @@ -27,5 +90,33 @@ int main(int argc, char** argv) MyClass* my_heap_object = new MyClass; my_heap_object->virtual_method(); assert(method_this.value(1) == my_heap_object); + auto spy11 = SPY(&One::one_method); + auto spy21 = SPY(&Two::one_method); + auto spy22 = SPY(&Two::two_method); + auto spy31 = SPY(&Three::one_method); + auto spy33 = SPY(&Three::three_method); + auto spy41 = SPY(&Four::one_method); + auto spy42 = SPY(&Four::two_method); + auto spy43 = SPY(&Four::three_method); + auto fake11 = spy::fake(spy11, &one_method1); + auto fake21 = spy::fake(spy21, &one_method2); + auto fake22 = spy::fake(spy22, &two_method2); + auto fake31 = spy::fake(spy31, &one_method3); + auto fake33 = spy::fake(spy33, &three_method3); + auto fake41 = spy::fake(spy41, &one_method4); + auto fake42 = spy::fake(spy42, &two_method4); + auto fake43 = spy::fake(spy43, &three_method4); + One* one = new One; + Two* two = new Two; + Three* three = new Three; + Four* four = new Four; + one->one_method(); + two->one_method(); + two->two_method(); + three->one_method(); + three->three_method(); + four->one_method(); + four->two_method(); + four->three_method(); return 0; }