Skip to content

Commit 6b2fd7d

Browse files
committed
use new file mapping API where available
1 parent a8582a3 commit 6b2fd7d

2 files changed

Lines changed: 159 additions & 89 deletions

File tree

Build/Chakra.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
%(PreprocessorDefinitions);
2929
BYTECODE_TESTING=1
3030
</PreprocessorDefinitions>
31+
<PreprocessorDefinitions Condition="'$(NTDDIVersion)'!=''" >%(PreprocessorDefinitions);NTDDI_VERSION=$(NTDDIVersion)</PreprocessorDefinitions>
3132
<!-- REVIEW: These are warning are introduced when moving to VS2015 tools, may want to clean these up -->
3233
<DisableSpecificWarnings>
3334
%(DisableSpecificWarnings);

lib/Common/Memory/SectionAllocWrapper.cpp

Lines changed: 158 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,112 @@
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+
1016
namespace 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)
13117
SectionMap32::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

407511
static const uint SectionAlignment = 65536;
408512

409-
LPVOID
513+
PVOID
410514
AllocLocalView(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

437529
BOOL
438530
FreeLocalView(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(&sectionHandle, 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

525617
LPVOID
@@ -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(&sectionHandle, 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(&sectionHandle, 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

Comments
 (0)