llvm-project/lldb/source/API/SBDebugger.cpp
Jonas Devlieghere 3dfc1d9b0b
[lldb] Use the terminal height for paging editline completions (#119914)
Currently, we arbitrarily paginate editline completions to 40 elements.
On large terminals, that leaves some real-estate unused. On small
terminals, it's pretty annoying to not see the first completions. We can
address both issues by using the terminal height for pagination.

This builds on the improvements of #116456.
2024-12-16 11:11:17 -08:00

1782 lines
52 KiB
C++

//===-- 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/Config/llvm-config.h" // for LLVM_ENABLE_CURL
#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<SystemLifetimeManager> 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 = Status::FromErrorString(
"plug-in refused to load "
"(lldb::PluginInitialize(lldb::SBDebugger) "
"returned false)");
} else {
error = Status::FromErrorString(
"plug-in is missing the required initialization: "
"lldb::PluginInitialize(lldb::SBDebugger)");
}
} else {
if (FileSystem::Instance().Exists(spec))
error = Status::FromErrorString(
"this file does not represent a loadable dylib");
else
error = Status::FromErrorString("no such file");
}
return llvm::sys::DynamicLibrary();
};
SBError error;
if (auto e = g_debugger_lifetime->Initialize(
std::make_unique<SystemInitializerFull>(), LoadPlugin)) {
error.SetError(Status::FromError(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<std::recursive_mutex> 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<NativeFile>(fh, transfer_ownership));
}
SBError SBDebugger::SetInputString(const char *data) {
LLDB_INSTRUMENT_VA(this, data);
SBError sb_error;
if (data == nullptr) {
sb_error = Status::FromErrorString("String data is null");
return sb_error;
}
size_t size = strlen(data);
if (size == 0) {
sb_error = Status::FromErrorString("String data is empty");
return sb_error;
}
if (!m_opaque_sp) {
sb_error = Status::FromErrorString("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() = Status::FromErrorString("invalid debugger");
return error;
}
if (!file) {
error.ref() = Status::FromErrorString("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<NativeFile>(fh, transfer_ownership));
}
SBError SBDebugger::SetOutputFile(SBFile file) {
LLDB_INSTRUMENT_VA(this, file);
SBError error;
if (!m_opaque_sp) {
error.ref() = Status::FromErrorString("invalid debugger");
return error;
}
if (!file) {
error.ref() = Status::FromErrorString("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<NativeFile>(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() = Status::FromErrorString("invalid debugger");
return error;
}
if (!file) {
error.ref() = Status::FromErrorString("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<std::recursive_mutex> lock;
if (target_sp)
lock = std::unique_lock<std::recursive_mutex>(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<NativeFile>(out, false);
FileSP errfile = std::make_shared<NativeFile>(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<std::recursive_mutex> 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<StructuredData::Dictionary>();
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<StructuredData::Array>();
#define LLVM_TARGET(target) \
array_up->AddItem(std::make_unique<StructuredData::String>(#target));
#include "llvm/Config/Targets.def"
auto entry_up = std::make_unique<StructuredData::Dictionary>();
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<StructuredData::Dictionary>();
AddBoolConfigEntry(
*config_up, "xml", XMLDocument::XMLEnabled(),
"A boolean value that indicates if XML support is enabled in LLDB");
AddBoolConfigEntry(
*config_up, "curl", LLVM_ENABLE_CURL,
"A boolean value that indicates if CURL 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 = Status::FromErrorString("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<void *>(m_opaque_sp.get()), filename, target_triple,
platform_name, add_dependent_modules, sb_error.GetCString(),
static_cast<void *>(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<void *>(m_opaque_sp.get()), filename, target_triple,
static_cast<void *>(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 = Status::FromErrorStringWithFormat("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<void *>(m_opaque_sp.get()),
filename ? filename : "<unspecified>",
arch_cstr ? arch_cstr : "<unspecified>",
static_cast<void *>(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<void *>(m_opaque_sp.get()), filename,
static_cast<void *>(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<void *>(m_opaque_sp.get()),
static_cast<void *>(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<void *>(m_opaque_sp.get()),
static_cast<void *>(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<void *>(m_opaque_sp.get()),
static_cast<void *>(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<void *>(m_opaque_sp.get()),
static_cast<void *>(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<void *>(m_opaque_sp.get()),
static_cast<void *>(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<void *>(m_opaque_sp.get()),
static_cast<void *>(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<StructuredData::Dictionary>();
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 = Status::FromErrorString("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 = Status::FromErrorStringWithFormat(
"invalid debugger instance name '%s'", debugger_instance_name);
}
if (error.Fail())
sb_error.SetError(std::move(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);
}
uint32_t SBDebugger::GetTerminalHeight() const {
LLDB_INSTRUMENT_VA(this);
return (m_opaque_sp ? m_opaque_sp->GetTerminalWidth() : 0);
}
void SBDebugger::SetTerminalHeight(uint32_t term_height) {
LLDB_INSTRUMENT_VA(this, term_height);
if (m_opaque_sp)
m_opaque_sp->SetTerminalHeight(term_height);
}
const char *SBDebugger::GetPrompt() const {
LLDB_INSTRUMENT_VA(this);
Log *log = GetLog(LLDBLog::API);
LLDB_LOG(log, "SBDebugger({0:x})::GetPrompt () => \"{1}\"",
static_cast<void *>(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::SetShowInlineDiagnostics(bool value) {
LLDB_INSTRUMENT_VA(this, value);
return (m_opaque_sp ? m_opaque_sp->SetShowInlineDiagnostics(value) : 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() = Status::FromErrorString("platform not found");
} else {
sb_error.ref() = Status::FromErrorString("invalid platform name");
}
} else {
sb_error.ref() = Status::FromErrorString("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()));
}
void SBDebugger::ResetStatistics() {
LLDB_INSTRUMENT_VA(this);
if (m_opaque_sp)
DebuggerStats::ResetStatistics(*m_opaque_sp, nullptr);
}
static llvm::ArrayRef<const char *> 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);
}