summaryrefslogtreecommitdiff
path: root/packaging/0035-PEImageLayout-flush-instruction-cache-only-for-pages.patch
blob: e986952668489cd972264e9e8b3b3328b2507c25 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
From c5539d864c61476446542bee351af3a125118ef3 Mon Sep 17 00:00:00 2001
From: Konstantin Baladurin <k.baladurin@partner.samsung.com>
Date: Mon, 14 May 2018 12:35:09 +0300
Subject: [PATCH 35/47] PEImageLayout: flush instruction cache only for pages
 with relocs.

We need to flush instruction cache only for pages that have relocations
instead of full sections because otherwise application's shared clean
memory is increased in some cases on Linux.
---
 src/vm/peimagelayout.cpp | 46 +++++++++++++++++++++++++++++-----------------
 1 file changed, 29 insertions(+), 17 deletions(-)

diff --git a/src/vm/peimagelayout.cpp b/src/vm/peimagelayout.cpp
index 4bfbe40..5e0243b 100644
--- a/src/vm/peimagelayout.cpp
+++ b/src/vm/peimagelayout.cpp
@@ -150,7 +150,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)
@@ -185,13 +188,6 @@ void PEImageLayout::ApplyBaseRelocations()
                                        dwOldProtection, &dwOldProtection))
                     ThrowLastError();
 
-                if (bRelocDone && bExecRegion)
-                {
-                    ClrFlushInstructionCache(pWriteableRegion, cbWriteableRegion);
-                }
-
-                bRelocDone = FALSE;
-
                 dwOldProtection = 0;
             }
 
@@ -224,6 +220,7 @@ void PEImageLayout::ApplyBaseRelocations()
             }
         }
 
+        BYTE* pEndAddressToFlush = NULL;
         for (COUNT_T fixupIndex = 0; fixupIndex < fixupsCount; fixupIndex++)
         {
             USHORT fixup = VAL16(fixups[fixupIndex]);
@@ -234,13 +231,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
 
@@ -253,24 +250,39 @@ 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);
 
     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 // FEATURE_PREJIT
-- 
2.7.4