// SPDX-License-Identifier: MIT #pragma once #include #include #include #include #include #include namespace FEXCore::Core { struct InternalThreadState; } namespace FEXCore::Context { class Context; } namespace FEX::Windows { /** * @brief Handles SMC and regular code invalidation */ class InvalidationTracker { public: InvalidationTracker(FEXCore::Context::Context& CTX, const std::unordered_map& Threads); void HandleMemoryProtectionNotification(uint64_t Address, uint64_t Size, ULONG Prot); void HandleImageMap(std::string_view Name, uint64_t Address); struct InvalidateContainingSectionResult { uint64_t SectionStart; uint64_t SectionSize; }; InvalidateContainingSectionResult InvalidateContainingSection(uint64_t Address, bool Free); void InvalidateAlignedInterval(uint64_t Address, uint64_t Size, bool Free); void ReprotectRWXIntervals(uint64_t Address, uint64_t Size); bool HandleRWXAccessViolation(FEXCore::Core::InternalThreadState* Thread, uint64_t HostPC, uint64_t FaultAddress); // Unprotects any RWX intervals in the input interval and invalidates code // NOTE: CodeInvalidationMutex must be locked when calling this, and if true is returned, kept locked until the write ends. bool BeginUntrackedWriteLocked(uint64_t Address, uint64_t Size); FEXCore::HLE::ExecutableRangeInfo QueryExecutableRange(uint64_t Address); private: void DetectMonoBackpatcherBlock(FEXCore::Core::InternalThreadState* Thread, uint64_t HostPC); void DisableSMCDetection(); void InvalidateIntervalInternal(uint64_t Address, uint64_t Size); // NOTE: This assumed CodeInvalidationMutex is locked by the caller void InvalidateIntervalInternalLocked(uint64_t Address, uint64_t Size); // NOTE: If ForWriteLocked is true then this assumes CodeInvalidationMutex is locked by the caller, // and any code in the range will be invalidated before protection as RWX, otherwise protects as RX if false. bool ProtectRWXIntervalsInternal(uint64_t Address, uint64_t Size, bool ForWriteLocked); FEXCore::IntervalList XIntervals; FEXCore::IntervalList RWXIntervals; std::shared_mutex IntervalsLock; FEXCore::Context::Context& CTX; const std::unordered_map& Threads; bool SMCDetectionDisabled {false}; // Protected by IntervalsLock bool MonoBackpatcherDetectionPending {false}; uint64_t MonoBase {0}; uint64_t MonoEnd {0}; }; } // namespace FEX::Windows