1cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//===- Win32/Memory.cpp - Win32 Memory Implementation -----------*- C++ -*-===//
21f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer//
3cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//                     The LLVM Compiler Infrastructure
4cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
71f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer//
8cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//===----------------------------------------------------------------------===//
9cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//
10cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer// This file provides the Win32 specific implementation of various Memory
11cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer// management utilities
12cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//
13cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//===----------------------------------------------------------------------===//
14cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer
151f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/DataTypes.h"
16bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor#include "llvm/Support/ErrorHandling.h"
171f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Process.h"
18cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/Support/WindowsError.h"
198a0ff3a2659e64408c76507ff0514748b6744b06Chandler Carruth
208a0ff3a2659e64408c76507ff0514748b6744b06Chandler Carruth// The Windows.h header must be the last one included.
2136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "WindowsSupport.h"
22bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
23bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylornamespace {
24bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
25bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew KaylorDWORD getWindowsProtectionFlags(unsigned Flags) {
26bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  switch (Flags) {
27bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  // Contrary to what you might expect, the Windows page protection flags
28bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  // are not a bitwise combination of RWX values
29bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  case llvm::sys::Memory::MF_READ:
30bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    return PAGE_READONLY;
31bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  case llvm::sys::Memory::MF_WRITE:
32bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    // Note: PAGE_WRITE is not supported by VirtualProtect
33bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    return PAGE_READWRITE;
34bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_WRITE:
35bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    return PAGE_READWRITE;
36bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_EXEC:
37bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    return PAGE_EXECUTE_READ;
38bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  case llvm::sys::Memory::MF_READ |
39bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor         llvm::sys::Memory::MF_WRITE |
40bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor         llvm::sys::Memory::MF_EXEC:
41bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    return PAGE_EXECUTE_READWRITE;
42bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  case llvm::sys::Memory::MF_EXEC:
43bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    return PAGE_EXECUTE;
44bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  default:
45bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    llvm_unreachable("Illegal memory protection flag specified!");
46bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  }
47bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  // Provide a default return value as required by some compilers.
48bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  return PAGE_NOACCESS;
49bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor}
50bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
51bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylorsize_t getAllocationGranularity() {
52bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  SYSTEM_INFO  Info;
53bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  ::GetSystemInfo(&Info);
54bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  if (Info.dwPageSize > Info.dwAllocationGranularity)
55bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    return Info.dwPageSize;
56bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  else
57bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    return Info.dwAllocationGranularity;
58bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor}
59bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
60bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor} // namespace
61cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer
62cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencernamespace llvm {
63bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylornamespace sys {
64cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer
65cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//===----------------------------------------------------------------------===//
661f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer//=== WARNING: Implementation here must contain only Win32 specific code
67b016a376abc0d35ab4e77ea32a5b0421d980482bReid Spencer//===          and must not be UNIX code
68cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer//===----------------------------------------------------------------------===//
69cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer
70bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew KaylorMemoryBlock Memory::allocateMappedMemory(size_t NumBytes,
71bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor                                         const MemoryBlock *const NearBlock,
72bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor                                         unsigned Flags,
73cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                         std::error_code &EC) {
74cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  EC = std::error_code();
75bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  if (NumBytes == 0)
76bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    return MemoryBlock();
77bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
78bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  // While we'd be happy to allocate single pages, the Windows allocation
79bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  // granularity may be larger than a single page (in practice, it is 64K)
80bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  // so mapping less than that will create an unreachable fragment of memory.
81bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  static const size_t Granularity = getAllocationGranularity();
82bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  const size_t NumBlocks = (NumBytes+Granularity-1)/Granularity;
83cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer
84bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  uintptr_t Start = NearBlock ? reinterpret_cast<uintptr_t>(NearBlock->base()) +
85bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor                                NearBlock->size()
867a7fc90ba3419490c478174d78a3d1fb5373054dAlp Toker                           : 0;
87b016a376abc0d35ab4e77ea32a5b0421d980482bReid Spencer
88bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  // If the requested address is not aligned to the allocation granularity,
89bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  // round up to get beyond NearBlock. VirtualAlloc would have rounded down.
90bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  if (Start && Start % Granularity != 0)
91bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    Start += Granularity - Start % Granularity;
92a00269bc3e97d4e53ed196325ef02e6d1f3d70dcAndrew Lenharth
93bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  DWORD Protect = getWindowsProtectionFlags(Flags);
94bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
95bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  void *PA = ::VirtualAlloc(reinterpret_cast<void*>(Start),
96bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor                            NumBlocks*Granularity,
97bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor                            MEM_RESERVE | MEM_COMMIT, Protect);
98bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  if (PA == NULL) {
99c5c36765e6ff3207576571e6c75b6e44cd5e9331NAKAMURA Takumi    if (NearBlock) {
100c5c36765e6ff3207576571e6c75b6e44cd5e9331NAKAMURA Takumi      // Try again without the NearBlock hint
101bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor      return allocateMappedMemory(NumBytes, NULL, Flags, EC);
102c5c36765e6ff3207576571e6c75b6e44cd5e9331NAKAMURA Takumi    }
103cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    EC = mapWindowsError(::GetLastError());
104bed22d89020ea8a46c48bc1aa6128321a445dbb2Chris Lattner    return MemoryBlock();
105cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer  }
106b016a376abc0d35ab4e77ea32a5b0421d980482bReid Spencer
107bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  MemoryBlock Result;
108bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  Result.Address = PA;
109bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  Result.Size = NumBlocks*Granularity;
1107a7fc90ba3419490c478174d78a3d1fb5373054dAlp Toker
111bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  if (Flags & MF_EXEC)
112bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    Memory::InvalidateInstructionCache(Result.Address, Result.Size);
113bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
114bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  return Result;
115cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer}
116cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer
117cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  std::error_code Memory::releaseMappedMemory(MemoryBlock &M) {
118bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  if (M.Address == 0 || M.Size == 0)
119cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return std::error_code();
120bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
121bed22d89020ea8a46c48bc1aa6128321a445dbb2Chris Lattner  if (!VirtualFree(M.Address, 0, MEM_RELEASE))
122cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return mapWindowsError(::GetLastError());
123bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
124bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  M.Address = 0;
125bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  M.Size = 0;
126bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
127cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return std::error_code();
128bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor}
129bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
130cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  std::error_code Memory::protectMappedMemory(const MemoryBlock &M,
131bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor                                       unsigned Flags) {
132bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  if (M.Address == 0 || M.Size == 0)
133cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return std::error_code();
134bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
135bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  DWORD Protect = getWindowsProtectionFlags(Flags);
136bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
137bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  DWORD OldFlags;
138bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  if (!VirtualProtect(M.Address, M.Size, Protect, &OldFlags))
139cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return mapWindowsError(::GetLastError());
140bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
141bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  if (Flags & MF_EXEC)
142bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    Memory::InvalidateInstructionCache(M.Address, M.Size);
143bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
144cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return std::error_code();
145bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor}
146bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
147bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor/// InvalidateInstructionCache - Before the JIT can run a block of code
148bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor/// that has been emitted it must invalidate the instruction cache on some
149bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor/// platforms.
150bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylorvoid Memory::InvalidateInstructionCache(
151bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    const void *Addr, size_t Len) {
152bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  FlushInstructionCache(GetCurrentProcess(), Addr, Len);
153bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor}
154bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
155bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
156bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew KaylorMemoryBlock Memory::AllocateRWX(size_t NumBytes,
157bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor                                const MemoryBlock *NearBlock,
158bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor                                std::string *ErrMsg) {
159bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  MemoryBlock MB;
160cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  std::error_code EC;
161bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  MB = allocateMappedMemory(NumBytes, NearBlock,
162bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor                            MF_READ|MF_WRITE|MF_EXEC, EC);
163cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (EC != std::error_code() && ErrMsg) {
164bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    MakeErrMsg(ErrMsg, EC.message());
165bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  }
166bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  return MB;
167bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor}
168bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor
169bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylorbool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) {
170cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  std::error_code EC = releaseMappedMemory(M);
171cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (EC == std::error_code())
172bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor    return false;
173bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  MakeErrMsg(ErrMsg, EC.message());
174bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  return true;
175cbad701d0b6fd42112e121e2d7af9c70aaee7440Reid Spencer}
176b016a376abc0d35ab4e77ea32a5b0421d980482bReid Spencer
1772dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencerstatic DWORD getProtection(const void *addr) {
1782dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  MEMORY_BASIC_INFORMATION info;
1792dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  if (sizeof(info) == ::VirtualQuery(addr, &info, sizeof(info))) {
1802dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer    return info.Protect;
1812dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  }
1822dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  return 0;
1832dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer}
1842dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer
185932a32d2512353478d16c4101582adff404a55a5Jim Grosbachbool Memory::setWritable(MemoryBlock &M, std::string *ErrMsg) {
1862dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  if (!setRangeWritable(M.Address, M.Size)) {
1872dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer    return MakeErrMsg(ErrMsg, "Cannot set memory to writeable: ");
1882dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  }
189c8a07733d3cb1ed13963e9da3e8958bed0e3018dArgyrios Kyrtzidis  return true;
190c8a07733d3cb1ed13963e9da3e8958bed0e3018dArgyrios Kyrtzidis}
191c8a07733d3cb1ed13963e9da3e8958bed0e3018dArgyrios Kyrtzidis
192932a32d2512353478d16c4101582adff404a55a5Jim Grosbachbool Memory::setExecutable(MemoryBlock &M, std::string *ErrMsg) {
1932dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  if (!setRangeExecutable(M.Address, M.Size)) {
1942dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer    return MakeErrMsg(ErrMsg, "Cannot set memory to executable: ");
1952dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  }
1962dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  return true;
197c8a07733d3cb1ed13963e9da3e8958bed0e3018dArgyrios Kyrtzidis}
198c8a07733d3cb1ed13963e9da3e8958bed0e3018dArgyrios Kyrtzidis
199932a32d2512353478d16c4101582adff404a55a5Jim Grosbachbool Memory::setRangeWritable(const void *Addr, size_t Size) {
2002dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  DWORD prot = getProtection(Addr);
2012dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  if (!prot)
2022dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer    return false;
2032dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer
2042dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  if (prot == PAGE_EXECUTE || prot == PAGE_EXECUTE_READ) {
2052dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer    prot = PAGE_EXECUTE_READWRITE;
2062dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  } else if (prot == PAGE_NOACCESS || prot == PAGE_READONLY) {
2072dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer    prot = PAGE_READWRITE;
2082dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  }
2092dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer
2102dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  DWORD oldProt;
211bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  Memory::InvalidateInstructionCache(Addr, Size);
2122dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  return ::VirtualProtect(const_cast<LPVOID>(Addr), Size, prot, &oldProt)
2132dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer            == TRUE;
214b016a376abc0d35ab4e77ea32a5b0421d980482bReid Spencer}
215b016a376abc0d35ab4e77ea32a5b0421d980482bReid Spencer
216932a32d2512353478d16c4101582adff404a55a5Jim Grosbachbool Memory::setRangeExecutable(const void *Addr, size_t Size) {
2172dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  DWORD prot = getProtection(Addr);
2182dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  if (!prot)
2192dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer    return false;
2202dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer
2212dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  if (prot == PAGE_NOACCESS) {
2222dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer    prot = PAGE_EXECUTE;
2232dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  } else if (prot == PAGE_READONLY) {
2242dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer    prot = PAGE_EXECUTE_READ;
2252dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  } else if (prot == PAGE_READWRITE) {
2262dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer    prot = PAGE_EXECUTE_READWRITE;
2272dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  }
2282dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer
2292dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  DWORD oldProt;
230bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor  Memory::InvalidateInstructionCache(Addr, Size);
2312dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer  return ::VirtualProtect(const_cast<LPVOID>(Addr), Size, prot, &oldProt)
2322dd0cfe118dc133721364515f7db4d1f22652ae3Michael J. Spencer            == TRUE;
233932a32d2512353478d16c4101582adff404a55a5Jim Grosbach}
234932a32d2512353478d16c4101582adff404a55a5Jim Grosbach
235bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor} // namespace sys
236bbf628b6cefc8d817eb9ec04c2a357ad3f27d618Andrew Kaylor} // namespace llvm
237