New public API for handling formatters: creating, deleting, modifying categories, and formatters, and managing type/formatter association. This provides SB classes for each of the main object types involved in providing formatter support: SBTypeCategory SBTypeFilter SBTypeFormat SBTypeSummary SBTypeSynthetic plus, an SBTypeNameSpecifier class that is used on the public API layer to abstract the notion that formatters can be applied to plain type-names as well as to regular expressions For naming consistency, this patch also renames a lot of formatters-related classes. Plus, the changes in how flags are handled that started with summaries is now extended to other classes as well. A new enum (lldb::eTypeOption) is meant to support this on the public side. The patch also adds several new calls to the formatter infrastructure that are used to implement by-index accessing and several other design changes required to accommodate the new API layer. An architectural change is introduced in that backing objects for formatters now become writable. On the public API layer, CoW is implemented to prevent unwanted propagation of changes. Lastly, there are some modifications in how the "default" category is constructed and managed in relation to other categories. llvm-svn: 150558
1203 lines
31 KiB
C++
1203 lines
31 KiB
C++
//===-- SBDebugger.cpp ------------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/API/SBDebugger.h"
|
|
|
|
#include "lldb/lldb-private.h"
|
|
|
|
#include "lldb/API/SBListener.h"
|
|
#include "lldb/API/SBBroadcaster.h"
|
|
#include "lldb/API/SBCommandInterpreter.h"
|
|
#include "lldb/API/SBCommandReturnObject.h"
|
|
#include "lldb/API/SBError.h"
|
|
#include "lldb/API/SBEvent.h"
|
|
#include "lldb/API/SBFrame.h"
|
|
#include "lldb/API/SBInputReader.h"
|
|
#include "lldb/API/SBProcess.h"
|
|
#include "lldb/API/SBSourceManager.h"
|
|
#include "lldb/API/SBStream.h"
|
|
#include "lldb/API/SBStringList.h"
|
|
#include "lldb/API/SBTarget.h"
|
|
#include "lldb/API/SBThread.h"
|
|
#include "lldb/API/SBTypeCategory.h"
|
|
#include "lldb/API/SBTypeFormat.h"
|
|
#include "lldb/API/SBTypeFilter.h"
|
|
#include "lldb/API/SBTypeNameSpecifier.h"
|
|
#include "lldb/API/SBTypeSummary.h"
|
|
#include "lldb/API/SBTypeSynthetic.h"
|
|
|
|
|
|
#include "lldb/Core/DataVisualization.h"
|
|
#include "lldb/Core/Debugger.h"
|
|
#include "lldb/Core/State.h"
|
|
#include "lldb/Interpreter/Args.h"
|
|
#include "lldb/Interpreter/CommandInterpreter.h"
|
|
#include "lldb/Interpreter/OptionGroupPlatform.h"
|
|
#include "lldb/Target/Process.h"
|
|
#include "lldb/Target/TargetList.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
void
|
|
SBDebugger::Initialize ()
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
if (log)
|
|
log->Printf ("SBDebugger::Initialize ()");
|
|
|
|
SBCommandInterpreter::InitializeSWIG ();
|
|
|
|
Debugger::Initialize();
|
|
}
|
|
|
|
void
|
|
SBDebugger::Terminate ()
|
|
{
|
|
Debugger::Terminate();
|
|
}
|
|
|
|
void
|
|
SBDebugger::Clear ()
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
if (log)
|
|
log->Printf ("SBDebugger(%p)::Clear ()", m_opaque_sp.get());
|
|
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->CleanUpInputReaders ();
|
|
|
|
m_opaque_sp.reset();
|
|
}
|
|
|
|
SBDebugger
|
|
SBDebugger::Create()
|
|
{
|
|
return SBDebugger::Create(false);
|
|
}
|
|
|
|
SBDebugger
|
|
SBDebugger::Create(bool source_init_files)
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
SBDebugger debugger;
|
|
debugger.reset(Debugger::CreateInstance());
|
|
|
|
if (log)
|
|
{
|
|
SBStream sstr;
|
|
debugger.GetDescription (sstr);
|
|
log->Printf ("SBDebugger::Create () => SBDebugger(%p): %s", debugger.m_opaque_sp.get(), sstr.GetData());
|
|
}
|
|
|
|
SBCommandInterpreter interp = debugger.GetCommandInterpreter();
|
|
if (source_init_files)
|
|
{
|
|
interp.get()->SkipLLDBInitFiles(false);
|
|
interp.get()->SkipAppInitFiles (false);
|
|
SBCommandReturnObject result;
|
|
interp.SourceInitFileInHomeDirectory(result);
|
|
}
|
|
else
|
|
{
|
|
interp.get()->SkipLLDBInitFiles(true);
|
|
interp.get()->SkipAppInitFiles (true);
|
|
}
|
|
return debugger;
|
|
}
|
|
|
|
void
|
|
SBDebugger::Destroy (SBDebugger &debugger)
|
|
{
|
|
LogSP log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
if (log)
|
|
{
|
|
SBStream sstr;
|
|
debugger.GetDescription (sstr);
|
|
log->Printf ("SBDebugger::Destroy () => SBDebugger(%p): %s", debugger.m_opaque_sp.get(), sstr.GetData());
|
|
}
|
|
|
|
Debugger::Destroy (debugger.m_opaque_sp);
|
|
|
|
if (debugger.m_opaque_sp.get() != NULL)
|
|
debugger.m_opaque_sp.reset();
|
|
}
|
|
|
|
void
|
|
SBDebugger::MemoryPressureDetected ()
|
|
{
|
|
ModuleList::RemoveOrphanSharedModules();
|
|
}
|
|
|
|
SBDebugger::SBDebugger () :
|
|
m_opaque_sp ()
|
|
{
|
|
}
|
|
|
|
SBDebugger::SBDebugger(const lldb::DebuggerSP &debugger_sp) :
|
|
m_opaque_sp(debugger_sp)
|
|
{
|
|
}
|
|
|
|
SBDebugger::SBDebugger(const SBDebugger &rhs) :
|
|
m_opaque_sp (rhs.m_opaque_sp)
|
|
{
|
|
}
|
|
|
|
SBDebugger &
|
|
SBDebugger::operator = (const SBDebugger &rhs)
|
|
{
|
|
if (this != &rhs)
|
|
{
|
|
m_opaque_sp = rhs.m_opaque_sp;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
SBDebugger::~SBDebugger ()
|
|
{
|
|
}
|
|
|
|
bool
|
|
SBDebugger::IsValid() const
|
|
{
|
|
return m_opaque_sp.get() != NULL;
|
|
}
|
|
|
|
|
|
void
|
|
SBDebugger::SetAsync (bool b)
|
|
{
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->SetAsyncExecution(b);
|
|
}
|
|
|
|
bool
|
|
SBDebugger::GetAsync ()
|
|
{
|
|
if (m_opaque_sp)
|
|
return m_opaque_sp->GetAsyncExecution();
|
|
else
|
|
return false;
|
|
}
|
|
|
|
void
|
|
SBDebugger::SkipLLDBInitFiles (bool b)
|
|
{
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->GetCommandInterpreter().SkipLLDBInitFiles (b);
|
|
}
|
|
|
|
void
|
|
SBDebugger::SkipAppInitFiles (bool b)
|
|
{
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->GetCommandInterpreter().SkipAppInitFiles (b);
|
|
}
|
|
|
|
// 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.
|
|
void
|
|
SBDebugger::SetInputFileHandle (FILE *fh, bool transfer_ownership)
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
if (log)
|
|
log->Printf ("SBDebugger(%p)::SetInputFileHandle (fh=%p, transfer_ownership=%i)", m_opaque_sp.get(),
|
|
fh, transfer_ownership);
|
|
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->SetInputFileHandle (fh, transfer_ownership);
|
|
}
|
|
|
|
void
|
|
SBDebugger::SetOutputFileHandle (FILE *fh, bool transfer_ownership)
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
|
|
if (log)
|
|
log->Printf ("SBDebugger(%p)::SetOutputFileHandle (fh=%p, transfer_ownership=%i)", m_opaque_sp.get(),
|
|
fh, transfer_ownership);
|
|
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->SetOutputFileHandle (fh, transfer_ownership);
|
|
}
|
|
|
|
void
|
|
SBDebugger::SetErrorFileHandle (FILE *fh, bool transfer_ownership)
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
|
|
if (log)
|
|
log->Printf ("SBDebugger(%p)::SetErrorFileHandle (fh=%p, transfer_ownership=%i)", m_opaque_sp.get(),
|
|
fh, transfer_ownership);
|
|
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->SetErrorFileHandle (fh, transfer_ownership);
|
|
}
|
|
|
|
FILE *
|
|
SBDebugger::GetInputFileHandle ()
|
|
{
|
|
if (m_opaque_sp)
|
|
return m_opaque_sp->GetInputFile().GetStream();
|
|
return NULL;
|
|
}
|
|
|
|
FILE *
|
|
SBDebugger::GetOutputFileHandle ()
|
|
{
|
|
if (m_opaque_sp)
|
|
return m_opaque_sp->GetOutputFile().GetStream();
|
|
return NULL;
|
|
}
|
|
|
|
FILE *
|
|
SBDebugger::GetErrorFileHandle ()
|
|
{
|
|
if (m_opaque_sp)
|
|
return m_opaque_sp->GetErrorFile().GetStream();
|
|
return NULL;
|
|
}
|
|
|
|
SBCommandInterpreter
|
|
SBDebugger::GetCommandInterpreter ()
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
SBCommandInterpreter sb_interpreter;
|
|
if (m_opaque_sp)
|
|
sb_interpreter.reset (&m_opaque_sp->GetCommandInterpreter());
|
|
|
|
if (log)
|
|
log->Printf ("SBDebugger(%p)::GetCommandInterpreter () => SBCommandInterpreter(%p)",
|
|
m_opaque_sp.get(), sb_interpreter.get());
|
|
|
|
return sb_interpreter;
|
|
}
|
|
|
|
void
|
|
SBDebugger::HandleCommand (const char *command)
|
|
{
|
|
if (m_opaque_sp)
|
|
{
|
|
TargetSP target_sp (m_opaque_sp->GetSelectedTarget());
|
|
Mutex::Locker api_locker;
|
|
if (target_sp)
|
|
api_locker.Reset(target_sp->GetAPIMutex().GetMutex());
|
|
|
|
SBCommandInterpreter sb_interpreter(GetCommandInterpreter ());
|
|
SBCommandReturnObject result;
|
|
|
|
sb_interpreter.HandleCommand (command, result, false);
|
|
|
|
if (GetErrorFileHandle() != NULL)
|
|
result.PutError (GetErrorFileHandle());
|
|
if (GetOutputFileHandle() != NULL)
|
|
result.PutOutput (GetOutputFileHandle());
|
|
|
|
if (m_opaque_sp->GetAsyncExecution() == false)
|
|
{
|
|
SBProcess process(GetCommandInterpreter().GetProcess ());
|
|
ProcessSP process_sp (process.GetSP());
|
|
if (process_sp)
|
|
{
|
|
EventSP event_sp;
|
|
Listener &lldb_listener = m_opaque_sp->GetListener();
|
|
while (lldb_listener.GetNextEventForBroadcaster (process_sp.get(), event_sp))
|
|
{
|
|
SBEvent event(event_sp);
|
|
HandleProcessEvent (process, event, GetOutputFileHandle(), GetErrorFileHandle());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SBListener
|
|
SBDebugger::GetListener ()
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
SBListener sb_listener;
|
|
if (m_opaque_sp)
|
|
sb_listener.reset(&m_opaque_sp->GetListener(), false);
|
|
|
|
if (log)
|
|
log->Printf ("SBDebugger(%p)::GetListener () => SBListener(%p)", m_opaque_sp.get(),
|
|
sb_listener.get());
|
|
|
|
return sb_listener;
|
|
}
|
|
|
|
void
|
|
SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event, FILE *out, FILE *err)
|
|
{
|
|
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;
|
|
|
|
Mutex::Locker api_locker (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 != NULL)
|
|
::fwrite (stdio_buffer, 1, len, out);
|
|
}
|
|
|
|
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 != NULL)
|
|
::fwrite (stdio_buffer, 1, len, err);
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
SBSourceManager
|
|
SBDebugger::GetSourceManager ()
|
|
{
|
|
SBSourceManager sb_source_manager (*this);
|
|
return sb_source_manager;
|
|
}
|
|
|
|
|
|
bool
|
|
SBDebugger::GetDefaultArchitecture (char *arch_name, size_t 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)
|
|
{
|
|
if (arch_name)
|
|
{
|
|
ArchSpec arch (arch_name, NULL);
|
|
if (arch.IsValid())
|
|
{
|
|
Target::SetDefaultArchitecture (arch);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
ScriptLanguage
|
|
SBDebugger::GetScriptingLanguage (const char *script_language_name)
|
|
{
|
|
|
|
return Args::StringToScriptLanguage (script_language_name,
|
|
eScriptLanguageDefault,
|
|
NULL);
|
|
}
|
|
|
|
const char *
|
|
SBDebugger::GetVersionString ()
|
|
{
|
|
return GetVersion();
|
|
}
|
|
|
|
const char *
|
|
SBDebugger::StateAsCString (StateType state)
|
|
{
|
|
return lldb_private::StateAsCString (state);
|
|
}
|
|
|
|
bool
|
|
SBDebugger::StateIsRunningState (StateType state)
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
const bool result = lldb_private::StateIsRunningState (state);
|
|
if (log)
|
|
log->Printf ("SBDebugger::StateIsRunningState (state=%s) => %i",
|
|
StateAsCString (state), result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
SBDebugger::StateIsStoppedState (StateType state)
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
const bool result = lldb_private::StateIsStoppedState (state, false);
|
|
if (log)
|
|
log->Printf ("SBDebugger::StateIsStoppedState (state=%s) => %i",
|
|
StateAsCString (state), result);
|
|
|
|
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)
|
|
{
|
|
SBTarget sb_target;
|
|
TargetSP target_sp;
|
|
if (m_opaque_sp)
|
|
{
|
|
sb_error.Clear();
|
|
FileSpec filename_spec (filename, true);
|
|
OptionGroupPlatform platform_options (false);
|
|
platform_options.SetPlatformName (platform_name);
|
|
|
|
sb_error.ref() = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp,
|
|
filename_spec,
|
|
target_triple,
|
|
add_dependent_modules,
|
|
&platform_options,
|
|
target_sp);
|
|
|
|
if (sb_error.Success())
|
|
sb_target.SetSP (target_sp);
|
|
}
|
|
else
|
|
{
|
|
sb_error.SetErrorString("invalid target");
|
|
}
|
|
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
if (log)
|
|
{
|
|
log->Printf ("SBDebugger(%p)::CreateTarget (filename=\"%s\", triple=%s, platform_name=%s, add_dependent_modules=%u, error=%s) => SBTarget(%p)",
|
|
m_opaque_sp.get(),
|
|
filename,
|
|
target_triple,
|
|
platform_name,
|
|
add_dependent_modules,
|
|
sb_error.GetCString(),
|
|
target_sp.get());
|
|
}
|
|
|
|
return sb_target;
|
|
}
|
|
|
|
SBTarget
|
|
SBDebugger::CreateTargetWithFileAndTargetTriple (const char *filename,
|
|
const char *target_triple)
|
|
{
|
|
SBTarget sb_target;
|
|
TargetSP target_sp;
|
|
if (m_opaque_sp)
|
|
{
|
|
FileSpec file_spec (filename, true);
|
|
TargetSP target_sp;
|
|
const bool add_dependent_modules = true;
|
|
Error error (m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp,
|
|
file_spec,
|
|
target_triple,
|
|
add_dependent_modules,
|
|
NULL,
|
|
target_sp));
|
|
sb_target.SetSP (target_sp);
|
|
}
|
|
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
if (log)
|
|
{
|
|
log->Printf ("SBDebugger(%p)::CreateTargetWithFileAndTargetTriple (filename=\"%s\", triple=%s) => SBTarget(%p)",
|
|
m_opaque_sp.get(), filename, target_triple, target_sp.get());
|
|
}
|
|
|
|
return sb_target;
|
|
}
|
|
|
|
SBTarget
|
|
SBDebugger::CreateTargetWithFileAndArch (const char *filename, const char *arch_cstr)
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
SBTarget sb_target;
|
|
TargetSP target_sp;
|
|
if (m_opaque_sp)
|
|
{
|
|
FileSpec file (filename, true);
|
|
Error error;
|
|
const bool add_dependent_modules = true;
|
|
|
|
error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp,
|
|
file,
|
|
arch_cstr,
|
|
add_dependent_modules,
|
|
NULL,
|
|
target_sp);
|
|
|
|
if (error.Success())
|
|
{
|
|
m_opaque_sp->GetTargetList().SetSelectedTarget (target_sp.get());
|
|
sb_target.SetSP (target_sp);
|
|
}
|
|
}
|
|
|
|
if (log)
|
|
{
|
|
log->Printf ("SBDebugger(%p)::CreateTargetWithFileAndArch (filename=\"%s\", arch=%s) => SBTarget(%p)",
|
|
m_opaque_sp.get(), filename, arch_cstr, target_sp.get());
|
|
}
|
|
|
|
return sb_target;
|
|
}
|
|
|
|
SBTarget
|
|
SBDebugger::CreateTarget (const char *filename)
|
|
{
|
|
SBTarget sb_target;
|
|
TargetSP target_sp;
|
|
if (m_opaque_sp)
|
|
{
|
|
FileSpec file (filename, true);
|
|
ArchSpec arch = Target::GetDefaultArchitecture ();
|
|
Error error;
|
|
const bool add_dependent_modules = true;
|
|
|
|
error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp,
|
|
file,
|
|
arch,
|
|
add_dependent_modules,
|
|
m_opaque_sp->GetPlatformList().GetSelectedPlatform(),
|
|
target_sp);
|
|
|
|
if (error.Success())
|
|
{
|
|
m_opaque_sp->GetTargetList().SetSelectedTarget (target_sp.get());
|
|
sb_target.SetSP (target_sp);
|
|
}
|
|
}
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
if (log)
|
|
{
|
|
log->Printf ("SBDebugger(%p)::CreateTarget (filename=\"%s\") => SBTarget(%p)",
|
|
m_opaque_sp.get(), filename, target_sp.get());
|
|
}
|
|
return sb_target;
|
|
}
|
|
|
|
bool
|
|
SBDebugger::DeleteTarget (lldb::SBTarget &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();
|
|
ModuleList::RemoveOrphanSharedModules();
|
|
}
|
|
}
|
|
|
|
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
if (log)
|
|
{
|
|
log->Printf ("SBDebugger(%p)::DeleteTarget (SBTarget(%p)) => %i", m_opaque_sp.get(), target.m_opaque_sp.get(), result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
SBTarget
|
|
SBDebugger::GetTargetAtIndex (uint32_t 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;
|
|
}
|
|
|
|
SBTarget
|
|
SBDebugger::FindTargetWithProcessID (pid_t 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)
|
|
{
|
|
SBTarget sb_target;
|
|
if (m_opaque_sp && filename && filename[0])
|
|
{
|
|
// No need to lock, the target list is thread safe
|
|
ArchSpec arch (arch_name, m_opaque_sp->GetPlatformList().GetSelectedPlatform().get());
|
|
TargetSP target_sp (m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture (FileSpec(filename, false), arch_name ? &arch : NULL));
|
|
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 ()
|
|
{
|
|
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 ()
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_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);
|
|
log->Printf ("SBDebugger(%p)::GetSelectedTarget () => SBTarget(%p): %s", m_opaque_sp.get(),
|
|
target_sp.get(), sstr.GetData());
|
|
}
|
|
|
|
return sb_target;
|
|
}
|
|
|
|
void
|
|
SBDebugger::SetSelectedTarget (SBTarget &sb_target)
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
TargetSP target_sp (sb_target.GetSP());
|
|
if (m_opaque_sp)
|
|
{
|
|
m_opaque_sp->GetTargetList().SetSelectedTarget (target_sp.get());
|
|
}
|
|
if (log)
|
|
{
|
|
SBStream sstr;
|
|
sb_target.GetDescription (sstr, eDescriptionLevelBrief);
|
|
log->Printf ("SBDebugger(%p)::SetSelectedTarget () => SBTarget(%p): %s", m_opaque_sp.get(),
|
|
target_sp.get(), sstr.GetData());
|
|
}
|
|
}
|
|
|
|
void
|
|
SBDebugger::DispatchInput (void *baton, const void *data, size_t data_len)
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
if (log)
|
|
log->Printf ("SBDebugger(%p)::DispatchInput (baton=%p, data=\"%.*s\", size_t=%zu)", m_opaque_sp.get(),
|
|
baton, (int) data_len, (const char *) data, data_len);
|
|
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->DispatchInput ((const char *) data, data_len);
|
|
}
|
|
|
|
void
|
|
SBDebugger::DispatchInputInterrupt ()
|
|
{
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->DispatchInputInterrupt ();
|
|
}
|
|
|
|
void
|
|
SBDebugger::DispatchInputEndOfFile ()
|
|
{
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->DispatchInputEndOfFile ();
|
|
}
|
|
|
|
bool
|
|
SBDebugger::InputReaderIsTopReader (const lldb::SBInputReader &reader)
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
if (log)
|
|
log->Printf ("SBDebugger(%p)::InputReaderIsTopReader (SBInputReader(%p))", m_opaque_sp.get(), &reader);
|
|
|
|
if (m_opaque_sp && reader.IsValid())
|
|
{
|
|
InputReaderSP reader_sp (*reader);
|
|
return m_opaque_sp->InputReaderIsTopReader (reader_sp);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
void
|
|
SBDebugger::PushInputReader (SBInputReader &reader)
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
if (log)
|
|
log->Printf ("SBDebugger(%p)::PushInputReader (SBInputReader(%p))", m_opaque_sp.get(), &reader);
|
|
|
|
if (m_opaque_sp && reader.IsValid())
|
|
{
|
|
TargetSP target_sp (m_opaque_sp->GetSelectedTarget());
|
|
Mutex::Locker api_locker;
|
|
if (target_sp)
|
|
api_locker.Reset(target_sp->GetAPIMutex().GetMutex());
|
|
InputReaderSP reader_sp(*reader);
|
|
m_opaque_sp->PushInputReader (reader_sp);
|
|
}
|
|
}
|
|
|
|
void
|
|
SBDebugger::NotifyTopInputReader (InputReaderAction notification)
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
if (log)
|
|
log->Printf ("SBDebugger(%p)::NotifyTopInputReader (%d)", m_opaque_sp.get(), notification);
|
|
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->NotifyTopInputReader (notification);
|
|
}
|
|
|
|
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)
|
|
{
|
|
// 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()
|
|
{
|
|
if (m_opaque_sp)
|
|
return m_opaque_sp->GetInstanceName().AsCString();
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
SBError
|
|
SBDebugger::SetInternalVariable (const char *var_name, const char *value, const char *debugger_instance_name)
|
|
{
|
|
UserSettingsControllerSP root_settings_controller = Debugger::GetSettingsController();
|
|
|
|
Error err = root_settings_controller->SetVariable (var_name,
|
|
value,
|
|
eVarSetOperationAssign,
|
|
true,
|
|
debugger_instance_name);
|
|
SBError sb_error;
|
|
sb_error.SetError (err);
|
|
|
|
return sb_error;
|
|
}
|
|
|
|
SBStringList
|
|
SBDebugger::GetInternalVariableValue (const char *var_name, const char *debugger_instance_name)
|
|
{
|
|
SBStringList ret_value;
|
|
SettableVariableType var_type;
|
|
Error err;
|
|
|
|
UserSettingsControllerSP root_settings_controller = Debugger::GetSettingsController();
|
|
|
|
StringList value = root_settings_controller->GetVariable (var_name, var_type, debugger_instance_name, err);
|
|
|
|
if (err.Success())
|
|
{
|
|
for (unsigned i = 0; i != value.GetSize(); ++i)
|
|
ret_value.AppendString (value.GetStringAtIndex(i));
|
|
}
|
|
else
|
|
{
|
|
ret_value.AppendString (err.AsCString());
|
|
}
|
|
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
uint32_t
|
|
SBDebugger::GetTerminalWidth () const
|
|
{
|
|
if (m_opaque_sp)
|
|
return m_opaque_sp->GetTerminalWidth ();
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
SBDebugger::SetTerminalWidth (uint32_t term_width)
|
|
{
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->SetTerminalWidth (term_width);
|
|
}
|
|
|
|
const char *
|
|
SBDebugger::GetPrompt() const
|
|
{
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
|
|
|
if (log)
|
|
log->Printf ("SBDebugger(%p)::GetPrompt () => \"%s\"", m_opaque_sp.get(),
|
|
(m_opaque_sp ? m_opaque_sp->GetPrompt() : ""));
|
|
|
|
if (m_opaque_sp)
|
|
return m_opaque_sp->GetPrompt ();
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
SBDebugger::SetPrompt (const char *prompt)
|
|
{
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->SetPrompt (prompt);
|
|
}
|
|
|
|
|
|
ScriptLanguage
|
|
SBDebugger::GetScriptLanguage() const
|
|
{
|
|
if (m_opaque_sp)
|
|
return m_opaque_sp->GetScriptLanguage ();
|
|
return eScriptLanguageNone;
|
|
}
|
|
|
|
void
|
|
SBDebugger::SetScriptLanguage (ScriptLanguage script_lang)
|
|
{
|
|
if (m_opaque_sp)
|
|
{
|
|
m_opaque_sp->SetScriptLanguage (script_lang);
|
|
}
|
|
}
|
|
|
|
bool
|
|
SBDebugger::SetUseExternalEditor (bool value)
|
|
{
|
|
if (m_opaque_sp)
|
|
return m_opaque_sp->SetUseExternalEditor (value);
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
SBDebugger::GetUseExternalEditor ()
|
|
{
|
|
if (m_opaque_sp)
|
|
return m_opaque_sp->GetUseExternalEditor ();
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
SBDebugger::GetDescription (SBStream &description)
|
|
{
|
|
Stream &strm = description.ref();
|
|
|
|
if (m_opaque_sp)
|
|
{
|
|
const char *name = m_opaque_sp->GetInstanceName().AsCString();
|
|
user_id_t id = m_opaque_sp->GetID();
|
|
strm.Printf ("Debugger (instance: \"%s\", id: %llu)", name, id);
|
|
}
|
|
else
|
|
strm.PutCString ("No value");
|
|
|
|
return true;
|
|
}
|
|
|
|
user_id_t
|
|
SBDebugger::GetID()
|
|
{
|
|
if (m_opaque_sp)
|
|
return m_opaque_sp->GetID();
|
|
return LLDB_INVALID_UID;
|
|
}
|
|
|
|
|
|
SBError
|
|
SBDebugger::SetCurrentPlatform (const char *platform_name)
|
|
{
|
|
SBError sb_error;
|
|
if (m_opaque_sp)
|
|
{
|
|
PlatformSP platform_sp (Platform::Create (platform_name, sb_error.ref()));
|
|
|
|
if (platform_sp)
|
|
{
|
|
bool make_selected = true;
|
|
m_opaque_sp->GetPlatformList().Append (platform_sp, make_selected);
|
|
}
|
|
}
|
|
return sb_error;
|
|
}
|
|
|
|
bool
|
|
SBDebugger::SetCurrentPlatformSDKRoot (const char *sysroot)
|
|
{
|
|
if (m_opaque_sp)
|
|
{
|
|
PlatformSP platform_sp (m_opaque_sp->GetPlatformList().GetSelectedPlatform());
|
|
|
|
if (platform_sp)
|
|
{
|
|
platform_sp->SetSDKRootDirectory (ConstString (sysroot));
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
SBDebugger::GetCloseInputOnEOF () const
|
|
{
|
|
if (m_opaque_sp)
|
|
return m_opaque_sp->GetCloseInputOnEOF ();
|
|
return false;
|
|
}
|
|
|
|
void
|
|
SBDebugger::SetCloseInputOnEOF (bool b)
|
|
{
|
|
if (m_opaque_sp)
|
|
m_opaque_sp->SetCloseInputOnEOF (b);
|
|
}
|
|
|
|
SBTypeCategory
|
|
SBDebugger::GetCategory (const char* 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::CreateCategory (const char* 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)
|
|
{
|
|
if (!category_name || *category_name == 0)
|
|
return false;
|
|
|
|
return DataVisualization::Categories::Delete(ConstString(category_name));
|
|
}
|
|
|
|
uint32_t
|
|
SBDebugger::GetNumCategories()
|
|
{
|
|
return DataVisualization::Categories::GetCount();
|
|
}
|
|
|
|
SBTypeCategory
|
|
SBDebugger::GetCategoryAtIndex (uint32_t index)
|
|
{
|
|
return SBTypeCategory(DataVisualization::Categories::GetCategoryAtIndex(index));
|
|
}
|
|
|
|
SBTypeCategory
|
|
SBDebugger::GetDefaultCategory()
|
|
{
|
|
return GetCategory("default");
|
|
}
|
|
|
|
SBTypeFormat
|
|
SBDebugger::GetFormatForType (SBTypeNameSpecifier 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)
|
|
{
|
|
SBTypeSummary summary_chosen;
|
|
uint32_t num_categories = GetNumCategories();
|
|
SBTypeCategory category_sb;
|
|
uint32_t prio_category = UINT32_MAX;
|
|
for (uint32_t category_id = 0;
|
|
category_id < num_categories;
|
|
category_id++)
|
|
{
|
|
category_sb = GetCategoryAtIndex(category_id);
|
|
if (category_sb.GetEnabled() == false)
|
|
continue;
|
|
SBTypeSummary summary_current = category_sb.GetSummaryForType(type_name);
|
|
if (summary_current.IsValid() && (summary_chosen.IsValid() == false || (prio_category > category_sb.m_opaque_sp->GetEnabledPosition())))
|
|
{
|
|
prio_category = category_sb.m_opaque_sp->GetEnabledPosition();
|
|
summary_chosen = summary_current;
|
|
}
|
|
}
|
|
return summary_chosen;
|
|
}
|
|
|
|
SBTypeFilter
|
|
SBDebugger::GetFilterForType (SBTypeNameSpecifier type_name)
|
|
{
|
|
SBTypeFilter filter_chosen;
|
|
uint32_t num_categories = GetNumCategories();
|
|
SBTypeCategory category_sb;
|
|
uint32_t prio_category = UINT32_MAX;
|
|
for (uint32_t category_id = 0;
|
|
category_id < num_categories;
|
|
category_id++)
|
|
{
|
|
category_sb = GetCategoryAtIndex(category_id);
|
|
if (category_sb.GetEnabled() == false)
|
|
continue;
|
|
SBTypeFilter filter_current = category_sb.GetFilterForType(type_name);
|
|
if (filter_current.IsValid() && (filter_chosen.IsValid() == false || (prio_category > category_sb.m_opaque_sp->GetEnabledPosition())))
|
|
{
|
|
prio_category = category_sb.m_opaque_sp->GetEnabledPosition();
|
|
filter_chosen = filter_current;
|
|
}
|
|
}
|
|
return filter_chosen;
|
|
}
|
|
|
|
SBTypeSynthetic
|
|
SBDebugger::GetSyntheticForType (SBTypeNameSpecifier type_name)
|
|
{
|
|
SBTypeSynthetic synth_chosen;
|
|
uint32_t num_categories = GetNumCategories();
|
|
SBTypeCategory category_sb;
|
|
uint32_t prio_category = UINT32_MAX;
|
|
for (uint32_t category_id = 0;
|
|
category_id < num_categories;
|
|
category_id++)
|
|
{
|
|
category_sb = GetCategoryAtIndex(category_id);
|
|
if (category_sb.GetEnabled() == false)
|
|
continue;
|
|
SBTypeSynthetic synth_current = category_sb.GetSyntheticForType(type_name);
|
|
if (synth_current.IsValid() && (synth_chosen.IsValid() == false || (prio_category > category_sb.m_opaque_sp->GetEnabledPosition())))
|
|
{
|
|
prio_category = category_sb.m_opaque_sp->GetEnabledPosition();
|
|
synth_chosen = synth_current;
|
|
}
|
|
}
|
|
return synth_chosen;
|
|
}
|
|
|