summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/API/SBCommandInterpreter.cpp126
-rw-r--r--lldb/source/API/SBCommandReturnObject.cpp7
-rw-r--r--lldb/source/Commands/CommandObjectPlugin.cpp117
-rw-r--r--lldb/source/Commands/CommandObjectPlugin.h36
-rw-r--r--lldb/source/Core/Debugger.cpp107
-rw-r--r--lldb/source/Host/common/DynamicLibrary.cpp27
-rw-r--r--lldb/source/Interpreter/CommandInterpreter.cpp22
7 files changed, 436 insertions, 6 deletions
diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp
index 08e845f7e15..f125f55e7a0 100644
--- a/lldb/source/API/SBCommandInterpreter.cpp
+++ b/lldb/source/API/SBCommandInterpreter.cpp
@@ -8,15 +8,14 @@
//===----------------------------------------------------------------------===//
#include "lldb/lldb-types.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Core/SourceManager.h"
#include "lldb/Core/Listener.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Target.h"
#include "lldb/API/SBBroadcaster.h"
-#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBProcess.h"
@@ -28,6 +27,34 @@
using namespace lldb;
using namespace lldb_private;
+class CommandPluginInterfaceImplementation : public CommandObjectParsed
+{
+public:
+ CommandPluginInterfaceImplementation (CommandInterpreter &interpreter,
+ const char *name,
+ lldb::SBCommandPluginInterface* backend,
+ const char *help = NULL,
+ const char *syntax = NULL,
+ uint32_t flags = 0) :
+ CommandObjectParsed (interpreter, name, help, syntax, flags),
+ m_backend(backend) {}
+
+ virtual bool
+ IsRemovable() { return true; }
+
+protected:
+ virtual bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ SBCommandReturnObject sb_return(&result);
+ SBCommandInterpreter sb_interpreter(&m_interpreter);
+ SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this());
+ bool ret = m_backend->DoExecute (debugger_sb,(char**)command.GetArgumentVector(), sb_return);
+ sb_return.Release();
+ return ret;
+ }
+ lldb::SBCommandPluginInterface* m_backend;
+};
SBCommandInterpreter::SBCommandInterpreter (CommandInterpreter *interpreter) :
m_opaque_ptr (interpreter)
@@ -218,6 +245,22 @@ SBCommandInterpreter::GetProcess ()
return sb_process;
}
+SBDebugger
+SBCommandInterpreter::GetDebugger ()
+{
+ SBDebugger sb_debugger;
+ if (m_opaque_ptr)
+ sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this());
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+ if (log)
+ log->Printf ("SBCommandInterpreter(%p)::GetDebugger () => SBDebugger(%p)",
+ m_opaque_ptr, sb_debugger.get());
+
+
+ return sb_debugger;
+}
+
CommandInterpreter *
SBCommandInterpreter::get ()
{
@@ -368,3 +411,82 @@ SBCommandInterpreter::InitializeSWIG ()
}
}
+lldb::SBCommand
+SBCommandInterpreter::AddMultiwordCommand (const char* name, const char* help)
+{
+ CommandObjectMultiword *new_command = new CommandObjectMultiword(*m_opaque_ptr,name,help);
+ new_command->SetRemovable (true);
+ lldb::CommandObjectSP new_command_sp(new_command);
+ if (new_command_sp && m_opaque_ptr->AddUserCommand(name, new_command_sp, true))
+ return lldb::SBCommand(new_command_sp);
+ return lldb::SBCommand();
+}
+
+lldb::SBCommand
+SBCommandInterpreter::AddCommand (const char* name, lldb::SBCommandPluginInterface* impl, const char* help)
+{
+ lldb::CommandObjectSP new_command_sp;
+ new_command_sp.reset(new CommandPluginInterfaceImplementation(*m_opaque_ptr,name,impl,help));
+
+ if (new_command_sp && m_opaque_ptr->AddUserCommand(name, new_command_sp, true))
+ return lldb::SBCommand(new_command_sp);
+ return lldb::SBCommand();
+}
+
+SBCommand::SBCommand ()
+{}
+
+SBCommand::SBCommand (lldb::CommandObjectSP cmd_sp) : m_opaque_sp (cmd_sp)
+{}
+
+bool
+SBCommand::IsValid ()
+{
+ return (bool)m_opaque_sp;
+}
+
+const char*
+SBCommand::GetName ()
+{
+ if (IsValid ())
+ return m_opaque_sp->GetCommandName ();
+ return NULL;
+}
+
+const char*
+SBCommand::GetHelp ()
+{
+ if (IsValid ())
+ return m_opaque_sp->GetHelp ();
+ return NULL;
+}
+
+lldb::SBCommand
+SBCommand::AddMultiwordCommand (const char* name, const char* help)
+{
+ if (!IsValid ())
+ return lldb::SBCommand();
+ if (m_opaque_sp->IsMultiwordObject() == false)
+ return lldb::SBCommand();
+ CommandObjectMultiword *new_command = new CommandObjectMultiword(m_opaque_sp->GetCommandInterpreter(),name,help);
+ new_command->SetRemovable (true);
+ lldb::CommandObjectSP new_command_sp(new_command);
+ if (new_command_sp && m_opaque_sp->LoadSubCommand(name,new_command_sp))
+ return lldb::SBCommand(new_command_sp);
+ return lldb::SBCommand();
+}
+
+lldb::SBCommand
+SBCommand::AddCommand (const char* name, lldb::SBCommandPluginInterface *impl, const char* help)
+{
+ if (!IsValid ())
+ return lldb::SBCommand();
+ if (m_opaque_sp->IsMultiwordObject() == false)
+ return lldb::SBCommand();
+ lldb::CommandObjectSP new_command_sp;
+ new_command_sp.reset(new CommandPluginInterfaceImplementation(m_opaque_sp->GetCommandInterpreter(),name,impl,help));
+ if (new_command_sp && m_opaque_sp->LoadSubCommand(name,new_command_sp))
+ return lldb::SBCommand(new_command_sp);
+ return lldb::SBCommand();
+}
+
diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp
index 4e633e4b9ac..4632009679b 100644
--- a/lldb/source/API/SBCommandReturnObject.cpp
+++ b/lldb/source/API/SBCommandReturnObject.cpp
@@ -190,6 +190,13 @@ SBCommandReturnObject::AppendMessage (const char *message)
m_opaque_ap->AppendMessage (message);
}
+void
+SBCommandReturnObject::AppendWarning (const char *message)
+{
+ if (m_opaque_ap.get())
+ m_opaque_ap->AppendWarning (message);
+}
+
CommandReturnObject *
SBCommandReturnObject::operator ->() const
{
diff --git a/lldb/source/Commands/CommandObjectPlugin.cpp b/lldb/source/Commands/CommandObjectPlugin.cpp
new file mode 100644
index 00000000000..6570c1d8978
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectPlugin.cpp
@@ -0,0 +1,117 @@
+//===-- CommandObjectPlugin.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectPlugin.h"
+
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBCommandInterpreter.h"
+#include "lldb/API/SBCommandReturnObject.h"
+
+#include "lldb/Host/Host.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class CommandObjectPluginLoad : public CommandObjectParsed
+{
+private:
+public:
+ CommandObjectPluginLoad (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "plugin load",
+ "Import a dylib that implements an LLDB plugin.",
+ NULL)
+ {
+ CommandArgumentEntry arg1;
+ CommandArgumentData cmd_arg;
+
+ // Define the first (and only) variant of this arg.
+ cmd_arg.arg_type = eArgTypeFilename;
+ cmd_arg.arg_repetition = eArgRepeatPlain;
+
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg1.push_back (cmd_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back (arg1);
+ }
+
+ ~CommandObjectPluginLoad ()
+ {
+ }
+
+ int
+ HandleArgumentCompletion (Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ OptionElementVector &opt_element_vector,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+ {
+ std::string completion_str (input.GetArgumentAtIndex(cursor_index));
+ completion_str.erase (cursor_char_position);
+
+ CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
+ CommandCompletions::eDiskFileCompletion,
+ completion_str.c_str(),
+ match_start_point,
+ max_return_elements,
+ NULL,
+ word_complete,
+ matches);
+ return matches.GetSize();
+ }
+
+protected:
+ bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ typedef void (*LLDBCommandPluginInit) (lldb::SBDebugger debugger);
+
+ size_t argc = command.GetArgumentCount();
+
+ if (argc != 1)
+ {
+ result.AppendError ("'plugin load' requires one argument");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const char* path = command.GetArgumentAtIndex(0);
+
+ Error error;
+
+ FileSpec dylib_fspec(path,true);
+
+ if (m_interpreter.GetDebugger().LoadPlugin(dylib_fspec))
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+
+ return result.Succeeded();
+ }
+};
+
+CommandObjectPlugin::CommandObjectPlugin (CommandInterpreter &interpreter) :
+CommandObjectMultiword (interpreter,
+ "plugin",
+ "A set of commands for managing or customizing plugin commands.",
+ "plugin <subcommand> [<subcommand-options>]")
+{
+ LoadSubCommand ("load", CommandObjectSP (new CommandObjectPluginLoad (interpreter)));
+}
+
+CommandObjectPlugin::~CommandObjectPlugin ()
+{
+}
diff --git a/lldb/source/Commands/CommandObjectPlugin.h b/lldb/source/Commands/CommandObjectPlugin.h
new file mode 100644
index 00000000000..9d0f0fcc1ed
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectPlugin.h
@@ -0,0 +1,36 @@
+//===-- CommandObjectPlugin.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectPlugin_h_
+#define liblldb_CommandObjectPlugin_h_
+
+// C Includes
+// C++ Includes
+
+
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-types.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+ class CommandObjectPlugin : public CommandObjectMultiword
+ {
+ public:
+ CommandObjectPlugin (CommandInterpreter &interpreter);
+
+ virtual
+ ~CommandObjectPlugin ();
+ };
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectPlugin_h_
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index b6e4f811062..86b0cf53e3c 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/API/SBDebugger.h"
+
#include "lldb/Core/Debugger.h"
#include <map>
@@ -28,6 +30,7 @@
#include "lldb/Core/Timer.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Host/DynamicLibrary.h"
#include "lldb/Host/Terminal.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionValueSInt64.h"
@@ -334,6 +337,109 @@ Debugger::SettingsTerminate ()
Target::SettingsTerminate ();
}
+bool
+Debugger::LoadPlugin (const FileSpec& spec)
+{
+ lldb::DynamicLibrarySP dynlib_sp(new lldb_private::DynamicLibrary(spec));
+ lldb::DebuggerSP debugger_sp(shared_from_this());
+ lldb::SBDebugger debugger_sb(debugger_sp);
+ // TODO: mangle this differently for your system - on OSX, the first underscore needs to be removed and the second one stays
+ LLDBCommandPluginInit init_func = dynlib_sp->GetSymbol<LLDBCommandPluginInit>("_ZN4lldb16PluginInitializeENS_10SBDebuggerE");
+ if (!init_func)
+ return false;
+ if (init_func(debugger_sb))
+ {
+ m_loaded_plugins.push_back(dynlib_sp);
+ return true;
+ }
+ return false;
+}
+
+static FileSpec::EnumerateDirectoryResult
+LoadPluginCallback
+(
+ void *baton,
+ FileSpec::FileType file_type,
+ const FileSpec &file_spec
+ )
+{
+ Error error;
+
+ static ConstString g_dylibext("dylib");
+
+ if (!baton)
+ return FileSpec::eEnumerateDirectoryResultQuit;
+
+ Debugger *debugger = (Debugger*)baton;
+
+ // If we have a regular file, a symbolic link or unknown file type, try
+ // and process the file. We must handle unknown as sometimes the directory
+ // enumeration might be enumerating a file system that doesn't have correct
+ // file type information.
+ if (file_type == FileSpec::eFileTypeRegular ||
+ file_type == FileSpec::eFileTypeSymbolicLink ||
+ file_type == FileSpec::eFileTypeUnknown )
+ {
+ FileSpec plugin_file_spec (file_spec);
+ plugin_file_spec.ResolvePath ();
+
+ if (plugin_file_spec.GetFileNameExtension() != g_dylibext)
+ return FileSpec::eEnumerateDirectoryResultNext;
+
+ debugger->LoadPlugin (plugin_file_spec);
+
+ return FileSpec::eEnumerateDirectoryResultNext;
+ }
+
+ else if (file_type == FileSpec::eFileTypeUnknown ||
+ file_type == FileSpec::eFileTypeDirectory ||
+ file_type == FileSpec::eFileTypeSymbolicLink )
+ {
+ // Try and recurse into anything that a directory or symbolic link.
+ // We must also do this for unknown as sometimes the directory enumeration
+ // might be enurating a file system that doesn't have correct file type
+ // information.
+ return FileSpec::eEnumerateDirectoryResultEnter;
+ }
+
+ return FileSpec::eEnumerateDirectoryResultNext;
+}
+
+void
+Debugger::InstanceInitialize ()
+{
+ FileSpec dir_spec;
+ const bool find_directories = true;
+ const bool find_files = true;
+ const bool find_other = true;
+ char dir_path[PATH_MAX];
+ if (Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec))
+ {
+ if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path)))
+ {
+ FileSpec::EnumerateDirectory (dir_path,
+ find_directories,
+ find_files,
+ find_other,
+ LoadPluginCallback,
+ this);
+ }
+ }
+
+ if (Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec))
+ {
+ if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path)))
+ {
+ FileSpec::EnumerateDirectory (dir_path,
+ find_directories,
+ find_files,
+ find_other,
+ LoadPluginCallback,
+ this);
+ }
+ }
+}
+
DebuggerSP
Debugger::CreateInstance (lldb::LogOutputCallback log_callback, void *baton)
{
@@ -343,6 +449,7 @@ Debugger::CreateInstance (lldb::LogOutputCallback log_callback, void *baton)
Mutex::Locker locker (GetDebuggerListMutex ());
GetDebuggerList().push_back(debugger_sp);
}
+ debugger_sp->InstanceInitialize ();
return debugger_sp;
}
diff --git a/lldb/source/Host/common/DynamicLibrary.cpp b/lldb/source/Host/common/DynamicLibrary.cpp
new file mode 100644
index 00000000000..e1ac3666829
--- /dev/null
+++ b/lldb/source/Host/common/DynamicLibrary.cpp
@@ -0,0 +1,27 @@
+//===-- DynamicLibrary.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/Core/Error.h"
+#include "lldb/Host/DynamicLibrary.h"
+
+using namespace lldb_private;
+
+DynamicLibrary::DynamicLibrary (const FileSpec& spec, uint32_t options) : m_filespec(spec)
+{
+ Error err;
+ m_handle = Host::DynamicLibraryOpen (spec,options,err);
+ if (err.Fail())
+ m_handle = NULL;
+}
+
+DynamicLibrary::~DynamicLibrary ()
+{
+ if (m_handle)
+ Host::DynamicLibraryClose (m_handle);
+}
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 52ba414c5f8..eed403866ae 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -26,6 +26,7 @@
#include "../Commands/CommandObjectLog.h"
#include "../Commands/CommandObjectMemory.h"
#include "../Commands/CommandObjectPlatform.h"
+#include "../Commands/CommandObjectPlugin.h"
#include "../Commands/CommandObjectProcess.h"
#include "../Commands/CommandObjectQuit.h"
#include "../Commands/CommandObjectRegister.h"
@@ -356,6 +357,7 @@ CommandInterpreter::LoadCommandDictionary ()
m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this));
m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this));
m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this));
+ m_command_dict["plugin"] = CommandObjectSP (new CommandObjectPlugin (*this));
m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this));
m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this));
@@ -627,6 +629,8 @@ CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &c
if (m_command_dict.find (name_sstr) != m_command_dict.end())
return false;
}
+ if (m_command_dict[name_sstr]->IsRemovable() == false)
+ return false;
m_command_dict[name_sstr] = cmd_sp;
return true;
}
@@ -645,11 +649,21 @@ CommandInterpreter::AddUserCommand (std::string name,
// do not allow replacement of internal commands
if (CommandExists(name_cstr))
- return false;
+ {
+ if (can_replace == false)
+ return false;
+ if (m_command_dict[name]->IsRemovable() == false)
+ return false;
+ }
+
+ if (UserCommandExists(name_cstr))
+ {
+ if (can_replace == false)
+ return false;
+ if (m_user_dict[name]->IsRemovable() == false)
+ return false;
+ }
- if (can_replace == false && UserCommandExists(name_cstr))
- return false;
-
m_user_dict[name] = cmd_sp;
return true;
}
OpenPOWER on IntegriCloud