[llvm] 3df88ec - [Support] Don't print stacktrace if DbgHelp.dll hasn't been loaded yet

Andy Yankovsky via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 8 08:38:06 PST 2022


Author: Andy Yankovsky
Date: 2022-02-08T16:37:36Z
New Revision: 3df88ec335da7c3ed1625014d6f9b05fd5b54f31

URL: https://github.com/llvm/llvm-project/commit/3df88ec335da7c3ed1625014d6f9b05fd5b54f31
DIFF: https://github.com/llvm/llvm-project/commit/3df88ec335da7c3ed1625014d6f9b05fd5b54f31.diff

LOG: [Support] Don't print stacktrace if DbgHelp.dll hasn't been loaded yet

On Windows certain function from `Signals.h` require that `DbgHelp.dll` is loaded. This typically happens when the main program calls `llvm::InitLLVM`, however in some cases main program doesn't do that (e.g. when the application is using LLDB via `liblldb.dll`). This patch adds a safe guard to prevent crashes. More discussion in
https://reviews.llvm.org/D119009.

Reviewed By: aganea

Differential Revision: https://reviews.llvm.org/D119181

Added: 
    

Modified: 
    llvm/lib/Support/Windows/Signals.inc
    llvm/unittests/Support/ProgramTest.cpp
    llvm/utils/unittest/UnitTestMain/TestMain.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc
index 32186bbe51607..fab3886f46dfc 100644
--- a/llvm/lib/Support/Windows/Signals.inc
+++ b/llvm/lib/Support/Windows/Signals.inc
@@ -159,6 +159,10 @@ static fpSymInitialize fSymInitialize;
 typedef BOOL (WINAPI *fpEnumerateLoadedModules)(HANDLE,PENUMLOADED_MODULES_CALLBACK64,PVOID);
 static fpEnumerateLoadedModules fEnumerateLoadedModules;
 
+static bool isDebugHelpInitialized() {
+  return fStackWalk64 && fSymInitialize && fSymSetOptions && fMiniDumpWriteDump;
+}
+
 static bool load64BitDebugHelp(void) {
   HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll");
   if (hLib) {
@@ -181,7 +185,7 @@ static bool load64BitDebugHelp(void) {
     fEnumerateLoadedModules = (fpEnumerateLoadedModules)
       ::GetProcAddress(hLib, "EnumerateLoadedModules64");
   }
-  return fStackWalk64 && fSymInitialize && fSymSetOptions && fMiniDumpWriteDump;
+  return isDebugHelpInitialized();
 }
 
 using namespace llvm;
@@ -296,6 +300,12 @@ static bool findModulesAndOffsets(void **StackTrace, int Depth,
 static void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE hProcess,
                                      HANDLE hThread, STACKFRAME64 &StackFrame,
                                      CONTEXT *Context) {
+  // It's possible that DbgHelp.dll hasn't been loaded yet (e.g. if this
+  // function is called before the main program called `llvm::InitLLVM`).
+  // In this case just return, not stacktrace will be printed.
+  if (!isDebugHelpInitialized())
+    return;
+
   // Initialize the symbol handler.
   fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
   fSymInitialize(hProcess, NULL, TRUE);

diff  --git a/llvm/unittests/Support/ProgramTest.cpp b/llvm/unittests/Support/ProgramTest.cpp
index fbbcd847e3c7a..fdd0478f70515 100644
--- a/llvm/unittests/Support/ProgramTest.cpp
+++ b/llvm/unittests/Support/ProgramTest.cpp
@@ -12,6 +12,7 @@
 #include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/Signals.h"
 #include "gtest/gtest.h"
 #include <stdlib.h>
 #include <thread>
@@ -426,4 +427,28 @@ TEST_F(ProgramEnvTest, TestLockFile) {
   sys::fs::remove(LockedFile);
 }
 
+TEST_F(ProgramEnvTest, TestExecuteWithNoStacktraceHandler) {
+  using namespace llvm::sys;
+
+  if (getenv("LLVM_PROGRAM_TEST_NO_STACKTRACE_HANDLER")) {
+    sys::PrintStackTrace(errs());
+    exit(0);
+  }
+
+  std::string Executable =
+      sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
+  StringRef argv[] = {
+      Executable,
+      "--gtest_filter=ProgramEnvTest.TestExecuteWithNoStacktraceHandler"};
+
+  addEnvVar("LLVM_PROGRAM_TEST_NO_STACKTRACE_HANDLER=1");
+
+  std::string Error;
+  bool ExecutionFailed;
+  int RetCode = ExecuteAndWait(Executable, argv, getEnviron(), {}, 0, 0, &Error,
+                               &ExecutionFailed);
+  EXPECT_FALSE(ExecutionFailed) << Error;
+  ASSERT_EQ(0, RetCode);
+}
+
 } // end anonymous namespace

diff  --git a/llvm/utils/unittest/UnitTestMain/TestMain.cpp b/llvm/utils/unittest/UnitTestMain/TestMain.cpp
index 1be819fab72e6..35ba72ba3fcd3 100644
--- a/llvm/utils/unittest/UnitTestMain/TestMain.cpp
+++ b/llvm/utils/unittest/UnitTestMain/TestMain.cpp
@@ -10,6 +10,7 @@
 #include "llvm/Support/Signals.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include <stdlib.h>
 
 #if defined(_WIN32)
 # include <windows.h>
@@ -21,8 +22,12 @@
 const char *TestMainArgv0;
 
 int main(int argc, char **argv) {
-  llvm::sys::PrintStackTraceOnErrorSignal(argv[0],
-                                          true /* Disable crash reporting */);
+  // Skip setting up signal handlers for tests that need to test things without
+  // them configured.
+  if (!getenv("LLVM_PROGRAM_TEST_NO_STACKTRACE_HANDLER")) {
+    llvm::sys::PrintStackTraceOnErrorSignal(argv[0],
+                                            true /* Disable crash reporting */);
+  }
 
   // Initialize both gmock and gtest.
   testing::InitGoogleMock(&argc, argv);


        


More information about the llvm-commits mailing list