diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Utility/Diagnostics.cpp')
-rw-r--r-- | contrib/llvm-project/lldb/source/Utility/Diagnostics.cpp | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Utility/Diagnostics.cpp b/contrib/llvm-project/lldb/source/Utility/Diagnostics.cpp new file mode 100644 index 000000000000..b2a08165dd6c --- /dev/null +++ b/contrib/llvm-project/lldb/source/Utility/Diagnostics.cpp @@ -0,0 +1,115 @@ +//===-- 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" +#include <optional> + +using namespace lldb_private; +using namespace lldb; +using namespace llvm; + +static constexpr size_t g_num_log_messages = 100; + +void Diagnostics::Initialize() { + lldbassert(!InstanceImpl() && "Already initialized."); + InstanceImpl().emplace(); +} + +void Diagnostics::Terminate() { + lldbassert(InstanceImpl() && "Already terminated."); + InstanceImpl().reset(); +} + +bool Diagnostics::Enabled() { return InstanceImpl().operator bool(); } + +std::optional<Diagnostics> &Diagnostics::InstanceImpl() { + static std::optional<Diagnostics> g_diagnostics; + return g_diagnostics; +} + +Diagnostics &Diagnostics::Instance() { return *InstanceImpl(); } + +Diagnostics::Diagnostics() : m_log_handler(g_num_log_messages) {} + +Diagnostics::~Diagnostics() {} + +Diagnostics::CallbackID Diagnostics::AddCallback(Callback callback) { + std::lock_guard<std::mutex> guard(m_callbacks_mutex); + CallbackID id = m_callback_id++; + m_callbacks.emplace_back(id, callback); + return id; +} + +void Diagnostics::RemoveCallback(CallbackID id) { + std::lock_guard<std::mutex> guard(m_callbacks_mutex); + llvm::erase_if(m_callbacks, + [id](const CallbackEntry &e) { return e.id == id; }); +} + +bool Diagnostics::Dump(raw_ostream &stream) { + Expected<FileSpec> diagnostics_dir = CreateUniqueDirectory(); + if (!diagnostics_dir) { + stream << "unable to create diagnostic dir: " + << toString(diagnostics_dir.takeError()) << '\n'; + return false; + } + + return Dump(stream, *diagnostics_dir); +} + +bool Diagnostics::Dump(raw_ostream &stream, const FileSpec &dir) { + stream << "LLDB diagnostics will be written to " << dir.GetPath() << "\n"; + stream << "Please include the directory content when filing a bug report\n"; + + if (Error error = Create(dir)) { + stream << toString(std::move(error)) << '\n'; + return false; + } + + return true; +} + +llvm::Expected<FileSpec> Diagnostics::CreateUniqueDirectory() { + SmallString<128> diagnostics_dir; + std::error_code ec = + sys::fs::createUniqueDirectory("diagnostics", diagnostics_dir); + if (ec) + return errorCodeToError(ec); + return FileSpec(diagnostics_dir.str()); +} + +Error Diagnostics::Create(const FileSpec &dir) { + if (Error err = DumpDiangosticsLog(dir)) + return err; + + for (CallbackEntry e : m_callbacks) { + if (Error err = e.callback(dir)) + return err; + } + + return Error::success(); +} + +llvm::Error Diagnostics::DumpDiangosticsLog(const FileSpec &dir) const { + FileSpec log_file = dir.CopyByAppendingPathComponent("diagnostics.log"); + std::error_code ec; + llvm::raw_fd_ostream stream(log_file.GetPath(), ec, llvm::sys::fs::OF_None); + if (ec) + return errorCodeToError(ec); + m_log_handler.Dump(stream); + return Error::success(); +} + +void Diagnostics::Report(llvm::StringRef message) { + m_log_handler.Emit(message); +} |