diff --git a/src/ll/api/memory/Hook.cpp b/src/ll/api/memory/Hook.cpp index b0f02830d2..e14c79a48d 100644 --- a/src/ll/api/memory/Hook.cpp +++ b/src/ll/api/memory/Hook.cpp @@ -1,24 +1,29 @@ #include "ll/api/memory/Hook.h" + +#include +#include + +#include "pl/Hook.h" + #include "ll/api/Logger.h" #include "ll/api/memory/Memory.h" #include "ll/api/service/ServerInfo.h" -#include "ll/api/utils/StacktraceUtils.h" +#include "ll/api/thread/GlobalThreadPauser.h" #include "ll/api/utils/WinUtils.h" -#include "pl/Hook.h" namespace ll::memory { -int hook(FuncPtr target, FuncPtr detour, FuncPtr* originalFunc, HookPriority priority, bool stopTheWorld) { +int hook(FuncPtr target, FuncPtr detour, FuncPtr* originalFunc, HookPriority priority, bool suspendThreads) { std::unique_ptr pauser; - if (stopTheWorld && getServerStatus() != ServerStatus::Default) { + if (suspendThreads && getServerStatus() != ServerStatus::Default) { pauser = std::make_unique(); } return pl::hook::pl_hook(target, detour, originalFunc, static_cast(priority)); } -bool unhook(FuncPtr target, FuncPtr detour, bool stopTheWorld) { +bool unhook(FuncPtr target, FuncPtr detour, bool suspendThreads) { std::unique_ptr pauser; - if (stopTheWorld && getServerStatus() != ServerStatus::Default) { + if (suspendThreads && getServerStatus() != ServerStatus::Default) { pauser = std::make_unique(); } return pl::hook::pl_unhook(target, detour); diff --git a/src/ll/api/memory/Hook.h b/src/ll/api/memory/Hook.h index 4020e3746f..82057536c4 100644 --- a/src/ll/api/memory/Hook.h +++ b/src/ll/api/memory/Hook.h @@ -3,10 +3,14 @@ // #define LL_HOOK_DEBUG #include +#include #include +#include +#include #include -#include "ll/api/base/Concepts.h" +#include "ll/api/base/Concepts.h" // IWYU pragma: keep +#include "ll/api/base/FixedString.h" #include "ll/api/base/Macro.h" #include "ll/api/memory/Memory.h" #include "ll/api/reflection/TypeName.h" @@ -17,7 +21,7 @@ #define LL_HOOK_DEBUG_OUTPUT(IDENTIFIER) \ static inline int debugger() { \ try { \ - static FuncPtr t = ll::memory::resolveIdentifier(IDENTIFIER); \ + static FuncPtr t = ll::memory::resolveIdentifier<_OriginFuncType>(IDENTIFIER); \ if (t == nullptr) { \ fmt::print("\x1b[91mCan't resolve: [" #IDENTIFIER "]\x1b[0m\n"); \ } else { \ @@ -52,7 +56,7 @@ template struct IsConstMemberFun : std::true_type {}; template -inline constexpr bool IsConstMemberFunV = IsConstMemberFun::value; +constexpr bool IsConstMemberFunV = IsConstMemberFun::value; template struct AddConstAtMemberFun { @@ -67,9 +71,6 @@ struct AddConstAtMemberFun { template using AddConstAtMemberFunT = typename AddConstAtMemberFun::type; -template -using AddConstAtMemberFunIfOriginIs = std::conditional_t, T>; - /** * @brief Hook priority enum. * @details The higher priority, the hook will be executed earlier @@ -82,9 +83,10 @@ enum class HookPriority : int { Lowest = 400, }; -LLAPI int hook(FuncPtr target, FuncPtr detour, FuncPtr* originalFunc, HookPriority priority, bool stopTheWorld = true); +LLAPI int +hook(FuncPtr target, FuncPtr detour, FuncPtr* originalFunc, HookPriority priority, bool suspendThreads = true); -LLAPI bool unhook(FuncPtr target, FuncPtr detour, bool stopTheWorld = true); +LLAPI bool unhook(FuncPtr target, FuncPtr detour, bool suspendThreads = true); /** * @brief Get the pointer of a function by identifier. @@ -115,11 +117,11 @@ constexpr FuncPtr resolveIdentifier(uintptr_t address) { return resolveIdentifier(address); } -template +template consteval bool virtualDetector() noexcept { return false; } -template +template consteval bool virtualDetector() noexcept { return reflection::getRawName().find("::`vcall'{") != std::string::npos; } @@ -160,30 +162,49 @@ class HookRegistrar { HookRegistrar& operator=(HookRegistrar&&) noexcept = default; }; +struct __declspec(empty_bases) Hook {}; + } // namespace ll::memory #define LL_HOOK_IMPL(REGISTER, FUNC_PTR, STATIC, CALL, DEF_TYPE, TYPE, PRIORITY, IDENTIFIER, RET_TYPE, ...) \ - struct DEF_TYPE TYPE { \ - using FuncPtr = ::ll::memory::FuncPtr; \ - using HookPriority = ::ll::memory::HookPriority; \ + struct DEF_TYPE : public TYPE { \ + using _FuncPtr = ::ll::memory::FuncPtr; \ + using HookPriority = ::ll::memory::HookPriority; \ + using _RawFuncType = RET_TYPE FUNC_PTR(__VA_ARGS__); \ + using _RawConstFuncType = ::ll::memory::AddConstAtMemberFunT<_RawFuncType>; \ + \ template \ - static constexpr bool isConstMemberFunction = \ - requires(T const&) { static_cast(IDENTIFIER); }; \ - using OriginFuncType = ::ll::memory:: \ - AddConstAtMemberFunIfOriginIs>; \ + struct _ConstDetector { \ + static constexpr bool value = false; \ + explicit constexpr _ConstDetector(T) {} \ + }; \ + template \ + [[maybe_unused]] _ConstDetector(T) -> _ConstDetector; \ + [[maybe_unused]] _ConstDetector(_RawFuncType) -> _ConstDetector<_RawFuncType>; \ + template <> \ + struct _ConstDetector<_RawConstFuncType> { \ + static constexpr bool value = true; \ + explicit constexpr _ConstDetector(_RawConstFuncType) {} \ + }; \ + template , int> = 0> \ + [[maybe_unused]] _ConstDetector(_RawConstFuncType) -> _ConstDetector<_RawConstFuncType>; \ + \ + static constexpr bool _IsConstMemberFunction = decltype(_ConstDetector{IDENTIFIER})::value; \ + \ + using _OriginFuncType = std::conditional_t<_IsConstMemberFunction, _RawConstFuncType, _RawFuncType>; \ \ - inline static FuncPtr target__{}; \ - inline static OriginFuncType originFunc__{}; \ + inline static _FuncPtr _HookTarget{}; \ + inline static _OriginFuncType _OriginalFunc{}; \ \ LL_HOOK_DEBUG_OUTPUT(IDENTIFIER); \ \ template \ static consteval void detector() { \ if constexpr (requires { \ - ::ll::memory::virtualDetector(IDENTIFIER)>(); \ - ll::memory::resolveIdentifier(IDENTIFIER); \ + ::ll::memory::virtualDetector<_OriginFuncType, IDENTIFIER>(); \ + ::ll::memory::resolveIdentifier<_OriginFuncType>(IDENTIFIER); \ }) { \ - if constexpr (::ll::memory::virtualDetector(IDENTIFIER)>()) { \ + if constexpr (::ll::memory::virtualDetector<_OriginFuncType, IDENTIFIER>()) { \ static_assert( \ ::ll::concepts::always_false, \ #IDENTIFIER " is a virtual function, for now you can't use function pointer to hook it." \ @@ -199,23 +220,23 @@ class HookRegistrar { \ STATIC RET_TYPE detour(__VA_ARGS__); \ \ - static int hook(bool stopTheWorld = true) { \ + static int hook(bool suspendThreads = true) { \ detector(); \ - target__ = ll::memory::resolveIdentifier(IDENTIFIER); \ - if (target__ == nullptr) { \ + _HookTarget = ::ll::memory::resolveIdentifier<_OriginFuncType>(IDENTIFIER); \ + if (_HookTarget == nullptr) { \ return -1; \ } \ - return ll::memory::hook( \ - target__, \ - ll::memory::toFuncPtr(&DEF_TYPE::detour), \ - reinterpret_cast(&originFunc__), \ + return ::ll::memory::hook( \ + _HookTarget, \ + ::ll::memory::toFuncPtr(&DEF_TYPE::detour), \ + reinterpret_cast<_FuncPtr*>(&_OriginalFunc), \ PRIORITY, \ - stopTheWorld \ + suspendThreads \ ); \ } \ \ - static bool unhook(bool stopTheWorld = true) { \ - return ll::memory::unhook(target__, ll::memory::toFuncPtr(&DEF_TYPE::detour), stopTheWorld); \ + static bool unhook(bool suspendThreads = true) { \ + return ::ll::memory::unhook(_HookTarget, ::ll::memory::toFuncPtr(&DEF_TYPE::detour), suspendThreads); \ } \ }; \ REGISTER; \ @@ -233,15 +254,15 @@ class HookRegistrar { #define LL_MANUAL_REG_HOOK_IMPL(...) LL_VA_EXPAND(LL_HOOK_IMPL(, __VA_ARGS__)) -#define LL_STATIC_HOOK_IMPL(...) LL_VA_EXPAND(LL_MANUAL_REG_HOOK_IMPL((*), static, originFunc__, __VA_ARGS__)) +#define LL_STATIC_HOOK_IMPL(...) LL_VA_EXPAND(LL_MANUAL_REG_HOOK_IMPL((*), static, _OriginalFunc, __VA_ARGS__)) -#define LL_AUTO_STATIC_HOOK_IMPL(...) LL_VA_EXPAND(LL_AUTO_REG_HOOK_IMPL((*), static, originFunc__, __VA_ARGS__)) +#define LL_AUTO_STATIC_HOOK_IMPL(...) LL_VA_EXPAND(LL_AUTO_REG_HOOK_IMPL((*), static, _OriginalFunc, __VA_ARGS__)) -#define LL_INSTANCE_HOOK_IMPL(DEF_TYPE, ...) \ - LL_VA_EXPAND(LL_MANUAL_REG_HOOK_IMPL((DEF_TYPE::*), , (this->*originFunc__), DEF_TYPE, __VA_ARGS__)) +#define LL_INSTANCE_HOOK_IMPL(DEF_TYPE, TYPE, ...) \ + LL_VA_EXPAND(LL_MANUAL_REG_HOOK_IMPL((TYPE::*), , (this->*_OriginalFunc), DEF_TYPE, TYPE, __VA_ARGS__)) -#define LL_AUTO_INSTANCE_HOOK_IMPL(DEF_TYPE, ...) \ - LL_VA_EXPAND(LL_AUTO_REG_HOOK_IMPL((DEF_TYPE::*), , (this->*originFunc__), DEF_TYPE, __VA_ARGS__)) +#define LL_AUTO_INSTANCE_HOOK_IMPL(DEF_TYPE, TYPE, ...) \ + LL_VA_EXPAND(LL_AUTO_REG_HOOK_IMPL((TYPE::*), , (this->*_OriginalFunc), DEF_TYPE, TYPE, __VA_ARGS__)) /** * @brief Register a hook for a typed static function. @@ -255,7 +276,7 @@ class HookRegistrar { * @note register or unregister by calling DEF_TYPE::hook() and DEF_TYPE::unhook(). */ #define LL_TYPE_STATIC_HOOK(DEF_TYPE, PRIORITY, TYPE, IDENTIFIER, RET_TYPE, ...) \ - LL_VA_EXPAND(LL_STATIC_HOOK_IMPL(DEF_TYPE, : public TYPE, PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) + LL_VA_EXPAND(LL_STATIC_HOOK_IMPL(DEF_TYPE, TYPE, PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) /** * @brief Register a hook for a static function. @@ -268,7 +289,7 @@ class HookRegistrar { * @note register or unregister by calling DEF_TYPE::hook() and DEF_TYPE::unhook(). */ #define LL_STATIC_HOOK(DEF_TYPE, PRIORITY, IDENTIFIER, RET_TYPE, ...) \ - LL_VA_EXPAND(LL_STATIC_HOOK_IMPL(DEF_TYPE, , PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) + LL_VA_EXPAND(LL_STATIC_HOOK_IMPL(DEF_TYPE, ::ll::memory::Hook, PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) /** * @brief Register a hook for a typed static function. @@ -276,7 +297,7 @@ class HookRegistrar { * @see LL_TYPE_STATIC_HOOK for usage. */ #define LL_AUTO_TYPE_STATIC_HOOK(DEF_TYPE, PRIORITY, TYPE, IDENTIFIER, RET_TYPE, ...) \ - LL_VA_EXPAND(LL_AUTO_STATIC_HOOK_IMPL(DEF_TYPE, : public TYPE, PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) + LL_VA_EXPAND(LL_AUTO_STATIC_HOOK_IMPL(DEF_TYPE, TYPE, PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) /** * @brief Register a hook for a static function. @@ -284,7 +305,7 @@ class HookRegistrar { * @see LL_STATIC_HOOK for usage. */ #define LL_AUTO_STATIC_HOOK(DEF_TYPE, PRIORITY, IDENTIFIER, RET_TYPE, ...) \ - LL_VA_EXPAND(LL_AUTO_STATIC_HOOK_IMPL(DEF_TYPE, , PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) + LL_VA_EXPAND(LL_AUTO_STATIC_HOOK_IMPL(DEF_TYPE, ::ll::memory::Hook, PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) /** * @brief Register a hook for a typed instance function. @@ -298,7 +319,7 @@ class HookRegistrar { * @note register or unregister by calling DEF_TYPE::hook() and DEF_TYPE::unhook(). */ #define LL_TYPE_INSTANCE_HOOK(DEF_TYPE, PRIORITY, TYPE, IDENTIFIER, RET_TYPE, ...) \ - LL_VA_EXPAND(LL_INSTANCE_HOOK_IMPL(DEF_TYPE, : public TYPE, PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) + LL_VA_EXPAND(LL_INSTANCE_HOOK_IMPL(DEF_TYPE, TYPE, PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) /** * @brief Register a hook for a instance function. @@ -311,7 +332,7 @@ class HookRegistrar { * @note register or unregister by calling DEF_TYPE::hook() and DEF_TYPE::unhook(). */ #define LL_INSTANCE_HOOK(DEF_TYPE, PRIORITY, IDENTIFIER, RET_TYPE, ...) \ - LL_VA_EXPAND(LL_INSTANCE_HOOK_IMPL(DEF_TYPE, , PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) + LL_VA_EXPAND(LL_INSTANCE_HOOK_IMPL(DEF_TYPE, ::ll::memory::Hook, PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) /** * @brief Register a hook for a typed instance function. @@ -319,7 +340,7 @@ class HookRegistrar { * @see LL_TYPE_INSTANCE_HOOK for usage. */ #define LL_AUTO_TYPE_INSTANCE_HOOK(DEF_TYPE, PRIORITY, TYPE, IDENTIFIER, RET_TYPE, ...) \ - LL_VA_EXPAND(LL_AUTO_INSTANCE_HOOK_IMPL(DEF_TYPE, : public TYPE, PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) + LL_VA_EXPAND(LL_AUTO_INSTANCE_HOOK_IMPL(DEF_TYPE, TYPE, PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) /** * @brief Register a hook for a instance function. @@ -327,4 +348,4 @@ class HookRegistrar { * @see LL_INSTANCE_HOOK for usage. */ #define LL_AUTO_INSTANCE_HOOK(DEF_TYPE, PRIORITY, IDENTIFIER, RET_TYPE, ...) \ - LL_VA_EXPAND(LL_AUTO_INSTANCE_HOOK_IMPL(DEF_TYPE, , PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) + LL_VA_EXPAND(LL_AUTO_INSTANCE_HOOK_IMPL(DEF_TYPE, ::ll::memory::Hook, PRIORITY, IDENTIFIER, RET_TYPE, __VA_ARGS__)) diff --git a/src/ll/api/reflection/Reflection.h b/src/ll/api/reflection/Reflection.h index 4be6d8f07e..72c8983652 100644 --- a/src/ll/api/reflection/Reflection.h +++ b/src/ll/api/reflection/Reflection.h @@ -1,12 +1,12 @@ #pragma once -#include +#include #include - -#include "ll/api/reflection/TypeName.h" +#include #include "ll/api/base/Concepts.h" #include "ll/api/base/Meta.h" +#include "ll/api/reflection/TypeName.h" #if defined(__clang__) && !defined(BOOST_PFR_CORE_NAME_PARSING) #define BOOST_PFR_CORE_NAME_PARSING \ @@ -15,6 +15,7 @@ #endif #include "boost/pfr.hpp" +#include "boost/pfr/detail/make_integer_sequence.hpp" #include "boost/pfr/detail/offset_based_getter.hpp" #include "magic_enum.hpp" diff --git a/src/ll/api/service/ServiceId.h b/src/ll/api/service/ServiceId.h index 68f36ea850..b7ecd5fb8d 100644 --- a/src/ll/api/service/ServiceId.h +++ b/src/ll/api/service/ServiceId.h @@ -46,7 +46,7 @@ constexpr ServiceId getServiceId = []() -> ServiceId { if constexpr (requires { self::ServiceId; } && self::ServiceId != EmptyServiceId) { return self::ServiceId; } else { - static_assert(false, "ServiceId not defined for type"); + static_assert(ll::concepts::always_false, "ServiceId not defined for type"); } }(); } // namespace ll::service diff --git a/src/ll/test/HookTest.cpp b/src/ll/test/HookTest.cpp new file mode 100644 index 0000000000..d511e52990 --- /dev/null +++ b/src/ll/test/HookTest.cpp @@ -0,0 +1,21 @@ +#include "ll/api/memory/Hook.h" + +#include + +namespace { +class TestClass { +protected: + int some = 0; + +public: + int test(int a, int b) const { return a + b; } + int test(int a, int b) { return a + b; } + std::string test(std::string a, std::string b) { return a + b; } +}; + +// they will choose non-const version if possible +LL_TYPE_INSTANCE_HOOK(TestHook, HookPriority::Normal, TestClass, &TestClass::test, int, int a, int b) { + some = 1; + return a + b; +} +} // namespace diff --git a/src/mc/world/level/block/utils/StaticVanillaBlocks.cpp b/src/mc/world/level/block/utils/StaticVanillaBlocks.cpp index 5a559e70aa..ccacb78011 100644 --- a/src/mc/world/level/block/utils/StaticVanillaBlocks.cpp +++ b/src/mc/world/level/block/utils/StaticVanillaBlocks.cpp @@ -1,5 +1,7 @@ #include "mc/world/level/block/utils/StaticVanillaBlocks.h" + #include "ll/api/memory/Hook.h" + #include "mc/world/level/block/registry/BlockTypeRegistry.h" #include "mc/world/level/block/utils/BedrockBlockNames.h" #include "mc/world/level/block/utils/VanillaBlockTypeIds.h" diff --git a/xmake.lua b/xmake.lua index 37cd6f6548..f051d66afa 100644 --- a/xmake.lua +++ b/xmake.lua @@ -64,6 +64,7 @@ target("LeviLamina") ) add_cxflags( "/EHs", + "-Wno-ignored-qualifiers", "-Wno-c++2b-extensions", "-Wno-microsoft-cast", "-Wno-pragma-system-header-outside-header",