diff options
-rw-r--r-- | src/vm/peimagelayout.cpp | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/src/vm/peimagelayout.cpp b/src/vm/peimagelayout.cpp index a3514e5a06..5f70363f7c 100644 --- a/src/vm/peimagelayout.cpp +++ b/src/vm/peimagelayout.cpp @@ -149,7 +149,10 @@ void PEImageLayout::ApplyBaseRelocations() SIZE_T cbWriteableRegion = 0; DWORD dwOldProtection = 0; - BOOL bRelocDone = FALSE; + BYTE * pFlushRegion = NULL; + SIZE_T cbFlushRegion = 0; + // The page size of PE file relocs is always 4096 bytes + const SIZE_T cbPageSize = 4096; COUNT_T dirPos = 0; while (dirPos < dirSize) @@ -184,13 +187,6 @@ void PEImageLayout::ApplyBaseRelocations() dwOldProtection, &dwOldProtection)) ThrowLastError(); - if (bRelocDone && bExecRegion) - { - ClrFlushInstructionCache(pWriteableRegion, cbWriteableRegion); - } - - bRelocDone = FALSE; - dwOldProtection = 0; } @@ -223,6 +219,7 @@ void PEImageLayout::ApplyBaseRelocations() } } + BYTE* pEndAddressToFlush = NULL; for (COUNT_T fixupIndex = 0; fixupIndex < fixupsCount; fixupIndex++) { USHORT fixup = VAL16(fixups[fixupIndex]); @@ -233,13 +230,13 @@ void PEImageLayout::ApplyBaseRelocations() { case IMAGE_REL_BASED_PTR: *(TADDR *)address += delta; - bRelocDone = TRUE; + pEndAddressToFlush = max(pEndAddressToFlush, address + sizeof(TADDR)); break; #ifdef _TARGET_ARM_ case IMAGE_REL_BASED_THUMB_MOV32: PutThumb2Mov32((UINT16 *)address, GetThumb2Mov32((UINT16 *)address) + delta); - bRelocDone = TRUE; + pEndAddressToFlush = max(pEndAddressToFlush, address + 8); break; #endif @@ -252,6 +249,24 @@ void PEImageLayout::ApplyBaseRelocations() } } + BOOL bExecRegion = (dwOldProtection & (PAGE_EXECUTE | PAGE_EXECUTE_READ | + PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) != 0; + + if (bExecRegion && pEndAddressToFlush != NULL) + { + // If the current page is not next to the pending region to flush, flush the current pending region and start a new one + if (pageAddress >= pFlushRegion + cbFlushRegion + cbPageSize || pageAddress < pFlushRegion) + { + if (pFlushRegion != NULL) + { + ClrFlushInstructionCache(pFlushRegion, cbFlushRegion); + } + pFlushRegion = pageAddress; + } + + cbFlushRegion = pEndAddressToFlush - pFlushRegion; + } + dirPos += fixupsSize; } _ASSERTE(dirSize == dirPos); @@ -259,18 +274,15 @@ void PEImageLayout::ApplyBaseRelocations() #ifndef CROSSGEN_COMPILE if (dwOldProtection != 0) { - BOOL bExecRegion = (dwOldProtection & (PAGE_EXECUTE | PAGE_EXECUTE_READ | - PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) != 0; - // Restore the protection if (!ClrVirtualProtect(pWriteableRegion, cbWriteableRegion, dwOldProtection, &dwOldProtection)) ThrowLastError(); + } - if (bRelocDone && bExecRegion) - { - ClrFlushInstructionCache(pWriteableRegion, cbWriteableRegion); - } + if (pFlushRegion != NULL) + { + ClrFlushInstructionCache(pFlushRegion, cbFlushRegion); } #endif // CROSSGEN_COMPILE } |