at 22.05-pre 1.7 kB view raw
1--- lib/Support/Unix/Memory.inc 2+++ lib/Support/Unix/Memory.inc 3@@ -126,8 +126,12 @@ 4 Result.Address = Addr; 5 Result.Size = NumPages*PageSize; 6 7- if (PFlags & MF_EXEC) 8- Memory::InvalidateInstructionCache(Result.Address, Result.Size); 9+ // Rely on protectMappedMemory to invalidate instruction cache. 10+ if (PFlags & MF_EXEC) { 11+ EC = Memory::protectMappedMemory (Result, PFlags); 12+ if (EC != std::error_code()) 13+ return MemoryBlock(); 14+ } 15 16 return Result; 17 } 18@@ -156,15 +160,31 @@ 19 return std::error_code(EINVAL, std::generic_category()); 20 21 int Protect = getPosixProtectionFlags(Flags); 22- 23 uintptr_t Start = alignAddr((uint8_t *)M.Address - PageSize + 1, PageSize); 24 uintptr_t End = alignAddr((uint8_t *)M.Address + M.Size, PageSize); 25+ 26+ bool InvalidateCache = (Flags & MF_EXEC); 27+ 28+#if defined(__arm__) || defined(__aarch64__) 29+ // Certain ARM implementations treat icache clear instruction as a memory read, 30+ // and CPU segfaults on trying to clear cache on !PROT_READ page. Therefore we need 31+ // to temporarily add PROT_READ for the sake of flushing the instruction caches. 32+ if (InvalidateCache && !(Protect & PROT_READ)) { 33+ int Result = ::mprotect((void *)Start, End - Start, Protect | PROT_READ); 34+ if (Result != 0) 35+ return std::error_code(errno, std::generic_category()); 36+ 37+ Memory::InvalidateInstructionCache(M.Address, M.Size); 38+ InvalidateCache = false; 39+ } 40+#endif 41+ 42 int Result = ::mprotect((void *)Start, End - Start, Protect); 43 44 if (Result != 0) 45 return std::error_code(errno, std::generic_category()); 46 47- if (Flags & MF_EXEC) 48+ if (InvalidateCache) 49 Memory::InvalidateInstructionCache(M.Address, M.Size); 50 51 return std::error_code();