77#if _WIN32
88#include " ../Core/DelayLoadLibrary.h"
99
10+ #ifdef NTDDI_WIN10_RS2
11+ #if (NTDDI_VERSION >= NTDDI_WIN10_RS2)
12+ #define USEFILEMAP2 1
13+ #endif
14+ #endif
15+
1016namespace Memory
1117{
18+
19+ void CloseSectionHandle (HANDLE handle)
20+ {
21+ #if USEFILEMAP2
22+ CloseHandle (handle);
23+ #else
24+ NtdllLibrary::Instance->Close (handle);
25+ #endif
26+ }
27+
28+ HANDLE CreateSection (size_t sectionSize, bool commit)
29+ {
30+ const ULONG allocAttributes = commit ? SEC_COMMIT : SEC_RESERVE;
31+ #if USEFILEMAP2
32+ #if TARGET_32
33+ DWORD sizeHigh = 0 ;
34+ #elif TARGET_64
35+ DWORD sizeHigh = (DWORD)(sectionSize >> 32 );
36+ #endif
37+ HANDLE handle = CreateFileMapping (INVALID_HANDLE_VALUE, NULL , PAGE_EXECUTE_READWRITE | allocAttributes, sizeHigh, (DWORD)sectionSize, NULL );
38+ if (handle == nullptr )
39+ {
40+ return nullptr ;
41+ }
42+ #else
43+ NtdllLibrary::OBJECT_ATTRIBUTES attr;
44+ NtdllLibrary::Instance->InitializeObjectAttributes (&attr, NULL , NtdllLibrary::OBJ_KERNEL_HANDLE, NULL , NULL );
45+ LARGE_INTEGER size = { 0 };
46+ #if TARGET_32
47+ size.LowPart = sectionSize;
48+ #elif TARGET_64
49+ size.QuadPart = sectionSize;
50+ #endif
51+ HANDLE handle = nullptr ;
52+ int status = NtdllLibrary::Instance->CreateSection (&handle, SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_QUERY | SECTION_MAP_EXECUTE, &attr, &size, PAGE_EXECUTE_READWRITE, allocAttributes, NULL );
53+ if (status != 0 )
54+ {
55+ return nullptr ;
56+ }
57+ #endif
58+ return handle;
59+ }
60+
61+ void UnmapView (HANDLE process, PVOID address)
62+ {
63+ #if USEFILEMAP2
64+ UnmapViewOfFile2 (process, address, 0 );
65+ #else
66+ NtdllLibrary::Instance->UnmapViewOfSection (process, address);
67+ #endif
68+ }
69+
70+ PVOID MapView (HANDLE process, HANDLE sectionHandle, size_t size, size_t offset, bool local)
71+ {
72+ PVOID address = nullptr ;
73+ DWORD flags = 0 ;
74+ if (local)
75+ {
76+ if (process != GetCurrentProcess ())
77+ {
78+ return nullptr ;
79+ }
80+ flags = PAGE_READWRITE;
81+ }
82+ else
83+ {
84+ if (process == GetCurrentProcess ())
85+ {
86+ return nullptr ;
87+ }
88+ flags = AutoSystemInfo::Data.IsCFGEnabled () ? PAGE_EXECUTE_RO_TARGETS_INVALID : PAGE_EXECUTE;
89+ }
90+
91+ #if USEFILEMAP2
92+ address = MapViewOfFile2 (sectionHandle, process, offset, nullptr , size, NULL , flags);
93+ if (local && address != nullptr )
94+ {
95+ address = VirtualAlloc (address, size, MEM_COMMIT, flags);
96+ }
97+ #else
98+ LARGE_INTEGER mapOffset = { 0 };
99+ #if TARGET_32
100+ mapOffset.LowPart = offset;
101+ #elif TARGET_64
102+ mapOffset.QuadPart = offset;
103+ #else
104+ CompileAssert (UNREACHED);
105+ #endif
106+ SIZE_T viewSize = size;
107+ int status = NtdllLibrary::Instance->MapViewOfSection (sectionHandle, process, &address, NULL , viewSize, &mapOffset, &viewSize, NtdllLibrary::ViewUnmap, NULL , flags);
108+ if (status != 0 )
109+ {
110+ return nullptr ;
111+ }
112+ #endif
113+ return address;
114+ }
115+
12116#if defined(_M_X64_OR_ARM64)
13117SectionMap32::SectionMap32 (__in char * startAddress) :
14118 startAddress(startAddress),
@@ -177,7 +281,7 @@ SectionMap32::L2MapChunk::~L2MapChunk()
177281 if (map[i] != nullptr )
178282 {
179283 // in case runtime process has abnormal termination, map may not be empty
180- NtdllLibrary::Instance-> Close (map[i]->handle );
284+ CloseSectionHandle (map[i]->handle );
181285 HeapDelete (map[i]);
182286 }
183287 }
@@ -406,39 +510,27 @@ SectionMap64::FindNode(void * address) const
406510
407511static const uint SectionAlignment = 65536 ;
408512
409- LPVOID
513+ PVOID
410514AllocLocalView (HANDLE sectionHandle, LPVOID remoteBaseAddr, LPVOID remoteRequestAddress, size_t requestSize)
411515{
412516 const size_t offset = (uintptr_t )remoteRequestAddress - (uintptr_t )remoteBaseAddr;
413- LARGE_INTEGER mapOffset = { 0 };
414517 const size_t offsetAlignment = offset % SectionAlignment;
415- #if TARGET_32
416- mapOffset.LowPart = offset - offsetAlignment;
417- #elif TARGET_64
418- mapOffset.QuadPart = offset - offsetAlignment;
419- #else
420- CompileAssert (UNREACHED);
421- #endif
422- LPVOID address = nullptr ;
423- SIZE_T viewSize = requestSize + offsetAlignment;
424- int status = NtdllLibrary::Instance->MapViewOfSection (sectionHandle, GetCurrentProcess (), &address, NULL , viewSize, &mapOffset, &viewSize, NtdllLibrary::ViewUnmap, NULL , PAGE_READWRITE);
425- if (status != 0 || address == nullptr )
426- {
427- return nullptr ;
428- }
429- if (viewSize < requestSize)
518+ const size_t alignedOffset = offset - offsetAlignment;
519+ const size_t viewSize = requestSize + offsetAlignment;
520+
521+ PVOID address = MapView (GetCurrentProcess (), sectionHandle, viewSize, alignedOffset, true );
522+ if (address == nullptr )
430523 {
431- NtdllLibrary::Instance->UnmapViewOfSection (GetCurrentProcess (), address);
432524 return nullptr ;
433525 }
434- return (LPVOID )((uintptr_t )address + offsetAlignment);
526+ return (PVOID )((uintptr_t )address + offsetAlignment);
435527}
436528
437529BOOL
438530FreeLocalView (LPVOID lpAddress)
439531{
440532 const size_t alignment = (uintptr_t )lpAddress % SectionAlignment;
441- NtdllLibrary::Instance-> UnmapViewOfSection (GetCurrentProcess (), (LPVOID)((uintptr_t )lpAddress - alignment));
533+ UnmapView (GetCurrentProcess (), (LPVOID)((uintptr_t )lpAddress - alignment));
442534 return TRUE ;
443535}
444536
@@ -459,49 +551,33 @@ SectionAllocWrapper::Alloc(LPVOID requestAddress, size_t dwSize, DWORD allocatio
459551 // REVIEW: is this needed?
460552 AutoEnableDynamicCodeGen enableCodeGen (true );
461553#endif
462-
463- const DWORD allocProtectFlags = AutoSystemInfo::Data. IsCFGEnabled () ? PAGE_EXECUTE_RO_TARGETS_INVALID : PAGE_EXECUTE ;
554+ HANDLE sectionHandle = nullptr ;
555+ SectionInfo * section = nullptr ;
464556
465557 // for new allocations, create new section and fully map it (reserved) into runtime process
466558 if (requestAddress == nullptr )
467559 {
468- NtdllLibrary::OBJECT_ATTRIBUTES attr;
469- NtdllLibrary::Instance->InitializeObjectAttributes (&attr, NULL , NtdllLibrary::OBJ_KERNEL_HANDLE, NULL , NULL );
470- LARGE_INTEGER size = { 0 };
471- #if TARGET_32
472- size.LowPart = dwSize;
473- #elif TARGET_64
474- size.QuadPart = dwSize;
475- #endif
476- HANDLE sectionHandle = nullptr ;
477- const ULONG allocAttributes = ((allocationType & MEM_COMMIT) == MEM_COMMIT) ? SEC_COMMIT : SEC_RESERVE;
478- int status = NtdllLibrary::Instance->CreateSection (§ionHandle, SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_QUERY | SECTION_MAP_EXECUTE, &attr, &size, PAGE_EXECUTE_READWRITE, allocAttributes, NULL );
479- if (status != 0 )
560+ sectionHandle = CreateSection (dwSize, ((allocationType & MEM_COMMIT) == MEM_COMMIT));
561+ if (sectionHandle == nullptr )
480562 {
481- return nullptr ;
563+ goto FailureCleanup ;
482564 }
483-
484- SIZE_T viewSize = 0 ;
485- status = NtdllLibrary::Instance->MapViewOfSection (sectionHandle, this ->process , &address, NULL , NULL , NULL , &viewSize, NtdllLibrary::ViewUnmap, NULL , allocProtectFlags);
486- if (status != 0 || address == nullptr )
565+ address = MapView (this ->process , sectionHandle, 0 , 0 , false );
566+ if (address == nullptr )
487567 {
488- NtdllLibrary::Instance->Close (sectionHandle);
489- return nullptr ;
568+ goto FailureCleanup;
490569 }
491- SectionInfo * section = HeapNewNoThrowStruct (SectionInfo);
492- if (!section)
570+
571+ section = HeapNewNoThrowStruct (SectionInfo);
572+ if (section == nullptr )
493573 {
494- NtdllLibrary::Instance->Close (sectionHandle);
495- return nullptr ;
574+ goto FailureCleanup;
496575 }
497576 section->handle = sectionHandle;
498577 section->runtimeBaseAddress = address;
499- if (viewSize < dwSize || !sections.SetSection (address, (uint)(dwSize / AutoSystemInfo::PageSize), section))
578+ if (!sections.SetSection (address, (uint)(dwSize / AutoSystemInfo::PageSize), section))
500579 {
501- HeapDelete (section);
502- NtdllLibrary::Instance->Close (sectionHandle);
503- NtdllLibrary::Instance->UnmapViewOfSection (this ->process , address);
504- return nullptr ;
580+ goto FailureCleanup;
505581 }
506582 }
507583 else
@@ -514,12 +590,28 @@ SectionAllocWrapper::Alloc(LPVOID requestAddress, size_t dwSize, DWORD allocatio
514590
515591 if ((allocationType & MEM_COMMIT) == MEM_COMMIT)
516592 {
593+ const DWORD allocProtectFlags = AutoSystemInfo::Data.IsCFGEnabled () ? PAGE_EXECUTE_RO_TARGETS_INVALID : PAGE_EXECUTE;
517594 address = VirtualAllocEx (this ->process , address, dwSize, MEM_COMMIT, allocProtectFlags);
518595 }
519-
520596 }
521597
522598 return address;
599+
600+ FailureCleanup:
601+ // if section allocation failed, free whatever we started to allocate
602+ if (sectionHandle != nullptr )
603+ {
604+ CloseSectionHandle (sectionHandle);
605+ }
606+ if (address != nullptr )
607+ {
608+ UnmapView (this ->process , address);
609+ }
610+ if (section != nullptr )
611+ {
612+ HeapDelete (section);
613+ }
614+ return nullptr ;
523615}
524616
525617LPVOID
@@ -547,8 +639,8 @@ BOOL SectionAllocWrapper::Free(LPVOID lpAddress, size_t dwSize, DWORD dwFreeType
547639 Assert (section->runtimeBaseAddress == lpAddress);
548640 sections.ClearSection (lpAddress, (uint)(dwSize / AutoSystemInfo::PageSize));
549641
550- NtdllLibrary::Instance-> UnmapViewOfSection (this ->process , lpAddress);
551- NtdllLibrary::Instance-> Close (section->handle );
642+ UnmapView (this ->process , lpAddress);
643+ CloseSectionHandle (section->handle );
552644 }
553645 else
554646 {
@@ -595,8 +687,8 @@ PreReservedSectionAllocWrapper::~PreReservedSectionAllocWrapper()
595687{
596688 if (IsPreReservedRegionPresent ())
597689 {
598- NtdllLibrary::Instance-> UnmapViewOfSection (this ->process , this ->preReservedStartAddress );
599- NtdllLibrary::Instance-> Close (this ->section );
690+ UnmapView (this ->process , this ->preReservedStartAddress );
691+ CloseSectionHandle (this ->section );
600692 PreReservedHeapTrace (_u (" MEM_RELEASE the PreReservedSegment. Start Address: 0x%p, Size: 0x%x * 0x%x bytes" ), this ->preReservedStartAddress , PreReservedAllocationSegmentCount,
601693 AutoSystemInfo::Data.GetAllocationGranularityPageSize ());
602694#if !_M_X64_OR_ARM64 && _CONTROL_FLOW_GUARD
@@ -691,30 +783,18 @@ LPVOID PreReservedSectionAllocWrapper::EnsurePreReservedRegionInternal()
691783 return startAddress;
692784 }
693785
694- const DWORD allocProtectFlags = AutoSystemInfo::Data.IsCFGEnabled () ? PAGE_EXECUTE_RO_TARGETS_INVALID : PAGE_EXECUTE;
695786 size_t bytes = PreReservedAllocationSegmentCount * AutoSystemInfo::Data.GetAllocationGranularityPageSize ();
696787 if (PHASE_FORCE1 (Js::PreReservedHeapAllocPhase))
697788 {
698- NtdllLibrary::OBJECT_ATTRIBUTES attr;
699- NtdllLibrary::Instance->InitializeObjectAttributes (&attr, NULL , NtdllLibrary::OBJ_KERNEL_HANDLE, NULL , NULL );
700- LARGE_INTEGER size = { 0 };
701- #if TARGET_32
702- size.LowPart = bytes;
703- #elif TARGET_64
704- size.QuadPart = bytes;
705- #endif
706- HANDLE sectionHandle = nullptr ;
707- int status = NtdllLibrary::Instance->CreateSection (§ionHandle, SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_QUERY | SECTION_MAP_EXECUTE, &attr, &size, PAGE_EXECUTE_READWRITE, SEC_RESERVE, NULL );
708- if (status != 0 )
789+ HANDLE sectionHandle = CreateSection (bytes, false );
790+ if (sectionHandle == nullptr )
709791 {
710792 return nullptr ;
711793 }
712-
713- SIZE_T viewSize = 0 ;
714- status = NtdllLibrary::Instance->MapViewOfSection (sectionHandle, this ->process , &startAddress, NULL , 0 , NULL , &viewSize, NtdllLibrary::ViewUnmap, NULL , allocProtectFlags);
715- if (status != 0 || startAddress == nullptr )
794+ startAddress = MapView (this ->process , sectionHandle, 0 , 0 , false );
795+ if (startAddress == nullptr )
716796 {
717- NtdllLibrary::Instance-> Close (sectionHandle);
797+ CloseSectionHandle (sectionHandle);
718798 return nullptr ;
719799 }
720800 PreReservedHeapTrace (_u (" Reserving PreReservedSegment For the first time(CFG Non-Enabled). Address: 0x%p\n " ), this ->preReservedStartAddress );
@@ -745,26 +825,15 @@ LPVOID PreReservedSectionAllocWrapper::EnsurePreReservedRegionInternal()
745825
746826 if (AutoSystemInfo::Data.IsCFGEnabled () && supportPreReservedRegion)
747827 {
748- NtdllLibrary::OBJECT_ATTRIBUTES attr;
749- NtdllLibrary::Instance->InitializeObjectAttributes (&attr, NULL , NtdllLibrary::OBJ_KERNEL_HANDLE, NULL , NULL );
750- LARGE_INTEGER size = { 0 };
751- #if TARGET_32
752- size.LowPart = bytes;
753- #elif TARGET_64
754- size.QuadPart = bytes;
755- #endif
756- HANDLE sectionHandle = nullptr ;
757- int status = NtdllLibrary::Instance->CreateSection (§ionHandle, SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_QUERY | SECTION_MAP_EXECUTE, &attr, &size, PAGE_EXECUTE_READWRITE, SEC_RESERVE, NULL );
758- if (status != 0 )
828+ HANDLE sectionHandle = CreateSection (bytes, false );
829+ if (sectionHandle == nullptr )
759830 {
760831 return nullptr ;
761832 }
762-
763- SIZE_T viewSize = 0 ;
764- status = NtdllLibrary::Instance->MapViewOfSection (sectionHandle, this ->process , &startAddress, NULL , 0 , NULL , &viewSize, NtdllLibrary::ViewUnmap, NULL , allocProtectFlags);
765- if (status != 0 || startAddress == nullptr )
833+ startAddress = MapView (this ->process , sectionHandle, 0 , 0 , false );
834+ if (startAddress == nullptr )
766835 {
767- NtdllLibrary::Instance-> Close (sectionHandle);
836+ CloseSectionHandle (sectionHandle);
768837 return nullptr ;
769838 }
770839 PreReservedHeapTrace (_u (" Reserving PreReservedSegment For the first time(CFG Enabled). Address: 0x%p\n " ), this ->preReservedStartAddress );
0 commit comments