diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/API/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lldb/source/API/SBDebugger.cpp | 25 | ||||
-rw-r--r-- | lldb/source/API/SBInitializerOptions.cpp | 49 | ||||
-rw-r--r-- | lldb/source/API/SystemInitializerFull.cpp | 8 | ||||
-rw-r--r-- | lldb/source/API/SystemInitializerFull.h | 2 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectReproducer.cpp | 128 | ||||
-rw-r--r-- | lldb/source/Core/Debugger.cpp | 18 | ||||
-rw-r--r-- | lldb/source/Host/common/HostInfoBase.cpp | 33 | ||||
-rw-r--r-- | lldb/source/Initialization/SystemInitializerCommon.cpp | 17 | ||||
-rw-r--r-- | lldb/source/Initialization/SystemLifetimeManager.cpp | 10 | ||||
-rw-r--r-- | lldb/source/Utility/Reproducer.cpp | 65 |
11 files changed, 162 insertions, 194 deletions
diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt index 3c5f4ddb43f..d2ab24c7c01 100644 --- a/lldb/source/API/CMakeLists.txt +++ b/lldb/source/API/CMakeLists.txt @@ -29,6 +29,7 @@ add_lldb_library(liblldb SHARED SBFrame.cpp SBFunction.cpp SBHostOS.cpp + SBInitializerOptions.cpp SBInstruction.cpp SBInstructionList.cpp SBLanguageRuntime.cpp diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp index a7217964abf..af343233c90 100644 --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -125,13 +125,23 @@ SBDebugger &SBDebugger::operator=(const SBDebugger &rhs) { } void SBDebugger::Initialize() { + SBInitializerOptions options; + SBDebugger::Initialize(options); +} + +lldb::SBError SBDebugger::Initialize(SBInitializerOptions &options) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); if (log) log->Printf("SBDebugger::Initialize ()"); - g_debugger_lifetime->Initialize(llvm::make_unique<SystemInitializerFull>(), - LoadPlugin); + SBError error; + if (auto e = g_debugger_lifetime->Initialize( + llvm::make_unique<SystemInitializerFull>(), *options.m_opaque_up, + LoadPlugin)) { + error.SetError(Status(std::move(e))); + } + return error; } void SBDebugger::Terminate() { g_debugger_lifetime->Terminate(); } @@ -1057,17 +1067,6 @@ const char *SBDebugger::GetReproducerPath() const { : nullptr); } -SBError SBDebugger::ReplayReproducer(const char *p) { - SBError sb_error; - if (m_opaque_sp) { - auto error = - m_opaque_sp->SetReproducerReplay(llvm::StringRef::withNullAsEmpty(p)); - std::string error_str = llvm::toString(std::move(error)); - sb_error.ref().SetErrorString(error_str); - } - return sb_error; -} - ScriptLanguage SBDebugger::GetScriptLanguage() const { return (m_opaque_sp ? m_opaque_sp->GetScriptLanguage() : eScriptLanguageNone); } diff --git a/lldb/source/API/SBInitializerOptions.cpp b/lldb/source/API/SBInitializerOptions.cpp new file mode 100644 index 00000000000..8d8ec28190e --- /dev/null +++ b/lldb/source/API/SBInitializerOptions.cpp @@ -0,0 +1,49 @@ +//===-- SBInitializerOptions.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/API/SBInitializerOptions.h" +#include "lldb/Initialization/SystemInitializer.h" + +using namespace lldb; +using namespace lldb_private; + +SBInitializerOptions::SBInitializerOptions(const SBInitializerOptions &rhs) { + m_opaque_up.reset(new InitializerOptions()); + *(m_opaque_up.get()) = rhs.ref(); +} + +const SBInitializerOptions &SBInitializerOptions:: +operator=(const SBInitializerOptions &rhs) { + if (this != &rhs) { + this->ref() = rhs.ref(); + } + return *this; +} + +SBInitializerOptions::~SBInitializerOptions() {} + +SBInitializerOptions::SBInitializerOptions() { + m_opaque_up.reset(new InitializerOptions()); +} + +void SBInitializerOptions::SetCaptureReproducer(bool b) { + m_opaque_up->reproducer_capture = b; +} + +void SBInitializerOptions::SetReplayReproducer(bool b) { + m_opaque_up->reproducer_replay = b; +} + +void SBInitializerOptions::SetReproducerPath(const char *path) { + m_opaque_up->reproducer_path = path; +} + +InitializerOptions &SBInitializerOptions::ref() const { + return *(m_opaque_up.get()); +} diff --git a/lldb/source/API/SystemInitializerFull.cpp b/lldb/source/API/SystemInitializerFull.cpp index 671077ca0b0..937604425b4 100644 --- a/lldb/source/API/SystemInitializerFull.cpp +++ b/lldb/source/API/SystemInitializerFull.cpp @@ -263,8 +263,10 @@ SystemInitializerFull::SystemInitializerFull() {} SystemInitializerFull::~SystemInitializerFull() {} -void SystemInitializerFull::Initialize() { - SystemInitializerCommon::Initialize(); +llvm::Error +SystemInitializerFull::Initialize(const InitializerOptions &options) { + if (auto e = SystemInitializerCommon::Initialize(options)) + return e; ObjectFileELF::Initialize(); ObjectFileMachO::Initialize(); @@ -396,6 +398,8 @@ void SystemInitializerFull::Initialize() { // AFTER PluginManager::Initialize is called. Debugger::SettingsInitialize(); + + return llvm::Error::success(); } void SystemInitializerFull::InitializeSWIG() { diff --git a/lldb/source/API/SystemInitializerFull.h b/lldb/source/API/SystemInitializerFull.h index 9cfc6896da6..b0cf476e919 100644 --- a/lldb/source/API/SystemInitializerFull.h +++ b/lldb/source/API/SystemInitializerFull.h @@ -26,7 +26,7 @@ public: SystemInitializerFull(); ~SystemInitializerFull() override; - void Initialize() override; + llvm::Error Initialize(const InitializerOptions &options) override; void Terminate() override; private: diff --git a/lldb/source/Commands/CommandObjectReproducer.cpp b/lldb/source/Commands/CommandObjectReproducer.cpp index 03a3e230980..f393f17d9ae 100644 --- a/lldb/source/Commands/CommandObjectReproducer.cpp +++ b/lldb/source/Commands/CommandObjectReproducer.cpp @@ -19,65 +19,6 @@ using namespace lldb; using namespace lldb_private; -static void AppendErrorToResult(llvm::Error e, CommandReturnObject &result) { - std::string error_str = llvm::toString(std::move(e)); - result.AppendErrorWithFormat("%s", error_str.c_str()); -} - -class CommandObjectReproducerCaptureEnable : public CommandObjectParsed { -public: - CommandObjectReproducerCaptureEnable(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "reproducer capture enable", - "Enable gathering information for reproducer", - nullptr) {} - - ~CommandObjectReproducerCaptureEnable() override = default; - -protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { - if (!command.empty()) { - result.AppendErrorWithFormat("'%s' takes no arguments", - m_cmd_name.c_str()); - return false; - } - - if (auto e = m_interpreter.GetDebugger().SetReproducerCapture(true)) { - AppendErrorToResult(std::move(e), result); - return false; - } - - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); - } -}; - -class CommandObjectReproducerCaptureDisable : public CommandObjectParsed { -public: - CommandObjectReproducerCaptureDisable(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "reproducer capture enable", - "Disable gathering information for reproducer", - nullptr) {} - - ~CommandObjectReproducerCaptureDisable() override = default; - -protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { - if (!command.empty()) { - result.AppendErrorWithFormat("'%s' takes no arguments", - m_cmd_name.c_str()); - return false; - } - - if (auto e = m_interpreter.GetDebugger().SetReproducerCapture(false)) { - AppendErrorToResult(std::move(e), result); - return false; - } - - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); - } -}; - class CommandObjectReproducerGenerate : public CommandObjectParsed { public: CommandObjectReproducerGenerate(CommandInterpreter &interpreter) @@ -110,82 +51,47 @@ protected: } }; -class CommandObjectReproducerReplay : public CommandObjectParsed { +class CommandObjectReproducerStatus : public CommandObjectParsed { public: - CommandObjectReproducerReplay(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "reproducer replay", - "Replay a reproducer.", nullptr) { - CommandArgumentEntry arg1; - CommandArgumentData path_arg; - - // Define the first (and only) variant of this arg. - path_arg.arg_type = eArgTypePath; - path_arg.arg_repetition = eArgRepeatPlain; - - // There is only one variant this argument could be; put it into the - // argument entry. - arg1.push_back(path_arg); - - // Push the data for the first argument into the m_arguments vector. - m_arguments.push_back(arg1); - } + CommandObjectReproducerStatus(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "reproducer status", + "Show the current reproducer status.", nullptr) {} - ~CommandObjectReproducerReplay() override = default; + ~CommandObjectReproducerStatus() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - if (command.empty()) { - result.AppendErrorWithFormat( - "'%s' takes a single argument: the reproducer path", - m_cmd_name.c_str()); + if (!command.empty()) { + result.AppendErrorWithFormat("'%s' takes no arguments", + m_cmd_name.c_str()); return false; } auto &r = repro::Reproducer::Instance(); + if (auto generator = r.GetGenerator()) { + result.GetOutputStream() << "Reproducer is in capture mode.\n"; + } else if (auto generator = r.GetLoader()) { + result.GetOutputStream() << "Reproducer is in replay mode.\n"; + } else { - const char *repro_path = command.GetArgumentAtIndex(0); - if (auto e = r.SetReplay(FileSpec(repro_path))) { - std::string error_str = llvm::toString(std::move(e)); - result.AppendErrorWithFormat("%s", error_str.c_str()); - return false; + result.GetOutputStream() << "Reproducer is off.\n"; } - result.SetStatus(eReturnStatusSuccessFinishNoResult); + result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } }; -class CommandObjectReproducerCapture : public CommandObjectMultiword { -private: -public: - CommandObjectReproducerCapture(CommandInterpreter &interpreter) - : CommandObjectMultiword( - interpreter, "reproducer capture", - "Manage gathering of information needed to generate a reproducer.", - NULL) { - LoadSubCommand( - "enable", - CommandObjectSP(new CommandObjectReproducerCaptureEnable(interpreter))); - LoadSubCommand("disable", - CommandObjectSP( - new CommandObjectReproducerCaptureDisable(interpreter))); - } - - ~CommandObjectReproducerCapture() {} -}; - CommandObjectReproducer::CommandObjectReproducer( CommandInterpreter &interpreter) : CommandObjectMultiword(interpreter, "reproducer", "Commands controlling LLDB reproducers.", "log <subcommand> [<command-options>]") { - LoadSubCommand("capture", CommandObjectSP(new CommandObjectReproducerCapture( - interpreter))); LoadSubCommand( "generate", CommandObjectSP(new CommandObjectReproducerGenerate(interpreter))); - LoadSubCommand("replay", CommandObjectSP( - new CommandObjectReproducerReplay(interpreter))); + LoadSubCommand("status", CommandObjectSP( + new CommandObjectReproducerStatus(interpreter))); } CommandObjectReproducer::~CommandObjectReproducer() = default; diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 1f12dc4dbd6..6e86519b501 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -418,24 +418,6 @@ llvm::StringRef Debugger::GetReproducerPath() const { return r.GetReproducerPath().GetCString(); } -llvm::Error Debugger::SetReproducerReplay(llvm::StringRef p) { - llvm::Optional<FileSpec> arg = llvm::None; - - if (!p.empty()) - arg = FileSpec(p); - - return repro::Reproducer::Instance().SetReplay(arg); -} - -llvm::Error Debugger::SetReproducerCapture(bool b) { - llvm::Optional<FileSpec> arg = llvm::None; - - if (b) - arg = HostInfo::GetReproducerTempDir(); - - return repro::Reproducer::Instance().SetCapture(arg); -} - const FormatEntity::Entry *Debugger::GetThreadFormat() const { const uint32_t idx = ePropertyThreadFormat; return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp index e82fec36705..34c362efc9e 100644 --- a/lldb/source/Host/common/HostInfoBase.cpp +++ b/lldb/source/Host/common/HostInfoBase.cpp @@ -194,19 +194,6 @@ FileSpec HostInfoBase::GetGlobalTempDir() { return success ? g_fields->m_lldb_global_tmp_dir : FileSpec(); } -FileSpec HostInfoBase::GetReproducerTempDir() { - static llvm::once_flag g_once_flag; - static bool success = false; - llvm::call_once(g_once_flag, []() { - success = HostInfo::ComputeReproducerTempFileDirectory( - g_fields->m_lldb_global_tmp_dir); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - LLDB_LOG(log, "reproducer temp dir -> `{0}`", - g_fields->m_lldb_global_tmp_dir); - }); - return success ? g_fields->m_lldb_global_tmp_dir : FileSpec(); -} - ArchSpec HostInfoBase::GetAugmentedArchSpec(llvm::StringRef triple) { if (triple.empty()) return ArchSpec(); @@ -289,26 +276,6 @@ bool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) { return true; } -bool HostInfoBase::ComputeReproducerTempFileDirectory(FileSpec &file_spec) { - file_spec.Clear(); - - FileSpec temp_file_spec; - if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec)) - return false; - - temp_file_spec.AppendPathComponent("reproducer"); - if (llvm::sys::fs::create_directory(temp_file_spec.GetPath())) - return false; - - std::string pid_str{llvm::to_string(Host::GetCurrentProcessID())}; - temp_file_spec.AppendPathComponent(pid_str); - if (llvm::sys::fs::create_directory(temp_file_spec.GetPath())) - return false; - - file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); - return true; -} - bool HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec) { // TODO(zturner): Figure out how to compute the header directory for all // platforms. diff --git a/lldb/source/Initialization/SystemInitializerCommon.cpp b/lldb/source/Initialization/SystemInitializerCommon.cpp index 221dc8c58b7..d1d55fcfde7 100644 --- a/lldb/source/Initialization/SystemInitializerCommon.cpp +++ b/lldb/source/Initialization/SystemInitializerCommon.cpp @@ -19,6 +19,7 @@ #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/Reproducer.h" #include "lldb/Utility/Timer.h" #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) @@ -35,12 +36,14 @@ #include <string> using namespace lldb_private; +using namespace lldb_private::repro; SystemInitializerCommon::SystemInitializerCommon() {} SystemInitializerCommon::~SystemInitializerCommon() {} -void SystemInitializerCommon::Initialize() { +llvm::Error +SystemInitializerCommon::Initialize(const InitializerOptions &options) { #if defined(_MSC_VER) const char *disable_crash_dialog_var = getenv("LLDB_DISABLE_CRASH_DIALOG"); if (disable_crash_dialog_var && @@ -63,6 +66,15 @@ void SystemInitializerCommon::Initialize() { } #endif + ReproducerMode mode = ReproducerMode::Off; + if (options.reproducer_capture) + mode = ReproducerMode::Capture; + if (options.reproducer_replay) + mode = ReproducerMode::Replay; + + if (auto e = Reproducer::Initialize(mode, FileSpec(options.reproducer_path))) + return e; + FileSystem::Initialize(); Log::Initialize(); HostInfo::Initialize(); @@ -89,6 +101,8 @@ void SystemInitializerCommon::Initialize() { #if defined(_MSC_VER) ProcessWindowsLog::Initialize(); #endif + + return llvm::Error::success(); } void SystemInitializerCommon::Terminate() { @@ -109,4 +123,5 @@ void SystemInitializerCommon::Terminate() { HostInfo::Terminate(); Log::DisableAllLogChannels(); FileSystem::Terminate(); + Reproducer::Terminate(); } diff --git a/lldb/source/Initialization/SystemLifetimeManager.cpp b/lldb/source/Initialization/SystemLifetimeManager.cpp index 4d271787833..65431bf6017 100644 --- a/lldb/source/Initialization/SystemLifetimeManager.cpp +++ b/lldb/source/Initialization/SystemLifetimeManager.cpp @@ -24,9 +24,9 @@ SystemLifetimeManager::~SystemLifetimeManager() { "SystemLifetimeManager destroyed without calling Terminate!"); } -void SystemLifetimeManager::Initialize( +llvm::Error SystemLifetimeManager::Initialize( std::unique_ptr<SystemInitializer> initializer, - LoadPluginCallbackType plugin_callback) { + const InitializerOptions &options, LoadPluginCallbackType plugin_callback) { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (!m_initialized) { assert(!m_initializer && "Attempting to call " @@ -35,9 +35,13 @@ void SystemLifetimeManager::Initialize( m_initialized = true; m_initializer = std::move(initializer); - m_initializer->Initialize(); + if (auto e = m_initializer->Initialize(options)) + return e; + Debugger::Initialize(plugin_callback); } + + return llvm::Error::success(); } void SystemLifetimeManager::Terminate() { diff --git a/lldb/source/Utility/Reproducer.cpp b/lldb/source/Utility/Reproducer.cpp index 0048a11970d..a6b5fa849c2 100644 --- a/lldb/source/Utility/Reproducer.cpp +++ b/lldb/source/Utility/Reproducer.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Utility/Reproducer.h" +#include "lldb/Utility/LLDBAssert.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Threading.h" @@ -18,8 +19,46 @@ using namespace lldb_private::repro; using namespace llvm; using namespace llvm::yaml; -Reproducer &Reproducer::Instance() { - static Reproducer g_reproducer; +Reproducer &Reproducer::Instance() { return *InstanceImpl(); } + +llvm::Error Reproducer::Initialize(ReproducerMode mode, + llvm::Optional<FileSpec> root) { + lldbassert(!InstanceImpl() && "Already initialized."); + InstanceImpl().emplace(); + + switch (mode) { + case ReproducerMode::Capture: { + if (!root) { + SmallString<128> repro_dir; + auto ec = sys::fs::createUniqueDirectory("reproducer", repro_dir); + if (ec) + return make_error<StringError>( + "unable to create unique reproducer directory", ec); + root.emplace(repro_dir); + } else { + auto ec = sys::fs::create_directories(root->GetPath()); + if (ec) + return make_error<StringError>("unable to create reproducer directory", + ec); + } + return Instance().SetCapture(root); + } break; + case ReproducerMode::Replay: + return Instance().SetReplay(root); + case ReproducerMode::Off: + break; + }; + + return Error::success(); +} + +void Reproducer::Terminate() { + lldbassert(InstanceImpl() && "Already terminated."); + InstanceImpl().reset(); +} + +Optional<Reproducer> &Reproducer::InstanceImpl() { + static Optional<Reproducer> g_reproducer; return g_reproducer; } @@ -59,11 +98,12 @@ llvm::Error Reproducer::SetCapture(llvm::Optional<FileSpec> root) { "cannot generate a reproducer when replay one", inconvertibleErrorCode()); - if (root) - m_generator.emplace(*root); - else + if (!root) { m_generator.reset(); + return Error::success(); + } + m_generator.emplace(*root); return Error::success(); } @@ -75,14 +115,15 @@ llvm::Error Reproducer::SetReplay(llvm::Optional<FileSpec> root) { "cannot replay a reproducer when generating one", inconvertibleErrorCode()); - if (root) { - m_loader.emplace(*root); - if (auto e = m_loader->LoadIndex()) - return e; - } else { + if (!root) { m_loader.reset(); + return Error::success(); } + m_loader.emplace(*root); + if (auto e = m_loader->LoadIndex()) + return e; + return Error::success(); } @@ -153,14 +194,14 @@ llvm::Error Loader::LoadIndex() { auto error_or_file = MemoryBuffer::getFile(index.GetPath()); if (auto err = error_or_file.getError()) - return errorCodeToError(err); + return make_error<StringError>("unable to load reproducer index", err); std::vector<ProviderInfo> provider_info; yaml::Input yin((*error_or_file)->getBuffer()); yin >> provider_info; if (auto err = yin.error()) - return errorCodeToError(err); + return make_error<StringError>("unable to read reproducer index", err); for (auto &info : provider_info) m_provider_info[info.name] = info; |