1bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer//===- KillTheDoctor - Prevent Dr. Watson from stopping tests ---*- C++ -*-===//
2bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer//
3bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer//                     The LLVM Compiler Infrastructure
4bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer//
5bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// This file is distributed under the University of Illinois Open Source
6bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// License. See LICENSE.TXT for details.
7bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer//
8bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer//===----------------------------------------------------------------------===//
9bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer//
10bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// This program provides an extremely hacky way to stop Dr. Watson from starting
11bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// due to unhandled exceptions in child processes.
12bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer//
13bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// This simply starts the program named in the first positional argument with
14bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// the arguments following it under a debugger. All this debugger does is catch
15bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// any unhandled exceptions thrown in the child process and close the program
16bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// (and hopefully tells someone about it).
17bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer//
18bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// This also provides another really hacky method to prevent assert dialog boxes
19a1d942fb70bfb76a3e6e2e2104b7ddecdcaf1244Michael J. Spencer// from popping up. When --no-user32 is passed, if any process loads user32.dll,
20bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// we assume it is trying to call MessageBoxEx and terminate it. The proper way
21bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// to do this would be to actually set a break point, but there's quite a bit
22bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// of code involved to get the address of MessageBoxEx in the remote process's
23bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// address space due to Address space layout randomization (ASLR). This can be
24bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// added if it's ever actually needed.
25bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer//
26a1d942fb70bfb76a3e6e2e2104b7ddecdcaf1244Michael J. Spencer// If the subprocess exits for any reason other than successful termination, -1
27bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// is returned. If the process exits normally the value it returned is returned.
28bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer//
29bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer// I hate Windows.
30bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer//
31bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer//===----------------------------------------------------------------------===//
32bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
33bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include "llvm/ADT/STLExtras.h"
34bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include "llvm/ADT/SmallString.h"
35bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include "llvm/ADT/SmallVector.h"
36bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include "llvm/ADT/StringExtras.h"
37bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include "llvm/ADT/StringRef.h"
38bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include "llvm/ADT/Twine.h"
39bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include "llvm/Support/CommandLine.h"
40bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include "llvm/Support/ManagedStatic.h"
41bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include "llvm/Support/PrettyStackTrace.h"
421f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Signals.h"
43cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/Support/WindowsError.h"
444ffd89fa4d2788611187d1a534d2ed46adf1702cChandler Carruth#include "llvm/Support/raw_ostream.h"
454ffd89fa4d2788611187d1a534d2ed46adf1702cChandler Carruth#include "llvm/Support/type_traits.h"
46bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include <algorithm>
47bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include <cerrno>
48bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include <cstdlib>
49bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include <map>
50bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#include <string>
51cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include <system_error>
524ffd89fa4d2788611187d1a534d2ed46adf1702cChandler Carruth
5377f06d93b96d373f1e1d00f3a28c143c8d1562ecBill Wendling// These includes must be last.
544ffd89fa4d2788611187d1a534d2ed46adf1702cChandler Carruth#include <Windows.h>
5530cd56bc56b4a3cc3fdc207134d4db1e84d0a2a0NAKAMURA Takumi#include <WinError.h>
5630cd56bc56b4a3cc3fdc207134d4db1e84d0a2a0NAKAMURA Takumi#include <Dbghelp.h>
5730cd56bc56b4a3cc3fdc207134d4db1e84d0a2a0NAKAMURA Takumi#include <psapi.h>
584ffd89fa4d2788611187d1a534d2ed46adf1702cChandler Carruth
59bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencerusing namespace llvm;
60bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
61bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer#undef max
62bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
63bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencernamespace {
64bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  cl::opt<std::string> ProgramToRun(cl::Positional,
65bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    cl::desc("<program to run>"));
66bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  cl::list<std::string>  Argv(cl::ConsumeAfter,
67bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    cl::desc("<program arguments>..."));
68bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  cl::opt<bool> TraceExecution("x",
69bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    cl::desc("Print detailed output about what is being run to stderr."));
70bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  cl::opt<unsigned> Timeout("t", cl::init(0),
71bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    cl::desc("Set maximum runtime in seconds. Defaults to infinite."));
72bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  cl::opt<bool> NoUser32("no-user32",
73bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    cl::desc("Terminate process if it loads user32.dll."));
74bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
75bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  StringRef ToolName;
76bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
77bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  template <typename HandleType>
78bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  class ScopedHandle {
79bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    typedef typename HandleType::handle_type handle_type;
80bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
81bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    handle_type Handle;
82bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
83bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  public:
84bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    ScopedHandle()
85bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      : Handle(HandleType::GetInvalidHandle()) {}
86bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
87bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    explicit ScopedHandle(handle_type handle)
88bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      : Handle(handle) {}
89bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
90bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    ~ScopedHandle() {
91bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      HandleType::Destruct(Handle);
92bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
93bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
94bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    ScopedHandle& operator=(handle_type handle) {
95bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      // Cleanup current handle.
96bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      if (!HandleType::isValid(Handle))
97bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        HandleType::Destruct(Handle);
98bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      Handle = handle;
99bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      return *this;
100bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
101bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
102bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    operator bool() const {
103bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      return HandleType::isValid(Handle);
104bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
105bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
106bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    operator handle_type() {
107bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      return Handle;
108bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
109bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  };
110bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
111bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  // This implements the most common handle in the Windows API.
112bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  struct CommonHandle {
113bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    typedef HANDLE handle_type;
114bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
115bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    static handle_type GetInvalidHandle() {
116bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      return INVALID_HANDLE_VALUE;
117bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
118bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
119bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    static void Destruct(handle_type Handle) {
120bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      ::CloseHandle(Handle);
121bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
122bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
123bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    static bool isValid(handle_type Handle) {
124bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      return Handle != GetInvalidHandle();
125bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
126bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  };
127bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
128bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  struct FileMappingHandle {
129bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    typedef HANDLE handle_type;
130bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
131bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    static handle_type GetInvalidHandle() {
132bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      return NULL;
133bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
134bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
135bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    static void Destruct(handle_type Handle) {
136bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      ::CloseHandle(Handle);
137bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
138bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
139bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    static bool isValid(handle_type Handle) {
140bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      return Handle != GetInvalidHandle();
141bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
142bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  };
143bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
144bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  struct MappedViewOfFileHandle {
145bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    typedef LPVOID handle_type;
146bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
147bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    static handle_type GetInvalidHandle() {
148bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      return NULL;
149bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
150bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
151bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    static void Destruct(handle_type Handle) {
152bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      ::UnmapViewOfFile(Handle);
153bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
154bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
155bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    static bool isValid(handle_type Handle) {
156bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      return Handle != GetInvalidHandle();
157bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
158bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  };
159bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
160bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  struct ProcessHandle : CommonHandle {};
161bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  struct ThreadHandle  : CommonHandle {};
162bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  struct TokenHandle   : CommonHandle {};
163bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  struct FileHandle    : CommonHandle {};
164bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
165bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  typedef ScopedHandle<FileMappingHandle>       FileMappingScopedHandle;
166bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  typedef ScopedHandle<MappedViewOfFileHandle>  MappedViewOfFileScopedHandle;
167bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  typedef ScopedHandle<ProcessHandle>           ProcessScopedHandle;
168bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  typedef ScopedHandle<ThreadHandle>            ThreadScopedHandle;
169bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  typedef ScopedHandle<TokenHandle>             TokenScopedHandle;
170bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  typedef ScopedHandle<FileHandle>              FileScopedHandle;
171bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer}
172bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
173cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic std::error_code windows_error(DWORD E) { return mapWindowsError(E); }
174cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
175cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic std::error_code GetFileNameFromHandle(HANDLE FileHandle,
176cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                             std::string &Name) {
177bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  char Filename[MAX_PATH+1];
1787a2bdde0a0eebcd2125055e0eacaca040f0b766cChris Lattner  bool Success = false;
179bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  Name.clear();
180bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
181bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  // Get the file size.
182bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  LARGE_INTEGER FileSize;
1837a2bdde0a0eebcd2125055e0eacaca040f0b766cChris Lattner  Success = ::GetFileSizeEx(FileHandle, &FileSize);
184bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
1857a2bdde0a0eebcd2125055e0eacaca040f0b766cChris Lattner  if (!Success)
18693e5ec2cba6656417c9502ad80709aeca5eac968Michael J. Spencer    return windows_error(::GetLastError());
187bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
188bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  // Create a file mapping object.
189bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  FileMappingScopedHandle FileMapping(
190bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    ::CreateFileMappingA(FileHandle,
191bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                         NULL,
192bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                         PAGE_READONLY,
193bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                         0,
194bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                         1,
195bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                         NULL));
196bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
197bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  if (!FileMapping)
19893e5ec2cba6656417c9502ad80709aeca5eac968Michael J. Spencer    return windows_error(::GetLastError());
199bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
200bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  // Create a file mapping to get the file name.
201bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  MappedViewOfFileScopedHandle MappedFile(
202bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    ::MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 1));
203bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
204bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  if (!MappedFile)
20593e5ec2cba6656417c9502ad80709aeca5eac968Michael J. Spencer    return windows_error(::GetLastError());
206bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
2077a2bdde0a0eebcd2125055e0eacaca040f0b766cChris Lattner  Success = ::GetMappedFileNameA(::GetCurrentProcess(),
208bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                MappedFile,
209bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                Filename,
210bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                array_lengthof(Filename) - 1);
211bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
2127a2bdde0a0eebcd2125055e0eacaca040f0b766cChris Lattner  if (!Success)
21393e5ec2cba6656417c9502ad80709aeca5eac968Michael J. Spencer    return windows_error(::GetLastError());
214bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  else {
215bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    Name = Filename;
216cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return std::error_code();
217bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  }
218bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer}
219bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
220bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer/// @brief Find program using shell lookup rules.
221bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer/// @param Program This is either an absolute path, relative path, or simple a
222bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer///        program name. Look in PATH for any programs that match. If no
223bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer///        extension is present, try all extensions in PATHEXT.
224bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer/// @return If ec == errc::success, The absolute path to the program. Otherwise
225bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer///         the return value is undefined.
226cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic std::string FindProgram(const std::string &Program,
227cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                               std::error_code &ec) {
228bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  char PathName[MAX_PATH + 1];
229bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  typedef SmallVector<StringRef, 12> pathext_t;
230bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  pathext_t pathext;
231bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  // Check for the program without an extension (in case it already has one).
232bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  pathext.push_back("");
233bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  SplitString(std::getenv("PATHEXT"), pathext, ";");
234bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
235bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  for (pathext_t::iterator i = pathext.begin(), e = pathext.end(); i != e; ++i){
236bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    SmallString<5> ext;
237bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    for (std::size_t ii = 0, e = i->size(); ii != e; ++ii)
238bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      ext.push_back(::tolower((*i)[ii]));
239bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    LPCSTR Extension = NULL;
240bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    if (ext.size() && ext[0] == '.')
241bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      Extension = ext.c_str();
242bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    DWORD length = ::SearchPathA(NULL,
243bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                 Program.c_str(),
244bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                 Extension,
245bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                 array_lengthof(PathName),
246bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                 PathName,
247bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                 NULL);
248bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    if (length == 0)
24993e5ec2cba6656417c9502ad80709aeca5eac968Michael J. Spencer      ec = windows_error(::GetLastError());
250bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    else if (length > array_lengthof(PathName)) {
251bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      // This may have been the file, return with error.
252cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      ec = windows_error(ERROR_BUFFER_OVERFLOW);
253bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      break;
254bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    } else {
255bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      // We found the path! Return it.
256cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      ec = std::error_code();
257bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      break;
258bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
259bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  }
260bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
261bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  // Make sure PathName is valid.
262bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  PathName[MAX_PATH] = 0;
263bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  return PathName;
264bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer}
265bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
266bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencerstatic StringRef ExceptionCodeToString(DWORD ExceptionCode) {
267bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  switch(ExceptionCode) {
268bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_ACCESS_VIOLATION: return "EXCEPTION_ACCESS_VIOLATION";
269bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
270bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
271bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_BREAKPOINT: return "EXCEPTION_BREAKPOINT";
272bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_DATATYPE_MISALIGNMENT:
273bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    return "EXCEPTION_DATATYPE_MISALIGNMENT";
274bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_FLT_DENORMAL_OPERAND: return "EXCEPTION_FLT_DENORMAL_OPERAND";
275bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
276bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_FLT_INEXACT_RESULT: return "EXCEPTION_FLT_INEXACT_RESULT";
277bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_FLT_INVALID_OPERATION:
278bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    return "EXCEPTION_FLT_INVALID_OPERATION";
279bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_FLT_OVERFLOW: return "EXCEPTION_FLT_OVERFLOW";
280bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_FLT_STACK_CHECK: return "EXCEPTION_FLT_STACK_CHECK";
281bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_FLT_UNDERFLOW: return "EXCEPTION_FLT_UNDERFLOW";
282bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_ILLEGAL_INSTRUCTION: return "EXCEPTION_ILLEGAL_INSTRUCTION";
283bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_IN_PAGE_ERROR: return "EXCEPTION_IN_PAGE_ERROR";
284bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_INT_DIVIDE_BY_ZERO: return "EXCEPTION_INT_DIVIDE_BY_ZERO";
285bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_INT_OVERFLOW: return "EXCEPTION_INT_OVERFLOW";
286bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_INVALID_DISPOSITION: return "EXCEPTION_INVALID_DISPOSITION";
287bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_NONCONTINUABLE_EXCEPTION:
288bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
289bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_PRIV_INSTRUCTION: return "EXCEPTION_PRIV_INSTRUCTION";
290bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_SINGLE_STEP: return "EXCEPTION_SINGLE_STEP";
291bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  case EXCEPTION_STACK_OVERFLOW: return "EXCEPTION_STACK_OVERFLOW";
292bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  default: return "<unknown>";
293bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  }
294bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer}
295bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
296bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencerint main(int argc, char **argv) {
297bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  // Print a stack trace if we signal out.
298bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  sys::PrintStackTraceOnErrorSignal();
299bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  PrettyStackTraceProgram X(argc, argv);
300bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
301bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
302bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  ToolName = argv[0];
303bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
304bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  cl::ParseCommandLineOptions(argc, argv, "Dr. Watson Assassin.\n");
305bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  if (ProgramToRun.size() == 0) {
306bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    cl::PrintHelpMessage();
307bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    return -1;
308bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  }
309bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
310bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  if (Timeout > std::numeric_limits<uint32_t>::max() / 1000) {
311bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    errs() << ToolName << ": Timeout value too large, must be less than: "
312bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                       << std::numeric_limits<uint32_t>::max() / 1000
313bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                       << '\n';
314bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    return -1;
315bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  }
316bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
317bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  std::string CommandLine(ProgramToRun);
318bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
319cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  std::error_code ec;
320bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  ProgramToRun = FindProgram(ProgramToRun, ec);
321bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  if (ec) {
322bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    errs() << ToolName << ": Failed to find program: '" << CommandLine
323bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer           << "': " << ec.message() << '\n';
324bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    return -1;
325bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  }
326bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
327bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  if (TraceExecution)
328bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    errs() << ToolName << ": Found Program: " << ProgramToRun << '\n';
329bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
330bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  for (std::vector<std::string>::iterator i = Argv.begin(),
331bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                          e = Argv.end();
332bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                          i != e; ++i) {
333bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    CommandLine.push_back(' ');
334bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    CommandLine.append(*i);
335bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  }
336bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
337bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  if (TraceExecution)
338bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    errs() << ToolName << ": Program Image Path: " << ProgramToRun << '\n'
339bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer           << ToolName << ": Command Line: " << CommandLine << '\n';
340bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
341bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  STARTUPINFO StartupInfo;
342bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  PROCESS_INFORMATION ProcessInfo;
343bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  std::memset(&StartupInfo, 0, sizeof(StartupInfo));
344bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  StartupInfo.cb = sizeof(StartupInfo);
345bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  std::memset(&ProcessInfo, 0, sizeof(ProcessInfo));
346bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
347a1d942fb70bfb76a3e6e2e2104b7ddecdcaf1244Michael J. Spencer  // Set error mode to not display any message boxes. The child process inherits
348bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  // this.
349bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  ::SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
350bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  ::_set_error_mode(_OUT_TO_STDERR);
351bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
352bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  BOOL success = ::CreateProcessA(ProgramToRun.c_str(),
353bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                            LPSTR(CommandLine.c_str()),
354bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                  NULL,
355bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                  NULL,
356bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                  FALSE,
357bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                  DEBUG_PROCESS,
358bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                  NULL,
359bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                  NULL,
360bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                  &StartupInfo,
361bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                  &ProcessInfo);
362bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  if (!success) {
363cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    errs() << ToolName << ": Failed to run program: '" << ProgramToRun << "': "
364cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines           << std::error_code(windows_error(::GetLastError())).message()
365bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer           << '\n';
366bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    return -1;
367bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  }
368bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
369bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  // Make sure ::CloseHandle is called on exit.
370bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  std::map<DWORD, HANDLE> ProcessIDToHandle;
371bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
372bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  DEBUG_EVENT DebugEvent;
373bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  std::memset(&DebugEvent, 0, sizeof(DebugEvent));
374bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  DWORD dwContinueStatus = DBG_CONTINUE;
375bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
376bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  // Run the program under the debugger until either it exits, or throws an
377bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  // exception.
378bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  if (TraceExecution)
379bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    errs() << ToolName << ": Debugging...\n";
380bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
381bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  while(true) {
382bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    DWORD TimeLeft = INFINITE;
383bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    if (Timeout > 0) {
384bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      FILETIME CreationTime, ExitTime, KernelTime, UserTime;
385bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      ULARGE_INTEGER a, b;
386bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      success = ::GetProcessTimes(ProcessInfo.hProcess,
387bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                  &CreationTime,
388bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                  &ExitTime,
389bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                  &KernelTime,
390bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                  &UserTime);
391bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      if (!success) {
39293e5ec2cba6656417c9502ad80709aeca5eac968Michael J. Spencer        ec = windows_error(::GetLastError());
393bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
394bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        errs() << ToolName << ": Failed to get process times: "
395bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer               << ec.message() << '\n';
396bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        return -1;
397bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      }
398bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      a.LowPart = KernelTime.dwLowDateTime;
399bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      a.HighPart = KernelTime.dwHighDateTime;
400bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      b.LowPart = UserTime.dwLowDateTime;
401bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      b.HighPart = UserTime.dwHighDateTime;
402a1d942fb70bfb76a3e6e2e2104b7ddecdcaf1244Michael J. Spencer      // Convert 100-nanosecond units to milliseconds.
403bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      uint64_t TotalTimeMiliseconds = (a.QuadPart + b.QuadPart) / 10000;
404bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      // Handle the case where the process has been running for more than 49
405bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      // days.
406bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      if (TotalTimeMiliseconds > std::numeric_limits<uint32_t>::max()) {
407bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        errs() << ToolName << ": Timeout Failed: Process has been running for"
408bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                              "more than 49 days.\n";
409bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        return -1;
410bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      }
411bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
412bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      // We check with > instead of using Timeleft because if
413bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      // TotalTimeMiliseconds is greater than Timeout * 1000, TimeLeft would
414bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      // underflow.
415bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      if (TotalTimeMiliseconds > (Timeout * 1000)) {
416bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        errs() << ToolName << ": Process timed out.\n";
417bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        ::TerminateProcess(ProcessInfo.hProcess, -1);
418bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        // Otherwise other stuff starts failing...
419bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        return -1;
420bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      }
421bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
422bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      TimeLeft = (Timeout * 1000) - static_cast<uint32_t>(TotalTimeMiliseconds);
423bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
424bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    success = WaitForDebugEvent(&DebugEvent, TimeLeft);
425bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
426bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    if (!success) {
427cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      DWORD LastError = ::GetLastError();
428cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      ec = windows_error(LastError);
429bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
430cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (LastError == ERROR_SEM_TIMEOUT || LastError == WSAETIMEDOUT) {
431bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        errs() << ToolName << ": Process timed out.\n";
432bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        ::TerminateProcess(ProcessInfo.hProcess, -1);
433bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        // Otherwise other stuff starts failing...
434bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        return -1;
435bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      }
436bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
437bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      errs() << ToolName << ": Failed to wait for debug event in program: '"
438bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer             << ProgramToRun << "': " << ec.message() << '\n';
439bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      return -1;
440bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
441bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
442bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    switch(DebugEvent.dwDebugEventCode) {
443bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    case CREATE_PROCESS_DEBUG_EVENT:
444bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      // Make sure we remove the handle on exit.
445bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      if (TraceExecution)
446bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        errs() << ToolName << ": Debug Event: CREATE_PROCESS_DEBUG_EVENT\n";
447bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      ProcessIDToHandle[DebugEvent.dwProcessId] =
448bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        DebugEvent.u.CreateProcessInfo.hProcess;
449bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      ::CloseHandle(DebugEvent.u.CreateProcessInfo.hFile);
450bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      break;
451bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    case EXIT_PROCESS_DEBUG_EVENT: {
452bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        if (TraceExecution)
453bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          errs() << ToolName << ": Debug Event: EXIT_PROCESS_DEBUG_EVENT\n";
454bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
455a1d942fb70bfb76a3e6e2e2104b7ddecdcaf1244Michael J. Spencer        // If this is the process we originally created, exit with its exit
456bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        // code.
457bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        if (DebugEvent.dwProcessId == ProcessInfo.dwProcessId)
458bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          return DebugEvent.u.ExitProcess.dwExitCode;
459bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
460bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        // Otherwise cleanup any resources we have for it.
461bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        std::map<DWORD, HANDLE>::iterator ExitingProcess =
462bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          ProcessIDToHandle.find(DebugEvent.dwProcessId);
463bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        if (ExitingProcess == ProcessIDToHandle.end()) {
464bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          errs() << ToolName << ": Got unknown process id!\n";
465bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          return -1;
466bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        }
467bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        ::CloseHandle(ExitingProcess->second);
468bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        ProcessIDToHandle.erase(ExitingProcess);
469bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      }
470bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      break;
471bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    case CREATE_THREAD_DEBUG_EVENT:
472bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      ::CloseHandle(DebugEvent.u.CreateThread.hThread);
473bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      break;
474bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    case LOAD_DLL_DEBUG_EVENT: {
475bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        // Cleanup the file handle.
476bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        FileScopedHandle DLLFile(DebugEvent.u.LoadDll.hFile);
477bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        std::string DLLName;
478bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        ec = GetFileNameFromHandle(DLLFile, DLLName);
479bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        if (ec) {
480bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          DLLName = "<failed to get file name from file handle> : ";
481bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          DLLName += ec.message();
482bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        }
483bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        if (TraceExecution) {
484bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          errs() << ToolName << ": Debug Event: LOAD_DLL_DEBUG_EVENT\n";
485bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          errs().indent(ToolName.size()) << ": DLL Name : " << DLLName << '\n';
486bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        }
487bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
488738550910156b5cefdc0c12923ec8cc6982fb26fMichael J. Spencer        if (NoUser32 && sys::path::stem(DLLName) == "user32") {
489bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          // Program is loading user32.dll, in the applications we are testing,
490bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          // this only happens if an assert has fired. By now the message has
491bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          // already been printed, so simply close the program.
492bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          errs() << ToolName << ": user32.dll loaded!\n";
493bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          errs().indent(ToolName.size())
494bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                 << ": This probably means that assert was called. Closing "
495a1d942fb70bfb76a3e6e2e2104b7ddecdcaf1244Michael J. Spencer                    "program to prevent message box from popping up.\n";
496bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          dwContinueStatus = DBG_CONTINUE;
497bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          ::TerminateProcess(ProcessIDToHandle[DebugEvent.dwProcessId], -1);
498bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          return -1;
499bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        }
500bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      }
501bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      break;
502bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    case EXCEPTION_DEBUG_EVENT: {
503bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        // Close the application if this exception will not be handled by the
504bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        // child application.
505bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        if (TraceExecution)
506bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          errs() << ToolName << ": Debug Event: EXCEPTION_DEBUG_EVENT\n";
507bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
508bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        EXCEPTION_DEBUG_INFO  &Exception = DebugEvent.u.Exception;
509bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        if (Exception.dwFirstChance > 0) {
510bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          if (TraceExecution) {
511bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer            errs().indent(ToolName.size()) << ": Debug Info : ";
512bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer            errs() << "First chance exception at "
513bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                   << Exception.ExceptionRecord.ExceptionAddress
514bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                   << ", exception code: "
515bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                   << ExceptionCodeToString(
516bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                        Exception.ExceptionRecord.ExceptionCode)
517bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                   << " (" << Exception.ExceptionRecord.ExceptionCode << ")\n";
518bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          }
519bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
520bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        } else {
521bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          errs() << ToolName << ": Unhandled exception in: " << ProgramToRun
522bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                 << "!\n";
523bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                 errs().indent(ToolName.size()) << ": location: ";
524bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                 errs() << Exception.ExceptionRecord.ExceptionAddress
525bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                        << ", exception code: "
526bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                        << ExceptionCodeToString(
527bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                            Exception.ExceptionRecord.ExceptionCode)
528bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                        << " (" << Exception.ExceptionRecord.ExceptionCode
529bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                        << ")\n";
530bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          dwContinueStatus = DBG_CONTINUE;
531bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          ::TerminateProcess(ProcessIDToHandle[DebugEvent.dwProcessId], -1);
532bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer          return -1;
533bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        }
534bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      }
535bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      break;
536bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    default:
537bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      // Do nothing.
538bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      if (TraceExecution)
539bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer        errs() << ToolName << ": Debug Event: <unknown>\n";
540bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      break;
541bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
542bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
543bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    success = ContinueDebugEvent(DebugEvent.dwProcessId,
544bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                 DebugEvent.dwThreadId,
545bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer                                 dwContinueStatus);
546bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    if (!success) {
54793e5ec2cba6656417c9502ad80709aeca5eac968Michael J. Spencer      ec = windows_error(::GetLastError());
548bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      errs() << ToolName << ": Failed to continue debugging program: '"
549bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer             << ProgramToRun << "': " << ec.message() << '\n';
550bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer      return -1;
551bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    }
552bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
553bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer    dwContinueStatus = DBG_CONTINUE;
554bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  }
555bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer
556bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  assert(0 && "Fell out of debug loop. This shouldn't be possible!");
557bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer  return -1;
558bbb9ea7b70971df53eedfb42fc9cb606f815eaaaMichael J. Spencer}
559