diff options
Diffstat (limited to 'lib/Support/Windows')
| -rw-r--r-- | lib/Support/Windows/Memory.inc | 167 | ||||
| -rw-r--r-- | lib/Support/Windows/Path.inc | 2 | ||||
| -rw-r--r-- | lib/Support/Windows/PathV2.inc | 6 | ||||
| -rw-r--r-- | lib/Support/Windows/Process.inc | 87 | ||||
| -rw-r--r-- | lib/Support/Windows/Program.inc | 26 | ||||
| -rw-r--r-- | lib/Support/Windows/Signals.inc | 2 |
6 files changed, 201 insertions, 89 deletions
diff --git a/lib/Support/Windows/Memory.inc b/lib/Support/Windows/Memory.inc index fcc7283..4c5aebd 100644 --- a/lib/Support/Windows/Memory.inc +++ b/lib/Support/Windows/Memory.inc @@ -12,51 +12,165 @@ // //===----------------------------------------------------------------------===// -#include "Windows.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Process.h" +// The Windows.h header must be the last one included. +#include "Windows.h" + +namespace { + +DWORD getWindowsProtectionFlags(unsigned Flags) { + switch (Flags) { + // Contrary to what you might expect, the Windows page protection flags + // are not a bitwise combination of RWX values + case llvm::sys::Memory::MF_READ: + return PAGE_READONLY; + case llvm::sys::Memory::MF_WRITE: + // Note: PAGE_WRITE is not supported by VirtualProtect + return PAGE_READWRITE; + case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_WRITE: + return PAGE_READWRITE; + case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_EXEC: + return PAGE_EXECUTE_READ; + case llvm::sys::Memory::MF_READ | + llvm::sys::Memory::MF_WRITE | + llvm::sys::Memory::MF_EXEC: + return PAGE_EXECUTE_READWRITE; + case llvm::sys::Memory::MF_EXEC: + return PAGE_EXECUTE; + default: + llvm_unreachable("Illegal memory protection flag specified!"); + } + // Provide a default return value as required by some compilers. + return PAGE_NOACCESS; +} + +size_t getAllocationGranularity() { + SYSTEM_INFO Info; + ::GetSystemInfo(&Info); + if (Info.dwPageSize > Info.dwAllocationGranularity) + return Info.dwPageSize; + else + return Info.dwAllocationGranularity; +} + +} // namespace + namespace llvm { -using namespace sys; +namespace sys { //===----------------------------------------------------------------------===// //=== WARNING: Implementation here must contain only Win32 specific code //=== and must not be UNIX code //===----------------------------------------------------------------------===// -MemoryBlock Memory::AllocateRWX(size_t NumBytes, - const MemoryBlock *NearBlock, - std::string *ErrMsg) { - if (NumBytes == 0) return MemoryBlock(); +MemoryBlock Memory::allocateMappedMemory(size_t NumBytes, + const MemoryBlock *const NearBlock, + unsigned Flags, + error_code &EC) { + EC = error_code::success(); + if (NumBytes == 0) + return MemoryBlock(); + + // While we'd be happy to allocate single pages, the Windows allocation + // granularity may be larger than a single page (in practice, it is 64K) + // so mapping less than that will create an unreachable fragment of memory. + static const size_t Granularity = getAllocationGranularity(); + const size_t NumBlocks = (NumBytes+Granularity-1)/Granularity; - static const size_t pageSize = Process::GetPageSize(); - size_t NumPages = (NumBytes+pageSize-1)/pageSize; + uintptr_t Start = NearBlock ? reinterpret_cast<uintptr_t>(NearBlock->base()) + + NearBlock->size() + : NULL; - PVOID start = NearBlock ? static_cast<unsigned char *>(NearBlock->base()) + - NearBlock->size() : NULL; + // If the requested address is not aligned to the allocation granularity, + // round up to get beyond NearBlock. VirtualAlloc would have rounded down. + if (Start && Start % Granularity != 0) + Start += Granularity - Start % Granularity; - void *pa = VirtualAlloc(start, NumPages*pageSize, MEM_RESERVE | MEM_COMMIT, - PAGE_EXECUTE_READWRITE); - if (pa == NULL) { + DWORD Protect = getWindowsProtectionFlags(Flags); + + void *PA = ::VirtualAlloc(reinterpret_cast<void*>(Start), + NumBlocks*Granularity, + MEM_RESERVE | MEM_COMMIT, Protect); + if (PA == NULL) { if (NearBlock) { // Try again without the NearBlock hint - return AllocateRWX(NumBytes, NULL, ErrMsg); + return allocateMappedMemory(NumBytes, NULL, Flags, EC); } - MakeErrMsg(ErrMsg, "Can't allocate RWX Memory: "); + EC = error_code(::GetLastError(), system_category()); return MemoryBlock(); } - MemoryBlock result; - result.Address = pa; - result.Size = NumPages*pageSize; - return result; + MemoryBlock Result; + Result.Address = PA; + Result.Size = NumBlocks*Granularity; + ; + if (Flags & MF_EXEC) + Memory::InvalidateInstructionCache(Result.Address, Result.Size); + + return Result; } -bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { - if (M.Address == 0 || M.Size == 0) return false; +error_code Memory::releaseMappedMemory(MemoryBlock &M) { + if (M.Address == 0 || M.Size == 0) + return error_code::success(); + if (!VirtualFree(M.Address, 0, MEM_RELEASE)) - return MakeErrMsg(ErrMsg, "Can't release RWX Memory: "); - return false; + return error_code(::GetLastError(), system_category()); + + M.Address = 0; + M.Size = 0; + + return error_code::success(); +} + +error_code Memory::protectMappedMemory(const MemoryBlock &M, + unsigned Flags) { + if (M.Address == 0 || M.Size == 0) + return error_code::success(); + + DWORD Protect = getWindowsProtectionFlags(Flags); + + DWORD OldFlags; + if (!VirtualProtect(M.Address, M.Size, Protect, &OldFlags)) + return error_code(::GetLastError(), system_category()); + + if (Flags & MF_EXEC) + Memory::InvalidateInstructionCache(M.Address, M.Size); + + return error_code::success(); +} + +/// InvalidateInstructionCache - Before the JIT can run a block of code +/// that has been emitted it must invalidate the instruction cache on some +/// platforms. +void Memory::InvalidateInstructionCache( + const void *Addr, size_t Len) { + FlushInstructionCache(GetCurrentProcess(), Addr, Len); +} + + +MemoryBlock Memory::AllocateRWX(size_t NumBytes, + const MemoryBlock *NearBlock, + std::string *ErrMsg) { + MemoryBlock MB; + error_code EC; + MB = allocateMappedMemory(NumBytes, NearBlock, + MF_READ|MF_WRITE|MF_EXEC, EC); + if (EC != error_code::success() && ErrMsg) { + MakeErrMsg(ErrMsg, EC.message()); + } + return MB; +} + +bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { + error_code EC = releaseMappedMemory(M); + if (EC == error_code::success()) + return false; + MakeErrMsg(ErrMsg, EC.message()); + return true; } static DWORD getProtection(const void *addr) { @@ -93,7 +207,7 @@ bool Memory::setRangeWritable(const void *Addr, size_t Size) { } DWORD oldProt; - sys::Memory::InvalidateInstructionCache(Addr, Size); + Memory::InvalidateInstructionCache(Addr, Size); return ::VirtualProtect(const_cast<LPVOID>(Addr), Size, prot, &oldProt) == TRUE; } @@ -112,9 +226,10 @@ bool Memory::setRangeExecutable(const void *Addr, size_t Size) { } DWORD oldProt; - sys::Memory::InvalidateInstructionCache(Addr, Size); + Memory::InvalidateInstructionCache(Addr, Size); return ::VirtualProtect(const_cast<LPVOID>(Addr), Size, prot, &oldProt) == TRUE; } -} +} // namespace sys +} // namespace llvm diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc index 2280b34..98d8a18 100644 --- a/lib/Support/Windows/Path.inc +++ b/lib/Support/Windows/Path.inc @@ -17,8 +17,8 @@ //===----------------------------------------------------------------------===// #include "Windows.h" -#include <malloc.h> #include <cstdio> +#include <malloc.h> // We need to undo a macro defined in Windows.h, otherwise we won't compile: #undef CopyFile diff --git a/lib/Support/Windows/PathV2.inc b/lib/Support/Windows/PathV2.inc index 696768b..2e6cc96 100644 --- a/lib/Support/Windows/PathV2.inc +++ b/lib/Support/Windows/PathV2.inc @@ -328,7 +328,7 @@ error_code resize_file(const Twine &path, uint64_t size) { path_utf16)) return ec; - int fd = ::_wopen(path_utf16.begin(), O_BINARY, S_IREAD | S_IWRITE); + int fd = ::_wopen(path_utf16.begin(), O_BINARY | _O_RDWR, S_IWRITE); if (fd == -1) return error_code(errno, generic_category()); #ifdef HAVE__CHSIZE_S @@ -794,7 +794,7 @@ mapped_file_region::mapped_file_region(const Twine &path, SmallVector<wchar_t, 128> path_utf16; // Convert path to UTF-16. - if (ec = UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) + if ((ec = UTF8ToUTF16(path.toStringRef(path_storage), path_utf16))) return; // Get file handle for creating a file mapping. @@ -861,7 +861,7 @@ mapped_file_region::~mapped_file_region() { ::CloseHandle(FileHandle); } -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES mapped_file_region::mapped_file_region(mapped_file_region &&other) : Mode(other.Mode) , Size(other.Size) diff --git a/lib/Support/Windows/Process.inc b/lib/Support/Windows/Process.inc index e29eb6d..ad94128 100644 --- a/lib/Support/Windows/Process.inc +++ b/lib/Support/Windows/Process.inc @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "Windows.h" -#include <psapi.h> -#include <malloc.h> -#include <io.h> #include <direct.h> +#include <io.h> +#include <malloc.h> +#include <psapi.h> #ifdef __MINGW32__ #if (HAVE_LIBPSAPI != 1) @@ -35,13 +35,47 @@ # define _HEAPOK (-2) #endif -namespace llvm { +using namespace llvm; using namespace sys; + +process::id_type self_process::get_id() { + return GetCurrentProcess(); +} + +static TimeValue getTimeValueFromFILETIME(FILETIME Time) { + ULARGE_INTEGER TimeInteger; + TimeInteger.LowPart = Time.dwLowDateTime; + TimeInteger.HighPart = Time.dwHighDateTime; + + // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) + return TimeValue( + static_cast<TimeValue::SecondsType>(TimeInteger.QuadPart / 10000000), + static_cast<TimeValue::NanoSecondsType>( + (TimeInteger.QuadPart % 10000000) * 100)); +} + +TimeValue self_process::get_user_time() const { + FILETIME ProcCreate, ProcExit, KernelTime, UserTime; + if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, + &UserTime) == 0) + return TimeValue(); + + return getTimeValueFromFILETIME(UserTime); +} + +TimeValue self_process::get_system_time() const { + FILETIME ProcCreate, ProcExit, KernelTime, UserTime; + if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, + &UserTime) == 0) + return TimeValue(); + + return getTimeValueFromFILETIME(KernelTime); +} + // This function retrieves the page size using GetSystemInfo and is present -// solely so it can be called once in Process::GetPageSize to initialize the -// static variable PageSize. -inline unsigned GetPageSizeOnce() { +// solely so it can be called once to initialize the self_process member below. +static unsigned getPageSize() { // NOTE: A 32-bit application running under WOW64 is supposed to use // GetNativeSystemInfo. However, this interface is not present prior // to Windows XP so to use it requires dynamic linking. It is not clear @@ -52,12 +86,12 @@ inline unsigned GetPageSizeOnce() { return static_cast<unsigned>(info.dwPageSize); } -unsigned -Process::GetPageSize() { - static const unsigned PageSize = GetPageSizeOnce(); - return PageSize; +// This constructor guaranteed to be run exactly once on a single thread, and +// sets up various process invariants that can be queried cheaply from then on. +self_process::self_process() : PageSize(getPageSize()) { } + size_t Process::GetMallocUsage() { @@ -72,30 +106,17 @@ Process::GetMallocUsage() return size; } -size_t -Process::GetTotalMemoryUsage() -{ - PROCESS_MEMORY_COUNTERS pmc; - GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); - return pmc.PagefileUsage; -} - -void -Process::GetTimeUsage( - TimeValue& elapsed, TimeValue& user_time, TimeValue& sys_time) -{ +void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, + TimeValue &sys_time) { elapsed = TimeValue::now(); - uint64_t ProcCreate, ProcExit, KernelTime, UserTime; - GetProcessTimes(GetCurrentProcess(), (FILETIME*)&ProcCreate, - (FILETIME*)&ProcExit, (FILETIME*)&KernelTime, - (FILETIME*)&UserTime); + FILETIME ProcCreate, ProcExit, KernelTime, UserTime; + if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, + &UserTime) == 0) + return; - // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) - user_time.seconds( UserTime / 10000000 ); - user_time.nanoseconds( unsigned(UserTime % 10000000) * 100 ); - sys_time.seconds( KernelTime / 10000000 ); - sys_time.nanoseconds( unsigned(KernelTime % 10000000) * 100 ); + user_time = getTimeValueFromFILETIME(UserTime); + sys_time = getTimeValueFromFILETIME(KernelTime); } int Process::GetCurrentUserId() @@ -255,5 +276,3 @@ const char *Process::ResetColor() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors()); return 0; } - -} diff --git a/lib/Support/Windows/Program.inc b/lib/Support/Windows/Program.inc index 80ccaa6..691d6d4 100644 --- a/lib/Support/Windows/Program.inc +++ b/lib/Support/Windows/Program.inc @@ -13,9 +13,9 @@ #include "Windows.h" #include <cstdio> -#include <malloc.h> -#include <io.h> #include <fcntl.h> +#include <io.h> +#include <malloc.h> //===----------------------------------------------------------------------===// //=== WARNING: Implementation here must contain only Win32 specific code @@ -43,11 +43,6 @@ Program::~Program() { } } -unsigned Program::GetPid() const { - Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_); - return wpi->dwProcessId; -} - // This function just uses the PATH environment variable to find the program. Path Program::FindProgramByName(const std::string& progName) { @@ -380,23 +375,6 @@ Program::Wait(const Path &path, return 1; } -bool -Program::Kill(std::string* ErrMsg) { - if (Data_ == 0) { - MakeErrMsg(ErrMsg, "Process not started!"); - return true; - } - - Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_); - HANDLE hProcess = wpi->hProcess; - if (TerminateProcess(hProcess, 1) == 0) { - MakeErrMsg(ErrMsg, "The process couldn't be killed!"); - return true; - } - - return false; -} - error_code Program::ChangeStdinToBinary(){ int result = _setmode( _fileno(stdin), _O_BINARY ); if (result == -1) diff --git a/lib/Support/Windows/Signals.inc b/lib/Support/Windows/Signals.inc index 38308f6..a969753 100644 --- a/lib/Support/Windows/Signals.inc +++ b/lib/Support/Windows/Signals.inc @@ -12,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "Windows.h" +#include <algorithm> #include <stdio.h> #include <vector> -#include <algorithm> #ifdef __MINGW32__ #include <imagehlp.h> |
