aganea updated this revision to Diff 227779.
aganea added a comment.
Herald added a subscriber: dexonsmith.

Fix missing `llvm::InitializeAllTargets()` in driver.cpp


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D69825/new/

https://reviews.llvm.org/D69825

Files:
  clang/include/clang/Driver/Job.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/Job.cpp
  clang/tools/driver/driver.cpp
  llvm/include/llvm/Support/CrashRecoveryContext.h
  llvm/lib/Support/CrashRecoveryContext.cpp
  llvm/lib/Support/Windows/Signals.inc

Index: llvm/lib/Support/Windows/Signals.inc
===================================================================
--- llvm/lib/Support/Windows/Signals.inc
+++ llvm/lib/Support/Windows/Signals.inc
@@ -187,7 +187,7 @@
 using namespace llvm;
 
 // Forward declare.
-static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep);
+LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep);
 static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType);
 
 // The function to call if ctrl-c is pressed.
@@ -521,10 +521,13 @@
 extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord);
 #endif
 
-void llvm::sys::PrintStackTrace(raw_ostream &OS) {
-  STACKFRAME64 StackFrame = {};
-  CONTEXT Context = {};
-  ::RtlCaptureContext(&Context);
+static void LocalPrintStackTrace(raw_ostream &OS, PCONTEXT C) {
+  STACKFRAME64 StackFrame{};
+  CONTEXT Context{};
+  if (!C) {
+    ::RtlCaptureContext(&Context);
+    C = &Context;
+  }
 #if defined(_M_X64)
   StackFrame.AddrPC.Offset = Context.Rip;
   StackFrame.AddrStack.Offset = Context.Rsp;
@@ -546,9 +549,12 @@
   StackFrame.AddrStack.Mode = AddrModeFlat;
   StackFrame.AddrFrame.Mode = AddrModeFlat;
   PrintStackTraceForThread(OS, GetCurrentProcess(), GetCurrentThread(),
-                           StackFrame, &Context);
+                           StackFrame, C);
 }
 
+void llvm::sys::PrintStackTrace(raw_ostream &OS) {
+  LocalPrintStackTrace(OS, nullptr);
+}
 
 void llvm::sys::SetInterruptFunction(void (*IF)()) {
   RegisterHandler();
@@ -785,7 +791,7 @@
   return std::error_code();
 }
 
-static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
+LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
   Cleanup();
 
   // We'll automatically write a Minidump file here to help diagnose
@@ -803,42 +809,9 @@
                    << "\n";
   }
 
-  // Initialize the STACKFRAME structure.
-  STACKFRAME64 StackFrame = {};
-
-#if defined(_M_X64)
-  StackFrame.AddrPC.Offset = ep->ContextRecord->Rip;
-  StackFrame.AddrPC.Mode = AddrModeFlat;
-  StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp;
-  StackFrame.AddrStack.Mode = AddrModeFlat;
-  StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp;
-  StackFrame.AddrFrame.Mode = AddrModeFlat;
-#elif defined(_M_IX86)
-  StackFrame.AddrPC.Offset = ep->ContextRecord->Eip;
-  StackFrame.AddrPC.Mode = AddrModeFlat;
-  StackFrame.AddrStack.Offset = ep->ContextRecord->Esp;
-  StackFrame.AddrStack.Mode = AddrModeFlat;
-  StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp;
-  StackFrame.AddrFrame.Mode = AddrModeFlat;
-#elif defined(_M_ARM64) || defined(_M_ARM)
-  StackFrame.AddrPC.Offset = ep->ContextRecord->Pc;
-  StackFrame.AddrPC.Mode = AddrModeFlat;
-  StackFrame.AddrStack.Offset = ep->ContextRecord->Sp;
-  StackFrame.AddrStack.Mode = AddrModeFlat;
-#if defined(_M_ARM64)
-  StackFrame.AddrFrame.Offset = ep->ContextRecord->Fp;
-#else
-  StackFrame.AddrFrame.Offset = ep->ContextRecord->R11;
-#endif
-  StackFrame.AddrFrame.Mode = AddrModeFlat;
-#endif
-
-  HANDLE hProcess = GetCurrentProcess();
-  HANDLE hThread = GetCurrentThread();
-  PrintStackTraceForThread(llvm::errs(), hProcess, hThread, StackFrame,
-                           ep->ContextRecord);
-
-  _exit(ep->ExceptionRecord->ExceptionCode);
+  LocalPrintStackTrace(llvm::errs(), ep->ContextRecord);
+
+  return EXCEPTION_EXECUTE_HANDLER;
 }
 
 static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) {
Index: llvm/lib/Support/CrashRecoveryContext.cpp
===================================================================
--- llvm/lib/Support/CrashRecoveryContext.cpp
+++ llvm/lib/Support/CrashRecoveryContext.cpp
@@ -13,6 +13,9 @@
 #include "llvm/Support/ThreadLocal.h"
 #include <mutex>
 #include <setjmp.h>
+#if defined(_WIN32)
+#include <windows.h>
+#endif
 using namespace llvm;
 
 namespace {
@@ -54,7 +57,7 @@
 #endif
   }
 
-  void HandleCrash() {
+  void HandleCrash(int retCode) {
     // Eliminate the current context entry, to avoid re-entering in case the
     // cleanup code crashes.
     CurrentContext->set(Next);
@@ -62,6 +65,8 @@
     assert(!Failed && "Crash recovery context already failed!");
     Failed = true;
 
+    CRC->RetCode = retCode;
+
     // FIXME: Stash the backtrace.
 
     // Jump back to the RunSafely we were called under.
@@ -171,6 +176,9 @@
 static void installExceptionOrSignalHandlers() {}
 static void uninstallExceptionOrSignalHandlers() {}
 
+// In Signals.inc
+LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep);
+
 bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
   if (!gCrashRecoveryEnabled) {
     Fn();
@@ -178,9 +186,15 @@
   }
 
   bool Result = true;
+  // FIXME error: cannot compile this 'this' captured by SEH yet
+  CrashRecoveryContext *This = this;
   __try {
     Fn();
-  } __except (1) { // Catch any exception.
+  } __except (This->EnableExceptionHandler
+                  ? LLVMUnhandledExceptionFilter(GetExceptionInformation())
+                  : 1) {
+    // assert(false);
+    This->RetCode = GetExceptionCode();
     Result = false;
   }
   return Result;
@@ -237,7 +251,8 @@
   // implementation if we so choose.
 
   // Handle the crash
-  const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash();
+  const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(
+      (int)ExceptionInfo->ExceptionRecord->ExceptionCode);
 
   // Note that we don't actually get here because HandleCrash calls
   // longjmp, which means the HandleCrash function never returns.
@@ -320,7 +335,7 @@
   sigprocmask(SIG_UNBLOCK, &SigMask, nullptr);
 
   if (CRCI)
-    const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash();
+    const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(Signal);
 }
 
 static void installExceptionOrSignalHandlers() {
@@ -364,7 +379,7 @@
 void CrashRecoveryContext::HandleCrash() {
   CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
   assert(CRCI && "Crash recovery context never initialized!");
-  CRCI->HandleCrash();
+  CRCI->HandleCrash(-1);
 }
 
 // FIXME: Portability.
Index: llvm/include/llvm/Support/CrashRecoveryContext.h
===================================================================
--- llvm/include/llvm/Support/CrashRecoveryContext.h
+++ llvm/include/llvm/Support/CrashRecoveryContext.h
@@ -100,6 +100,15 @@
   /// Explicitly trigger a crash recovery in the current process, and
   /// return failure from RunSafely(). This function does not return.
   void HandleCrash();
+
+  /// In case of a crash, this is the crash identifier
+  int RetCode{};
+
+  /// Selects whether the global exception handler should be called. When this
+  /// is active, a crash has the same side-effect as uncatched code (callstack
+  /// print and minidump), except that here we recover the execution flow after
+  /// the call to RunSafely().
+  bool EnableExceptionHandler{};
 };
 
 /// Abstract base class of cleanup handlers.
Index: clang/tools/driver/driver.cpp
===================================================================
--- clang/tools/driver/driver.cpp
+++ clang/tools/driver/driver.cpp
@@ -30,6 +30,8 @@
 #include "llvm/Option/OptTable.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Host.h"
@@ -318,6 +320,8 @@
   return 1;
 }
 
+int ClangDriverMain(SmallVectorImpl<const char *> &argv);
+
 int main(int argc_, const char **argv_) {
   noteBottomOfStack();
   llvm::InitLLVM X(argc_, argv_);
@@ -327,6 +331,19 @@
     return 1;
 
   llvm::InitializeAllTargets();
+  return ClangDriverMain(argv);
+}
+
+int ClangDriverMain(SmallVectorImpl<const char *> &argv) {
+  static LLVM_THREAD_LOCAL bool EnterPE = true;
+  if (EnterPE) {
+    llvm::sys::DynamicLibrary::AddSymbol("ClangDriverMain",
+                                         (void *)(intptr_t)&ClangDriverMain);
+    EnterPE = false;
+  } else {
+    llvm::cl::ResetAllOptionOccurrences();
+  }
+
   auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(argv[0]);
 
   llvm::BumpPtrAllocator A;
@@ -503,7 +520,7 @@
 
 #ifdef _WIN32
   // Exit status should not be negative on Win32, unless abnormal termination.
-  // Once abnormal termiation was caught, negative status should not be
+  // Once abnormal termination was caught, negative status should not be
   // propagated.
   if (Res < 0)
     Res = 1;
Index: clang/lib/Driver/Job.cpp
===================================================================
--- clang/lib/Driver/Job.cpp
+++ clang/lib/Driver/Job.cpp
@@ -19,8 +19,11 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Program.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -313,6 +316,8 @@
   Environment.push_back(nullptr);
 }
 
+LLVM_THREAD_LOCAL bool Command::ReenterTool = true;
+
 int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
                      std::string *ErrMsg, bool *ExecutionFailed) const {
   if (PrintInputFilenames) {
@@ -321,7 +326,7 @@
     llvm::outs().flush();
   }
 
-  SmallVector<const char*, 128> Argv;
+  SmallVector<const char *, 128> Argv;
 
   Optional<ArrayRef<StringRef>> Env;
   std::vector<StringRef> ArgvVectorStorage;
@@ -332,42 +337,81 @@
     Env = makeArrayRef(ArgvVectorStorage);
   }
 
+  typedef int (*ClangDriverMainFunc)(SmallVectorImpl<const char *> &);
+  ClangDriverMainFunc ClangDriverMain = nullptr;
+
+  if (ReenterTool) {
+    StringRef F = llvm::sys::path::filename(Executable);
+    if (F.endswith_lower(".exe"))
+      F = F.drop_back(4);
+    for (auto &A : {"clang", "clang++", "clang-cl", "clang-cpp"}) {
+      if (F.equals_lower(A)) {
+        ClangDriverMain = (ClangDriverMainFunc)(intptr_t)
+            llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
+                "ClangDriverMain");
+        break;
+      }
+    }
+  }
+
   if (ResponseFile == nullptr) {
     Argv.push_back(Executable);
     Argv.append(Arguments.begin(), Arguments.end());
-    Argv.push_back(nullptr);
-
-    auto Args = llvm::toStringRefArray(Argv.data());
-    return llvm::sys::ExecuteAndWait(
-        Executable, Args, Env, Redirects, /*secondsToWait*/ 0,
-        /*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
+    if (!ClangDriverMain)
+      Argv.push_back(nullptr);
+  } else {
+    // If the command is too large, we need to put arguments in a response file.
+    std::string RespContents;
+    llvm::raw_string_ostream SS(RespContents);
+
+    // Write file contents and build the Argv vector
+    writeResponseFile(SS);
+    buildArgvForResponseFile(Argv);
+    if (!ClangDriverMain)
+      Argv.push_back(nullptr);
+    SS.flush();
+
+    // Save the response file in the appropriate encoding
+    if (std::error_code EC = writeFileWithEncoding(
+            ResponseFile, RespContents, Creator.getResponseFileEncoding())) {
+      if (ErrMsg)
+        *ErrMsg = EC.message();
+      if (ExecutionFailed)
+        *ExecutionFailed = true;
+      return -1;
+    }
   }
 
-  // We need to put arguments in a response file (command is too large)
-  // Open stream to store the response file contents
-  std::string RespContents;
-  llvm::raw_string_ostream SS(RespContents);
-
-  // Write file contents and build the Argv vector
-  writeResponseFile(SS);
-  buildArgvForResponseFile(Argv);
-  Argv.push_back(nullptr);
-  SS.flush();
-
-  // Save the response file in the appropriate encoding
-  if (std::error_code EC = writeFileWithEncoding(
-          ResponseFile, RespContents, Creator.getResponseFileEncoding())) {
-    if (ErrMsg)
-      *ErrMsg = EC.message();
+  if (ClangDriverMain) {
     if (ExecutionFailed)
-      *ExecutionFailed = true;
-    return -1;
-  }
+      *ExecutionFailed = false;
 
-  auto Args = llvm::toStringRefArray(Argv.data());
-  return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects,
-                                   /*secondsToWait*/ 0,
-                                   /*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
+    static bool CRCEnabled{};
+    if (!CRCEnabled) {
+      llvm::CrashRecoveryContext::Enable();
+      CRCEnabled = true;
+    }
+
+    llvm::CrashRecoveryContext CRC;
+    CRC.EnableExceptionHandler = true;
+
+    const void *PrettyState = llvm::SavePrettyStackState();
+
+    int Ret = 0;
+    auto ExecuteClangMain = [&]() { Ret = ClangDriverMain(Argv); };
+
+    if (!CRC.RunSafely(ExecuteClangMain)) {
+      llvm::RestorePrettyStackState(PrettyState);
+      return CRC.RetCode;
+    }
+    return Ret;
+  } else {
+    auto Args = llvm::toStringRefArray(Argv.data());
+    return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects,
+                                     /*secondsToWait*/ 0,
+                                     /*memoryLimit*/ 0, ErrMsg,
+                                     ExecutionFailed);
+  }
 }
 
 FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -1333,6 +1333,10 @@
 
   BuildJobs(C);
 
+  // Call a new clang.exe for rendering the preprocessed output, to minimize the
+  // chances of a crash (in case this function was called due to an exception)
+  Command::ReenterTool = false;
+
   // If there were errors building the compilation, quit now.
   if (Trap.hasErrorOccurred()) {
     Diag(clang::diag::note_drv_command_failed_diag_msg)
Index: clang/include/clang/Driver/Job.h
===================================================================
--- clang/include/clang/Driver/Job.h
+++ clang/include/clang/Driver/Job.h
@@ -130,6 +130,11 @@
 
   /// Set whether to print the input filenames when executing.
   void setPrintInputFilenames(bool P) { PrintInputFilenames = P; }
+
+  /// When set, we will try re-entering this process for the CC1 command
+  /// execution, instead of creating a new process. This is an optimization for
+  /// speed.
+  static LLVM_THREAD_LOCAL bool ReenterTool;
 };
 
 /// Like Command, but with a fallback which is executed in case
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to