LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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"
15 
16 #include "Windows.h"
17 #include <direct.h>
18 #include <io.h>
19 #include <malloc.h>
20 #include <psapi.h>
21 #include <shellapi.h>
22 
23 #ifdef __MINGW32__
24  #if (HAVE_LIBPSAPI != 1)
25  #error "libpsapi.a should be present"
26  #endif
27  #if (HAVE_LIBSHELL32 != 1)
28  #error "libshell32.a should be present"
29  #endif
30 #else
31  #pragma comment(lib, "psapi.lib")
32  #pragma comment(lib, "shell32.lib")
33 #endif
34 
35 //===----------------------------------------------------------------------===//
36 //=== WARNING: Implementation here must contain only Win32 specific code
37 //=== and must not be UNIX code
38 //===----------------------------------------------------------------------===//
39 
40 #ifdef __MINGW32__
41 // This ban should be lifted when MinGW 1.0+ has defined this value.
42 # define _HEAPOK (-2)
43 #endif
44 
45 using namespace llvm;
46 using namespace sys;
47 
48 
50  return GetCurrentProcessId();
51 }
52 
53 static TimeValue getTimeValueFromFILETIME(FILETIME Time) {
54  ULARGE_INTEGER TimeInteger;
55  TimeInteger.LowPart = Time.dwLowDateTime;
56  TimeInteger.HighPart = Time.dwHighDateTime;
57 
58  // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
59  return TimeValue(
60  static_cast<TimeValue::SecondsType>(TimeInteger.QuadPart / 10000000),
61  static_cast<TimeValue::NanoSecondsType>(
62  (TimeInteger.QuadPart % 10000000) * 100));
63 }
64 
65 TimeValue self_process::get_user_time() const {
66  FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
67  if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
68  &UserTime) == 0)
69  return TimeValue();
70 
71  return getTimeValueFromFILETIME(UserTime);
72 }
73 
74 TimeValue self_process::get_system_time() const {
75  FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
76  if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
77  &UserTime) == 0)
78  return TimeValue();
79 
80  return getTimeValueFromFILETIME(KernelTime);
81 }
82 
83 // This function retrieves the page size using GetSystemInfo and is present
84 // solely so it can be called once to initialize the self_process member below.
85 static unsigned getPageSize() {
86  // NOTE: A 32-bit application running under WOW64 is supposed to use
87  // GetNativeSystemInfo. However, this interface is not present prior
88  // to Windows XP so to use it requires dynamic linking. It is not clear
89  // how this affects the reported page size, if at all. One could argue
90  // that LLVM ought to run as 64-bits on a 64-bit system, anyway.
91  SYSTEM_INFO info;
92  GetSystemInfo(&info);
93  // FIXME: FileOffset in MapViewOfFile() should be aligned to not dwPageSize,
94  // but dwAllocationGranularity.
95  return static_cast<unsigned>(info.dwPageSize);
96 }
97 
98 // This constructor guaranteed to be run exactly once on a single thread, and
99 // sets up various process invariants that can be queried cheaply from then on.
100 self_process::self_process() : PageSize(getPageSize()) {
101 }
102 
103 
104 size_t
106 {
107  _HEAPINFO hinfo;
108  hinfo._pentry = NULL;
109 
110  size_t size = 0;
111 
112  while (_heapwalk(&hinfo) == _HEAPOK)
113  size += hinfo._size;
114 
115  return size;
116 }
117 
118 void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
119  TimeValue &sys_time) {
120  elapsed = TimeValue::now();
121 
122  FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
123  if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
124  &UserTime) == 0)
125  return;
126 
127  user_time = getTimeValueFromFILETIME(UserTime);
128  sys_time = getTimeValueFromFILETIME(KernelTime);
129 }
130 
131 // Some LLVM programs such as bugpoint produce core files as a normal part of
132 // their operation. To prevent the disk from filling up, this configuration
133 // item does what's necessary to prevent their generation.
135  // Windows does have the concept of core files, called minidumps. However,
136  // disabling minidumps for a particular application extends past the lifetime
137  // of that application, which is the incorrect behavior for this API.
138  // Additionally, the APIs require elevated privileges to disable and re-
139  // enable minidumps, which makes this untenable. For more information, see
140  // WerAddExcludedApplication and WerRemoveExcludedApplication (Vista and
141  // later).
142  //
143  // Windows also has modal pop-up message boxes. As this method is used by
144  // bugpoint, preventing these pop-ups is additionally important.
145  SetErrorMode(SEM_FAILCRITICALERRORS |
146  SEM_NOGPFAULTERRORBOX |
147  SEM_NOOPENFILEERRORBOX);
148 }
149 
150 /// Returns the environment variable \arg Name's value as a string encoded in
151 /// UTF-8. \arg Name is assumed to be in UTF-8 encoding.
153  // Convert the argument to UTF-16 to pass it to _wgetenv().
154  SmallVector<wchar_t, 128> NameUTF16;
155  if (error_code ec = windows::UTF8ToUTF16(Name, NameUTF16))
156  return None;
157 
158  // Environment variable can be encoded in non-UTF8 encoding, and there's no
159  // way to know what the encoding is. The only reliable way to look up
160  // multibyte environment variable is to use GetEnvironmentVariableW().
162  size_t Size = MAX_PATH;
163  do {
164  Buf.reserve(Size);
165  Size =
166  GetEnvironmentVariableW(NameUTF16.data(), Buf.data(), Buf.capacity());
167  if (Size == 0)
168  return None;
169 
170  // Try again with larger buffer.
171  } while (Size > Buf.capacity());
172  Buf.set_size(Size);
173 
174  // Convert the result from UTF-16 to UTF-8.
176  if (error_code ec = windows::UTF16ToUTF8(Buf.data(), Size, Res))
177  return None;
178  return std::string(Res.data());
179 }
180 
184  SpecificBumpPtrAllocator<char> &ArgAllocator) {
185  int NewArgCount;
186  error_code ec;
187 
188  wchar_t **UnicodeCommandLine = CommandLineToArgvW(GetCommandLineW(),
189  &NewArgCount);
190  if (!UnicodeCommandLine)
191  return windows_error(::GetLastError());
192 
193  Args.reserve(NewArgCount);
194 
195  for (int i = 0; i < NewArgCount; ++i) {
196  SmallVector<char, MAX_PATH> NewArgString;
197  ec = windows::UTF16ToUTF8(UnicodeCommandLine[i],
198  wcslen(UnicodeCommandLine[i]),
199  NewArgString);
200  if (ec)
201  break;
202 
203  char *Buffer = ArgAllocator.Allocate(NewArgString.size() + 1);
204  ::memcpy(Buffer, NewArgString.data(), NewArgString.size() + 1);
205  Args.push_back(Buffer);
206  }
207  LocalFree(UnicodeCommandLine);
208  if (ec)
209  return ec;
210 
211  return error_code::success();
212 }
213 
215  return FileDescriptorIsDisplayed(0);
216 }
217 
219  return FileDescriptorIsDisplayed(1);
220 }
221 
223  return FileDescriptorIsDisplayed(2);
224 }
225 
227  DWORD Mode; // Unused
228  return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
229 }
230 
231 unsigned Process::StandardOutColumns() {
232  unsigned Columns = 0;
233  CONSOLE_SCREEN_BUFFER_INFO csbi;
234  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
235  Columns = csbi.dwSize.X;
236  return Columns;
237 }
238 
239 unsigned Process::StandardErrColumns() {
240  unsigned Columns = 0;
241  CONSOLE_SCREEN_BUFFER_INFO csbi;
242  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi))
243  Columns = csbi.dwSize.X;
244  return Columns;
245 }
246 
247 // The terminal always has colors.
249  return FileDescriptorIsDisplayed(fd);
250 }
251 
253  return FileDescriptorHasColors(1);
254 }
255 
257  return FileDescriptorHasColors(2);
258 }
259 
260 static bool UseANSI = false;
261 void Process::UseANSIEscapeCodes(bool enable) {
262  UseANSI = enable;
263 }
264 
265 namespace {
266 class DefaultColors
267 {
268  private:
269  WORD defaultColor;
270  public:
271  DefaultColors()
272  :defaultColor(GetCurrentColor()) {}
273  static unsigned GetCurrentColor() {
274  CONSOLE_SCREEN_BUFFER_INFO csbi;
275  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
276  return csbi.wAttributes;
277  return 0;
278  }
279  WORD operator()() const { return defaultColor; }
280 };
281 
282 DefaultColors defaultColors;
283 }
284 
286  return !UseANSI;
287 }
288 
289 const char *Process::OutputBold(bool bg) {
290  if (UseANSI) return "\033[1m";
291 
292  WORD colors = DefaultColors::GetCurrentColor();
293  if (bg)
294  colors |= BACKGROUND_INTENSITY;
295  else
296  colors |= FOREGROUND_INTENSITY;
297  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
298  return 0;
299 }
300 
301 const char *Process::OutputColor(char code, bool bold, bool bg) {
302  if (UseANSI) return colorcodes[bg?1:0][bold?1:0][code&7];
303 
304  WORD colors;
305  if (bg) {
306  colors = ((code&1) ? BACKGROUND_RED : 0) |
307  ((code&2) ? BACKGROUND_GREEN : 0 ) |
308  ((code&4) ? BACKGROUND_BLUE : 0);
309  if (bold)
310  colors |= BACKGROUND_INTENSITY;
311  } else {
312  colors = ((code&1) ? FOREGROUND_RED : 0) |
313  ((code&2) ? FOREGROUND_GREEN : 0 ) |
314  ((code&4) ? FOREGROUND_BLUE : 0);
315  if (bold)
316  colors |= FOREGROUND_INTENSITY;
317  }
318  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
319  return 0;
320 }
321 
322 static WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) {
323  CONSOLE_SCREEN_BUFFER_INFO info;
324  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
325  return info.wAttributes;
326 }
327 
328 const char *Process::OutputReverse() {
329  if (UseANSI) return "\033[7m";
330 
331  const WORD attributes
332  = GetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE));
333 
334  const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN |
335  FOREGROUND_RED | FOREGROUND_INTENSITY;
336  const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN |
337  BACKGROUND_RED | BACKGROUND_INTENSITY;
338  const WORD color_mask = foreground_mask | background_mask;
339 
340  WORD new_attributes =
341  ((attributes & FOREGROUND_BLUE )?BACKGROUND_BLUE :0) |
342  ((attributes & FOREGROUND_GREEN )?BACKGROUND_GREEN :0) |
343  ((attributes & FOREGROUND_RED )?BACKGROUND_RED :0) |
344  ((attributes & FOREGROUND_INTENSITY)?BACKGROUND_INTENSITY:0) |
345  ((attributes & BACKGROUND_BLUE )?FOREGROUND_BLUE :0) |
346  ((attributes & BACKGROUND_GREEN )?FOREGROUND_GREEN :0) |
347  ((attributes & BACKGROUND_RED )?FOREGROUND_RED :0) |
348  ((attributes & BACKGROUND_INTENSITY)?FOREGROUND_INTENSITY:0) |
349  0;
350  new_attributes = (attributes & ~color_mask) | (new_attributes & color_mask);
351 
352  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), new_attributes);
353  return 0;
354 }
355 
356 const char *Process::ResetColor() {
357  if (UseANSI) return "\033[0m";
358  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors());
359  return 0;
360 }
void set_size(unsigned N)
Definition: SmallVector.h:702
void push_back(const T &Elt)
Definition: SmallVector.h:236
void reserve(unsigned N)
Definition: SmallVector.h:425
static TimeValue now()
Creates a TimeValue with the current time (UTC).
static const char * ResetColor()
Resets the terminals colors, or returns an escape sequence to do so.
virtual TimeValue get_system_time() const
Get the system time consumed by this process.
static const char * OutputColor(char c, bool bold, bool bg)
static bool StandardErrHasColors()
static bool FileDescriptorHasColors(int fd)
static bool FileDescriptorIsDisplayed(int fd)
virtual id_type get_id()
Get the operating system specific identifier for this process.
lazy value info
error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, SmallVectorImpl< char > &utf8)
error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl< wchar_t > &utf16)
static bool ColorNeedsFlush()
static const char * OutputReverse()
static const char colorcodes[2][2][8][10]
Definition: Process.cpp:96
static bool StandardInIsUserInput()
static bool StandardOutIsDisplayed()
static void UseANSIEscapeCodes(bool enable)
static unsigned StandardOutColumns()
static void GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, TimeValue &sys_time)
virtual TimeValue get_user_time() const
Get the user time consumed by this process.
pid_t id_type
Operating system specific type to identify a process.
Definition: Process.h:63
T * Allocate(size_t num=1)
Allocate space for a specific count of elements.
Definition: Allocator.h:222
static size_t GetMallocUsage()
Return process memory usage. This static function will return the total amount of memory allocated by...
static bool StandardErrIsDisplayed()
static void PreventCoreFiles()
Prevent core file generation.
static unsigned StandardErrColumns()
static bool StandardOutHasColors()
pointer data()
data - Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:135
static error_code success()
Definition: system_error.h:732
static error_code GetArgumentVector(SmallVectorImpl< const char * > &Args, ArrayRef< const char * > ArgsFromMain, SpecificBumpPtrAllocator< char > &ArgAllocator)
Deduce function attributes
static const char * OutputBold(bool bg)
Same as OutputColor, but only enables the bold attribute.
static Optional< std::string > GetEnv(StringRef name)