#pragma once #include #include "../logger.h" typedef void* (*InstantiateInterfaceFn)(); struct InterfaceReg { InstantiateInterfaceFn m_CreateFn; const char* m_pName; InterfaceReg* m_pNext; }; inline void**& getvtable(void* inst, size_t offset = 0) { return *reinterpret_cast((size_t)inst + offset); } inline const void** getvtable(const void* inst, size_t offset = 0) { return *reinterpret_cast((size_t)inst + offset); } template inline Fn getvfunc(const void* inst, size_t index, size_t offset = 0) { return reinterpret_cast(getvtable(inst, offset)[index]); } template interface* GetInterface(const char* filename, const char* version, bool exact = false) { void* library = dlopen(filename, RTLD_NOLOAD | RTLD_NOW); if (!library) { // Log << " -- " << filename << " dlopen failed." << std::endl; return nullptr; } void* interfaces_sym = dlsym(library, "s_pInterfaceRegs"); if (!interfaces_sym) { // Log << " -- " << filename << " dlsym s_pInterfaceRegs failed." << // std::endl; dlclose(library); return nullptr; } dlclose(library); InterfaceReg* interfaces = *reinterpret_cast(interfaces_sym); InterfaceReg* cur_interface; for (cur_interface = interfaces; cur_interface; cur_interface = cur_interface->m_pNext) { if (exact) { if (strcmp(cur_interface->m_pName, version) == 0) return reinterpret_cast( cur_interface->m_CreateFn()); } else { if (strstr(cur_interface->m_pName, version) && strlen(cur_interface->m_pName) - 3 == strlen(version)) return reinterpret_cast( cur_interface->m_CreateFn()); } } // Log << " -- " << filename << " Cannot find interface." << std::endl; return nullptr; } inline uintptr_t GetAbsoluteAddress(uintptr_t instruction_ptr, int offset, int size) { return instruction_ptr + *reinterpret_cast(instruction_ptr + offset) + size; }; template T GetSymbolAddress(const char* filename, const char* symbol) { void* handle = dlopen(filename, RTLD_NOW); T result = reinterpret_cast(dlsym(handle, symbol)); dlclose(handle); return result; };