Home | History | Annotate | Download | only in Windows
      1 //===- Win32/Process.cpp - Win32 Process Implementation ------- -*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file provides the Win32 specific implementation of the Process class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "llvm/Support/Allocator.h"
     15 #include "llvm/Support/ErrorHandling.h"
     16 #include "llvm/Support/WindowsError.h"
     17 #include <malloc.h>
     18 
     19 // The Windows.h header must be after LLVM and standard headers.
     20 #include "WindowsSupport.h"
     21 
     22 #include <direct.h>
     23 #include <io.h>
     24 #include <psapi.h>
     25 #include <shellapi.h>
     26 
     27 #ifdef __MINGW32__
     28  #if (HAVE_LIBPSAPI != 1)
     29   #error "libpsapi.a should be present"
     30  #endif
     31  #if (HAVE_LIBSHELL32 != 1)
     32   #error "libshell32.a should be present"
     33  #endif
     34 #else
     35  #pragma comment(lib, "psapi.lib")
     36  #pragma comment(lib, "shell32.lib")
     37 #endif
     38 
     39 //===----------------------------------------------------------------------===//
     40 //=== WARNING: Implementation here must contain only Win32 specific code
     41 //===          and must not be UNIX code
     42 //===----------------------------------------------------------------------===//
     43 
     44 #ifdef __MINGW32__
     45 // This ban should be lifted when MinGW 1.0+ has defined this value.
     46 #  define _HEAPOK (-2)
     47 #endif
     48 
     49 using namespace llvm;
     50 using namespace sys;
     51 
     52 // This function retrieves the page size using GetNativeSystemInfo() and is
     53 // present solely so it can be called once to initialize the self_process member
     54 // below.
     55 static unsigned computePageSize() {
     56   // GetNativeSystemInfo() provides the physical page size which may differ
     57   // from GetSystemInfo() in 32-bit applications running under WOW64.
     58   SYSTEM_INFO info;
     59   GetNativeSystemInfo(&info);
     60   // FIXME: FileOffset in MapViewOfFile() should be aligned to not dwPageSize,
     61   // but dwAllocationGranularity.
     62   return static_cast<unsigned>(info.dwPageSize);
     63 }
     64 
     65 unsigned Process::getPageSize() {
     66   static unsigned Ret = computePageSize();
     67   return Ret;
     68 }
     69 
     70 size_t
     71 Process::GetMallocUsage()
     72 {
     73   _HEAPINFO hinfo;
     74   hinfo._pentry = NULL;
     75 
     76   size_t size = 0;
     77 
     78   while (_heapwalk(&hinfo) == _HEAPOK)
     79     size += hinfo._size;
     80 
     81   return size;
     82 }
     83 
     84 void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time,
     85                            std::chrono::nanoseconds &sys_time) {
     86   elapsed = std::chrono::system_clock::now();;
     87 
     88   FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
     89   if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
     90                       &UserTime) == 0)
     91     return;
     92 
     93   user_time = toDuration(UserTime);
     94   sys_time = toDuration(KernelTime);
     95 }
     96 
     97 // Some LLVM programs such as bugpoint produce core files as a normal part of
     98 // their operation. To prevent the disk from filling up, this configuration
     99 // item does what's necessary to prevent their generation.
    100 void Process::PreventCoreFiles() {
    101   // Windows does have the concept of core files, called minidumps.  However,
    102   // disabling minidumps for a particular application extends past the lifetime
    103   // of that application, which is the incorrect behavior for this API.
    104   // Additionally, the APIs require elevated privileges to disable and re-
    105   // enable minidumps, which makes this untenable. For more information, see
    106   // WerAddExcludedApplication and WerRemoveExcludedApplication (Vista and
    107   // later).
    108   //
    109   // Windows also has modal pop-up message boxes.  As this method is used by
    110   // bugpoint, preventing these pop-ups is additionally important.
    111   SetErrorMode(SEM_FAILCRITICALERRORS |
    112                SEM_NOGPFAULTERRORBOX |
    113                SEM_NOOPENFILEERRORBOX);
    114 
    115   coreFilesPrevented = true;
    116 }
    117 
    118 /// Returns the environment variable \arg Name's value as a string encoded in
    119 /// UTF-8. \arg Name is assumed to be in UTF-8 encoding.
    120 Optional<std::string> Process::GetEnv(StringRef Name) {
    121   // Convert the argument to UTF-16 to pass it to _wgetenv().
    122   SmallVector<wchar_t, 128> NameUTF16;
    123   if (windows::UTF8ToUTF16(Name, NameUTF16))
    124     return None;
    125 
    126   // Environment variable can be encoded in non-UTF8 encoding, and there's no
    127   // way to know what the encoding is. The only reliable way to look up
    128   // multibyte environment variable is to use GetEnvironmentVariableW().
    129   SmallVector<wchar_t, MAX_PATH> Buf;
    130   size_t Size = MAX_PATH;
    131   do {
    132     Buf.reserve(Size);
    133     Size =
    134         GetEnvironmentVariableW(NameUTF16.data(), Buf.data(), Buf.capacity());
    135     if (Size == 0)
    136       return None;
    137 
    138     // Try again with larger buffer.
    139   } while (Size > Buf.capacity());
    140   Buf.set_size(Size);
    141 
    142   // Convert the result from UTF-16 to UTF-8.
    143   SmallVector<char, MAX_PATH> Res;
    144   if (windows::UTF16ToUTF8(Buf.data(), Size, Res))
    145     return None;
    146   return std::string(Res.data());
    147 }
    148 
    149 static void AllocateAndPush(const SmallVectorImpl<char> &S,
    150                             SmallVectorImpl<const char *> &Vector,
    151                             SpecificBumpPtrAllocator<char> &Allocator) {
    152   char *Buffer = Allocator.Allocate(S.size() + 1);
    153   ::memcpy(Buffer, S.data(), S.size());
    154   Buffer[S.size()] = '\0';
    155   Vector.push_back(Buffer);
    156 }
    157 
    158 /// Convert Arg from UTF-16 to UTF-8 and push it onto Args.
    159 static std::error_code
    160 ConvertAndPushArg(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
    161                   SpecificBumpPtrAllocator<char> &Allocator) {
    162   SmallVector<char, MAX_PATH> ArgString;
    163   if (std::error_code ec = windows::UTF16ToUTF8(Arg, wcslen(Arg), ArgString))
    164     return ec;
    165   AllocateAndPush(ArgString, Args, Allocator);
    166   return std::error_code();
    167 }
    168 
    169 /// \brief Perform wildcard expansion of Arg, or just push it into Args if it
    170 /// doesn't have wildcards or doesn't match any files.
    171 static std::error_code
    172 WildcardExpand(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
    173                SpecificBumpPtrAllocator<char> &Allocator) {
    174   if (!wcspbrk(Arg, L"*?")) {
    175     // Arg does not contain any wildcard characters. This is the common case.
    176     return ConvertAndPushArg(Arg, Args, Allocator);
    177   }
    178 
    179   if (wcscmp(Arg, L"/?") == 0 || wcscmp(Arg, L"-?") == 0) {
    180     // Don't wildcard expand /?. Always treat it as an option.
    181     return ConvertAndPushArg(Arg, Args, Allocator);
    182   }
    183 
    184   // Extract any directory part of the argument.
    185   SmallVector<char, MAX_PATH> Dir;
    186   if (std::error_code ec = windows::UTF16ToUTF8(Arg, wcslen(Arg), Dir))
    187     return ec;
    188   sys::path::remove_filename(Dir);
    189   const int DirSize = Dir.size();
    190 
    191   // Search for matching files.
    192   // FIXME:  This assumes the wildcard is only in the file name and not in the
    193   // directory portion of the file path.  For example, it doesn't handle
    194   // "*\foo.c" nor "s?c\bar.cpp".
    195   WIN32_FIND_DATAW FileData;
    196   HANDLE FindHandle = FindFirstFileW(Arg, &FileData);
    197   if (FindHandle == INVALID_HANDLE_VALUE) {
    198     return ConvertAndPushArg(Arg, Args, Allocator);
    199   }
    200 
    201   std::error_code ec;
    202   do {
    203     SmallVector<char, MAX_PATH> FileName;
    204     ec = windows::UTF16ToUTF8(FileData.cFileName, wcslen(FileData.cFileName),
    205                               FileName);
    206     if (ec)
    207       break;
    208 
    209     // Append FileName to Dir, and remove it afterwards.
    210     llvm::sys::path::append(Dir, StringRef(FileName.data(), FileName.size()));
    211     AllocateAndPush(Dir, Args, Allocator);
    212     Dir.resize(DirSize);
    213   } while (FindNextFileW(FindHandle, &FileData));
    214 
    215   FindClose(FindHandle);
    216   return ec;
    217 }
    218 
    219 static std::error_code
    220 ExpandShortFileName(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
    221                     SpecificBumpPtrAllocator<char> &Allocator) {
    222   SmallVector<wchar_t, MAX_PATH> LongPath;
    223   DWORD Length = GetLongPathNameW(Arg, LongPath.data(), LongPath.capacity());
    224   if (Length == 0)
    225     return mapWindowsError(GetLastError());
    226   if (Length > LongPath.capacity()) {
    227     // We're not going to try to deal with paths longer than MAX_PATH, so we'll
    228     // treat this as an error.  GetLastError() returns ERROR_SUCCESS, which
    229     // isn't useful, so we'll hardcode an appropriate error value.
    230     return mapWindowsError(ERROR_INSUFFICIENT_BUFFER);
    231   }
    232   LongPath.set_size(Length);
    233   return ConvertAndPushArg(LongPath.data(), Args, Allocator);
    234 }
    235 
    236 std::error_code
    237 Process::GetArgumentVector(SmallVectorImpl<const char *> &Args,
    238                            ArrayRef<const char *>,
    239                            SpecificBumpPtrAllocator<char> &ArgAllocator) {
    240   int ArgCount;
    241   wchar_t **UnicodeCommandLine =
    242       CommandLineToArgvW(GetCommandLineW(), &ArgCount);
    243   if (!UnicodeCommandLine)
    244     return mapWindowsError(::GetLastError());
    245 
    246   Args.reserve(ArgCount);
    247   std::error_code ec;
    248 
    249   // The first argument may contain just the name of the executable (e.g.,
    250   // "clang") rather than the full path, so swap it with the full path.
    251   wchar_t ModuleName[MAX_PATH];
    252   int Length = ::GetModuleFileNameW(NULL, ModuleName, MAX_PATH);
    253   if (0 < Length && Length < MAX_PATH)
    254     UnicodeCommandLine[0] = ModuleName;
    255 
    256   // If the first argument is a shortened (8.3) name (which is possible even
    257   // if we got the module name), the driver will have trouble distinguishing it
    258   // (e.g., clang.exe v. clang++.exe), so expand it now.
    259   ec = ExpandShortFileName(UnicodeCommandLine[0], Args, ArgAllocator);
    260 
    261   for (int i = 1; i < ArgCount && !ec; ++i) {
    262     ec = WildcardExpand(UnicodeCommandLine[i], Args, ArgAllocator);
    263     if (ec)
    264       break;
    265   }
    266 
    267   LocalFree(UnicodeCommandLine);
    268   return ec;
    269 }
    270 
    271 std::error_code Process::FixupStandardFileDescriptors() {
    272   return std::error_code();
    273 }
    274 
    275 std::error_code Process::SafelyCloseFileDescriptor(int FD) {
    276   if (::close(FD) < 0)
    277     return std::error_code(errno, std::generic_category());
    278   return std::error_code();
    279 }
    280 
    281 bool Process::StandardInIsUserInput() {
    282   return FileDescriptorIsDisplayed(0);
    283 }
    284 
    285 bool Process::StandardOutIsDisplayed() {
    286   return FileDescriptorIsDisplayed(1);
    287 }
    288 
    289 bool Process::StandardErrIsDisplayed() {
    290   return FileDescriptorIsDisplayed(2);
    291 }
    292 
    293 bool Process::FileDescriptorIsDisplayed(int fd) {
    294   DWORD Mode;  // Unused
    295   return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
    296 }
    297 
    298 unsigned Process::StandardOutColumns() {
    299   unsigned Columns = 0;
    300   CONSOLE_SCREEN_BUFFER_INFO csbi;
    301   if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
    302     Columns = csbi.dwSize.X;
    303   return Columns;
    304 }
    305 
    306 unsigned Process::StandardErrColumns() {
    307   unsigned Columns = 0;
    308   CONSOLE_SCREEN_BUFFER_INFO csbi;
    309   if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi))
    310     Columns = csbi.dwSize.X;
    311   return Columns;
    312 }
    313 
    314 // The terminal always has colors.
    315 bool Process::FileDescriptorHasColors(int fd) {
    316   return FileDescriptorIsDisplayed(fd);
    317 }
    318 
    319 bool Process::StandardOutHasColors() {
    320   return FileDescriptorHasColors(1);
    321 }
    322 
    323 bool Process::StandardErrHasColors() {
    324   return FileDescriptorHasColors(2);
    325 }
    326 
    327 static bool UseANSI = false;
    328 void Process::UseANSIEscapeCodes(bool enable) {
    329   UseANSI = enable;
    330 }
    331 
    332 namespace {
    333 class DefaultColors
    334 {
    335   private:
    336     WORD defaultColor;
    337   public:
    338     DefaultColors()
    339      :defaultColor(GetCurrentColor()) {}
    340     static unsigned GetCurrentColor() {
    341       CONSOLE_SCREEN_BUFFER_INFO csbi;
    342       if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
    343         return csbi.wAttributes;
    344       return 0;
    345     }
    346     WORD operator()() const { return defaultColor; }
    347 };
    348 
    349 DefaultColors defaultColors;
    350 
    351 WORD fg_color(WORD color) {
    352   return color & (FOREGROUND_BLUE | FOREGROUND_GREEN |
    353                   FOREGROUND_INTENSITY | FOREGROUND_RED);
    354 }
    355 
    356 WORD bg_color(WORD color) {
    357   return color & (BACKGROUND_BLUE | BACKGROUND_GREEN |
    358                   BACKGROUND_INTENSITY | BACKGROUND_RED);
    359 }
    360 }
    361 
    362 bool Process::ColorNeedsFlush() {
    363   return !UseANSI;
    364 }
    365 
    366 const char *Process::OutputBold(bool bg) {
    367   if (UseANSI) return "\033[1m";
    368 
    369   WORD colors = DefaultColors::GetCurrentColor();
    370   if (bg)
    371     colors |= BACKGROUND_INTENSITY;
    372   else
    373     colors |= FOREGROUND_INTENSITY;
    374   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
    375   return 0;
    376 }
    377 
    378 const char *Process::OutputColor(char code, bool bold, bool bg) {
    379   if (UseANSI) return colorcodes[bg?1:0][bold?1:0][code&7];
    380 
    381   WORD current = DefaultColors::GetCurrentColor();
    382   WORD colors;
    383   if (bg) {
    384     colors = ((code&1) ? BACKGROUND_RED : 0) |
    385       ((code&2) ? BACKGROUND_GREEN : 0 ) |
    386       ((code&4) ? BACKGROUND_BLUE : 0);
    387     if (bold)
    388       colors |= BACKGROUND_INTENSITY;
    389     colors |= fg_color(current);
    390   } else {
    391     colors = ((code&1) ? FOREGROUND_RED : 0) |
    392       ((code&2) ? FOREGROUND_GREEN : 0 ) |
    393       ((code&4) ? FOREGROUND_BLUE : 0);
    394     if (bold)
    395       colors |= FOREGROUND_INTENSITY;
    396     colors |= bg_color(current);
    397   }
    398   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
    399   return 0;
    400 }
    401 
    402 static WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) {
    403   CONSOLE_SCREEN_BUFFER_INFO info;
    404   GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
    405   return info.wAttributes;
    406 }
    407 
    408 const char *Process::OutputReverse() {
    409   if (UseANSI) return "\033[7m";
    410 
    411   const WORD attributes
    412    = GetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE));
    413 
    414   const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN |
    415     FOREGROUND_RED | FOREGROUND_INTENSITY;
    416   const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN |
    417     BACKGROUND_RED | BACKGROUND_INTENSITY;
    418   const WORD color_mask = foreground_mask | background_mask;
    419 
    420   WORD new_attributes =
    421     ((attributes & FOREGROUND_BLUE     )?BACKGROUND_BLUE     :0) |
    422     ((attributes & FOREGROUND_GREEN    )?BACKGROUND_GREEN    :0) |
    423     ((attributes & FOREGROUND_RED      )?BACKGROUND_RED      :0) |
    424     ((attributes & FOREGROUND_INTENSITY)?BACKGROUND_INTENSITY:0) |
    425     ((attributes & BACKGROUND_BLUE     )?FOREGROUND_BLUE     :0) |
    426     ((attributes & BACKGROUND_GREEN    )?FOREGROUND_GREEN    :0) |
    427     ((attributes & BACKGROUND_RED      )?FOREGROUND_RED      :0) |
    428     ((attributes & BACKGROUND_INTENSITY)?FOREGROUND_INTENSITY:0) |
    429     0;
    430   new_attributes = (attributes & ~color_mask) | (new_attributes & color_mask);
    431 
    432   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), new_attributes);
    433   return 0;
    434 }
    435 
    436 const char *Process::ResetColor() {
    437   if (UseANSI) return "\033[0m";
    438   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors());
    439   return 0;
    440 }
    441 
    442 // Include GetLastError() in a fatal error message.
    443 static void ReportLastErrorFatal(const char *Msg) {
    444   std::string ErrMsg;
    445   MakeErrMsg(&ErrMsg, Msg);
    446   report_fatal_error(ErrMsg);
    447 }
    448 
    449 unsigned Process::GetRandomNumber() {
    450   HCRYPTPROV HCPC;
    451   if (!::CryptAcquireContextW(&HCPC, NULL, NULL, PROV_RSA_FULL,
    452                               CRYPT_VERIFYCONTEXT))
    453     ReportLastErrorFatal("Could not acquire a cryptographic context");
    454 
    455   ScopedCryptContext CryptoProvider(HCPC);
    456   unsigned Ret;
    457   if (!::CryptGenRandom(CryptoProvider, sizeof(Ret),
    458                         reinterpret_cast<BYTE *>(&Ret)))
    459     ReportLastErrorFatal("Could not generate a random number");
    460   return Ret;
    461 }
    462