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