LLVM  3.7.0
Windows/Process.inc
Go to the documentation of this file.
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"
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 static TimeValue getTimeValueFromFILETIME(FILETIME Time) {
53  ULARGE_INTEGER TimeInteger;
54  TimeInteger.LowPart = Time.dwLowDateTime;
55  TimeInteger.HighPart = Time.dwHighDateTime;
56 
57  // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
58  return TimeValue(
59  static_cast<TimeValue::SecondsType>(TimeInteger.QuadPart / 10000000),
60  static_cast<TimeValue::NanoSecondsType>(
61  (TimeInteger.QuadPart % 10000000) * 100));
62 }
63 
64 // This function retrieves the page size using GetNativeSystemInfo() and is
65 // present solely so it can be called once to initialize the self_process member
66 // below.
67 static unsigned computePageSize() {
68  // GetNativeSystemInfo() provides the physical page size which may differ
69  // from GetSystemInfo() in 32-bit applications running under WOW64.
70  SYSTEM_INFO info;
71  GetNativeSystemInfo(&info);
72  // FIXME: FileOffset in MapViewOfFile() should be aligned to not dwPageSize,
73  // but dwAllocationGranularity.
74  return static_cast<unsigned>(info.dwPageSize);
75 }
76 
77 unsigned Process::getPageSize() {
78  static unsigned Ret = computePageSize();
79  return Ret;
80 }
81 
82 size_t
84 {
85  _HEAPINFO hinfo;
86  hinfo._pentry = NULL;
87 
88  size_t size = 0;
89 
90  while (_heapwalk(&hinfo) == _HEAPOK)
91  size += hinfo._size;
92 
93  return size;
94 }
95 
96 void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
97  TimeValue &sys_time) {
98  elapsed = TimeValue::now();
99 
100  FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
101  if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
102  &UserTime) == 0)
103  return;
104 
105  user_time = getTimeValueFromFILETIME(UserTime);
106  sys_time = getTimeValueFromFILETIME(KernelTime);
107 }
108 
109 // Some LLVM programs such as bugpoint produce core files as a normal part of
110 // their operation. To prevent the disk from filling up, this configuration
111 // item does what's necessary to prevent their generation.
113  // Windows does have the concept of core files, called minidumps. However,
114  // disabling minidumps for a particular application extends past the lifetime
115  // of that application, which is the incorrect behavior for this API.
116  // Additionally, the APIs require elevated privileges to disable and re-
117  // enable minidumps, which makes this untenable. For more information, see
118  // WerAddExcludedApplication and WerRemoveExcludedApplication (Vista and
119  // later).
120  //
121  // Windows also has modal pop-up message boxes. As this method is used by
122  // bugpoint, preventing these pop-ups is additionally important.
123  SetErrorMode(SEM_FAILCRITICALERRORS |
124  SEM_NOGPFAULTERRORBOX |
125  SEM_NOOPENFILEERRORBOX);
126 }
127 
128 /// Returns the environment variable \arg Name's value as a string encoded in
129 /// UTF-8. \arg Name is assumed to be in UTF-8 encoding.
131  // Convert the argument to UTF-16 to pass it to _wgetenv().
132  SmallVector<wchar_t, 128> NameUTF16;
133  if (windows::UTF8ToUTF16(Name, NameUTF16))
134  return None;
135 
136  // Environment variable can be encoded in non-UTF8 encoding, and there's no
137  // way to know what the encoding is. The only reliable way to look up
138  // multibyte environment variable is to use GetEnvironmentVariableW().
140  size_t Size = MAX_PATH;
141  do {
142  Buf.reserve(Size);
143  Size =
144  GetEnvironmentVariableW(NameUTF16.data(), Buf.data(), Buf.capacity());
145  if (Size == 0)
146  return None;
147 
148  // Try again with larger buffer.
149  } while (Size > Buf.capacity());
150  Buf.set_size(Size);
151 
152  // Convert the result from UTF-16 to UTF-8.
154  if (windows::UTF16ToUTF8(Buf.data(), Size, Res))
155  return None;
156  return std::string(Res.data());
157 }
158 
159 static void AllocateAndPush(const SmallVectorImpl<char> &S,
161  SpecificBumpPtrAllocator<char> &Allocator) {
162  char *Buffer = Allocator.Allocate(S.size() + 1);
163  ::memcpy(Buffer, S.data(), S.size());
164  Buffer[S.size()] = '\0';
165  Vector.push_back(Buffer);
166 }
167 
168 /// Convert Arg from UTF-16 to UTF-8 and push it onto Args.
169 static std::error_code
170 ConvertAndPushArg(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
171  SpecificBumpPtrAllocator<char> &Allocator) {
172  SmallVector<char, MAX_PATH> ArgString;
173  if (std::error_code ec = windows::UTF16ToUTF8(Arg, wcslen(Arg), ArgString))
174  return ec;
175  AllocateAndPush(ArgString, Args, Allocator);
176  return std::error_code();
177 }
178 
179 /// \brief Perform wildcard expansion of Arg, or just push it into Args if it
180 /// doesn't have wildcards or doesn't match any files.
181 static std::error_code
182 WildcardExpand(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
183  SpecificBumpPtrAllocator<char> &Allocator) {
184  if (!wcspbrk(Arg, L"*?")) {
185  // Arg does not contain any wildcard characters. This is the common case.
186  return ConvertAndPushArg(Arg, Args, Allocator);
187  }
188 
189  if (wcscmp(Arg, L"/?") == 0 || wcscmp(Arg, L"-?") == 0) {
190  // Don't wildcard expand /?. Always treat it as an option.
191  return ConvertAndPushArg(Arg, Args, Allocator);
192  }
193 
194  // Extract any directory part of the argument.
196  if (std::error_code ec = windows::UTF16ToUTF8(Arg, wcslen(Arg), Dir))
197  return ec;
199  const int DirSize = Dir.size();
200 
201  // Search for matching files.
202  WIN32_FIND_DATAW FileData;
203  HANDLE FindHandle = FindFirstFileW(Arg, &FileData);
204  if (FindHandle == INVALID_HANDLE_VALUE) {
205  return ConvertAndPushArg(Arg, Args, Allocator);
206  }
207 
208  std::error_code ec;
209  do {
211  ec = windows::UTF16ToUTF8(FileData.cFileName, wcslen(FileData.cFileName),
212  FileName);
213  if (ec)
214  break;
215 
216  // Push the filename onto Dir, and remove it afterwards.
217  llvm::sys::path::append(Dir, StringRef(FileName.data(), FileName.size()));
218  AllocateAndPush(Dir, Args, Allocator);
219  Dir.resize(DirSize);
220  } while (FindNextFileW(FindHandle, &FileData));
221 
222  FindClose(FindHandle);
223  return ec;
224 }
225 
226 std::error_code
229  SpecificBumpPtrAllocator<char> &ArgAllocator) {
230  int ArgCount;
231  wchar_t **UnicodeCommandLine =
232  CommandLineToArgvW(GetCommandLineW(), &ArgCount);
233  if (!UnicodeCommandLine)
234  return mapWindowsError(::GetLastError());
235 
236  Args.reserve(ArgCount);
237  std::error_code ec;
238 
239  for (int i = 0; i < ArgCount; ++i) {
240  ec = WildcardExpand(UnicodeCommandLine[i], Args, ArgAllocator);
241  if (ec)
242  break;
243  }
244 
245  LocalFree(UnicodeCommandLine);
246  return ec;
247 }
248 
249 std::error_code Process::FixupStandardFileDescriptors() {
250  return std::error_code();
251 }
252 
253 std::error_code Process::SafelyCloseFileDescriptor(int FD) {
254  if (::close(FD) < 0)
255  return std::error_code(errno, std::generic_category());
256  return std::error_code();
257 }
258 
260  return FileDescriptorIsDisplayed(0);
261 }
262 
264  return FileDescriptorIsDisplayed(1);
265 }
266 
268  return FileDescriptorIsDisplayed(2);
269 }
270 
272  DWORD Mode; // Unused
273  return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
274 }
275 
276 unsigned Process::StandardOutColumns() {
277  unsigned Columns = 0;
278  CONSOLE_SCREEN_BUFFER_INFO csbi;
279  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
280  Columns = csbi.dwSize.X;
281  return Columns;
282 }
283 
284 unsigned Process::StandardErrColumns() {
285  unsigned Columns = 0;
286  CONSOLE_SCREEN_BUFFER_INFO csbi;
287  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi))
288  Columns = csbi.dwSize.X;
289  return Columns;
290 }
291 
292 // The terminal always has colors.
294  return FileDescriptorIsDisplayed(fd);
295 }
296 
298  return FileDescriptorHasColors(1);
299 }
300 
302  return FileDescriptorHasColors(2);
303 }
304 
305 static bool UseANSI = false;
306 void Process::UseANSIEscapeCodes(bool enable) {
307  UseANSI = enable;
308 }
309 
310 namespace {
311 class DefaultColors
312 {
313  private:
314  WORD defaultColor;
315  public:
316  DefaultColors()
317  :defaultColor(GetCurrentColor()) {}
318  static unsigned GetCurrentColor() {
319  CONSOLE_SCREEN_BUFFER_INFO csbi;
320  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
321  return csbi.wAttributes;
322  return 0;
323  }
324  WORD operator()() const { return defaultColor; }
325 };
326 
327 DefaultColors defaultColors;
328 
329 WORD fg_color(WORD color) {
330  return color & (FOREGROUND_BLUE | FOREGROUND_GREEN |
331  FOREGROUND_INTENSITY | FOREGROUND_RED);
332 }
333 
334 WORD bg_color(WORD color) {
335  return color & (BACKGROUND_BLUE | BACKGROUND_GREEN |
336  BACKGROUND_INTENSITY | BACKGROUND_RED);
337 }
338 }
339 
341  return !UseANSI;
342 }
343 
344 const char *Process::OutputBold(bool bg) {
345  if (UseANSI) return "\033[1m";
346 
347  WORD colors = DefaultColors::GetCurrentColor();
348  if (bg)
349  colors |= BACKGROUND_INTENSITY;
350  else
351  colors |= FOREGROUND_INTENSITY;
352  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
353  return 0;
354 }
355 
356 const char *Process::OutputColor(char code, bool bold, bool bg) {
357  if (UseANSI) return colorcodes[bg?1:0][bold?1:0][code&7];
358 
359  WORD current = DefaultColors::GetCurrentColor();
360  WORD colors;
361  if (bg) {
362  colors = ((code&1) ? BACKGROUND_RED : 0) |
363  ((code&2) ? BACKGROUND_GREEN : 0 ) |
364  ((code&4) ? BACKGROUND_BLUE : 0);
365  if (bold)
366  colors |= BACKGROUND_INTENSITY;
367  colors |= fg_color(current);
368  } else {
369  colors = ((code&1) ? FOREGROUND_RED : 0) |
370  ((code&2) ? FOREGROUND_GREEN : 0 ) |
371  ((code&4) ? FOREGROUND_BLUE : 0);
372  if (bold)
373  colors |= FOREGROUND_INTENSITY;
374  colors |= bg_color(current);
375  }
376  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
377  return 0;
378 }
379 
380 static WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) {
381  CONSOLE_SCREEN_BUFFER_INFO info;
382  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
383  return info.wAttributes;
384 }
385 
386 const char *Process::OutputReverse() {
387  if (UseANSI) return "\033[7m";
388 
389  const WORD attributes
390  = GetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE));
391 
392  const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN |
393  FOREGROUND_RED | FOREGROUND_INTENSITY;
394  const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN |
395  BACKGROUND_RED | BACKGROUND_INTENSITY;
396  const WORD color_mask = foreground_mask | background_mask;
397 
398  WORD new_attributes =
399  ((attributes & FOREGROUND_BLUE )?BACKGROUND_BLUE :0) |
400  ((attributes & FOREGROUND_GREEN )?BACKGROUND_GREEN :0) |
401  ((attributes & FOREGROUND_RED )?BACKGROUND_RED :0) |
402  ((attributes & FOREGROUND_INTENSITY)?BACKGROUND_INTENSITY:0) |
403  ((attributes & BACKGROUND_BLUE )?FOREGROUND_BLUE :0) |
404  ((attributes & BACKGROUND_GREEN )?FOREGROUND_GREEN :0) |
405  ((attributes & BACKGROUND_RED )?FOREGROUND_RED :0) |
406  ((attributes & BACKGROUND_INTENSITY)?FOREGROUND_INTENSITY:0) |
407  0;
408  new_attributes = (attributes & ~color_mask) | (new_attributes & color_mask);
409 
410  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), new_attributes);
411  return 0;
412 }
413 
414 const char *Process::ResetColor() {
415  if (UseANSI) return "\033[0m";
416  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors());
417  return 0;
418 }
419 
420 unsigned Process::GetRandomNumber() {
421  HCRYPTPROV HCPC;
422  if (!::CryptAcquireContextW(&HCPC, NULL, NULL, PROV_RSA_FULL,
423  CRYPT_VERIFYCONTEXT))
424  report_fatal_error("Could not acquire a cryptographic context");
425 
426  ScopedCryptContext CryptoProvider(HCPC);
427  unsigned Ret;
428  if (!::CryptGenRandom(CryptoProvider, sizeof(Ret),
429  reinterpret_cast<BYTE *>(&Ret)))
430  report_fatal_error("Could not generate a random number");
431  return Ret;
432 }
const NoneType None
Definition: None.h:23
void push_back(const T &Elt)
Definition: SmallVector.h:222
static TimeValue now()
This is a static constructor that returns a TimeValue that represents the current time...
size_t capacity() const
Return the total number of elements in the currently allocated buffer.
Definition: SmallVector.h:131
static const char * ResetColor()
Resets the terminals colors, or returns an escape sequence to do so.
static const char * OutputColor(char c, bool bold, bool bg)
This function returns the colorcode escape sequences.
static bool StandardErrHasColors()
This function determines whether the terminal connected to standard error supports colors...
static bool FileDescriptorHasColors(int fd)
This function determines if the given file descriptor is displayd and supports colors.
static bool FileDescriptorIsDisplayed(int fd)
This function determines if the given file descriptor is connected to a "tty" or "console" window...
void reserve(size_type N)
Definition: SmallVector.h:401
This file defines the MallocAllocator and BumpPtrAllocator interfaces.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
Reports a serious error, calling any installed error handler.
lazy value info
static std::error_code FixupStandardFileDescriptors()
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:443
static bool ColorNeedsFlush()
Whether changing colors requires the output to be flushed.
void remove_filename(SmallVectorImpl< char > &path)
Remove the last component from path unless it is the root dir.
Definition: Path.cpp:498
static const char * OutputReverse()
This function returns the escape sequence to reverse forground and background colors.
static const char colorcodes[2][2][8][10]
Definition: Process.cpp:71
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: ArrayRef.h:31
static bool StandardInIsUserInput()
This function determines if the standard input is connected directly to a user's input (keyboard prob...
static bool StandardOutIsDisplayed()
This function determines if the standard output is connected to a "tty" or "console" window...
static void UseANSIEscapeCodes(bool enable)
Enables or disables whether ANSI escape sequences are used to output colors.
static unsigned StandardOutColumns()
This function determines the number of columns in the window if standard output is connected to a "tt...
static void GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, TimeValue &sys_time)
This static function will set user_time to the amount of CPU time spent in user (non-kernel) mode and...
static std::error_code GetArgumentVector(SmallVectorImpl< const char * > &Args, ArrayRef< const char * > ArgsFromMain, SpecificBumpPtrAllocator< char > &ArgAllocator)
This function returns a SmallVector containing the arguments passed from the operating system to the ...
std::error_code mapWindowsError(unsigned EV)
std::error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl< wchar_t > &utf16)
T * Allocate(size_t num=1)
Allocate space for an array of objects without constructing them.
Definition: Allocator.h:394
static size_t GetMallocUsage()
Return process memory usage.
std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, SmallVectorImpl< char > &utf8)
static unsigned getPageSize()
static bool StandardErrIsDisplayed()
This function determines if the standard error is connected to a "tty" or "console" window...
static void PreventCoreFiles()
This function makes the necessary calls to the operating system to prevent core files or any other ki...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:861
static unsigned StandardErrColumns()
This function determines the number of columns in the window if standard error is connected to a "tty...
A BumpPtrAllocator that allows only elements of a specific type to be allocated.
Definition: Allocator.h:349
static bool StandardOutHasColors()
This function determines whether the terminal connected to standard output supports colors...
static unsigned GetRandomNumber()
Get the result of a process wide random number generator.
void set_size(size_type N)
Set the array size to N, which the current array must have enough capacity for.
Definition: SmallVector.h:685
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:134
Deduce function attributes
void size_t size
static const char * OutputBold(bool bg)
Same as OutputColor, but only enables the bold attribute.
static std::error_code SafelyCloseFileDescriptor(int FD)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
static Optional< std::string > GetEnv(StringRef name)
void resize(size_type N)
Definition: SmallVector.h:376