JITThunkEmitter.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. #if defined(ENABLE_NATIVE_CODEGEN) && defined(_CONTROL_FLOW_GUARD) && !defined(_M_ARM)
  7. template <typename TAlloc>
  8. class JITThunkEmitter
  9. {
  10. private:
  11. #if _M_IX86 || _M_AMD64
  12. static const BYTE DirectJmp[];
  13. static const uint DirectJmpTargetOffset = 1;
  14. static const uint DirectJmpIPAdjustment = 5;
  15. #endif
  16. #if _M_AMD64
  17. static const BYTE IndirectJmp[];
  18. static const uint IndirectJmpTargetOffset = 2;
  19. #endif
  20. #if _M_ARM64
  21. static const DWORD DirectB[];
  22. static const DWORD IndirectBR[];
  23. static const uint IndirectBRTempReg = 17;
  24. static const uint IndirectBRLo16Offset = 0;
  25. static const uint IndirectBRMid16Offset = 1;
  26. static const uint IndirectBRHi16Offset = 2;
  27. #endif
  28. static const uint PageCount = 100;
  29. static const size_t ThunkSize = 16;
  30. static const size_t ThunksPerPage = AutoSystemInfo::PageSize / ThunkSize;
  31. public:
  32. static const uintptr_t ThunkAlignmentMask = ~(ThunkSize-1);
  33. static const uint TotalThunkSize = AutoSystemInfo::PageSize * PageCount;
  34. static const size_t TotalThunkCount = TotalThunkSize / ThunkSize;
  35. private:
  36. CriticalSection cs;
  37. TAlloc * codeAllocator;
  38. uintptr_t baseAddress;
  39. HANDLE processHandle;
  40. BVStatic<TotalThunkCount> freeThunks;
  41. ThreadContextInfo * threadContext;
  42. BVIndex firstBitToCheck;
  43. public:
  44. JITThunkEmitter(ThreadContextInfo * threadContext, TAlloc * codeAllocator, HANDLE processHandle);
  45. ~JITThunkEmitter();
  46. uintptr_t CreateThunk(uintptr_t entryPoint);
  47. void FreeThunk(uintptr_t thunkAddress);
  48. uintptr_t EnsureInitialized();
  49. bool IsInThunk(uintptr_t address) const;
  50. static bool IsInThunk(uintptr_t thunkBaseAddress, uintptr_t address);
  51. private:
  52. uintptr_t GetThunkAddressFromIndex(BVIndex index) const;
  53. BVIndex GetThunkIndexFromAddress(uintptr_t index) const;
  54. void ProtectPage(void * address);
  55. void UnprotectPage(void * address);
  56. bool IsThunkPageEmpty(uintptr_t address) const;
  57. static void EncodeJmp(char * localPageAddress, uintptr_t thunkAddress, uintptr_t targetAddress);
  58. static uintptr_t GetThunkPageStart(uintptr_t address);
  59. };
  60. #if ENABLE_OOP_NATIVE_CODEGEN
  61. typedef JITThunkEmitter<SectionAllocWrapper> OOPJITThunkEmitter;
  62. #endif
  63. typedef JITThunkEmitter<VirtualAllocWrapper> InProcJITThunkEmitter;
  64. #endif