//------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #pragma once #if defined(ENABLE_NATIVE_CODEGEN) && defined(_CONTROL_FLOW_GUARD) && !defined(_M_ARM) template class JITThunkEmitter { private: #if _M_IX86 || _M_AMD64 static const BYTE DirectJmp[]; static const uint DirectJmpTargetOffset = 1; static const uint DirectJmpIPAdjustment = 5; #endif #if _M_AMD64 static const BYTE IndirectJmp[]; static const uint IndirectJmpTargetOffset = 2; #endif #if _M_ARM64 static const DWORD DirectB[]; static const DWORD IndirectBR[]; static const uint IndirectBRTempReg = 17; static const uint IndirectBRLo16Offset = 0; static const uint IndirectBRMid16Offset = 1; static const uint IndirectBRHi16Offset = 2; #endif static const uint PageCount = 100; static const size_t ThunkSize = 16; static const size_t ThunksPerPage = AutoSystemInfo::PageSize / ThunkSize; public: static const uintptr_t ThunkAlignmentMask = ~(ThunkSize-1); static const uint TotalThunkSize = AutoSystemInfo::PageSize * PageCount; static const size_t TotalThunkCount = TotalThunkSize / ThunkSize; private: CriticalSection cs; TAlloc * codeAllocator; uintptr_t baseAddress; HANDLE processHandle; BVStatic freeThunks; ThreadContextInfo * threadContext; BVIndex firstBitToCheck; public: JITThunkEmitter(ThreadContextInfo * threadContext, TAlloc * codeAllocator, HANDLE processHandle); ~JITThunkEmitter(); uintptr_t CreateThunk(uintptr_t entryPoint); void FreeThunk(uintptr_t thunkAddress); uintptr_t EnsureInitialized(); bool IsInThunk(uintptr_t address) const; static bool IsInThunk(uintptr_t thunkBaseAddress, uintptr_t address); private: uintptr_t GetThunkAddressFromIndex(BVIndex index) const; BVIndex GetThunkIndexFromAddress(uintptr_t index) const; void ProtectPage(void * address); void UnprotectPage(void * address); bool IsThunkPageEmpty(uintptr_t address) const; static void EncodeJmp(char * localPageAddress, uintptr_t thunkAddress, uintptr_t targetAddress); static uintptr_t GetThunkPageStart(uintptr_t address); }; #if ENABLE_OOP_NATIVE_CODEGEN typedef JITThunkEmitter OOPJITThunkEmitter; #endif typedef JITThunkEmitter InProcJITThunkEmitter; #endif