Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Vorlicek <jan.vorlicek@volny.cz>2021-06-10 16:26:40 +0300
committerGitHub <noreply@github.com>2021-06-10 16:26:40 +0300
commitd617e830ec621db80f6df9ed8ba75176f5ba6035 (patch)
treef2389aecbcca81cd24d0604263ea3bbc7ffab50c /src/coreclr/utilcode
parent7b3564a3de6c5d50515b0be31aa14e52c257a44f (diff)
Add writeable holders for executable memory (#53934)
* Add writeable holders for executable memory This change adds holders for writeable mappings for executable memory. It is the largest part of the W^X support. The ExecutableWriterHolder implementation is dummy in this change, but it was fully tested with coreclr / libraries tests on Windows arm, arm64, x64 and x86 with the real double memory mapping. There are few concepts / conventions used: * When the writeable pointer isn't known at a place where it is needed and also not at the caller, the ExecutableWriterHolder instance is created. * When a callee needs writeable pointer to executable memory and caller knows RW and RX, the argument is doubled with RX and RW suffixes. For constructors and member methods when "this" is the RW one, we pass just extra RX argument. * Locals holding RW pointer use RW suffix. * Locals holding RX pointer usually have no suffix to minimize number of changes, but in some cases they have a RX suffix where I felt like it was better to make things clear.
Diffstat (limited to 'src/coreclr/utilcode')
-rw-r--r--src/coreclr/utilcode/loaderheap.cpp30
1 files changed, 25 insertions, 5 deletions
diff --git a/src/coreclr/utilcode/loaderheap.cpp b/src/coreclr/utilcode/loaderheap.cpp
index 33974b9e290..adaf07d8f58 100644
--- a/src/coreclr/utilcode/loaderheap.cpp
+++ b/src/coreclr/utilcode/loaderheap.cpp
@@ -1330,8 +1330,14 @@ again:
if (pData)
{
#ifdef _DEBUG
+ BYTE *pAllocatedBytes = (BYTE*)pData;
+ ExecutableWriterHolder<void> dataWriterHolder;
+ if (m_Options & LHF_EXECUTABLE)
+ {
+ dataWriterHolder = ExecutableWriterHolder<void>(pData, dwSize);
+ pAllocatedBytes = (BYTE *)dataWriterHolder.GetRW();
+ }
- BYTE *pAllocatedBytes = (BYTE *)pData;
#if LOADER_HEAP_DEBUG_BOUNDARY > 0
// Don't fill the memory we allocated - it is assumed to be zeroed - fill the memory after it
memset(pAllocatedBytes + dwRequestedSize, 0xEE, LOADER_HEAP_DEBUG_BOUNDARY);
@@ -1344,7 +1350,7 @@ again:
if (!m_fExplicitControl)
{
- LoaderHeapValidationTag *pTag = AllocMem_GetTag(pData, dwRequestedSize);
+ LoaderHeapValidationTag *pTag = AllocMem_GetTag(pAllocatedBytes, dwRequestedSize);
pTag->m_allocationType = kAllocMem;
pTag->m_dwRequestedSize = dwRequestedSize;
pTag->m_szFile = szFile;
@@ -1514,7 +1520,14 @@ void UnlockedLoaderHeap::UnlockedBackoutMem(void *pMem,
{
// Cool. This was the last block allocated. We can just undo the allocation instead
// of going to the freelist.
- memset(pMem, 0x00, dwSize); // Fill freed region with 0
+ void *pMemRW = pMem;
+ ExecutableWriterHolder<void> memWriterHolder;
+ if (m_Options & LHF_EXECUTABLE)
+ {
+ memWriterHolder = ExecutableWriterHolder<void>(pMem, dwSize);
+ pMemRW = memWriterHolder.GetRW();
+ }
+ memset(pMemRW, 0x00, dwSize); // Fill freed region with 0
m_pAllocPtr = (BYTE*)pMem;
}
else
@@ -1626,7 +1639,14 @@ void *UnlockedLoaderHeap::UnlockedAllocAlignedMem_NoThrow(size_t dwRequestedSiz
((BYTE*&)pResult) += extra;
#ifdef _DEBUG
- BYTE *pAllocatedBytes = (BYTE *)pResult;
+ BYTE *pAllocatedBytes = (BYTE *)pResult;
+ ExecutableWriterHolder<void> resultWriterHolder;
+ if (m_Options & LHF_EXECUTABLE)
+ {
+ resultWriterHolder = ExecutableWriterHolder<void>(pResult, dwSize - extra);
+ pAllocatedBytes = (BYTE *)resultWriterHolder.GetRW();
+ }
+
#if LOADER_HEAP_DEBUG_BOUNDARY > 0
// Don't fill the entire memory - we assume it is all zeroed -just the memory after our alloc
memset(pAllocatedBytes + dwRequestedSize, 0xee, LOADER_HEAP_DEBUG_BOUNDARY);
@@ -1656,7 +1676,7 @@ void *UnlockedLoaderHeap::UnlockedAllocAlignedMem_NoThrow(size_t dwRequestedSiz
if (!m_fExplicitControl)
{
- LoaderHeapValidationTag *pTag = AllocMem_GetTag(((BYTE*)pResult) - extra, dwRequestedSize + extra);
+ LoaderHeapValidationTag *pTag = AllocMem_GetTag(pAllocatedBytes - extra, dwRequestedSize + extra);
pTag->m_allocationType = kAllocMem;
pTag->m_dwRequestedSize = dwRequestedSize + extra;
pTag->m_szFile = szFile;