static void PrintStackTraceOnError();
+ static void PrintDiagnosticsOnError();
+
static void Terminate();
// Deprecated, use the one that takes a source_init_files bool.
--- /dev/null
+//===-- Diagnostics.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_UTILITY_DIAGNOSTICS_H
+#define LLDB_UTILITY_DIAGNOSTICS_H
+
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Log.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Error.h"
+
+#include <functional>
+#include <mutex>
+#include <vector>
+
+namespace lldb_private {
+
+/// Diagnostics are a collection of files to help investigate bugs and
+/// troubleshoot issues. Any part of the debugger can register itself with the
+/// help of a callback to emit one or more files into the diagnostic directory.
+class Diagnostics {
+public:
+ Diagnostics();
+ ~Diagnostics();
+
+ /// Gather diagnostics in the given directory.
+ llvm::Error Create(const FileSpec &dir);
+
+ /// Gather diagnostics and print a message to the given output stream.
+ bool Dump(llvm::raw_ostream &stream);
+
+ using Callback = std::function<llvm::Error(const FileSpec &)>;
+
+ void AddCallback(Callback callback);
+
+ static Diagnostics &Instance();
+ static void Initialize();
+ static void Terminate();
+
+private:
+ static llvm::Optional<Diagnostics> &InstanceImpl();
+
+ llvm::SmallVector<Callback, 4> m_callbacks;
+ std::mutex m_callbacks_mutex;
+};
+
+} // namespace lldb_private
+
+#endif
#include "lldb/Target/Process.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Utility/Args.h"
+#include "lldb/Utility/Diagnostics.h"
#include "lldb/Utility/State.h"
#include "lldb/Version/Version.h"
llvm::sys::PrintStackTraceOnErrorSignal(executable);
}
+static void DumpDiagnostics(void *cookie) {
+ Diagnostics::Instance().Dump(llvm::errs());
+}
+
+void SBDebugger::PrintDiagnosticsOnError() {
+ LLDB_INSTRUMENT();
+
+ llvm::sys::AddSignalHandler(&DumpDiagnostics, nullptr);
+}
+
void SBDebugger::Terminate() {
LLDB_INSTRUMENT();
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadList.h"
#include "lldb/Utility/AnsiTerminal.h"
+#include "lldb/Utility/Diagnostics.h"
#include "lldb/Utility/Event.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Listener.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/Socket.h"
+#include "lldb/Target/Statistics.h"
+#include "lldb/Utility/Diagnostics.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Timer.h"
#include "lldb/Version/Version.h"
InitializeLldbChannel();
+ Diagnostics::Initialize();
FileSystem::Initialize();
HostInfo::Initialize(m_shlib_dir_helper);
HostInfo::Terminate();
Log::DisableAllLogChannels();
FileSystem::Terminate();
+ Diagnostics::Terminate();
}
DataBufferLLVM.cpp
DataEncoder.cpp
DataExtractor.cpp
+ Diagnostics.cpp
Environment.cpp
Event.cpp
FileSpec.cpp
--- /dev/null
+//===-- Diagnostics.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/Diagnostics.h"
+#include "lldb/Utility/LLDBAssert.h"
+
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace lldb_private;
+using namespace lldb;
+using namespace llvm;
+
+void Diagnostics::Initialize() {
+ lldbassert(!InstanceImpl() && "Already initialized.");
+ InstanceImpl().emplace();
+}
+
+void Diagnostics::Terminate() {
+ lldbassert(InstanceImpl() && "Already terminated.");
+ InstanceImpl().reset();
+}
+
+Optional<Diagnostics> &Diagnostics::InstanceImpl() {
+ static Optional<Diagnostics> g_diagnostics;
+ return g_diagnostics;
+}
+
+Diagnostics &Diagnostics::Instance() { return *InstanceImpl(); }
+
+Diagnostics::Diagnostics() {}
+
+Diagnostics::~Diagnostics() {}
+
+void Diagnostics::AddCallback(Callback callback) {
+ std::lock_guard<std::mutex> guard(m_callbacks_mutex);
+ m_callbacks.push_back(callback);
+}
+
+bool Diagnostics::Dump(raw_ostream &stream) {
+ SmallString<128> diagnostics_dir;
+ std::error_code ec =
+ sys::fs::createUniqueDirectory("diagnostics", diagnostics_dir);
+ if (ec) {
+ stream << "unable to create diagnostic dir: "
+ << toString(errorCodeToError(ec)) << '\n';
+ return false;
+ }
+
+ stream << "LLDB diagnostics written to " << diagnostics_dir << "\n";
+ stream << "Please include the directory content when filing a bug report\n";
+
+ Error error = Create(FileSpec(diagnostics_dir.str()));
+ if (error) {
+ stream << toString(std::move(error)) << '\n';
+ return false;
+ }
+
+ return true;
+}
+
+Error Diagnostics::Create(const FileSpec &dir) {
+ for (Callback c : m_callbacks) {
+ if (Error err = c(dir))
+ return err;
+ }
+ return Error::success();
+}
<< '\n';
return 1;
}
+
+ // Setup LLDB signal handlers once the debugger has been initialized.
+ SBDebugger::PrintDiagnosticsOnError();
+
SBHostOS::ThreadCreated("<lldb.driver.main-thread>");
signal(SIGINT, sigint_handler);