[Lldb-commits] [lldb] 83a6a0a - [lldb] Print lldbassert to debugger diagnostics

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Tue Jun 13 20:46:39 PDT 2023


Author: Jonas Devlieghere
Date: 2023-06-13T20:46:33-07:00
New Revision: 83a6a0a620476d2fa181cb663ccbf06cc9d7a24f

URL: https://github.com/llvm/llvm-project/commit/83a6a0a620476d2fa181cb663ccbf06cc9d7a24f
DIFF: https://github.com/llvm/llvm-project/commit/83a6a0a620476d2fa181cb663ccbf06cc9d7a24f.diff

LOG: [lldb] Print lldbassert to debugger diagnostics

When hitting an lldbassert in a non-assert build, we emit a blurb
including the assertion, the triggering file and line and a pretty
backtrace leading up to the issue. Currently, this is all printed to
stderr. That's fine on the command line, but when used as library, for
example from Xcode, this information doesn't make it to the user. This
patch uses the diagnostic infrastructure to report LLDB asserts as
diagnostic events.

The patch is slightly more complicated than I would've liked because of
layering. lldbassert is part of Utility while the debugger diagnostics
are implemented in Core.

Differential revision: https://reviews.llvm.org/D152866

Added: 
    

Modified: 
    lldb/include/lldb/Core/Debugger.h
    lldb/include/lldb/Utility/LLDBAssert.h
    lldb/source/API/SystemInitializerFull.cpp
    lldb/source/Core/Debugger.cpp
    lldb/source/Utility/LLDBAssert.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h
index b63597fc71b4c..4005bdbddacca 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -128,6 +128,9 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
                                         const ExecutionContext *exe_ctx,
                                         const Address *addr, Stream &s);
 
+  static void AssertCallback(llvm::StringRef message, llvm::StringRef backtrace,
+                             llvm::StringRef prompt);
+
   void Clear();
 
   bool GetAsyncExecution();

diff  --git a/lldb/include/lldb/Utility/LLDBAssert.h b/lldb/include/lldb/Utility/LLDBAssert.h
index 524f56fd77c80..aeef3e51e20a8 100644
--- a/lldb/include/lldb/Utility/LLDBAssert.h
+++ b/lldb/include/lldb/Utility/LLDBAssert.h
@@ -9,6 +9,8 @@
 #ifndef LLDB_UTILITY_LLDBASSERT_H
 #define LLDB_UTILITY_LLDBASSERT_H
 
+#include "llvm/ADT/StringRef.h"
+
 #ifndef NDEBUG
 #define lldbassert(x) assert(x)
 #else
@@ -29,6 +31,12 @@
 namespace lldb_private {
 void lldb_assert(bool expression, const char *expr_text, const char *func,
                  const char *file, unsigned int line);
+
+typedef void (*LLDBAssertCallback)(llvm::StringRef message,
+                                   llvm::StringRef backtrace,
+                                   llvm::StringRef prompt);
+
+void SetLLDBAssertCallback(LLDBAssertCallback callback);
 } // namespace lldb_private
 
 #endif // LLDB_UTILITY_LLDBASSERT_H

diff  --git a/lldb/source/API/SystemInitializerFull.cpp b/lldb/source/API/SystemInitializerFull.cpp
index 521aecf36fd8b..27319debc8582 100644
--- a/lldb/source/API/SystemInitializerFull.cpp
+++ b/lldb/source/API/SystemInitializerFull.cpp
@@ -78,6 +78,9 @@ llvm::Error SystemInitializerFull::Initialize() {
   // Settings must be initialized AFTER PluginManager::Initialize is called.
   Debugger::SettingsInitialize();
 
+  // Use the Debugger's LLDBAssert callback.
+  SetLLDBAssertCallback(Debugger::AssertCallback);
+
   return llvm::Error::success();
 }
 

diff  --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index ad177637f45b4..6f43cc608c2ce 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -1352,6 +1352,13 @@ bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
                               function_changed, initial_function);
 }
 
+void Debugger::AssertCallback(llvm::StringRef message,
+                              llvm::StringRef backtrace,
+                              llvm::StringRef prompt) {
+  Debugger::ReportError(
+      llvm::formatv("{0}\n{1}{2}", message, backtrace, prompt).str());
+}
+
 void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
                                   void *baton) {
   // For simplicity's sake, I am not going to deal with how to close down any

diff  --git a/lldb/source/Utility/LLDBAssert.cpp b/lldb/source/Utility/LLDBAssert.cpp
index 17689582cdc58..29bcacb6ad24c 100644
--- a/lldb/source/Utility/LLDBAssert.cpp
+++ b/lldb/source/Utility/LLDBAssert.cpp
@@ -8,7 +8,7 @@
 
 #include "lldb/Utility/LLDBAssert.h"
 #include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -16,12 +16,21 @@
 #include <os/log.h>
 #endif
 
-using namespace llvm;
-using namespace lldb_private;
+namespace lldb_private {
 
-void lldb_private::lldb_assert(bool expression, const char *expr_text,
-                               const char *func, const char *file,
-                               unsigned int line) {
+static void DefaultAssertCallback(llvm::StringRef message,
+                                  llvm::StringRef backtrace,
+                                  llvm::StringRef prompt) {
+  llvm::errs() << message << '\n';
+  llvm::errs() << backtrace; // Backtrace includes a newline.
+  llvm::errs() << prompt << '\n';
+}
+
+static std::atomic<LLDBAssertCallback> g_lldb_assert_callback =
+    &DefaultAssertCallback;
+
+void lldb_assert(bool expression, const char *expr_text, const char *func,
+                 const char *file, unsigned int line) {
   if (LLVM_LIKELY(expression))
     return;
 
@@ -35,10 +44,21 @@ void lldb_private::lldb_assert(bool expression, const char *expr_text,
 
   // Print a warning and encourage the user to file a bug report, similar to
   // LLVM’s crash handler, and then return execution.
-  errs() << format("Assertion failed: (%s), function %s, file %s, line %u\n",
-                   expr_text, func, file, line);
-  errs() << "backtrace leading to the failure:\n";
-  llvm::sys::PrintStackTrace(errs());
-  errs() << "please file a bug report against lldb reporting this failure "
-            "log, and as many details as possible\n";
+  std::string buffer;
+  llvm::raw_string_ostream backtrace(buffer);
+  llvm::sys::PrintStackTrace(backtrace);
+
+  (*g_lldb_assert_callback.load())(
+      llvm::formatv("Assertion failed: ({0}), function {1}, file {2}, line {3}",
+                    expr_text, func, file, line)
+          .str(),
+      backtrace.str(),
+      "Please file a bug report against lldb reporting this failure log, and "
+      "as many details as possible");
 }
+
+void SetLLDBAssertCallback(LLDBAssertCallback callback) {
+  g_lldb_assert_callback.exchange(callback);
+}
+
+} // namespace lldb_private


        


More information about the lldb-commits mailing list