[llvm-commits] [llvm] r116216 - in /llvm/trunk: CMakeLists.txt utils/KillTheDoctor/ utils/KillTheDoctor/CMakeLists.txt utils/KillTheDoctor/KillTheDoctor.cpp utils/KillTheDoctor/system_error.cpp utils/KillTheDoctor/system_error.h

Michael J. Spencer bigcheesegs at gmail.com
Mon Oct 11 12:55:38 PDT 2010


Author: mspencer
Date: Mon Oct 11 14:55:38 2010
New Revision: 116216

URL: http://llvm.org/viewvc/llvm-project?rev=116216&view=rev
Log:
Add KillTheDoctor.

Added:
    llvm/trunk/utils/KillTheDoctor/
    llvm/trunk/utils/KillTheDoctor/CMakeLists.txt
    llvm/trunk/utils/KillTheDoctor/KillTheDoctor.cpp
    llvm/trunk/utils/KillTheDoctor/system_error.cpp
    llvm/trunk/utils/KillTheDoctor/system_error.h
Modified:
    llvm/trunk/CMakeLists.txt

Modified: llvm/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/CMakeLists.txt?rev=116216&r1=116215&r2=116216&view=diff
==============================================================================
--- llvm/trunk/CMakeLists.txt (original)
+++ llvm/trunk/CMakeLists.txt Mon Oct 11 14:55:38 2010
@@ -389,6 +389,11 @@
   add_subdirectory(test)
   add_subdirectory(utils/unittest)
   add_subdirectory(unittests)
+  if (WIN32)
+    # This utility is used to prevent chrashing tests from calling Dr. Watson on
+    # Windows.
+    add_subdirectory(utils/KillTheDoctor)
+  endif()
 endif()
 
 add_subdirectory(cmake/modules)

Added: llvm/trunk/utils/KillTheDoctor/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/KillTheDoctor/CMakeLists.txt?rev=116216&view=auto
==============================================================================
--- llvm/trunk/utils/KillTheDoctor/CMakeLists.txt (added)
+++ llvm/trunk/utils/KillTheDoctor/CMakeLists.txt Mon Oct 11 14:55:38 2010
@@ -0,0 +1,6 @@
+add_executable(KillTheDoctor
+  KillTheDoctor.cpp
+  system_error.cpp
+  )
+
+target_link_libraries(KillTheDoctor LLVMSupport LLVMSystem)

Added: llvm/trunk/utils/KillTheDoctor/KillTheDoctor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/KillTheDoctor/KillTheDoctor.cpp?rev=116216&view=auto
==============================================================================
--- llvm/trunk/utils/KillTheDoctor/KillTheDoctor.cpp (added)
+++ llvm/trunk/utils/KillTheDoctor/KillTheDoctor.cpp Mon Oct 11 14:55:38 2010
@@ -0,0 +1,600 @@
+//===- KillTheDoctor - Prevent Dr. Watson from stopping tests ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This program provides an extremely hacky way to stop Dr. Watson from starting
+// due to unhandled exceptions in child processes.
+//
+// This simply starts the program named in the first positional argument with
+// the arguments following it under a debugger. All this debugger does is catch
+// any unhandled exceptions thrown in the child process and close the program
+// (and hopefully tells someone about it).
+//
+// This also provides another really hacky method to prevent assert dialog boxes
+// from poping up. When --no-user32 is passed, if any process loads user32.dll,
+// we assume it is trying to call MessageBoxEx and terminate it. The proper way
+// to do this would be to actually set a break point, but there's quite a bit
+// of code involved to get the address of MessageBoxEx in the remote process's
+// address space due to Address space layout randomization (ASLR). This can be
+// added if it's ever actually needed.
+//
+// If the subprocess exits for any reason other than sucessful termination, -1
+// is returned. If the process exits normally the value it returned is returned.
+//
+// I hate Windows.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/type_traits.h"
+#include "llvm/System/Signals.h"
+#include "system_error.h"
+#include <algorithm>
+#include <cerrno>
+#include <cstdlib>
+#include <map>
+#include <string>
+#include <Windows.h>
+#include <WinError.h>
+#include <Dbghelp.h>
+#include <psapi.h>
+using namespace llvm;
+
+#undef max
+
+namespace {
+  cl::opt<std::string> ProgramToRun(cl::Positional,
+    cl::desc("<program to run>"));
+  cl::list<std::string>  Argv(cl::ConsumeAfter,
+    cl::desc("<program arguments>..."));
+  cl::opt<bool> TraceExecution("x",
+    cl::desc("Print detailed output about what is being run to stderr."));
+  cl::opt<unsigned> Timeout("t", cl::init(0),
+    cl::desc("Set maximum runtime in seconds. Defaults to infinite."));
+  cl::opt<bool> NoUser32("no-user32",
+    cl::desc("Terminate process if it loads user32.dll."));
+
+  StringRef ToolName;
+
+  template <typename HandleType>
+  class ScopedHandle {
+    typedef typename HandleType::handle_type handle_type;
+
+    handle_type Handle;
+
+  public:
+    ScopedHandle()
+      : Handle(HandleType::GetInvalidHandle()) {}
+
+    explicit ScopedHandle(handle_type handle)
+      : Handle(handle) {}
+
+    ~ScopedHandle() {
+      HandleType::Destruct(Handle);
+    }
+
+    ScopedHandle& operator=(handle_type handle) {
+      // Cleanup current handle.
+      if (!HandleType::isValid(Handle))
+        HandleType::Destruct(Handle);
+      Handle = handle;
+      return *this;
+    }
+
+    operator bool() const {
+      return HandleType::isValid(Handle);
+    }
+
+    operator handle_type() {
+      return Handle;
+    }
+  };
+
+  // This implements the most common handle in the Windows API.
+  struct CommonHandle {
+    typedef HANDLE handle_type;
+
+    static handle_type GetInvalidHandle() {
+      return INVALID_HANDLE_VALUE;
+    }
+
+    static void Destruct(handle_type Handle) {
+      ::CloseHandle(Handle);
+    }
+
+    static bool isValid(handle_type Handle) {
+      return Handle != GetInvalidHandle();
+    }
+  };
+
+  struct FileMappingHandle {
+    typedef HANDLE handle_type;
+
+    static handle_type GetInvalidHandle() {
+      return NULL;
+    }
+
+    static void Destruct(handle_type Handle) {
+      ::CloseHandle(Handle);
+    }
+
+    static bool isValid(handle_type Handle) {
+      return Handle != GetInvalidHandle();
+    }
+  };
+
+  struct MappedViewOfFileHandle {
+    typedef LPVOID handle_type;
+
+    static handle_type GetInvalidHandle() {
+      return NULL;
+    }
+
+    static void Destruct(handle_type Handle) {
+      ::UnmapViewOfFile(Handle);
+    }
+
+    static bool isValid(handle_type Handle) {
+      return Handle != GetInvalidHandle();
+    }
+  };
+
+  struct ProcessHandle : CommonHandle {};
+  struct ThreadHandle  : CommonHandle {};
+  struct TokenHandle   : CommonHandle {};
+  struct FileHandle    : CommonHandle {};
+
+  typedef ScopedHandle<FileMappingHandle>       FileMappingScopedHandle;
+  typedef ScopedHandle<MappedViewOfFileHandle>  MappedViewOfFileScopedHandle;
+  typedef ScopedHandle<ProcessHandle>           ProcessScopedHandle;
+  typedef ScopedHandle<ThreadHandle>            ThreadScopedHandle;
+  typedef ScopedHandle<TokenHandle>             TokenScopedHandle;
+  typedef ScopedHandle<FileHandle>              FileScopedHandle;
+
+  error_code get_windows_last_error() {
+    return make_error_code(windows_error(::GetLastError()));
+  }
+}
+
+static error_code GetFileNameFromHandle(HANDLE FileHandle,
+                                        std::string& Name) {
+  char Filename[MAX_PATH+1];
+  bool Sucess = false;
+  Name.clear();
+
+  // Get the file size.
+  LARGE_INTEGER FileSize;
+  Sucess = ::GetFileSizeEx(FileHandle, &FileSize);
+
+  if (!Sucess)
+   return get_windows_last_error();
+
+  // Create a file mapping object.
+  FileMappingScopedHandle FileMapping(
+    ::CreateFileMappingA(FileHandle,
+                         NULL,
+                         PAGE_READONLY,
+                         0,
+                         1,
+                         NULL));
+
+  if (!FileMapping)
+    return get_windows_last_error();
+
+  // Create a file mapping to get the file name.
+  MappedViewOfFileScopedHandle MappedFile(
+    ::MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 1));
+
+  if (!MappedFile)
+    return get_windows_last_error();
+
+  Sucess = ::GetMappedFileNameA(::GetCurrentProcess(),
+                                MappedFile,
+                                Filename,
+                                array_lengthof(Filename) - 1);
+
+  if (!Sucess)
+    return get_windows_last_error();
+  else {
+    Name = Filename;
+    return windows_error::success;
+  }
+}
+
+static std::string QuoteProgramPathIfNeeded(StringRef Command) {
+  if (Command.find_first_of(' ') == StringRef::npos)
+    return Command;
+  else {
+    std::string ret;
+    ret.reserve(Command.size() + 3);
+    ret.push_back('"');
+    ret.append(Command.begin(), Command.end());
+    ret.push_back('"');
+    return ret;
+  }
+}
+
+/// @brief Find program using shell lookup rules.
+/// @param Program This is either an absolute path, relative path, or simple a
+///        program name. Look in PATH for any programs that match. If no
+///        extension is present, try all extensions in PATHEXT.
+/// @return If ec == errc::success, The absolute path to the program. Otherwise
+///         the return value is undefined.
+static std::string FindProgram(const std::string &Program, error_code &ec) {
+  char PathName[MAX_PATH + 1];
+  typedef SmallVector<StringRef, 12> pathext_t;
+  pathext_t pathext;
+  // Check for the program without an extension (in case it already has one).
+  pathext.push_back("");
+  SplitString(std::getenv("PATHEXT"), pathext, ";");
+
+  for (pathext_t::iterator i = pathext.begin(), e = pathext.end(); i != e; ++i){
+    SmallString<5> ext;
+    for (std::size_t ii = 0, e = i->size(); ii != e; ++ii)
+      ext.push_back(::tolower((*i)[ii]));
+    LPCSTR Extension = NULL;
+    if (ext.size() && ext[0] == '.')
+      Extension = ext.c_str();
+    DWORD length = ::SearchPathA(NULL,
+                                 Program.c_str(),
+                                 Extension,
+                                 array_lengthof(PathName),
+                                 PathName,
+                                 NULL);
+    if (length == 0)
+      ec = get_windows_last_error();
+    else if (length > array_lengthof(PathName)) {
+      // This may have been the file, return with error.
+      ec = error_code(windows_error::buffer_overflow);
+      break;
+    } else {
+      // We found the path! Return it.
+      ec = windows_error::success;
+      break;
+    }
+  }
+
+  // Make sure PathName is valid.
+  PathName[MAX_PATH] = 0;
+  return PathName;
+}
+
+static error_code EnableDebugPrivileges() {
+  HANDLE TokenHandle;
+  BOOL success = ::OpenProcessToken(::GetCurrentProcess(),
+                                    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
+                                    &TokenHandle);
+  if (!success)
+    return error_code(::GetLastError(), system_category());
+
+  TokenScopedHandle Token(TokenHandle);
+  TOKEN_PRIVILEGES  TokenPrivileges;
+  LUID              LocallyUniqueID;
+
+  success = ::LookupPrivilegeValueA(NULL,
+                                    SE_DEBUG_NAME,
+                                    &LocallyUniqueID);
+  if (!success)
+    return error_code(::GetLastError(), system_category());
+
+  TokenPrivileges.PrivilegeCount = 1;
+  TokenPrivileges.Privileges[0].Luid = LocallyUniqueID;
+  TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+  success = ::AdjustTokenPrivileges(Token,
+                                    FALSE,
+                                    &TokenPrivileges,
+                                    sizeof(TOKEN_PRIVILEGES),
+                                    NULL,
+                                    NULL);
+  // The value of success is basically useless. Either way we are just returning
+  // the value of ::GetLastError().
+  return error_code(::GetLastError(), system_category());
+}
+
+static StringRef ExceptionCodeToString(DWORD ExceptionCode) {
+  switch(ExceptionCode) {
+  case EXCEPTION_ACCESS_VIOLATION: return "EXCEPTION_ACCESS_VIOLATION";
+  case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+    return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
+  case EXCEPTION_BREAKPOINT: return "EXCEPTION_BREAKPOINT";
+  case EXCEPTION_DATATYPE_MISALIGNMENT:
+    return "EXCEPTION_DATATYPE_MISALIGNMENT";
+  case EXCEPTION_FLT_DENORMAL_OPERAND: return "EXCEPTION_FLT_DENORMAL_OPERAND";
+  case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
+  case EXCEPTION_FLT_INEXACT_RESULT: return "EXCEPTION_FLT_INEXACT_RESULT";
+  case EXCEPTION_FLT_INVALID_OPERATION:
+    return "EXCEPTION_FLT_INVALID_OPERATION";
+  case EXCEPTION_FLT_OVERFLOW: return "EXCEPTION_FLT_OVERFLOW";
+  case EXCEPTION_FLT_STACK_CHECK: return "EXCEPTION_FLT_STACK_CHECK";
+  case EXCEPTION_FLT_UNDERFLOW: return "EXCEPTION_FLT_UNDERFLOW";
+  case EXCEPTION_ILLEGAL_INSTRUCTION: return "EXCEPTION_ILLEGAL_INSTRUCTION";
+  case EXCEPTION_IN_PAGE_ERROR: return "EXCEPTION_IN_PAGE_ERROR";
+  case EXCEPTION_INT_DIVIDE_BY_ZERO: return "EXCEPTION_INT_DIVIDE_BY_ZERO";
+  case EXCEPTION_INT_OVERFLOW: return "EXCEPTION_INT_OVERFLOW";
+  case EXCEPTION_INVALID_DISPOSITION: return "EXCEPTION_INVALID_DISPOSITION";
+  case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+    return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
+  case EXCEPTION_PRIV_INSTRUCTION: return "EXCEPTION_PRIV_INSTRUCTION";
+  case EXCEPTION_SINGLE_STEP: return "EXCEPTION_SINGLE_STEP";
+  case EXCEPTION_STACK_OVERFLOW: return "EXCEPTION_STACK_OVERFLOW";
+  default: return "<unknown>";
+  }
+}
+
+int main(int argc, char **argv) {
+  // Print a stack trace if we signal out.
+  sys::PrintStackTraceOnErrorSignal();
+  PrettyStackTraceProgram X(argc, argv);
+  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
+
+  ToolName = argv[0];
+
+  cl::ParseCommandLineOptions(argc, argv, "Dr. Watson Assassin.\n");
+  if (ProgramToRun.size() == 0) {
+    cl::PrintHelpMessage();
+    return -1;
+  }
+
+  if (Timeout > std::numeric_limits<uint32_t>::max() / 1000) {
+    errs() << ToolName << ": Timeout value too large, must be less than: "
+                       << std::numeric_limits<uint32_t>::max() / 1000
+                       << '\n';
+    return -1;
+  }
+
+  std::string CommandLine(ProgramToRun);
+
+  error_code ec;
+  ProgramToRun = FindProgram(ProgramToRun, ec);
+  if (ec) {
+    errs() << ToolName << ": Failed to find program: '" << CommandLine
+           << "': " << ec.message() << '\n';
+    return -1;
+  }
+
+  if (TraceExecution)
+    errs() << ToolName << ": Found Program: " << ProgramToRun << '\n';
+
+  for (std::vector<std::string>::iterator i = Argv.begin(),
+                                          e = Argv.end();
+                                          i != e; ++i) {
+    CommandLine.push_back(' ');
+    CommandLine.append(*i);
+  }
+
+  if (TraceExecution)
+    errs() << ToolName << ": Program Image Path: " << ProgramToRun << '\n'
+           << ToolName << ": Command Line: " << CommandLine << '\n';
+
+  STARTUPINFO StartupInfo;
+  PROCESS_INFORMATION ProcessInfo;
+  std::memset(&StartupInfo, 0, sizeof(StartupInfo));
+  StartupInfo.cb = sizeof(StartupInfo);
+  std::memset(&ProcessInfo, 0, sizeof(ProcessInfo));
+
+  // Set error mode to not display any message boxes. The child process inherets
+  // this.
+  ::SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
+  ::_set_error_mode(_OUT_TO_STDERR);
+
+  BOOL success = ::CreateProcessA(ProgramToRun.c_str(),
+                            LPSTR(CommandLine.c_str()),
+                                  NULL,
+                                  NULL,
+                                  FALSE,
+                                  DEBUG_PROCESS,
+                                  NULL,
+                                  NULL,
+                                  &StartupInfo,
+                                  &ProcessInfo);
+  if (!success) {
+    errs() << ToolName << ": Failed to run program: '" << ProgramToRun
+           << "': " << error_code(::GetLastError(), system_category()).message()
+           << '\n';
+    return -1;
+  }
+
+  // Make sure ::CloseHandle is called on exit.
+  std::map<DWORD, HANDLE> ProcessIDToHandle;
+
+  DEBUG_EVENT DebugEvent;
+  std::memset(&DebugEvent, 0, sizeof(DebugEvent));
+  DWORD dwContinueStatus = DBG_CONTINUE;
+
+  // Run the program under the debugger until either it exits, or throws an
+  // exception.
+  if (TraceExecution)
+    errs() << ToolName << ": Debugging...\n";
+
+  while(true) {
+    DWORD TimeLeft = INFINITE;
+    if (Timeout > 0) {
+      FILETIME CreationTime, ExitTime, KernelTime, UserTime;
+      ULARGE_INTEGER a, b;
+      success = ::GetProcessTimes(ProcessInfo.hProcess,
+                                  &CreationTime,
+                                  &ExitTime,
+                                  &KernelTime,
+                                  &UserTime);
+      if (!success) {
+        ec = error_code(::GetLastError(), system_category());
+
+        errs() << ToolName << ": Failed to get process times: "
+               << ec.message() << '\n';
+        return -1;
+      }
+      a.LowPart = KernelTime.dwLowDateTime;
+      a.HighPart = KernelTime.dwHighDateTime;
+      b.LowPart = UserTime.dwLowDateTime;
+      b.HighPart = UserTime.dwHighDateTime;
+      // Convert 100-nanosecond units to miliseconds.
+      uint64_t TotalTimeMiliseconds = (a.QuadPart + b.QuadPart) / 10000;
+      // Handle the case where the process has been running for more than 49
+      // days.
+      if (TotalTimeMiliseconds > std::numeric_limits<uint32_t>::max()) {
+        errs() << ToolName << ": Timeout Failed: Process has been running for"
+                              "more than 49 days.\n";
+        return -1;
+      }
+
+      // We check with > instead of using Timeleft because if
+      // TotalTimeMiliseconds is greater than Timeout * 1000, TimeLeft would
+      // underflow.
+      if (TotalTimeMiliseconds > (Timeout * 1000)) {
+        errs() << ToolName << ": Process timed out.\n";
+        ::TerminateProcess(ProcessInfo.hProcess, -1);
+        // Otherwise other stuff starts failing...
+        return -1;
+      }
+
+      TimeLeft = (Timeout * 1000) - static_cast<uint32_t>(TotalTimeMiliseconds);
+    }
+    success = WaitForDebugEvent(&DebugEvent, TimeLeft);
+
+    if (!success) {
+      ec = error_code(::GetLastError(), system_category());
+
+      if (ec == error_condition(errc::timed_out)) {
+        errs() << ToolName << ": Process timed out.\n";
+        ::TerminateProcess(ProcessInfo.hProcess, -1);
+        // Otherwise other stuff starts failing...
+        return -1;
+      }
+
+      errs() << ToolName << ": Failed to wait for debug event in program: '"
+             << ProgramToRun << "': " << ec.message() << '\n';
+      return -1;
+    }
+
+    switch(DebugEvent.dwDebugEventCode) {
+    case CREATE_PROCESS_DEBUG_EVENT:
+      // Make sure we remove the handle on exit.
+      if (TraceExecution)
+        errs() << ToolName << ": Debug Event: CREATE_PROCESS_DEBUG_EVENT\n";
+      ProcessIDToHandle[DebugEvent.dwProcessId] =
+        DebugEvent.u.CreateProcessInfo.hProcess;
+      ::CloseHandle(DebugEvent.u.CreateProcessInfo.hFile);
+      break;
+    case EXIT_PROCESS_DEBUG_EVENT: {
+        if (TraceExecution)
+          errs() << ToolName << ": Debug Event: EXIT_PROCESS_DEBUG_EVENT\n";
+
+        // If this is the process we origionally created, exit with its exit
+        // code.
+        if (DebugEvent.dwProcessId == ProcessInfo.dwProcessId)
+          return DebugEvent.u.ExitProcess.dwExitCode;
+
+        // Otherwise cleanup any resources we have for it.
+        std::map<DWORD, HANDLE>::iterator ExitingProcess =
+          ProcessIDToHandle.find(DebugEvent.dwProcessId);
+        if (ExitingProcess == ProcessIDToHandle.end()) {
+          errs() << ToolName << ": Got unknown process id!\n";
+          return -1;
+        }
+        ::CloseHandle(ExitingProcess->second);
+        ProcessIDToHandle.erase(ExitingProcess);
+      }
+      break;
+    case CREATE_THREAD_DEBUG_EVENT:
+      ::CloseHandle(DebugEvent.u.CreateThread.hThread);
+      break;
+    case LOAD_DLL_DEBUG_EVENT: {
+        // Cleanup the file handle.
+        FileScopedHandle DLLFile(DebugEvent.u.LoadDll.hFile);
+        std::string DLLName;
+        ec = GetFileNameFromHandle(DLLFile, DLLName);
+        if (ec) {
+          DLLName = "<failed to get file name from file handle> : ";
+          DLLName += ec.message();
+        }
+        if (TraceExecution) {
+          errs() << ToolName << ": Debug Event: LOAD_DLL_DEBUG_EVENT\n";
+          errs().indent(ToolName.size()) << ": DLL Name : " << DLLName << '\n';
+        }
+
+        if (NoUser32 && sys::Path(DLLName).getBasename() == "user32") {
+          // Program is loading user32.dll, in the applications we are testing,
+          // this only happens if an assert has fired. By now the message has
+          // already been printed, so simply close the program.
+          errs() << ToolName << ": user32.dll loaded!\n";
+          errs().indent(ToolName.size())
+                 << ": This probably means that assert was called. Closing "
+                    "program to prevent message box from poping up.\n";
+          dwContinueStatus = DBG_CONTINUE;
+          ::TerminateProcess(ProcessIDToHandle[DebugEvent.dwProcessId], -1);
+          return -1;
+        }
+      }
+      break;
+    case EXCEPTION_DEBUG_EVENT: {
+        // Close the application if this exception will not be handled by the
+        // child application.
+        if (TraceExecution)
+          errs() << ToolName << ": Debug Event: EXCEPTION_DEBUG_EVENT\n";
+
+        EXCEPTION_DEBUG_INFO  &Exception = DebugEvent.u.Exception;
+        if (Exception.dwFirstChance > 0) {
+          if (TraceExecution) {
+            errs().indent(ToolName.size()) << ": Debug Info : ";
+            errs() << "First chance exception at "
+                   << Exception.ExceptionRecord.ExceptionAddress
+                   << ", exception code: "
+                   << ExceptionCodeToString(
+                        Exception.ExceptionRecord.ExceptionCode)
+                   << " (" << Exception.ExceptionRecord.ExceptionCode << ")\n";
+          }
+          dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
+        } else {
+          errs() << ToolName << ": Unhandled exception in: " << ProgramToRun
+                 << "!\n";
+                 errs().indent(ToolName.size()) << ": location: ";
+                 errs() << Exception.ExceptionRecord.ExceptionAddress
+                        << ", exception code: "
+                        << ExceptionCodeToString(
+                            Exception.ExceptionRecord.ExceptionCode)
+                        << " (" << Exception.ExceptionRecord.ExceptionCode
+                        << ")\n";
+          dwContinueStatus = DBG_CONTINUE;
+          ::TerminateProcess(ProcessIDToHandle[DebugEvent.dwProcessId], -1);
+          return -1;
+        }
+      }
+      break;
+    default:
+      // Do nothing.
+      if (TraceExecution)
+        errs() << ToolName << ": Debug Event: <unknown>\n";
+      break;
+    }
+
+    success = ContinueDebugEvent(DebugEvent.dwProcessId,
+                                 DebugEvent.dwThreadId,
+                                 dwContinueStatus);
+    if (!success) {
+      ec = error_code(::GetLastError(), system_category());
+      errs() << ToolName << ": Failed to continue debugging program: '"
+             << ProgramToRun << "': " << ec.message() << '\n';
+      return -1;
+    }
+
+    dwContinueStatus = DBG_CONTINUE;
+  }
+
+  assert(0 && "Fell out of debug loop. This shouldn't be possible!");
+  return -1;
+}

Added: llvm/trunk/utils/KillTheDoctor/system_error.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/KillTheDoctor/system_error.cpp?rev=116216&view=auto
==============================================================================
--- llvm/trunk/utils/KillTheDoctor/system_error.cpp (added)
+++ llvm/trunk/utils/KillTheDoctor/system_error.cpp Mon Oct 11 14:55:38 2010
@@ -0,0 +1,287 @@
+//===---------------------- system_error.cpp ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This was lifted from libc++ and modified for C++03.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/config.h"
+#include "system_error.h"
+#include <string>
+#include <cstring>
+
+namespace llvm {
+
+// class error_category
+
+error_category::error_category() {
+}
+
+error_category::~error_category() {
+}
+
+error_condition
+error_category::default_error_condition(int ev) const {
+  return error_condition(ev, *this);
+}
+
+bool
+error_category::equivalent(int code, const error_condition& condition) const {
+  return default_error_condition(code) == condition;
+}
+
+bool
+error_category::equivalent(const error_code& code, int condition) const {
+  return *this == code.category() && code.value() == condition;
+}
+
+std::string
+_do_message::message(int ev) const {
+  return std::string(std::strerror(ev));
+}
+
+class _generic_error_category : public _do_message {
+public:
+  virtual const char* name() const;
+  virtual std::string message(int ev) const;
+};
+
+const char*
+_generic_error_category::name() const {
+  return "generic";
+}
+
+std::string
+_generic_error_category::message(int ev) const {
+#ifdef ELAST
+  if (ev > ELAST)
+    return std::string("unspecified generic_category error");
+#endif  // ELAST
+  return _do_message::message(ev);
+}
+
+const error_category&
+generic_category() {
+  static _generic_error_category s;
+  return s;
+}
+
+class _system_error_category : public _do_message {
+public:
+  virtual const char* name() const;
+  virtual std::string message(int ev) const;
+  virtual error_condition default_error_condition(int ev) const;
+};
+
+const char*
+_system_error_category::name() const {
+  return "system";
+}
+
+// std::string _system_error_category::message(int ev) const {
+// Is in Platform/system_error.inc
+
+// error_condition _system_error_category::default_error_condition(int ev) const
+// Is in Platform/system_error.inc
+
+const error_category&
+system_category() {
+  static _system_error_category s;
+  return s;
+}
+
+// error_condition
+
+std::string
+error_condition::message() const {
+  return _cat_->message(_val_);
+}
+
+// error_code
+
+std::string
+error_code::message() const {
+  return _cat_->message(_val_);
+}
+
+// system_error
+
+std::string
+system_error::_init(const error_code& ec, std::string what_arg) {
+  if (ec)
+  {
+    if (!what_arg.empty())
+      what_arg += ": ";
+    what_arg += ec.message();
+  }
+  return what_arg;
+}
+
+system_error::system_error(error_code ec, const std::string& what_arg)
+  : runtime_error(_init(ec, what_arg)), _ec_(ec) {
+}
+
+system_error::system_error(error_code ec, const char* what_arg)
+  : runtime_error(_init(ec, what_arg)), _ec_(ec) {
+}
+
+system_error::system_error(error_code ec)
+  : runtime_error(_init(ec, "")), _ec_(ec) {
+}
+
+system_error::system_error(int ev, const error_category& ecat,
+                           const std::string& what_arg)
+  : runtime_error(_init(error_code(ev, ecat), what_arg))
+  , _ec_(error_code(ev, ecat)) {
+}
+
+system_error::system_error(int ev, const error_category& ecat,
+                           const char* what_arg)
+  : runtime_error(_init(error_code(ev, ecat), what_arg))
+  , _ec_(error_code(ev, ecat)) {
+}
+
+system_error::system_error(int ev, const error_category& ecat)
+  : runtime_error(_init(error_code(ev, ecat), "")), _ec_(error_code(ev, ecat)) {
+}
+
+system_error::~system_error() throw() {
+}
+
+void
+_throw_system_error(int ev, const char* what_arg) {
+  throw system_error(error_code(ev, system_category()), what_arg);
+}
+
+} // end namespace llvm
+
+#ifdef LLVM_ON_WIN32
+#include <Windows.h>
+#include <WinError.h>
+
+namespace llvm {
+
+std::string
+_system_error_category::message(int ev) const {
+  LPVOID lpMsgBuf = 0;
+  DWORD retval = ::FormatMessageA(
+    FORMAT_MESSAGE_ALLOCATE_BUFFER |
+    FORMAT_MESSAGE_FROM_SYSTEM |
+    FORMAT_MESSAGE_IGNORE_INSERTS,
+    NULL,
+    ev,
+    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+    (LPSTR) &lpMsgBuf,
+    0,
+    NULL);
+  if (retval == 0) {
+    ::LocalFree(lpMsgBuf);
+    return std::string("Unknown error");
+  }
+
+  std::string str( static_cast<LPCSTR>(lpMsgBuf) );
+  ::LocalFree(lpMsgBuf);
+
+  while (str.size()
+     && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r'))
+    str.erase( str.size()-1 );
+  if (str.size() && str[str.size()-1] == '.')
+    str.erase( str.size()-1 );
+  return str;
+}
+
+error_condition
+_system_error_category::default_error_condition(int ev) const {
+  switch (ev)
+  {
+  case 0: return make_error_condition(errc::success);
+  // Windows system -> posix_errno decode table  ---------------------------//
+  // see WinError.h comments for descriptions of errors
+  case ERROR_ACCESS_DENIED: return make_error_condition(errc::permission_denied);
+  case ERROR_ALREADY_EXISTS: return make_error_condition(errc::file_exists);
+  case ERROR_BAD_UNIT: return make_error_condition(errc::no_such_device);
+  case ERROR_BUFFER_OVERFLOW: return make_error_condition(errc::filename_too_long);
+  case ERROR_BUSY: return make_error_condition(errc::device_or_resource_busy);
+  case ERROR_BUSY_DRIVE: return make_error_condition(errc::device_or_resource_busy);
+  case ERROR_CANNOT_MAKE: return make_error_condition(errc::permission_denied);
+  case ERROR_CANTOPEN: return make_error_condition(errc::io_error);
+  case ERROR_CANTREAD: return make_error_condition(errc::io_error);
+  case ERROR_CANTWRITE: return make_error_condition(errc::io_error);
+  case ERROR_CURRENT_DIRECTORY: return make_error_condition(errc::permission_denied);
+  case ERROR_DEV_NOT_EXIST: return make_error_condition(errc::no_such_device);
+  case ERROR_DEVICE_IN_USE: return make_error_condition(errc::device_or_resource_busy);
+  case ERROR_DIR_NOT_EMPTY: return make_error_condition(errc::directory_not_empty);
+  case ERROR_DIRECTORY: return make_error_condition(errc::invalid_argument);
+  case ERROR_DISK_FULL: return make_error_condition(errc::no_space_on_device);
+  case ERROR_FILE_EXISTS: return make_error_condition(errc::file_exists);
+  case ERROR_FILE_NOT_FOUND: return make_error_condition(errc::no_such_file_or_directory);
+  case ERROR_HANDLE_DISK_FULL: return make_error_condition(errc::no_space_on_device);
+  case ERROR_INVALID_ACCESS: return make_error_condition(errc::permission_denied);
+  case ERROR_INVALID_DRIVE: return make_error_condition(errc::no_such_device);
+  case ERROR_INVALID_FUNCTION: return make_error_condition(errc::function_not_supported);
+  case ERROR_INVALID_HANDLE: return make_error_condition(errc::invalid_argument);
+  case ERROR_INVALID_NAME: return make_error_condition(errc::invalid_argument);
+  case ERROR_LOCK_VIOLATION: return make_error_condition(errc::no_lock_available);
+  case ERROR_LOCKED: return make_error_condition(errc::no_lock_available);
+  case ERROR_NEGATIVE_SEEK: return make_error_condition(errc::invalid_argument);
+  case ERROR_NOACCESS: return make_error_condition(errc::permission_denied);
+  case ERROR_NOT_ENOUGH_MEMORY: return make_error_condition(errc::not_enough_memory);
+  case ERROR_NOT_READY: return make_error_condition(errc::resource_unavailable_try_again);
+  case ERROR_NOT_SAME_DEVICE: return make_error_condition(errc::cross_device_link);
+  case ERROR_OPEN_FAILED: return make_error_condition(errc::io_error);
+  case ERROR_OPEN_FILES: return make_error_condition(errc::device_or_resource_busy);
+  case ERROR_OPERATION_ABORTED: return make_error_condition(errc::operation_canceled);
+  case ERROR_OUTOFMEMORY: return make_error_condition(errc::not_enough_memory);
+  case ERROR_PATH_NOT_FOUND: return make_error_condition(errc::no_such_file_or_directory);
+  case ERROR_READ_FAULT: return make_error_condition(errc::io_error);
+  case ERROR_RETRY: return make_error_condition(errc::resource_unavailable_try_again);
+  case ERROR_SEEK: return make_error_condition(errc::io_error);
+  case ERROR_SHARING_VIOLATION: return make_error_condition(errc::permission_denied);
+  case ERROR_TOO_MANY_OPEN_FILES: return make_error_condition(errc::too_many_files_open);
+  case ERROR_WRITE_FAULT: return make_error_condition(errc::io_error);
+  case ERROR_WRITE_PROTECT: return make_error_condition(errc::permission_denied);
+  case ERROR_SEM_TIMEOUT: return make_error_condition(errc::timed_out);
+  case WSAEACCES: return make_error_condition(errc::permission_denied);
+  case WSAEADDRINUSE: return make_error_condition(errc::address_in_use);
+  case WSAEADDRNOTAVAIL: return make_error_condition(errc::address_not_available);
+  case WSAEAFNOSUPPORT: return make_error_condition(errc::address_family_not_supported);
+  case WSAEALREADY: return make_error_condition(errc::connection_already_in_progress);
+  case WSAEBADF: return make_error_condition(errc::bad_file_descriptor);
+  case WSAECONNABORTED: return make_error_condition(errc::connection_aborted);
+  case WSAECONNREFUSED: return make_error_condition(errc::connection_refused);
+  case WSAECONNRESET: return make_error_condition(errc::connection_reset);
+  case WSAEDESTADDRREQ: return make_error_condition(errc::destination_address_required);
+  case WSAEFAULT: return make_error_condition(errc::bad_address);
+  case WSAEHOSTUNREACH: return make_error_condition(errc::host_unreachable);
+  case WSAEINPROGRESS: return make_error_condition(errc::operation_in_progress);
+  case WSAEINTR: return make_error_condition(errc::interrupted);
+  case WSAEINVAL: return make_error_condition(errc::invalid_argument);
+  case WSAEISCONN: return make_error_condition(errc::already_connected);
+  case WSAEMFILE: return make_error_condition(errc::too_many_files_open);
+  case WSAEMSGSIZE: return make_error_condition(errc::message_size);
+  case WSAENAMETOOLONG: return make_error_condition(errc::filename_too_long);
+  case WSAENETDOWN: return make_error_condition(errc::network_down);
+  case WSAENETRESET: return make_error_condition(errc::network_reset);
+  case WSAENETUNREACH: return make_error_condition(errc::network_unreachable);
+  case WSAENOBUFS: return make_error_condition(errc::no_buffer_space);
+  case WSAENOPROTOOPT: return make_error_condition(errc::no_protocol_option);
+  case WSAENOTCONN: return make_error_condition(errc::not_connected);
+  case WSAENOTSOCK: return make_error_condition(errc::not_a_socket);
+  case WSAEOPNOTSUPP: return make_error_condition(errc::operation_not_supported);
+  case WSAEPROTONOSUPPORT: return make_error_condition(errc::protocol_not_supported);
+  case WSAEPROTOTYPE: return make_error_condition(errc::wrong_protocol_type);
+  case WSAETIMEDOUT: return make_error_condition(errc::timed_out);
+  case WSAEWOULDBLOCK: return make_error_condition(errc::operation_would_block);
+  default: return error_condition(ev, system_category());
+  }
+}
+
+} // end namespace llvm
+
+#endif // LLVM_ON_WIN32

Added: llvm/trunk/utils/KillTheDoctor/system_error.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/KillTheDoctor/system_error.h?rev=116216&view=auto
==============================================================================
--- llvm/trunk/utils/KillTheDoctor/system_error.h (added)
+++ llvm/trunk/utils/KillTheDoctor/system_error.h Mon Oct 11 14:55:38 2010
@@ -0,0 +1,662 @@
+//===---------------------------- system_error ----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This was lifted from libc++ and modified for C++03.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SYSTEM_SYSTEM_ERROR_H
+#define LLVM_SYSTEM_SYSTEM_ERROR_H
+
+/*
+    system_error synopsis
+
+namespace std
+{
+
+class error_category
+{
+public:
+    virtual ~error_category();
+
+    error_category(const error_category&) = delete;
+    error_category& operator=(const error_category&) = delete;
+
+    virtual const char* name() const = 0;
+    virtual error_condition default_error_condition(int ev) const;
+    virtual bool equivalent(int code, const error_condition& condition) const;
+    virtual bool equivalent(const error_code& code, int condition) const;
+    virtual std::string message(int ev) const = 0;
+
+    bool operator==(const error_category& rhs) const;
+    bool operator!=(const error_category& rhs) const;
+    bool operator<(const error_category& rhs) const;
+};
+
+const error_category& generic_category();
+const error_category& system_category();
+
+template <class T> struct is_error_code_enum
+    : public false_type {};
+
+template <class T> struct is_error_condition_enum
+    : public false_type {};
+
+class error_code
+{
+public:
+    // constructors:
+    error_code();
+    error_code(int val, const error_category& cat);
+    template <class ErrorCodeEnum>
+        error_code(ErrorCodeEnum e);
+
+    // modifiers:
+    void assign(int val, const error_category& cat);
+    template <class ErrorCodeEnum>
+        error_code& operator=(ErrorCodeEnum e);
+    void clear();
+
+    // observers:
+    int value() const;
+    const error_category& category() const;
+    error_condition default_error_condition() const;
+    std::string message() const;
+    explicit operator bool() const;
+};
+
+// non-member functions:
+bool operator<(const error_code& lhs, const error_code& rhs);
+template <class charT, class traits>
+    basic_ostream<charT,traits>&
+    operator<<(basic_ostream<charT,traits>& os, const error_code& ec);
+
+class error_condition
+{
+public:
+    // constructors:
+    error_condition();
+    error_condition(int val, const error_category& cat);
+    template <class ErrorConditionEnum>
+        error_condition(ErrorConditionEnum e);
+
+    // modifiers:
+    void assign(int val, const error_category& cat);
+    template <class ErrorConditionEnum>
+        error_condition& operator=(ErrorConditionEnum e);
+    void clear();
+
+    // observers:
+    int value() const;
+    const error_category& category() const;
+    std::string message() const;
+    explicit operator bool() const;
+};
+
+bool operator<(const error_condition& lhs, const error_condition& rhs);
+
+class system_error
+    : public runtime_error
+{
+public:
+    system_error(error_code ec, const std::string& what_arg);
+    system_error(error_code ec, const char* what_arg);
+    system_error(error_code ec);
+    system_error(int ev, const error_category& ecat, const std::string& what_arg);
+    system_error(int ev, const error_category& ecat, const char* what_arg);
+    system_error(int ev, const error_category& ecat);
+
+    const error_code& code() const throw();
+    const char* what() const throw();
+};
+
+enum class errc
+{
+    address_family_not_supported,       // EAFNOSUPPORT
+    address_in_use,                     // EADDRINUSE
+    address_not_available,              // EADDRNOTAVAIL
+    already_connected,                  // EISCONN
+    argument_list_too_long,             // E2BIG
+    argument_out_of_domain,             // EDOM
+    bad_address,                        // EFAULT
+    bad_file_descriptor,                // EBADF
+    bad_message,                        // EBADMSG
+    broken_pipe,                        // EPIPE
+    connection_aborted,                 // ECONNABORTED
+    connection_already_in_progress,     // EALREADY
+    connection_refused,                 // ECONNREFUSED
+    connection_reset,                   // ECONNRESET
+    cross_device_link,                  // EXDEV
+    destination_address_required,       // EDESTADDRREQ
+    device_or_resource_busy,            // EBUSY
+    directory_not_empty,                // ENOTEMPTY
+    executable_format_error,            // ENOEXEC
+    file_exists,                        // EEXIST
+    file_too_large,                     // EFBIG
+    filename_too_long,                  // ENAMETOOLONG
+    function_not_supported,             // ENOSYS
+    host_unreachable,                   // EHOSTUNREACH
+    identifier_removed,                 // EIDRM
+    illegal_byte_sequence,              // EILSEQ
+    inappropriate_io_control_operation, // ENOTTY
+    interrupted,                        // EINTR
+    invalid_argument,                   // EINVAL
+    invalid_seek,                       // ESPIPE
+    io_error,                           // EIO
+    is_a_directory,                     // EISDIR
+    message_size,                       // EMSGSIZE
+    network_down,                       // ENETDOWN
+    network_reset,                      // ENETRESET
+    network_unreachable,                // ENETUNREACH
+    no_buffer_space,                    // ENOBUFS
+    no_child_process,                   // ECHILD
+    no_link,                            // ENOLINK
+    no_lock_available,                  // ENOLCK
+    no_message_available,               // ENODATA
+    no_message,                         // ENOMSG
+    no_protocol_option,                 // ENOPROTOOPT
+    no_space_on_device,                 // ENOSPC
+    no_stream_resources,                // ENOSR
+    no_such_device_or_address,          // ENXIO
+    no_such_device,                     // ENODEV
+    no_such_file_or_directory,          // ENOENT
+    no_such_process,                    // ESRCH
+    not_a_directory,                    // ENOTDIR
+    not_a_socket,                       // ENOTSOCK
+    not_a_stream,                       // ENOSTR
+    not_connected,                      // ENOTCONN
+    not_enough_memory,                  // ENOMEM
+    not_supported,                      // ENOTSUP
+    operation_canceled,                 // ECANCELED
+    operation_in_progress,              // EINPROGRESS
+    operation_not_permitted,            // EPERM
+    operation_not_supported,            // EOPNOTSUPP
+    operation_would_block,              // EWOULDBLOCK
+    owner_dead,                         // EOWNERDEAD
+    permission_denied,                  // EACCES
+    protocol_error,                     // EPROTO
+    protocol_not_supported,             // EPROTONOSUPPORT
+    read_only_file_system,              // EROFS
+    resource_deadlock_would_occur,      // EDEADLK
+    resource_unavailable_try_again,     // EAGAIN
+    result_out_of_range,                // ERANGE
+    state_not_recoverable,              // ENOTRECOVERABLE
+    stream_timeout,                     // ETIME
+    text_file_busy,                     // ETXTBSY
+    timed_out,                          // ETIMEDOUT
+    too_many_files_open_in_system,      // ENFILE
+    too_many_files_open,                // EMFILE
+    too_many_links,                     // EMLINK
+    too_many_symbolic_link_levels,      // ELOOP
+    value_too_large,                    // EOVERFLOW
+    wrong_protocol_type                 // EPROTOTYPE
+};
+
+template <> struct is_error_condition_enum<errc> : true_type { }
+
+error_code make_error_code(errc e);
+error_condition make_error_condition(errc e);
+
+// Comparison operators:
+bool operator==(const error_code& lhs, const error_code& rhs);
+bool operator==(const error_code& lhs, const error_condition& rhs);
+bool operator==(const error_condition& lhs, const error_code& rhs);
+bool operator==(const error_condition& lhs, const error_condition& rhs);
+bool operator!=(const error_code& lhs, const error_code& rhs);
+bool operator!=(const error_code& lhs, const error_condition& rhs);
+bool operator!=(const error_condition& lhs, const error_code& rhs);
+bool operator!=(const error_condition& lhs, const error_condition& rhs);
+
+template <> struct hash<std::error_code>;
+
+}  // std
+
+*/
+
+#include "llvm/Config/config.h"
+#include "llvm/Support/type_traits.h"
+#include <cerrno>
+#include <string>
+
+namespace llvm {
+
+template <class T, T v>
+struct integral_constant {
+  typedef T value_type;
+  static const value_type value = v;
+  typedef integral_constant<T,v> type;
+  operator value_type() { return value; }
+};
+
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+
+// is_error_code_enum
+
+template <class Tp> struct is_error_code_enum : public false_type {};
+
+// is_error_condition_enum
+
+template <class Tp> struct is_error_condition_enum : public false_type {};
+
+// Some error codes are not present on all platforms, so we provide equivalents
+// for them:
+
+//enum class errc
+struct errc {
+enum _ {
+  success                             = 0,
+  address_family_not_supported        = EAFNOSUPPORT,
+  address_in_use                      = EADDRINUSE,
+  address_not_available               = EADDRNOTAVAIL,
+  already_connected                   = EISCONN,
+  argument_list_too_long              = E2BIG,
+  argument_out_of_domain              = EDOM,
+  bad_address                         = EFAULT,
+  bad_file_descriptor                 = EBADF,
+  bad_message                         = EBADMSG,
+  broken_pipe                         = EPIPE,
+  connection_aborted                  = ECONNABORTED,
+  connection_already_in_progress      = EALREADY,
+  connection_refused                  = ECONNREFUSED,
+  connection_reset                    = ECONNRESET,
+  cross_device_link                   = EXDEV,
+  destination_address_required        = EDESTADDRREQ,
+  device_or_resource_busy             = EBUSY,
+  directory_not_empty                 = ENOTEMPTY,
+  executable_format_error             = ENOEXEC,
+  file_exists                         = EEXIST,
+  file_too_large                      = EFBIG,
+  filename_too_long                   = ENAMETOOLONG,
+  function_not_supported              = ENOSYS,
+  host_unreachable                    = EHOSTUNREACH,
+  identifier_removed                  = EIDRM,
+  illegal_byte_sequence               = EILSEQ,
+  inappropriate_io_control_operation  = ENOTTY,
+  interrupted                         = EINTR,
+  invalid_argument                    = EINVAL,
+  invalid_seek                        = ESPIPE,
+  io_error                            = EIO,
+  is_a_directory                      = EISDIR,
+  message_size                        = EMSGSIZE,
+  network_down                        = ENETDOWN,
+  network_reset                       = ENETRESET,
+  network_unreachable                 = ENETUNREACH,
+  no_buffer_space                     = ENOBUFS,
+  no_child_process                    = ECHILD,
+  no_link                             = ENOLINK,
+  no_lock_available                   = ENOLCK,
+#ifdef ENODATA
+  no_message_available                = ENODATA,
+#else
+  no_message_available                = ENOMSG,
+#endif
+  no_message                          = ENOMSG,
+  no_protocol_option                  = ENOPROTOOPT,
+  no_space_on_device                  = ENOSPC,
+#ifdef ENOSR
+  no_stream_resources                 = ENOSR,
+#else
+  no_stream_resources                 = ENOMEM,
+#endif
+  no_such_device_or_address           = ENXIO,
+  no_such_device                      = ENODEV,
+  no_such_file_or_directory           = ENOENT,
+  no_such_process                     = ESRCH,
+  not_a_directory                     = ENOTDIR,
+  not_a_socket                        = ENOTSOCK,
+#ifdef ENOSTR
+  not_a_stream                        = ENOSTR,
+#else
+  not_a_stream                        = EINVAL,
+#endif
+  not_connected                       = ENOTCONN,
+  not_enough_memory                   = ENOMEM,
+  not_supported                       = ENOTSUP,
+  operation_canceled                  = ECANCELED,
+  operation_in_progress               = EINPROGRESS,
+  operation_not_permitted             = EPERM,
+  operation_not_supported             = EOPNOTSUPP,
+  operation_would_block               = EWOULDBLOCK,
+  owner_dead                          = EOWNERDEAD,
+  permission_denied                   = EACCES,
+  protocol_error                      = EPROTO,
+  protocol_not_supported              = EPROTONOSUPPORT,
+  read_only_file_system               = EROFS,
+  resource_deadlock_would_occur       = EDEADLK,
+  resource_unavailable_try_again      = EAGAIN,
+  result_out_of_range                 = ERANGE,
+  state_not_recoverable               = ENOTRECOVERABLE,
+#ifdef ETIME
+  stream_timeout                      = ETIME,
+#else
+  stream_timeout                      = ETIMEDOUT,
+#endif
+  text_file_busy                      = ETXTBSY,
+  timed_out                           = ETIMEDOUT,
+  too_many_files_open_in_system       = ENFILE,
+  too_many_files_open                 = EMFILE,
+  too_many_links                      = EMLINK,
+  too_many_symbolic_link_levels       = ELOOP,
+  value_too_large                     = EOVERFLOW,
+  wrong_protocol_type                 = EPROTOTYPE
+};
+
+  _ v_;
+
+  errc(_ v) : v_(v) {}
+  operator int() const {return v_;}
+};
+
+template <> struct is_error_condition_enum<errc> : true_type { };
+
+template <> struct is_error_condition_enum<errc::_> : true_type { };
+
+class error_condition;
+class error_code;
+
+// class error_category
+
+class _do_message;
+
+class error_category
+{
+public:
+  virtual ~error_category();
+
+private:
+  error_category();
+  error_category(const error_category&);// = delete;
+  error_category& operator=(const error_category&);// = delete;
+
+public:
+  virtual const char* name() const = 0;
+  virtual error_condition default_error_condition(int _ev) const;
+  virtual bool equivalent(int _code, const error_condition& _condition) const;
+  virtual bool equivalent(const error_code& _code, int _condition) const;
+  virtual std::string message(int _ev) const = 0;
+
+  bool operator==(const error_category& _rhs) const {return this == &_rhs;}
+
+  bool operator!=(const error_category& _rhs) const {return !(*this == _rhs);}
+
+  bool operator< (const error_category& _rhs) const {return this < &_rhs;}
+
+  friend class _do_message;
+};
+
+class _do_message : public error_category
+{
+public:
+  virtual std::string message(int ev) const;
+};
+
+const error_category& generic_category();
+const error_category& system_category();
+
+class error_condition
+{
+  int _val_;
+  const error_category* _cat_;
+public:
+  error_condition() : _val_(0), _cat_(&generic_category()) {}
+
+  error_condition(int _val, const error_category& _cat)
+    : _val_(_val), _cat_(&_cat) {}
+
+  template <class E>
+  error_condition(E _e, typename enable_if_c<
+                          is_error_condition_enum<E>::value
+                        >::type* = 0)
+    {*this = make_error_condition(_e);}
+
+  void assign(int _val, const error_category& _cat) {
+    _val_ = _val;
+    _cat_ = &_cat;
+  }
+
+  template <class E>
+    typename enable_if_c
+    <
+      is_error_condition_enum<E>::value,
+      error_condition&
+    >::type
+    operator=(E _e)
+      {*this = make_error_condition(_e); return *this;}
+
+  void clear() {
+    _val_ = 0;
+    _cat_ = &generic_category();
+  }
+
+  int value() const {return _val_;}
+
+  const error_category& category() const {return *_cat_;}
+  std::string message() const;
+
+  // explicit
+  operator bool() const {return _val_ != 0;}
+};
+
+inline error_condition make_error_condition(errc _e) {
+  return error_condition(static_cast<int>(_e), generic_category());
+}
+
+inline bool operator<(const error_condition& _x, const error_condition& _y) {
+  return _x.category() < _y.category()
+      || _x.category() == _y.category() && _x.value() < _y.value();
+}
+
+// error_code
+
+class error_code {
+  int _val_;
+  const error_category* _cat_;
+public:
+  error_code() : _val_(0), _cat_(&system_category()) {}
+
+  error_code(int _val, const error_category& _cat)
+    : _val_(_val), _cat_(&_cat) {}
+
+  template <class E>
+  error_code(E _e, typename enable_if_c<
+                     is_error_code_enum<E>::value
+                   >::type* = 0) {
+    *this = make_error_code(_e);
+  }
+
+  void assign(int _val, const error_category& _cat) {
+      _val_ = _val;
+      _cat_ = &_cat;
+  }
+
+  template <class E>
+    typename enable_if_c
+    <
+      is_error_code_enum<E>::value,
+      error_code&
+    >::type
+    operator=(E _e)
+      {*this = make_error_code(_e); return *this;}
+
+  void clear() {
+    _val_ = 0;
+    _cat_ = &system_category();
+  }
+
+  int value() const {return _val_;}
+
+  const error_category& category() const {return *_cat_;}
+
+  error_condition default_error_condition() const
+    {return _cat_->default_error_condition(_val_);}
+
+  std::string message() const;
+
+  // explicit
+  operator bool() const {return _val_ != 0;}
+};
+
+inline error_code make_error_code(errc _e) {
+  return error_code(static_cast<int>(_e), generic_category());
+}
+
+inline bool operator<(const error_code& _x, const error_code& _y) {
+  return _x.category() < _y.category()
+      || _x.category() == _y.category() && _x.value() < _y.value();
+}
+
+inline bool operator==(const error_code& _x, const error_code& _y) {
+  return _x.category() == _y.category() && _x.value() == _y.value();
+}
+
+inline bool operator==(const error_code& _x, const error_condition& _y) {
+  return _x.category().equivalent(_x.value(), _y)
+      || _y.category().equivalent(_x, _y.value());
+}
+
+inline bool operator==(const error_condition& _x, const error_code& _y) {
+  return _y == _x;
+}
+
+inline bool operator==(const error_condition& _x, const error_condition& _y) {
+   return _x.category() == _y.category() && _x.value() == _y.value();
+}
+
+inline bool operator!=(const error_code& _x, const error_code& _y) {
+  return !(_x == _y);
+}
+
+inline bool operator!=(const error_code& _x, const error_condition& _y) {
+  return !(_x == _y);
+}
+
+inline bool operator!=(const error_condition& _x, const error_code& _y) {
+  return !(_x == _y);
+}
+
+inline bool operator!=(const error_condition& _x, const error_condition& _y) {
+  return !(_x == _y);
+}
+
+// system_error
+
+class system_error : public std::runtime_error {
+  error_code _ec_;
+public:
+  system_error(error_code _ec, const std::string& _what_arg);
+  system_error(error_code _ec, const char* _what_arg);
+  system_error(error_code _ec);
+  system_error(int _ev, const error_category& _ecat,
+               const std::string& _what_arg);
+  system_error(int _ev, const error_category& _ecat, const char* _what_arg);
+  system_error(int _ev, const error_category& _ecat);
+  ~system_error() throw();
+
+  const error_code& code() const throw() {return _ec_;}
+
+private:
+  static std::string _init(const error_code&, std::string);
+};
+
+void _throw_system_error(int ev, const char* what_arg);
+
+} // end namespace llvm
+
+#ifdef LLVM_ON_WIN32
+#include <Windows.h>
+#include <WinError.h>
+
+namespace llvm {
+
+//  To construct an error_code after a API error:
+//
+//      error_code( ::GetLastError(), system_category() )
+struct windows_error {
+enum _ {
+  success = 0,
+  // These names and values are based on Windows winerror.h
+  invalid_function = ERROR_INVALID_FUNCTION,
+  file_not_found = ERROR_FILE_NOT_FOUND,
+  path_not_found = ERROR_PATH_NOT_FOUND,
+  too_many_open_files = ERROR_TOO_MANY_OPEN_FILES,
+  access_denied = ERROR_ACCESS_DENIED,
+  invalid_handle = ERROR_INVALID_HANDLE,
+  arena_trashed = ERROR_ARENA_TRASHED,
+  not_enough_memory = ERROR_NOT_ENOUGH_MEMORY,
+  invalid_block = ERROR_INVALID_BLOCK,
+  bad_environment = ERROR_BAD_ENVIRONMENT,
+  bad_format = ERROR_BAD_FORMAT,
+  invalid_access = ERROR_INVALID_ACCESS,
+  outofmemory = ERROR_OUTOFMEMORY,
+  invalid_drive = ERROR_INVALID_DRIVE,
+  current_directory = ERROR_CURRENT_DIRECTORY,
+  not_same_device = ERROR_NOT_SAME_DEVICE,
+  no_more_files = ERROR_NO_MORE_FILES,
+  write_protect = ERROR_WRITE_PROTECT,
+  bad_unit = ERROR_BAD_UNIT,
+  not_ready = ERROR_NOT_READY,
+  bad_command = ERROR_BAD_COMMAND,
+  crc = ERROR_CRC,
+  bad_length = ERROR_BAD_LENGTH,
+  seek = ERROR_SEEK,
+  not_dos_disk = ERROR_NOT_DOS_DISK,
+  sector_not_found = ERROR_SECTOR_NOT_FOUND,
+  out_of_paper = ERROR_OUT_OF_PAPER,
+  write_fault = ERROR_WRITE_FAULT,
+  read_fault = ERROR_READ_FAULT,
+  gen_failure = ERROR_GEN_FAILURE,
+  sharing_violation = ERROR_SHARING_VIOLATION,
+  lock_violation = ERROR_LOCK_VIOLATION,
+  wrong_disk = ERROR_WRONG_DISK,
+  sharing_buffer_exceeded = ERROR_SHARING_BUFFER_EXCEEDED,
+  handle_eof = ERROR_HANDLE_EOF,
+  handle_disk_full= ERROR_HANDLE_DISK_FULL,
+  rem_not_list = ERROR_REM_NOT_LIST,
+  dup_name = ERROR_DUP_NAME,
+  bad_net_path = ERROR_BAD_NETPATH,
+  network_busy = ERROR_NETWORK_BUSY,
+  // ...
+  file_exists = ERROR_FILE_EXISTS,
+  cannot_make = ERROR_CANNOT_MAKE,
+  // ...
+  broken_pipe = ERROR_BROKEN_PIPE,
+  open_failed = ERROR_OPEN_FAILED,
+  buffer_overflow = ERROR_BUFFER_OVERFLOW,
+  disk_full= ERROR_DISK_FULL,
+  // ...
+  lock_failed = ERROR_LOCK_FAILED,
+  busy = ERROR_BUSY,
+  cancel_violation = ERROR_CANCEL_VIOLATION,
+  already_exists = ERROR_ALREADY_EXISTS
+  // ...
+
+  // TODO: add more Windows errors
+};
+  _ v_;
+
+  windows_error(_ v) : v_(v) {}
+  explicit windows_error(DWORD v) : v_(_(v)) {}
+  operator int() const {return v_;}
+};
+
+
+template <> struct is_error_code_enum<windows_error> : true_type { };
+
+template <> struct is_error_code_enum<windows_error::_> : true_type { };
+
+inline error_code make_error_code(windows_error e) {
+  return error_code(static_cast<int>(e), system_category());
+}
+
+} // end namespace llvm
+
+#endif // LLVM_ON_WINDOWS
+
+#endif





More information about the llvm-commits mailing list