1 --- lib/Support/Unix/Memory.inc
2 +++ lib/Support/Unix/Memory.inc
5 Result.Size = NumPages*PageSize;
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();
19 return std::error_code(EINVAL, std::generic_category());
21 int Protect = getPosixProtectionFlags(Flags);
23 uintptr_t Start = alignAddr((uint8_t *)M.Address - PageSize + 1, PageSize);
24 uintptr_t End = alignAddr((uint8_t *)M.Address + M.Size, PageSize);
26 + bool InvalidateCache = (Flags & MF_EXEC);
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);
35 + return std::error_code(errno, std::generic_category());
37 + Memory::InvalidateInstructionCache(M.Address, M.Size);
38 + InvalidateCache = false;
42 int Result = ::mprotect((void *)Start, End - Start, Protect);
45 return std::error_code(errno, std::generic_category());
47 - if (Flags & MF_EXEC)
48 + if (InvalidateCache)
49 Memory::InvalidateInstructionCache(M.Address, M.Size);
51 return std::error_code();