#pragma once // Check Architecture #ifndef __arm__ #error "Symbols Are ARM-Only" #endif // Headers #include #include #include #include #include #include #include #include // Internal Macros #define __PREVENT_DESTRUCTION(self) \ ~self() = delete #define __PREVENT_CONSTRUCTION(self) \ self() = delete; \ __PREVENT_DESTRUCTION(self) #define __PREVENT_COPY(self) \ self(const self &) = delete; \ self &operator=(const self &) = delete // Virtual Function Information struct __VirtualFunctionInfo { // Constructors template __VirtualFunctionInfo(Ret (**const addr_)(Self, Args...), Ret (*const parent_)(Super, Args...)): addr((void **) addr_), parent((void *) parent_) {} template __VirtualFunctionInfo(T **const addr_, const std::nullptr_t parent_): __VirtualFunctionInfo(addr_, (T *) parent_) {} // Method [[nodiscard]] bool can_overwrite() const { return *addr != parent; } // Properties void **const addr; void *const parent; }; // Thunks typedef void *(*thunk_enabler_t)(void *target, void *thunk); extern thunk_enabler_t thunk_enabler; // Function Information template class __Function; template class __Function { // Prevent Copying __PREVENT_COPY(__Function); __PREVENT_DESTRUCTION(__Function); public: // Types typedef Ret (*ptr_type)(Args...); typedef std::function type; typedef std::function overwrite_type; // Normal Function __Function(const std::string name_, const ptr_type thunk_, const ptr_type func_): func(func_), enabled(true), name(name_), backup(func_), thunk(thunk_) {} // Virtual Function template __Function(const std::string name_, const ptr_type thunk_, ptr_type *const func_, const Parent parent): 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 (ptr_type *) 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 std::string 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; // 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