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