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