diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/API/SBCommandInterpreter.cpp | 126 | ||||
-rw-r--r-- | lldb/source/API/SBCommandReturnObject.cpp | 7 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectPlugin.cpp | 117 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectPlugin.h | 36 | ||||
-rw-r--r-- | lldb/source/Core/Debugger.cpp | 107 | ||||
-rw-r--r-- | lldb/source/Host/common/DynamicLibrary.cpp | 27 | ||||
-rw-r--r-- | lldb/source/Interpreter/CommandInterpreter.cpp | 22 |
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; } |