SectionAllocWrapper.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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 _WIN32
  7. namespace Memory
  8. {
  9. struct SectionInfo
  10. {
  11. HANDLE handle;
  12. void * runtimeBaseAddress;
  13. };
  14. // multi level map, modeled after HeapBlockMap
  15. class SectionMap32
  16. {
  17. #if TARGET_64
  18. friend class SectionMap64;
  19. #endif
  20. public:
  21. #if TARGET_64
  22. SectionMap32(__in char * startAddress);
  23. #else
  24. SectionMap32();
  25. #endif
  26. ~SectionMap32();
  27. bool SetSection(void * address, uint pageCount, SectionInfo * section);
  28. SectionInfo * GetSection(void * address);
  29. void ClearSection(void * address, uint pageCount);
  30. private:
  31. #if TARGET_64
  32. static const size_t TotalSize = 0x100000000; // 4GB
  33. #endif
  34. static const uint L1Count = 4096;
  35. static const uint L2Count = 256;
  36. static uint GetLevel1Id(void * address)
  37. {
  38. return ::Math::PointerCastToIntegralTruncate<uint>(address) / L2Count / AutoSystemInfo::PageSize;
  39. }
  40. static uint GetLevel2Id(void * address)
  41. {
  42. return ::Math::PointerCastToIntegralTruncate<uint>(address) % (L2Count * AutoSystemInfo::PageSize) / AutoSystemInfo::PageSize;
  43. }
  44. bool EnsureSection(void * address, uint pageCount);
  45. void SetSectionNoCheck(void * address, uint pageCount, SectionInfo * section);
  46. void Cleanup();
  47. class L2MapChunk
  48. {
  49. public:
  50. SectionInfo * Get(void * address);
  51. void Set(uint id2, uint pageCount, SectionInfo * section);
  52. void Clear(uint id2, uint pageCount);
  53. bool IsEmpty() const;
  54. ~L2MapChunk();
  55. private:
  56. SectionInfo * map[L2Count];
  57. };
  58. uint count;
  59. L2MapChunk * map[L1Count];
  60. #if TARGET_64
  61. // On 64 bit, this structure only maps one particular 32 bit space, always 4GB aligned
  62. char * startAddress;
  63. #endif
  64. };
  65. #if TARGET_64
  66. class SectionMap64
  67. {
  68. public:
  69. SectionMap64();
  70. ~SectionMap64();
  71. bool SetSection(void * address, uint pageCount, SectionInfo * section);
  72. SectionInfo * GetSection(void * address);
  73. void ClearSection(void * address, uint pageCount);
  74. private:
  75. bool EnsureSection(void * address, size_t pageCount);
  76. void SetSectionNoCheck(void * address, size_t pageCount, SectionInfo * section);
  77. static const uint PagesPer4GB = 1 << 20; // = 1M, assume page size = 4K
  78. struct Node
  79. {
  80. Node(__in char * startAddress) : map(startAddress) { }
  81. uint nodeIndex;
  82. Node * next;
  83. SectionMap32 map;
  84. };
  85. Node * FindOrInsertNode(void * address);
  86. Node * FindNode(void * address) const;
  87. template <class Fn>
  88. void ForEachNodeInAddressRange(void * address, size_t pageCount, Fn fn);
  89. Node * list;
  90. static uint GetNodeIndex(void * address)
  91. {
  92. return GetNodeIndex((ULONG64)address);
  93. }
  94. static uint GetNodeIndex(ULONG64 address)
  95. {
  96. return (uint)((ULONG64)address >> 32);
  97. }
  98. static char * GetNodeStartAddress(void * address)
  99. {
  100. return (char *)(((size_t)address) & ~(SectionMap32::TotalSize - 1));
  101. }
  102. };
  103. typedef SectionMap64 SectionMap;
  104. #else
  105. typedef SectionMap32 SectionMap;
  106. #endif // TARGET_64
  107. class SectionAllocWrapper
  108. {
  109. public:
  110. SectionAllocWrapper(HANDLE process);
  111. LPVOID Alloc(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation);
  112. BOOL Free(LPVOID lpAddress, size_t dwSize, DWORD dwFreeType);
  113. LPVOID AllocLocal(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize);
  114. BOOL FreeLocal(LPVOID lpAddress);
  115. private:
  116. HANDLE process;
  117. SectionMap sections;
  118. };
  119. class PreReservedSectionAllocWrapper
  120. {
  121. public:
  122. #if _M_IX86_OR_ARM32
  123. static const uint PreReservedAllocationSegmentCount = 256; // (256 * 64K) == 16 MB, if 64k is the AllocationGranularity
  124. #else // _M_X64_OR_ARM64
  125. static const uint PreReservedAllocationSegmentCount = 4096; //(4096 * 64K) == 256MB, if 64k is the AllocationGranularity
  126. #endif
  127. #if !_M_X64_OR_ARM64 && _CONTROL_FLOW_GUARD
  128. static const unsigned MaxPreReserveSegment = 6;
  129. #endif
  130. PreReservedSectionAllocWrapper(HANDLE process);
  131. ~PreReservedSectionAllocWrapper();
  132. LPVOID Alloc(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation);
  133. BOOL Free(LPVOID lpAddress, size_t dwSize, DWORD dwFreeType);
  134. LPVOID AllocLocal(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize);
  135. BOOL FreeLocal(LPVOID lpAddress);
  136. bool IsInRange(void * address);
  137. static bool IsInRange(void * regionStart, void * address);
  138. LPVOID EnsurePreReservedRegion();
  139. LPVOID GetPreReservedEndAddress();
  140. static LPVOID GetPreReservedEndAddress(void * regionStart);
  141. #if !_M_X64_OR_ARM64 && _CONTROL_FLOW_GUARD
  142. static int NumPreReservedSegment() { return numPreReservedSegment; }
  143. #endif
  144. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  145. bool IsPreReservedEndAddress(LPVOID address)
  146. {
  147. return IsPreReservedRegionPresent() && address == GetPreReservedEndAddress();
  148. }
  149. #endif
  150. private:
  151. LPVOID EnsurePreReservedRegionInternal();
  152. bool IsPreReservedRegionPresent();
  153. LPVOID GetPreReservedStartAddress();
  154. BVStatic<PreReservedAllocationSegmentCount> freeSegments;
  155. LPVOID preReservedStartAddress;
  156. CriticalSection cs;
  157. #if !_M_X64_OR_ARM64 && _CONTROL_FLOW_GUARD
  158. static uint numPreReservedSegment;
  159. #endif
  160. HANDLE process;
  161. HANDLE section;
  162. };
  163. } // namespace Memory
  164. #endif