#pragma once // Check Architecture #ifndef __arm__ #error "Symbols Are ARM-Only" #endif // Headers #include #include #include #include #include #include #include #include // Virtual Function Information template class __Function; template class __VirtualFunctionInfo { __VirtualFunctionInfo(T *const addr_, void *const parent_): addr(addr_), parent(parent_) {} [[nodiscard]] bool can_overwrite() const { return ((void *) *addr) != parent; } T *const addr; void *const parent; friend class __Function>; }; // Thunks typedef void *(*thunk_enabler_t)(void *target, void *thunk); extern thunk_enabler_t thunk_enabler; // Function Information template class __Function { public: // Types using ptr_type = Ret (*)(Args...); using type = std::function; using overwrite_type = std::function; // Normal Function __Function(const char *const name_, const ptr_type func_, const ptr_type thunk_): func(func_), enabled(true), name(name_), backup(func_), thunk(thunk_) {} // Virtual Function __Function(const char *const name_, ptr_type *const func_, void *const parent, const ptr_type thunk_): func(__VirtualFunctionInfo(func_, parent)), enabled(std::get<__VirtualFunctionInfo>(func).can_overwrite()), name(name_), backup(*get_vtable_addr()), thunk(thunk_) {} // Overwrite Function [[nodiscard]] bool overwrite(overwrite_type target) { // Check If Enabled if (!enabled) { return false; } // Enable Thunk enable_thunk(); // Overwrite type original = get_thunk_target(); thunk_target = [original, target](Args... args) { return target(original, std::forward(args)...); }; return true; } // Getters [[nodiscard]] ptr_type get(bool result_will_be_stored) { if (!enabled) { return nullptr; } else { if (result_will_be_stored) { enable_thunk(); } if (is_virtual()) { return *get_vtable_addr(); } else { return std::get(func); } } } [[nodiscard]] ptr_type *get_vtable_addr() const { return std::get<__VirtualFunctionInfo>(func).addr; } [[nodiscard]] type get_thunk_target() const { if (thunk_target) { return thunk_target; } else { return backup; } } private: // Current Function std::variant> func; [[nodiscard]] bool is_virtual() const { return func.index() == 1; } public: // State const bool enabled; const char *const name; // Backup Of Original Function Pointer const ptr_type backup; private: // Thunk const ptr_type thunk; type thunk_target; bool thunk_enabled = false; void enable_thunk() { if (!thunk_enabled && enabled) { ptr_type real_thunk = (ptr_type) thunk_enabler((void *) backup, (void *) thunk); if (!is_virtual()) { func = real_thunk; } thunk_enabled = true; } } }; // Shortcuts typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; // Duplicate VTable #define RTTI_SIZE 4 template T *dup_vtable(T *vtable) { // Check static_assert(std::is_constructible_v, "Unable To Construct VTable"); // Get Size const uchar *real_vtable = (uchar *) vtable; real_vtable -= RTTI_SIZE; const size_t real_vtable_size = sizeof(T) + RTTI_SIZE; // Allocate uchar *new_vtable = (uchar *) ::operator new(real_vtable_size); // Copy memcpy(new_vtable, real_vtable, real_vtable_size); // Return new_vtable += RTTI_SIZE; return (T *) new_vtable; } #undef RTTI_SIZE // Forward Declarations {{ forwardDeclarations }} // Extra Headers {{ extraHeaders }} // Warnings #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Winvalid-offsetof" #pragma GCC diagnostic ignored "-Wshadow" {{ main }} // Cleanup Warnings #pragma GCC diagnostic pop