//===-- SBDebugger.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/API/SBDebugger.h" #include "SystemInitializerFull.h" #include "lldb/Utility/Instrumentation.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBCommandInterpreter.h" #include "lldb/API/SBCommandInterpreterRunOptions.h" #include "lldb/API/SBCommandReturnObject.h" #include "lldb/API/SBError.h" #include "lldb/API/SBEvent.h" #include "lldb/API/SBFile.h" #include "lldb/API/SBFrame.h" #include "lldb/API/SBListener.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBSourceManager.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStringList.h" #include "lldb/API/SBStructuredData.h" #include "lldb/API/SBTarget.h" #include "lldb/API/SBThread.h" #include "lldb/API/SBTrace.h" #include "lldb/API/SBTypeCategory.h" #include "lldb/API/SBTypeFilter.h" #include "lldb/API/SBTypeFormat.h" #include "lldb/API/SBTypeNameSpecifier.h" #include "lldb/API/SBTypeSummary.h" #include "lldb/API/SBTypeSynthetic.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/DebuggerEvents.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Progress.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/Host/Config.h" #include "lldb/Host/StreamFile.h" #include "lldb/Host/XML.h" #include "lldb/Initialization/SystemLifetimeManager.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupPlatform.h" #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" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" using namespace lldb; using namespace lldb_private; static llvm::ManagedStatic g_debugger_lifetime; SBError SBInputReader::Initialize( lldb::SBDebugger &sb_debugger, unsigned long (*callback)(void *, lldb::SBInputReader *, lldb::InputReaderAction, char const *, unsigned long), void *a, lldb::InputReaderGranularity b, char const *c, char const *d, bool e) { LLDB_INSTRUMENT_VA(this, sb_debugger, callback, a, b, c, d, e); return SBError(); } void SBInputReader::SetIsDone(bool b) { LLDB_INSTRUMENT_VA(this, b); } bool SBInputReader::IsActive() const { LLDB_INSTRUMENT_VA(this); return false; } SBDebugger::SBDebugger() { LLDB_INSTRUMENT_VA(this); } SBDebugger::SBDebugger(const lldb::DebuggerSP &debugger_sp) : m_opaque_sp(debugger_sp) { LLDB_INSTRUMENT_VA(this, debugger_sp); } SBDebugger::SBDebugger(const SBDebugger &rhs) : m_opaque_sp(rhs.m_opaque_sp) { LLDB_INSTRUMENT_VA(this, rhs); } SBDebugger::~SBDebugger() = default; SBDebugger &SBDebugger::operator=(const SBDebugger &rhs) { LLDB_INSTRUMENT_VA(this, rhs); if (this != &rhs) { m_opaque_sp = rhs.m_opaque_sp; } return *this; } const char *SBDebugger::GetBroadcasterClass() { LLDB_INSTRUMENT(); return ConstString(Debugger::GetStaticBroadcasterClass()).AsCString(); } const char *SBDebugger::GetProgressFromEvent(const lldb::SBEvent &event, uint64_t &progress_id, uint64_t &completed, uint64_t &total, bool &is_debugger_specific) { LLDB_INSTRUMENT_VA(event); const ProgressEventData *progress_data = ProgressEventData::GetEventDataFromEvent(event.get()); if (progress_data == nullptr) return nullptr; progress_id = progress_data->GetID(); completed = progress_data->GetCompleted(); total = progress_data->GetTotal(); is_debugger_specific = progress_data->IsDebuggerSpecific(); ConstString message(progress_data->GetMessage()); return message.AsCString(); } lldb::SBStructuredData SBDebugger::GetProgressDataFromEvent(const lldb::SBEvent &event) { LLDB_INSTRUMENT_VA(event); StructuredData::DictionarySP dictionary_sp = ProgressEventData::GetAsStructuredData(event.get()); if (!dictionary_sp) return {}; SBStructuredData data; data.m_impl_up->SetObjectSP(std::move(dictionary_sp)); return data; } lldb::SBStructuredData SBDebugger::GetDiagnosticFromEvent(const lldb::SBEvent &event) { LLDB_INSTRUMENT_VA(event); StructuredData::DictionarySP dictionary_sp = DiagnosticEventData::GetAsStructuredData(event.get()); if (!dictionary_sp) return {}; SBStructuredData data; data.m_impl_up->SetObjectSP(std::move(dictionary_sp)); return data; } SBBroadcaster SBDebugger::GetBroadcaster() { LLDB_INSTRUMENT_VA(this); SBBroadcaster broadcaster(&m_opaque_sp->GetBroadcaster(), false); return broadcaster; } void SBDebugger::Initialize() { LLDB_INSTRUMENT(); SBError ignored = SBDebugger::InitializeWithErrorHandling(); } lldb::SBError SBDebugger::InitializeWithErrorHandling() { LLDB_INSTRUMENT(); auto LoadPlugin = [](const lldb::DebuggerSP &debugger_sp, const FileSpec &spec, Status &error) -> llvm::sys::DynamicLibrary { llvm::sys::DynamicLibrary dynlib = llvm::sys::DynamicLibrary::getPermanentLibrary(spec.GetPath().c_str()); if (dynlib.isValid()) { typedef bool (*LLDBCommandPluginInit)(lldb::SBDebugger & debugger); lldb::SBDebugger debugger_sb(debugger_sp); // This calls the bool lldb::PluginInitialize(lldb::SBDebugger debugger) // function. // TODO: mangle this differently for your system - on OSX, the first // underscore needs to be removed and the second one stays LLDBCommandPluginInit init_func = (LLDBCommandPluginInit)(uintptr_t)dynlib.getAddressOfSymbol( "_ZN4lldb16PluginInitializeENS_10SBDebuggerE"); if (init_func) { if (init_func(debugger_sb)) return dynlib; else error.SetErrorString("plug-in refused to load " "(lldb::PluginInitialize(lldb::SBDebugger) " "returned false)"); } else { error.SetErrorString("plug-in is missing the required initialization: " "lldb::PluginInitialize(lldb::SBDebugger)"); } } else { if (FileSystem::Instance().Exists(spec)) error.SetErrorString("this file does not represent a loadable dylib"); else error.SetErrorString("no such file"); } return llvm::sys::DynamicLibrary(); }; SBError error; if (auto e = g_debugger_lifetime->Initialize( std::make_unique(), LoadPlugin)) { error.SetError(Status(std::move(e))); } return error; } void SBDebugger::PrintStackTraceOnError() { LLDB_INSTRUMENT(); llvm::EnablePrettyStackTrace(); static std::string executable = llvm::sys::fs::getMainExecutable(nullptr, nullptr); 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(); g_debugger_lifetime->Terminate(); } void SBDebugger::Clear() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) m_opaque_sp->ClearIOHandlers(); m_opaque_sp.reset(); } SBDebugger SBDebugger::Create() { LLDB_INSTRUMENT(); return SBDebugger::Create(false, nullptr, nullptr); } SBDebugger SBDebugger::Create(bool source_init_files) { LLDB_INSTRUMENT_VA(source_init_files); return SBDebugger::Create(source_init_files, nullptr, nullptr); } SBDebugger SBDebugger::Create(bool source_init_files, lldb::LogOutputCallback callback, void *baton) { LLDB_INSTRUMENT_VA(source_init_files, callback, baton); SBDebugger debugger; // Currently we have issues if this function is called simultaneously on two // different threads. The issues mainly revolve around the fact that the // lldb_private::FormatManager uses global collections and having two threads // parsing the .lldbinit files can cause mayhem. So to get around this for // now we need to use a mutex to prevent bad things from happening. static std::recursive_mutex g_mutex; std::lock_guard guard(g_mutex); debugger.reset(Debugger::CreateInstance(callback, baton)); SBCommandInterpreter interp = debugger.GetCommandInterpreter(); if (source_init_files) { interp.get()->SkipLLDBInitFiles(false); interp.get()->SkipAppInitFiles(false); SBCommandReturnObject result; interp.SourceInitFileInGlobalDirectory(result); interp.SourceInitFileInHomeDirectory(result, false); } else { interp.get()->SkipLLDBInitFiles(true); interp.get()->SkipAppInitFiles(true); } return debugger; } void SBDebugger::Destroy(SBDebugger &debugger) { LLDB_INSTRUMENT_VA(debugger); Debugger::Destroy(debugger.m_opaque_sp); if (debugger.m_opaque_sp.get() != nullptr) debugger.m_opaque_sp.reset(); } void SBDebugger::MemoryPressureDetected() { LLDB_INSTRUMENT(); // Since this function can be call asynchronously, we allow it to be non- // mandatory. We have seen deadlocks with this function when called so we // need to safeguard against this until we can determine what is causing the // deadlocks. const bool mandatory = false; ModuleList::RemoveOrphanSharedModules(mandatory); } bool SBDebugger::IsValid() const { LLDB_INSTRUMENT_VA(this); return this->operator bool(); } SBDebugger::operator bool() const { LLDB_INSTRUMENT_VA(this); return m_opaque_sp.get() != nullptr; } void SBDebugger::SetAsync(bool b) { LLDB_INSTRUMENT_VA(this, b); if (m_opaque_sp) m_opaque_sp->SetAsyncExecution(b); } bool SBDebugger::GetAsync() { LLDB_INSTRUMENT_VA(this); return (m_opaque_sp ? m_opaque_sp->GetAsyncExecution() : false); } void SBDebugger::SkipLLDBInitFiles(bool b) { LLDB_INSTRUMENT_VA(this, b); if (m_opaque_sp) m_opaque_sp->GetCommandInterpreter().SkipLLDBInitFiles(b); } void SBDebugger::SkipAppInitFiles(bool b) { LLDB_INSTRUMENT_VA(this, b); if (m_opaque_sp) m_opaque_sp->GetCommandInterpreter().SkipAppInitFiles(b); } void SBDebugger::SetInputFileHandle(FILE *fh, bool transfer_ownership) { LLDB_INSTRUMENT_VA(this, fh, transfer_ownership); if (m_opaque_sp) m_opaque_sp->SetInputFile( (FileSP)std::make_shared(fh, transfer_ownership)); } SBError SBDebugger::SetInputString(const char *data) { LLDB_INSTRUMENT_VA(this, data); SBError sb_error; if (data == nullptr) { sb_error.SetErrorString("String data is null"); return sb_error; } size_t size = strlen(data); if (size == 0) { sb_error.SetErrorString("String data is empty"); return sb_error; } if (!m_opaque_sp) { sb_error.SetErrorString("invalid debugger"); return sb_error; } sb_error.SetError(m_opaque_sp->SetInputString(data)); return sb_error; } // Shouldn't really be settable after initialization as this could cause lots // of problems; don't want users trying to switch modes in the middle of a // debugging session. SBError SBDebugger::SetInputFile(SBFile file) { LLDB_INSTRUMENT_VA(this, file); SBError error; if (!m_opaque_sp) { error.ref().SetErrorString("invalid debugger"); return error; } if (!file) { error.ref().SetErrorString("invalid file"); return error; } m_opaque_sp->SetInputFile(file.m_opaque_sp); return error; } SBError SBDebugger::SetInputFile(FileSP file_sp) { LLDB_INSTRUMENT_VA(this, file_sp); return SetInputFile(SBFile(file_sp)); } SBError SBDebugger::SetOutputFile(FileSP file_sp) { LLDB_INSTRUMENT_VA(this, file_sp); return SetOutputFile(SBFile(file_sp)); } void SBDebugger::SetOutputFileHandle(FILE *fh, bool transfer_ownership) { LLDB_INSTRUMENT_VA(this, fh, transfer_ownership); SetOutputFile((FileSP)std::make_shared(fh, transfer_ownership)); } SBError SBDebugger::SetOutputFile(SBFile file) { LLDB_INSTRUMENT_VA(this, file); SBError error; if (!m_opaque_sp) { error.ref().SetErrorString("invalid debugger"); return error; } if (!file) { error.ref().SetErrorString("invalid file"); return error; } m_opaque_sp->SetOutputFile(file.m_opaque_sp); return error; } void SBDebugger::SetErrorFileHandle(FILE *fh, bool transfer_ownership) { LLDB_INSTRUMENT_VA(this, fh, transfer_ownership); SetErrorFile((FileSP)std::make_shared(fh, transfer_ownership)); } SBError SBDebugger::SetErrorFile(FileSP file_sp) { LLDB_INSTRUMENT_VA(this, file_sp); return SetErrorFile(SBFile(file_sp)); } SBError SBDebugger::SetErrorFile(SBFile file) { LLDB_INSTRUMENT_VA(this, file); SBError error; if (!m_opaque_sp) { error.ref().SetErrorString("invalid debugger"); return error; } if (!file) { error.ref().SetErrorString("invalid file"); return error; } m_opaque_sp->SetErrorFile(file.m_opaque_sp); return error; } lldb::SBStructuredData SBDebugger::GetSetting(const char *setting) { LLDB_INSTRUMENT_VA(this, setting); SBStructuredData data; if (!m_opaque_sp) return data; StreamString json_strm; ExecutionContext exe_ctx( m_opaque_sp->GetCommandInterpreter().GetExecutionContext()); if (setting && strlen(setting) > 0) m_opaque_sp->DumpPropertyValue(&exe_ctx, json_strm, setting, /*dump_mask*/ 0, /*is_json*/ true); else m_opaque_sp->DumpAllPropertyValues(&exe_ctx, json_strm, /*dump_mask*/ 0, /*is_json*/ true); data.m_impl_up->SetObjectSP(StructuredData::ParseJSON(json_strm.GetString())); return data; } FILE *SBDebugger::GetInputFileHandle() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) { File &file_sp = m_opaque_sp->GetInputFile(); return file_sp.GetStream(); } return nullptr; } SBFile SBDebugger::GetInputFile() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) { return SBFile(m_opaque_sp->GetInputFileSP()); } return SBFile(); } FILE *SBDebugger::GetOutputFileHandle() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) { StreamFile &stream_file = m_opaque_sp->GetOutputStream(); return stream_file.GetFile().GetStream(); } return nullptr; } SBFile SBDebugger::GetOutputFile() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) { SBFile file(m_opaque_sp->GetOutputStream().GetFileSP()); return file; } return SBFile(); } FILE *SBDebugger::GetErrorFileHandle() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) { StreamFile &stream_file = m_opaque_sp->GetErrorStream(); return stream_file.GetFile().GetStream(); } return nullptr; } SBFile SBDebugger::GetErrorFile() { LLDB_INSTRUMENT_VA(this); SBFile file; if (m_opaque_sp) { SBFile file(m_opaque_sp->GetErrorStream().GetFileSP()); return file; } return SBFile(); } void SBDebugger::SaveInputTerminalState() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) m_opaque_sp->SaveInputTerminalState(); } void SBDebugger::RestoreInputTerminalState() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) m_opaque_sp->RestoreInputTerminalState(); } SBCommandInterpreter SBDebugger::GetCommandInterpreter() { LLDB_INSTRUMENT_VA(this); SBCommandInterpreter sb_interpreter; if (m_opaque_sp) sb_interpreter.reset(&m_opaque_sp->GetCommandInterpreter()); return sb_interpreter; } void SBDebugger::HandleCommand(const char *command) { LLDB_INSTRUMENT_VA(this, command); if (m_opaque_sp) { TargetSP target_sp(m_opaque_sp->GetSelectedTarget()); std::unique_lock lock; if (target_sp) lock = std::unique_lock(target_sp->GetAPIMutex()); SBCommandInterpreter sb_interpreter(GetCommandInterpreter()); SBCommandReturnObject result; sb_interpreter.HandleCommand(command, result, false); result.PutError(m_opaque_sp->GetErrorStream().GetFileSP()); result.PutOutput(m_opaque_sp->GetOutputStream().GetFileSP()); if (!m_opaque_sp->GetAsyncExecution()) { SBProcess process(GetCommandInterpreter().GetProcess()); ProcessSP process_sp(process.GetSP()); if (process_sp) { EventSP event_sp; ListenerSP lldb_listener_sp = m_opaque_sp->GetListener(); while (lldb_listener_sp->GetEventForBroadcaster( process_sp.get(), event_sp, std::chrono::seconds(0))) { SBEvent event(event_sp); HandleProcessEvent(process, event, GetOutputFile(), GetErrorFile()); } } } } } SBListener SBDebugger::GetListener() { LLDB_INSTRUMENT_VA(this); SBListener sb_listener; if (m_opaque_sp) sb_listener.reset(m_opaque_sp->GetListener()); return sb_listener; } void SBDebugger::HandleProcessEvent(const SBProcess &process, const SBEvent &event, SBFile out, SBFile err) { LLDB_INSTRUMENT_VA(this, process, event, out, err); return HandleProcessEvent(process, event, out.m_opaque_sp, err.m_opaque_sp); } void SBDebugger::HandleProcessEvent(const SBProcess &process, const SBEvent &event, FILE *out, FILE *err) { LLDB_INSTRUMENT_VA(this, process, event, out, err); FileSP outfile = std::make_shared(out, false); FileSP errfile = std::make_shared(err, false); return HandleProcessEvent(process, event, outfile, errfile); } void SBDebugger::HandleProcessEvent(const SBProcess &process, const SBEvent &event, FileSP out_sp, FileSP err_sp) { LLDB_INSTRUMENT_VA(this, process, event, out_sp, err_sp); if (!process.IsValid()) return; TargetSP target_sp(process.GetTarget().GetSP()); if (!target_sp) return; const uint32_t event_type = event.GetType(); char stdio_buffer[1024]; size_t len; std::lock_guard guard(target_sp->GetAPIMutex()); if (event_type & (Process::eBroadcastBitSTDOUT | Process::eBroadcastBitStateChanged)) { // Drain stdout when we stop just in case we have any bytes while ((len = process.GetSTDOUT(stdio_buffer, sizeof(stdio_buffer))) > 0) if (out_sp) out_sp->Write(stdio_buffer, len); } if (event_type & (Process::eBroadcastBitSTDERR | Process::eBroadcastBitStateChanged)) { // Drain stderr when we stop just in case we have any bytes while ((len = process.GetSTDERR(stdio_buffer, sizeof(stdio_buffer))) > 0) if (err_sp) err_sp->Write(stdio_buffer, len); } if (event_type & Process::eBroadcastBitStateChanged) { StateType event_state = SBProcess::GetStateFromEvent(event); if (event_state == eStateInvalid) return; bool is_stopped = StateIsStoppedState(event_state); if (!is_stopped) process.ReportEventState(event, out_sp); } } SBSourceManager SBDebugger::GetSourceManager() { LLDB_INSTRUMENT_VA(this); SBSourceManager sb_source_manager(*this); return sb_source_manager; } bool SBDebugger::GetDefaultArchitecture(char *arch_name, size_t arch_name_len) { LLDB_INSTRUMENT_VA(arch_name, arch_name_len); if (arch_name && arch_name_len) { ArchSpec default_arch = Target::GetDefaultArchitecture(); if (default_arch.IsValid()) { const std::string &triple_str = default_arch.GetTriple().str(); if (!triple_str.empty()) ::snprintf(arch_name, arch_name_len, "%s", triple_str.c_str()); else ::snprintf(arch_name, arch_name_len, "%s", default_arch.GetArchitectureName()); return true; } } if (arch_name && arch_name_len) arch_name[0] = '\0'; return false; } bool SBDebugger::SetDefaultArchitecture(const char *arch_name) { LLDB_INSTRUMENT_VA(arch_name); if (arch_name) { ArchSpec arch(arch_name); if (arch.IsValid()) { Target::SetDefaultArchitecture(arch); return true; } } return false; } ScriptLanguage SBDebugger::GetScriptingLanguage(const char *script_language_name) { LLDB_INSTRUMENT_VA(this, script_language_name); if (!script_language_name) return eScriptLanguageDefault; return OptionArgParser::ToScriptLanguage( llvm::StringRef(script_language_name), eScriptLanguageDefault, nullptr); } SBStructuredData SBDebugger::GetScriptInterpreterInfo(lldb::ScriptLanguage language) { LLDB_INSTRUMENT_VA(this, language); SBStructuredData data; if (m_opaque_sp) { lldb_private::ScriptInterpreter *interp = m_opaque_sp->GetScriptInterpreter(language); if (interp) { data.m_impl_up->SetObjectSP(interp->GetInterpreterInfo()); } } return data; } const char *SBDebugger::GetVersionString() { LLDB_INSTRUMENT(); return lldb_private::GetVersion(); } const char *SBDebugger::StateAsCString(StateType state) { LLDB_INSTRUMENT_VA(state); return lldb_private::StateAsCString(state); } static void AddBoolConfigEntry(StructuredData::Dictionary &dict, llvm::StringRef name, bool value, llvm::StringRef description) { auto entry_up = std::make_unique(); entry_up->AddBooleanItem("value", value); entry_up->AddStringItem("description", description); dict.AddItem(name, std::move(entry_up)); } static void AddLLVMTargets(StructuredData::Dictionary &dict) { auto array_up = std::make_unique(); #define LLVM_TARGET(target) \ array_up->AddItem(std::make_unique(#target)); #include "llvm/Config/Targets.def" auto entry_up = std::make_unique(); entry_up->AddItem("value", std::move(array_up)); entry_up->AddStringItem("description", "A list of configured LLVM targets."); dict.AddItem("targets", std::move(entry_up)); } SBStructuredData SBDebugger::GetBuildConfiguration() { LLDB_INSTRUMENT(); auto config_up = std::make_unique(); AddBoolConfigEntry( *config_up, "xml", XMLDocument::XMLEnabled(), "A boolean value that indicates if XML support is enabled in LLDB"); AddBoolConfigEntry( *config_up, "curses", LLDB_ENABLE_CURSES, "A boolean value that indicates if curses support is enabled in LLDB"); AddBoolConfigEntry( *config_up, "editline", LLDB_ENABLE_LIBEDIT, "A boolean value that indicates if editline support is enabled in LLDB"); AddBoolConfigEntry(*config_up, "editline_wchar", LLDB_EDITLINE_USE_WCHAR, "A boolean value that indicates if editline wide " "characters support is enabled in LLDB"); AddBoolConfigEntry( *config_up, "lzma", LLDB_ENABLE_LZMA, "A boolean value that indicates if lzma support is enabled in LLDB"); AddBoolConfigEntry( *config_up, "python", LLDB_ENABLE_PYTHON, "A boolean value that indicates if python support is enabled in LLDB"); AddBoolConfigEntry( *config_up, "lua", LLDB_ENABLE_LUA, "A boolean value that indicates if lua support is enabled in LLDB"); AddBoolConfigEntry(*config_up, "fbsdvmcore", LLDB_ENABLE_FBSDVMCORE, "A boolean value that indicates if fbsdvmcore support is " "enabled in LLDB"); AddLLVMTargets(*config_up); SBStructuredData data; data.m_impl_up->SetObjectSP(std::move(config_up)); return data; } bool SBDebugger::StateIsRunningState(StateType state) { LLDB_INSTRUMENT_VA(state); const bool result = lldb_private::StateIsRunningState(state); return result; } bool SBDebugger::StateIsStoppedState(StateType state) { LLDB_INSTRUMENT_VA(state); const bool result = lldb_private::StateIsStoppedState(state, false); return result; } lldb::SBTarget SBDebugger::CreateTarget(const char *filename, const char *target_triple, const char *platform_name, bool add_dependent_modules, lldb::SBError &sb_error) { LLDB_INSTRUMENT_VA(this, filename, target_triple, platform_name, add_dependent_modules, sb_error); SBTarget sb_target; TargetSP target_sp; if (m_opaque_sp) { sb_error.Clear(); OptionGroupPlatform platform_options(false); platform_options.SetPlatformName(platform_name); sb_error.ref() = m_opaque_sp->GetTargetList().CreateTarget( *m_opaque_sp, filename, target_triple, add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, &platform_options, target_sp); if (sb_error.Success()) sb_target.SetSP(target_sp); } else { sb_error.SetErrorString("invalid debugger"); } Log *log = GetLog(LLDBLog::API); LLDB_LOGF(log, "SBDebugger(%p)::CreateTarget (filename=\"%s\", triple=%s, " "platform_name=%s, add_dependent_modules=%u, error=%s) => " "SBTarget(%p)", static_cast(m_opaque_sp.get()), filename, target_triple, platform_name, add_dependent_modules, sb_error.GetCString(), static_cast(target_sp.get())); return sb_target; } SBTarget SBDebugger::CreateTargetWithFileAndTargetTriple(const char *filename, const char *target_triple) { LLDB_INSTRUMENT_VA(this, filename, target_triple); SBTarget sb_target; TargetSP target_sp; if (m_opaque_sp) { const bool add_dependent_modules = true; Status error(m_opaque_sp->GetTargetList().CreateTarget( *m_opaque_sp, filename, target_triple, add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, nullptr, target_sp)); sb_target.SetSP(target_sp); } Log *log = GetLog(LLDBLog::API); LLDB_LOGF(log, "SBDebugger(%p)::CreateTargetWithFileAndTargetTriple " "(filename=\"%s\", triple=%s) => SBTarget(%p)", static_cast(m_opaque_sp.get()), filename, target_triple, static_cast(target_sp.get())); return sb_target; } SBTarget SBDebugger::CreateTargetWithFileAndArch(const char *filename, const char *arch_cstr) { LLDB_INSTRUMENT_VA(this, filename, arch_cstr); Log *log = GetLog(LLDBLog::API); SBTarget sb_target; TargetSP target_sp; if (m_opaque_sp) { Status error; if (arch_cstr == nullptr) { // The version of CreateTarget that takes an ArchSpec won't accept an // empty ArchSpec, so when the arch hasn't been specified, we need to // call the target triple version. error = m_opaque_sp->GetTargetList().CreateTarget( *m_opaque_sp, filename, arch_cstr, eLoadDependentsYes, nullptr, target_sp); } else { PlatformSP platform_sp = m_opaque_sp->GetPlatformList().GetSelectedPlatform(); ArchSpec arch = Platform::GetAugmentedArchSpec(platform_sp.get(), arch_cstr); if (arch.IsValid()) error = m_opaque_sp->GetTargetList().CreateTarget( *m_opaque_sp, filename, arch, eLoadDependentsYes, platform_sp, target_sp); else error.SetErrorStringWithFormat("invalid arch_cstr: %s", arch_cstr); } if (error.Success()) sb_target.SetSP(target_sp); } LLDB_LOGF(log, "SBDebugger(%p)::CreateTargetWithFileAndArch (filename=\"%s\", " "arch=%s) => SBTarget(%p)", static_cast(m_opaque_sp.get()), filename ? filename : "", arch_cstr ? arch_cstr : "", static_cast(target_sp.get())); return sb_target; } SBTarget SBDebugger::CreateTarget(const char *filename) { LLDB_INSTRUMENT_VA(this, filename); SBTarget sb_target; TargetSP target_sp; if (m_opaque_sp) { Status error; const bool add_dependent_modules = true; error = m_opaque_sp->GetTargetList().CreateTarget( *m_opaque_sp, filename, "", add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, nullptr, target_sp); if (error.Success()) sb_target.SetSP(target_sp); } Log *log = GetLog(LLDBLog::API); LLDB_LOGF(log, "SBDebugger(%p)::CreateTarget (filename=\"%s\") => SBTarget(%p)", static_cast(m_opaque_sp.get()), filename, static_cast(target_sp.get())); return sb_target; } SBTarget SBDebugger::GetDummyTarget() { LLDB_INSTRUMENT_VA(this); SBTarget sb_target; if (m_opaque_sp) { sb_target.SetSP(m_opaque_sp->GetDummyTarget().shared_from_this()); } Log *log = GetLog(LLDBLog::API); LLDB_LOGF(log, "SBDebugger(%p)::GetDummyTarget() => SBTarget(%p)", static_cast(m_opaque_sp.get()), static_cast(sb_target.GetSP().get())); return sb_target; } bool SBDebugger::DeleteTarget(lldb::SBTarget &target) { LLDB_INSTRUMENT_VA(this, target); bool result = false; if (m_opaque_sp) { TargetSP target_sp(target.GetSP()); if (target_sp) { // No need to lock, the target list is thread safe result = m_opaque_sp->GetTargetList().DeleteTarget(target_sp); target_sp->Destroy(); target.Clear(); } } Log *log = GetLog(LLDBLog::API); LLDB_LOGF(log, "SBDebugger(%p)::DeleteTarget (SBTarget(%p)) => %i", static_cast(m_opaque_sp.get()), static_cast(target.m_opaque_sp.get()), result); return result; } SBTarget SBDebugger::GetTargetAtIndex(uint32_t idx) { LLDB_INSTRUMENT_VA(this, idx); SBTarget sb_target; if (m_opaque_sp) { // No need to lock, the target list is thread safe sb_target.SetSP(m_opaque_sp->GetTargetList().GetTargetAtIndex(idx)); } return sb_target; } uint32_t SBDebugger::GetIndexOfTarget(lldb::SBTarget target) { LLDB_INSTRUMENT_VA(this, target); lldb::TargetSP target_sp = target.GetSP(); if (!target_sp) return UINT32_MAX; if (!m_opaque_sp) return UINT32_MAX; return m_opaque_sp->GetTargetList().GetIndexOfTarget(target.GetSP()); } SBTarget SBDebugger::FindTargetWithProcessID(lldb::pid_t pid) { LLDB_INSTRUMENT_VA(this, pid); SBTarget sb_target; if (m_opaque_sp) { // No need to lock, the target list is thread safe sb_target.SetSP(m_opaque_sp->GetTargetList().FindTargetWithProcessID(pid)); } return sb_target; } SBTarget SBDebugger::FindTargetWithFileAndArch(const char *filename, const char *arch_name) { LLDB_INSTRUMENT_VA(this, filename, arch_name); SBTarget sb_target; if (m_opaque_sp && filename && filename[0]) { // No need to lock, the target list is thread safe ArchSpec arch = Platform::GetAugmentedArchSpec( m_opaque_sp->GetPlatformList().GetSelectedPlatform().get(), arch_name); TargetSP target_sp( m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture( FileSpec(filename), arch_name ? &arch : nullptr)); sb_target.SetSP(target_sp); } return sb_target; } SBTarget SBDebugger::FindTargetWithLLDBProcess(const ProcessSP &process_sp) { SBTarget sb_target; if (m_opaque_sp) { // No need to lock, the target list is thread safe sb_target.SetSP( m_opaque_sp->GetTargetList().FindTargetWithProcess(process_sp.get())); } return sb_target; } uint32_t SBDebugger::GetNumTargets() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) { // No need to lock, the target list is thread safe return m_opaque_sp->GetTargetList().GetNumTargets(); } return 0; } SBTarget SBDebugger::GetSelectedTarget() { LLDB_INSTRUMENT_VA(this); Log *log = GetLog(LLDBLog::API); SBTarget sb_target; TargetSP target_sp; if (m_opaque_sp) { // No need to lock, the target list is thread safe target_sp = m_opaque_sp->GetTargetList().GetSelectedTarget(); sb_target.SetSP(target_sp); } if (log) { SBStream sstr; sb_target.GetDescription(sstr, eDescriptionLevelBrief); LLDB_LOGF(log, "SBDebugger(%p)::GetSelectedTarget () => SBTarget(%p): %s", static_cast(m_opaque_sp.get()), static_cast(target_sp.get()), sstr.GetData()); } return sb_target; } void SBDebugger::SetSelectedTarget(SBTarget &sb_target) { LLDB_INSTRUMENT_VA(this, sb_target); Log *log = GetLog(LLDBLog::API); TargetSP target_sp(sb_target.GetSP()); if (m_opaque_sp) { m_opaque_sp->GetTargetList().SetSelectedTarget(target_sp); } if (log) { SBStream sstr; sb_target.GetDescription(sstr, eDescriptionLevelBrief); LLDB_LOGF(log, "SBDebugger(%p)::SetSelectedTarget () => SBTarget(%p): %s", static_cast(m_opaque_sp.get()), static_cast(target_sp.get()), sstr.GetData()); } } SBPlatform SBDebugger::GetSelectedPlatform() { LLDB_INSTRUMENT_VA(this); Log *log = GetLog(LLDBLog::API); SBPlatform sb_platform; DebuggerSP debugger_sp(m_opaque_sp); if (debugger_sp) { sb_platform.SetSP(debugger_sp->GetPlatformList().GetSelectedPlatform()); } LLDB_LOGF(log, "SBDebugger(%p)::GetSelectedPlatform () => SBPlatform(%p): %s", static_cast(m_opaque_sp.get()), static_cast(sb_platform.GetSP().get()), sb_platform.GetName()); return sb_platform; } void SBDebugger::SetSelectedPlatform(SBPlatform &sb_platform) { LLDB_INSTRUMENT_VA(this, sb_platform); Log *log = GetLog(LLDBLog::API); DebuggerSP debugger_sp(m_opaque_sp); if (debugger_sp) { debugger_sp->GetPlatformList().SetSelectedPlatform(sb_platform.GetSP()); } LLDB_LOGF(log, "SBDebugger(%p)::SetSelectedPlatform (SBPlatform(%p) %s)", static_cast(m_opaque_sp.get()), static_cast(sb_platform.GetSP().get()), sb_platform.GetName()); } uint32_t SBDebugger::GetNumPlatforms() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) { // No need to lock, the platform list is thread safe return m_opaque_sp->GetPlatformList().GetSize(); } return 0; } SBPlatform SBDebugger::GetPlatformAtIndex(uint32_t idx) { LLDB_INSTRUMENT_VA(this, idx); SBPlatform sb_platform; if (m_opaque_sp) { // No need to lock, the platform list is thread safe sb_platform.SetSP(m_opaque_sp->GetPlatformList().GetAtIndex(idx)); } return sb_platform; } uint32_t SBDebugger::GetNumAvailablePlatforms() { LLDB_INSTRUMENT_VA(this); uint32_t idx = 0; while (true) { if (PluginManager::GetPlatformPluginNameAtIndex(idx).empty()) { break; } ++idx; } // +1 for the host platform, which should always appear first in the list. return idx + 1; } SBStructuredData SBDebugger::GetAvailablePlatformInfoAtIndex(uint32_t idx) { LLDB_INSTRUMENT_VA(this, idx); SBStructuredData data; auto platform_dict = std::make_unique(); llvm::StringRef name_str("name"), desc_str("description"); if (idx == 0) { PlatformSP host_platform_sp(Platform::GetHostPlatform()); platform_dict->AddStringItem(name_str, host_platform_sp->GetPluginName()); platform_dict->AddStringItem( desc_str, llvm::StringRef(host_platform_sp->GetDescription())); } else if (idx > 0) { llvm::StringRef plugin_name = PluginManager::GetPlatformPluginNameAtIndex(idx - 1); if (plugin_name.empty()) { return data; } platform_dict->AddStringItem(name_str, llvm::StringRef(plugin_name)); llvm::StringRef plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex(idx - 1); platform_dict->AddStringItem(desc_str, llvm::StringRef(plugin_desc)); } data.m_impl_up->SetObjectSP( StructuredData::ObjectSP(platform_dict.release())); return data; } void SBDebugger::DispatchInput(void *baton, const void *data, size_t data_len) { LLDB_INSTRUMENT_VA(this, baton, data, data_len); DispatchInput(data, data_len); } void SBDebugger::DispatchInput(const void *data, size_t data_len) { LLDB_INSTRUMENT_VA(this, data, data_len); // Log *log(GetLog (LLDBLog::API)); // // if (log) // LLDB_LOGF(log, "SBDebugger(%p)::DispatchInput (data=\"%.*s\", // size_t=%" PRIu64 ")", // m_opaque_sp.get(), // (int) data_len, // (const char *) data, // (uint64_t)data_len); // // if (m_opaque_sp) // m_opaque_sp->DispatchInput ((const char *) data, data_len); } void SBDebugger::DispatchInputInterrupt() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) m_opaque_sp->DispatchInputInterrupt(); } void SBDebugger::DispatchInputEndOfFile() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) m_opaque_sp->DispatchInputEndOfFile(); } void SBDebugger::PushInputReader(SBInputReader &reader) { LLDB_INSTRUMENT_VA(this, reader); } void SBDebugger::RunCommandInterpreter(bool auto_handle_events, bool spawn_thread) { LLDB_INSTRUMENT_VA(this, auto_handle_events, spawn_thread); if (m_opaque_sp) { CommandInterpreterRunOptions options; options.SetAutoHandleEvents(auto_handle_events); options.SetSpawnThread(spawn_thread); m_opaque_sp->GetCommandInterpreter().RunCommandInterpreter(options); } } void SBDebugger::RunCommandInterpreter(bool auto_handle_events, bool spawn_thread, SBCommandInterpreterRunOptions &options, int &num_errors, bool &quit_requested, bool &stopped_for_crash) { LLDB_INSTRUMENT_VA(this, auto_handle_events, spawn_thread, options, num_errors, quit_requested, stopped_for_crash); if (m_opaque_sp) { options.SetAutoHandleEvents(auto_handle_events); options.SetSpawnThread(spawn_thread); CommandInterpreter &interp = m_opaque_sp->GetCommandInterpreter(); CommandInterpreterRunResult result = interp.RunCommandInterpreter(options.ref()); num_errors = result.GetNumErrors(); quit_requested = result.IsResult(lldb::eCommandInterpreterResultQuitRequested); stopped_for_crash = result.IsResult(lldb::eCommandInterpreterResultInferiorCrash); } } SBCommandInterpreterRunResult SBDebugger::RunCommandInterpreter( const SBCommandInterpreterRunOptions &options) { LLDB_INSTRUMENT_VA(this, options); if (!m_opaque_sp) return SBCommandInterpreterRunResult(); CommandInterpreter &interp = m_opaque_sp->GetCommandInterpreter(); CommandInterpreterRunResult result = interp.RunCommandInterpreter(options.ref()); return SBCommandInterpreterRunResult(result); } SBError SBDebugger::RunREPL(lldb::LanguageType language, const char *repl_options) { LLDB_INSTRUMENT_VA(this, language, repl_options); SBError error; if (m_opaque_sp) error.ref() = m_opaque_sp->RunREPL(language, repl_options); else error.SetErrorString("invalid debugger"); return error; } void SBDebugger::reset(const DebuggerSP &debugger_sp) { m_opaque_sp = debugger_sp; } Debugger *SBDebugger::get() const { return m_opaque_sp.get(); } Debugger &SBDebugger::ref() const { assert(m_opaque_sp.get()); return *m_opaque_sp; } const lldb::DebuggerSP &SBDebugger::get_sp() const { return m_opaque_sp; } SBDebugger SBDebugger::FindDebuggerWithID(int id) { LLDB_INSTRUMENT_VA(id); // No need to lock, the debugger list is thread safe SBDebugger sb_debugger; DebuggerSP debugger_sp = Debugger::FindDebuggerWithID(id); if (debugger_sp) sb_debugger.reset(debugger_sp); return sb_debugger; } const char *SBDebugger::GetInstanceName() { LLDB_INSTRUMENT_VA(this); if (!m_opaque_sp) return nullptr; return ConstString(m_opaque_sp->GetInstanceName()).AsCString(); } SBError SBDebugger::SetInternalVariable(const char *var_name, const char *value, const char *debugger_instance_name) { LLDB_INSTRUMENT_VA(var_name, value, debugger_instance_name); SBError sb_error; DebuggerSP debugger_sp( Debugger::FindDebuggerWithInstanceName(debugger_instance_name)); Status error; if (debugger_sp) { ExecutionContext exe_ctx( debugger_sp->GetCommandInterpreter().GetExecutionContext()); error = debugger_sp->SetPropertyValue(&exe_ctx, eVarSetOperationAssign, var_name, value); } else { error.SetErrorStringWithFormat("invalid debugger instance name '%s'", debugger_instance_name); } if (error.Fail()) sb_error.SetError(error); return sb_error; } SBStringList SBDebugger::GetInternalVariableValue(const char *var_name, const char *debugger_instance_name) { LLDB_INSTRUMENT_VA(var_name, debugger_instance_name); DebuggerSP debugger_sp( Debugger::FindDebuggerWithInstanceName(debugger_instance_name)); Status error; if (debugger_sp) { ExecutionContext exe_ctx( debugger_sp->GetCommandInterpreter().GetExecutionContext()); lldb::OptionValueSP value_sp( debugger_sp->GetPropertyValue(&exe_ctx, var_name, error)); if (value_sp) { StreamString value_strm; value_sp->DumpValue(&exe_ctx, value_strm, OptionValue::eDumpOptionValue); const std::string &value_str = std::string(value_strm.GetString()); if (!value_str.empty()) { StringList string_list; string_list.SplitIntoLines(value_str); return SBStringList(&string_list); } } } return SBStringList(); } uint32_t SBDebugger::GetTerminalWidth() const { LLDB_INSTRUMENT_VA(this); return (m_opaque_sp ? m_opaque_sp->GetTerminalWidth() : 0); } void SBDebugger::SetTerminalWidth(uint32_t term_width) { LLDB_INSTRUMENT_VA(this, term_width); if (m_opaque_sp) m_opaque_sp->SetTerminalWidth(term_width); } const char *SBDebugger::GetPrompt() const { LLDB_INSTRUMENT_VA(this); Log *log = GetLog(LLDBLog::API); LLDB_LOG(log, "SBDebugger({0:x})::GetPrompt () => \"{1}\"", static_cast(m_opaque_sp.get()), (m_opaque_sp ? m_opaque_sp->GetPrompt() : "")); return (m_opaque_sp ? ConstString(m_opaque_sp->GetPrompt()).GetCString() : nullptr); } void SBDebugger::SetPrompt(const char *prompt) { LLDB_INSTRUMENT_VA(this, prompt); if (m_opaque_sp) m_opaque_sp->SetPrompt(llvm::StringRef(prompt)); } const char *SBDebugger::GetReproducerPath() const { LLDB_INSTRUMENT_VA(this); return "GetReproducerPath has been deprecated"; } ScriptLanguage SBDebugger::GetScriptLanguage() const { LLDB_INSTRUMENT_VA(this); return (m_opaque_sp ? m_opaque_sp->GetScriptLanguage() : eScriptLanguageNone); } void SBDebugger::SetScriptLanguage(ScriptLanguage script_lang) { LLDB_INSTRUMENT_VA(this, script_lang); if (m_opaque_sp) { m_opaque_sp->SetScriptLanguage(script_lang); } } LanguageType SBDebugger::GetREPLLanguage() const { LLDB_INSTRUMENT_VA(this); return (m_opaque_sp ? m_opaque_sp->GetREPLLanguage() : eLanguageTypeUnknown); } void SBDebugger::SetREPLLanguage(LanguageType repl_lang) { LLDB_INSTRUMENT_VA(this, repl_lang); if (m_opaque_sp) { m_opaque_sp->SetREPLLanguage(repl_lang); } } bool SBDebugger::SetUseExternalEditor(bool value) { LLDB_INSTRUMENT_VA(this, value); return (m_opaque_sp ? m_opaque_sp->SetUseExternalEditor(value) : false); } bool SBDebugger::GetUseExternalEditor() { LLDB_INSTRUMENT_VA(this); return (m_opaque_sp ? m_opaque_sp->GetUseExternalEditor() : false); } bool SBDebugger::SetUseColor(bool value) { LLDB_INSTRUMENT_VA(this, value); return (m_opaque_sp ? m_opaque_sp->SetUseColor(value) : false); } bool SBDebugger::GetUseColor() const { LLDB_INSTRUMENT_VA(this); return (m_opaque_sp ? m_opaque_sp->GetUseColor() : false); } bool SBDebugger::SetUseSourceCache(bool value) { LLDB_INSTRUMENT_VA(this, value); return (m_opaque_sp ? m_opaque_sp->SetUseSourceCache(value) : false); } bool SBDebugger::GetUseSourceCache() const { LLDB_INSTRUMENT_VA(this); return (m_opaque_sp ? m_opaque_sp->GetUseSourceCache() : false); } bool SBDebugger::GetDescription(SBStream &description) { LLDB_INSTRUMENT_VA(this, description); Stream &strm = description.ref(); if (m_opaque_sp) { const char *name = m_opaque_sp->GetInstanceName().c_str(); user_id_t id = m_opaque_sp->GetID(); strm.Printf("Debugger (instance: \"%s\", id: %" PRIu64 ")", name, id); } else strm.PutCString("No value"); return true; } user_id_t SBDebugger::GetID() { LLDB_INSTRUMENT_VA(this); return (m_opaque_sp ? m_opaque_sp->GetID() : LLDB_INVALID_UID); } SBError SBDebugger::SetCurrentPlatform(const char *platform_name_cstr) { LLDB_INSTRUMENT_VA(this, platform_name_cstr); SBError sb_error; if (m_opaque_sp) { if (platform_name_cstr && platform_name_cstr[0]) { PlatformList &platforms = m_opaque_sp->GetPlatformList(); if (PlatformSP platform_sp = platforms.GetOrCreate(platform_name_cstr)) platforms.SetSelectedPlatform(platform_sp); else sb_error.ref().SetErrorString("platform not found"); } else { sb_error.ref().SetErrorString("invalid platform name"); } } else { sb_error.ref().SetErrorString("invalid debugger"); } return sb_error; } bool SBDebugger::SetCurrentPlatformSDKRoot(const char *sysroot) { LLDB_INSTRUMENT_VA(this, sysroot); if (SBPlatform platform = GetSelectedPlatform()) { platform.SetSDKRoot(sysroot); return true; } return false; } bool SBDebugger::GetCloseInputOnEOF() const { LLDB_INSTRUMENT_VA(this); return false; } void SBDebugger::SetCloseInputOnEOF(bool b) { LLDB_INSTRUMENT_VA(this, b); } SBTypeCategory SBDebugger::GetCategory(const char *category_name) { LLDB_INSTRUMENT_VA(this, category_name); if (!category_name || *category_name == 0) return SBTypeCategory(); TypeCategoryImplSP category_sp; if (DataVisualization::Categories::GetCategory(ConstString(category_name), category_sp, false)) { return SBTypeCategory(category_sp); } else { return SBTypeCategory(); } } SBTypeCategory SBDebugger::GetCategory(lldb::LanguageType lang_type) { LLDB_INSTRUMENT_VA(this, lang_type); TypeCategoryImplSP category_sp; if (DataVisualization::Categories::GetCategory(lang_type, category_sp)) { return SBTypeCategory(category_sp); } else { return SBTypeCategory(); } } SBTypeCategory SBDebugger::CreateCategory(const char *category_name) { LLDB_INSTRUMENT_VA(this, category_name); if (!category_name || *category_name == 0) return SBTypeCategory(); TypeCategoryImplSP category_sp; if (DataVisualization::Categories::GetCategory(ConstString(category_name), category_sp, true)) { return SBTypeCategory(category_sp); } else { return SBTypeCategory(); } } bool SBDebugger::DeleteCategory(const char *category_name) { LLDB_INSTRUMENT_VA(this, category_name); if (!category_name || *category_name == 0) return false; return DataVisualization::Categories::Delete(ConstString(category_name)); } uint32_t SBDebugger::GetNumCategories() { LLDB_INSTRUMENT_VA(this); return DataVisualization::Categories::GetCount(); } SBTypeCategory SBDebugger::GetCategoryAtIndex(uint32_t index) { LLDB_INSTRUMENT_VA(this, index); return SBTypeCategory( DataVisualization::Categories::GetCategoryAtIndex(index)); } SBTypeCategory SBDebugger::GetDefaultCategory() { LLDB_INSTRUMENT_VA(this); return GetCategory("default"); } SBTypeFormat SBDebugger::GetFormatForType(SBTypeNameSpecifier type_name) { LLDB_INSTRUMENT_VA(this, type_name); SBTypeCategory default_category_sb = GetDefaultCategory(); if (default_category_sb.GetEnabled()) return default_category_sb.GetFormatForType(type_name); return SBTypeFormat(); } SBTypeSummary SBDebugger::GetSummaryForType(SBTypeNameSpecifier type_name) { LLDB_INSTRUMENT_VA(this, type_name); if (!type_name.IsValid()) return SBTypeSummary(); return SBTypeSummary(DataVisualization::GetSummaryForType(type_name.GetSP())); } SBTypeFilter SBDebugger::GetFilterForType(SBTypeNameSpecifier type_name) { LLDB_INSTRUMENT_VA(this, type_name); if (!type_name.IsValid()) return SBTypeFilter(); return SBTypeFilter(DataVisualization::GetFilterForType(type_name.GetSP())); } SBTypeSynthetic SBDebugger::GetSyntheticForType(SBTypeNameSpecifier type_name) { LLDB_INSTRUMENT_VA(this, type_name); if (!type_name.IsValid()) return SBTypeSynthetic(); return SBTypeSynthetic( DataVisualization::GetSyntheticForType(type_name.GetSP())); } static llvm::ArrayRef GetCategoryArray(const char **categories) { if (categories == nullptr) return {}; size_t len = 0; while (categories[len] != nullptr) ++len; return llvm::ArrayRef(categories, len); } bool SBDebugger::EnableLog(const char *channel, const char **categories) { LLDB_INSTRUMENT_VA(this, channel, categories); if (m_opaque_sp) { uint32_t log_options = LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; std::string error; llvm::raw_string_ostream error_stream(error); return m_opaque_sp->EnableLog(channel, GetCategoryArray(categories), "", log_options, /*buffer_size=*/0, eLogHandlerStream, error_stream); } else return false; } void SBDebugger::SetLoggingCallback(lldb::LogOutputCallback log_callback, void *baton) { LLDB_INSTRUMENT_VA(this, log_callback, baton); if (m_opaque_sp) { return m_opaque_sp->SetLoggingCallback(log_callback, baton); } } void SBDebugger::SetDestroyCallback( lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) { LLDB_INSTRUMENT_VA(this, destroy_callback, baton); if (m_opaque_sp) { return m_opaque_sp->SetDestroyCallback( destroy_callback, baton); } } lldb::callback_token_t SBDebugger::AddDestroyCallback(lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) { LLDB_INSTRUMENT_VA(this, destroy_callback, baton); if (m_opaque_sp) return m_opaque_sp->AddDestroyCallback(destroy_callback, baton); return LLDB_INVALID_CALLBACK_TOKEN; } bool SBDebugger::RemoveDestroyCallback(lldb::callback_token_t token) { LLDB_INSTRUMENT_VA(this, token); if (m_opaque_sp) return m_opaque_sp->RemoveDestroyCallback(token); return false; } SBTrace SBDebugger::LoadTraceFromFile(SBError &error, const SBFileSpec &trace_description_file) { LLDB_INSTRUMENT_VA(this, error, trace_description_file); return SBTrace::LoadTraceFromFile(error, *this, trace_description_file); } void SBDebugger::RequestInterrupt() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) m_opaque_sp->RequestInterrupt(); } void SBDebugger::CancelInterruptRequest() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) m_opaque_sp->CancelInterruptRequest(); } bool SBDebugger::InterruptRequested() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) return m_opaque_sp->InterruptRequested(); return false; } bool SBDebugger::SupportsLanguage(lldb::LanguageType language) { return TypeSystem::SupportsLanguageStatic(language); }