diff options
22 files changed, 657 insertions, 13 deletions
diff --git a/lldb/examples/plugins/commands/fooplugin.cpp b/lldb/examples/plugins/commands/fooplugin.cpp new file mode 100644 index 00000000000..86033bb0de8 --- /dev/null +++ b/lldb/examples/plugins/commands/fooplugin.cpp @@ -0,0 +1,47 @@ +/* +An example plugin for LLDB that provides a new foo command with a child subcommand +Compile this into a dylib foo.dylib and load by placing in appropriate locations on disk or +by typing plugin load foo.dylib at the LLDB command line +*/ + +#include <LLDB/SBCommandInterpreter.h> +#include <LLDB/SBCommandReturnObject.h> +#include <LLDB/SBDebugger.h> + +namespace lldb { + bool + PluginInitialize (lldb::SBDebugger debugger); +} + +class ChildCommand : public lldb::SBCommandPluginInterface +{ +public: + virtual bool + DoExecute (lldb::SBDebugger debugger, + char** command, + lldb::SBCommandReturnObject &result) + { + if (command) + { + const char* arg = *command; + while (arg) + { + printf("%s\n",arg); + arg = *(++command); + } + return true; + } + return false; + } + +}; + +bool +lldb::PluginInitialize (lldb::SBDebugger debugger) +{ + lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter(); + lldb::SBCommand foo = interpreter.AddMultiwordCommand("foo",NULL); + foo.AddCommand("child",new ChildCommand(),"a child of foo"); + return true; +} + diff --git a/lldb/include/lldb/API/SBCommandInterpreter.h b/lldb/include/lldb/API/SBCommandInterpreter.h index e30857b8784..ebcb6bf4715 100644 --- a/lldb/include/lldb/API/SBCommandInterpreter.h +++ b/lldb/include/lldb/API/SBCommandInterpreter.h @@ -11,6 +11,7 @@ #define LLDB_SBCommandInterpreter_h_ #include "lldb/API/SBDefines.h" +#include "lldb/API/SBDebugger.h" namespace lldb { @@ -65,6 +66,15 @@ public: lldb::SBProcess GetProcess (); + + lldb::SBDebugger + GetDebugger (); + + lldb::SBCommand + AddMultiwordCommand (const char* name, const char* help); + + lldb::SBCommand + AddCommand (const char* name, lldb::SBCommandPluginInterface *impl, const char* help); void SourceInitFileInHomeDirectory (lldb::SBCommandReturnObject &result); @@ -99,6 +109,9 @@ public: SetCommandOverrideCallback (const char *command_name, lldb::CommandOverrideCallback callback, void *baton); + + SBCommandInterpreter (lldb_private::CommandInterpreter *interpreter_ptr = NULL); // Access using SBDebugger::GetCommandInterpreter(); + protected: lldb_private::CommandInterpreter & @@ -112,14 +125,58 @@ protected: private: friend class SBDebugger; - SBCommandInterpreter (lldb_private::CommandInterpreter *interpreter_ptr = NULL); // Access using SBDebugger::GetCommandInterpreter(); - static void InitializeSWIG (); lldb_private::CommandInterpreter *m_opaque_ptr; }; +class SBCommandPluginInterface +{ +public: + virtual bool + DoExecute (lldb::SBDebugger debugger, + char** command, + lldb::SBCommandReturnObject &result) + { + return false; + } + + virtual + ~SBCommandPluginInterface () + {} +}; + +class SBCommand +{ +public: + + SBCommand (); + + bool + IsValid (); + + const char* + GetName (); + + const char* + GetHelp (); + + lldb::SBCommand + AddMultiwordCommand (const char* name, const char* help = NULL); + + lldb::SBCommand + AddCommand (const char* name, lldb::SBCommandPluginInterface* impl, const char* help = NULL); + +private: + + friend class SBDebugger; + friend class SBCommandInterpreter; + + SBCommand (lldb::CommandObjectSP cmd_sp); + + lldb::CommandObjectSP m_opaque_sp; +}; } // namespace lldb diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h index 1f4bfce8814..1dc632c84cc 100644 --- a/lldb/include/lldb/API/SBCommandReturnObject.h +++ b/lldb/include/lldb/API/SBCommandReturnObject.h @@ -74,6 +74,9 @@ public: void AppendMessage (const char *message); + void + AppendWarning (const char *message); + bool GetDescription (lldb::SBStream &description); diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h index 60ff518e390..41bcfa5068c 100644 --- a/lldb/include/lldb/API/SBDebugger.h +++ b/lldb/include/lldb/API/SBDebugger.h @@ -295,11 +295,12 @@ public: private: + friend class SBCommandInterpreter; friend class SBInputReader; + friend class SBListener; friend class SBProcess; friend class SBSourceManager; friend class SBTarget; - friend class SBListener; lldb::SBTarget FindTargetWithLLDBProcess (const lldb::ProcessSP &processSP); diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h index 82805d09568..7c958be4a18 100644 --- a/lldb/include/lldb/API/SBDefines.h +++ b/lldb/include/lldb/API/SBDefines.h @@ -29,7 +29,9 @@ class SBBlock; class SBBreakpoint; class SBBreakpointLocation; class SBBroadcaster; +class SBCommand; class SBCommandInterpreter; +class SBCommandPluginInterface; class SBCommandReturnObject; class SBCommunication; class SBCompileUnit; diff --git a/lldb/include/lldb/API/SBError.h b/lldb/include/lldb/API/SBError.h index a4aa56e82ea..89617c4ccab 100644 --- a/lldb/include/lldb/API/SBError.h +++ b/lldb/include/lldb/API/SBError.h @@ -66,7 +66,6 @@ public: protected: - friend class SBArguments; friend class SBData; friend class SBDebugger; friend class SBCommunication; diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index 11392c438dc..67fa370caaa 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -18,6 +18,9 @@ #include <stack> #include "lldb/lldb-public.h" + +#include "lldb/API/SBDefines.h" + #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Communication.h" #include "lldb/Core/FormatManager.h" @@ -319,6 +322,11 @@ public: { return m_instance_name; } + + typedef bool (*LLDBCommandPluginInit) (lldb::SBDebugger& debugger); + + bool + LoadPlugin (const FileSpec& spec); protected: @@ -357,7 +365,12 @@ protected: LogStreamMap m_log_streams; lldb::StreamSP m_log_callback_stream_sp; ConstString m_instance_name; - + typedef std::vector<lldb::DynamicLibrarySP> LoadedPluginsList; + LoadedPluginsList m_loaded_plugins; + + void + InstanceInitialize (); + private: // Use Debugger::CreateInstance() to get a shared pointer to a new diff --git a/lldb/include/lldb/Host/DynamicLibrary.h b/lldb/include/lldb/Host/DynamicLibrary.h new file mode 100644 index 00000000000..3a360b04f51 --- /dev/null +++ b/lldb/include/lldb/Host/DynamicLibrary.h @@ -0,0 +1,48 @@ +//===-- DynamicLibrary.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_DynamicLibrary_h_ +#define liblldb_DynamicLibrary_h_ + +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/Host.h" + +namespace lldb_private { + +class DynamicLibrary +{ +public: + DynamicLibrary (const FileSpec& spec, uint32_t options = Host::eDynamicLibraryOpenOptionLazy | + Host::eDynamicLibraryOpenOptionLocal | + Host::eDynamicLibraryOpenOptionLimitGetSymbol); + + ~DynamicLibrary (); + + template <typename T = void*> + T GetSymbol (const char* name) + { + Error err; + if (!m_handle) + return (T)NULL; + void* symbol = Host::DynamicLibraryGetSymbol (m_handle, name, err); + if (!symbol) + return (T)NULL; + return (T)symbol; + } + +private: + lldb_private::FileSpec m_filespec; + void* m_handle; + + DISALLOW_COPY_AND_ASSIGN (DynamicLibrary); +}; + +} // namespace lldb_private + +#endif // liblldb_DynamicLibrary_h_ diff --git a/lldb/include/lldb/Interpreter/CommandObject.h b/lldb/include/lldb/Interpreter/CommandObject.h index 54eaa8f9aa9..c9ffd520146 100644 --- a/lldb/include/lldb/Interpreter/CommandObject.h +++ b/lldb/include/lldb/Interpreter/CommandObject.h @@ -144,6 +144,17 @@ public: virtual bool IsMultiwordObject () { return false; } + // this is needed in order to allow the SBCommand class to + // transparently try and load subcommands - it will fail on + // anything but a multiword command, but it avoids us doing + // type checkings and casts + virtual bool + LoadSubCommand (const char *cmd_name, + const lldb::CommandObjectSP& command_obj) + { + return false; + } + virtual bool WantsRawCommandString() = 0; diff --git a/lldb/include/lldb/Interpreter/CommandObjectMultiword.h b/lldb/include/lldb/Interpreter/CommandObjectMultiword.h index 09004e9e4fa..eb41326a5bb 100644 --- a/lldb/include/lldb/Interpreter/CommandObjectMultiword.h +++ b/lldb/include/lldb/Interpreter/CommandObjectMultiword.h @@ -42,7 +42,7 @@ public: virtual bool IsMultiwordObject () { return true; } - bool + virtual bool LoadSubCommand (const char *cmd_name, const lldb::CommandObjectSP& command_obj); @@ -72,9 +72,20 @@ public: virtual bool Execute (const char *args_string, CommandReturnObject &result); + + virtual bool + IsRemovable() { return m_can_be_removed; } + + void + SetRemovable (bool removable) + { + m_can_be_removed = removable; + } + protected: CommandObject::CommandMap m_subcommand_dict; + bool m_can_be_removed; }; } // namespace lldb_private diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index 7f11f181521..84cecd184c5 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -94,6 +94,7 @@ class DataExtractor; class Debugger; class Declaration; class Disassembler; +class DynamicLibrary; class DynamicLoader; class EmulateInstruction; class Error; @@ -289,6 +290,7 @@ namespace lldb { typedef STD_SHARED_PTR(lldb_private::Debugger) DebuggerSP; typedef STD_WEAK_PTR( lldb_private::Debugger) DebuggerWP; typedef STD_SHARED_PTR(lldb_private::Disassembler) DisassemblerSP; + typedef STD_SHARED_PTR(lldb_private::DynamicLibrary) DynamicLibrarySP; typedef STD_SHARED_PTR(lldb_private::DynamicLoader) DynamicLoaderSP; typedef STD_SHARED_PTR(lldb_private::Event) EventSP; typedef STD_SHARED_PTR(lldb_private::ExecutionContextRef) ExecutionContextRefSP; diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index ea6816b0995..6cac3cb181f 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -515,6 +515,7 @@ 941BCC8214E48C4000BB969C /* SBTypeSynthetic.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568914E355F2003A195C /* SBTypeSynthetic.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9443B122140C18C40013457C /* SBData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9443B121140C18C10013457C /* SBData.cpp */; }; 9443B123140C26AB0013457C /* SBData.h in Headers */ = {isa = PBXBuildFile; fileRef = 9443B120140C18A90013457C /* SBData.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9456F2241616671900656F91 /* DynamicLibrary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9456F2211616644B00656F91 /* DynamicLibrary.cpp */; }; 94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94611EB113CCA4A4003A22AF /* RefCounter.cpp */; }; 9461569A14E358A6003A195C /* SBTypeFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9461568A14E35621003A195C /* SBTypeFilter.cpp */; }; 9461569B14E358A6003A195C /* SBTypeFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9461568B14E35621003A195C /* SBTypeFormat.cpp */; }; @@ -527,6 +528,8 @@ 9475C18914E5EA08001BFC6D /* SBTypeCategory.h in Headers */ = {isa = PBXBuildFile; fileRef = 9475C18514E5E9C5001BFC6D /* SBTypeCategory.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9475C18E14E5F834001BFC6D /* SBTypeNameSpecifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9475C18D14E5F834001BFC6D /* SBTypeNameSpecifier.cpp */; }; 9475C18F14E5F858001BFC6D /* SBTypeNameSpecifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 9475C18C14E5F826001BFC6D /* SBTypeNameSpecifier.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 947A1D641616476B0017C8D1 /* CommandObjectPlugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 947A1D621616476A0017C8D1 /* CommandObjectPlugin.cpp */; }; + 947A1D651616476B0017C8D1 /* CommandObjectPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 947A1D631616476A0017C8D1 /* CommandObjectPlugin.h */; }; 949ADF031406F648004833E1 /* ValueObjectConstResultImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949ADF021406F648004833E1 /* ValueObjectConstResultImpl.cpp */; }; 94B6E76213D88365005F417F /* ValueObjectSyntheticFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */; }; 94CDEB9D15F0258500DD2A7A /* CXXFormatterFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CDEB9C15F0258400DD2A7A /* CXXFormatterFunctions.cpp */; }; @@ -1504,6 +1507,8 @@ 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = FormatManager.cpp; path = source/Core/FormatManager.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 9443B120140C18A90013457C /* SBData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBData.h; path = include/lldb/API/SBData.h; sourceTree = "<group>"; }; 9443B121140C18C10013457C /* SBData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBData.cpp; path = source/API/SBData.cpp; sourceTree = "<group>"; }; + 9456F2211616644B00656F91 /* DynamicLibrary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLibrary.cpp; sourceTree = "<group>"; }; + 9456F2231616645A00656F91 /* DynamicLibrary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DynamicLibrary.h; path = include/lldb/Host/DynamicLibrary.h; sourceTree = "<group>"; }; 94611EAF13CCA363003A22AF /* RefCounter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RefCounter.h; path = include/lldb/Utility/RefCounter.h; sourceTree = "<group>"; }; 94611EB113CCA4A4003A22AF /* RefCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RefCounter.cpp; path = source/Utility/RefCounter.cpp; sourceTree = "<group>"; }; 9461568614E355F2003A195C /* SBTypeFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeFilter.h; path = include/lldb/API/SBTypeFilter.h; sourceTree = "<group>"; }; @@ -1530,6 +1535,8 @@ 9475C18B14E5F818001BFC6D /* SBTypeNameSpecifier.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBTypeNameSpecifier.i; sourceTree = "<group>"; }; 9475C18C14E5F826001BFC6D /* SBTypeNameSpecifier.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeNameSpecifier.h; path = include/lldb/API/SBTypeNameSpecifier.h; sourceTree = "<group>"; }; 9475C18D14E5F834001BFC6D /* SBTypeNameSpecifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBTypeNameSpecifier.cpp; path = source/API/SBTypeNameSpecifier.cpp; sourceTree = "<group>"; }; + 947A1D621616476A0017C8D1 /* CommandObjectPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectPlugin.cpp; path = source/Commands/CommandObjectPlugin.cpp; sourceTree = "<group>"; }; + 947A1D631616476A0017C8D1 /* CommandObjectPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectPlugin.h; path = source/Commands/CommandObjectPlugin.h; sourceTree = "<group>"; }; 949ADF001406F62E004833E1 /* ValueObjectConstResultImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectConstResultImpl.h; path = include/lldb/Core/ValueObjectConstResultImpl.h; sourceTree = "<group>"; }; 949ADF021406F648004833E1 /* ValueObjectConstResultImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectConstResultImpl.cpp; path = source/Core/ValueObjectConstResultImpl.cpp; sourceTree = "<group>"; }; 94A8287514031D05006C37A8 /* FormatNavigator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatNavigator.h; path = include/lldb/Core/FormatNavigator.h; sourceTree = "<group>"; }; @@ -2741,6 +2748,8 @@ 26BC7E3610F1B84700F91463 /* CommandObjectMemory.cpp */, 26879CE51333F5750012C1F8 /* CommandObjectPlatform.h */, 26879CE71333F58B0012C1F8 /* CommandObjectPlatform.cpp */, + 947A1D631616476A0017C8D1 /* CommandObjectPlugin.h */, + 947A1D621616476A0017C8D1 /* CommandObjectPlugin.cpp */, 26BC7D1F10F1B76300F91463 /* CommandObjectProcess.h */, 26BC7E3810F1B84700F91463 /* CommandObjectProcess.cpp */, 26BC7D2010F1B76300F91463 /* CommandObjectQuit.h */, @@ -2822,6 +2831,7 @@ 26BC7EE510F1B88100F91463 /* MacOSX */, 26BC7DD210F1B7D500F91463 /* Condition.h */, 266F5CBB12FC846200DFCE33 /* Config.h */, + 9456F2231616645A00656F91 /* DynamicLibrary.h */, 26BC7DD310F1B7D500F91463 /* Endian.h */, 260C6EA013011578005E16B0 /* File.h */, 26FA4315130103F400E71120 /* FileSpec.h */, @@ -3274,6 +3284,7 @@ 69A01E1A1236C5D400C660B5 /* common */ = { isa = PBXGroup; children = ( + 9456F2211616644B00656F91 /* DynamicLibrary.cpp */, 260C6EA213011581005E16B0 /* File.cpp */, 26FA43171301048600E71120 /* FileSpec.cpp */, 69A01E1B1236C5D400C660B5 /* Condition.cpp */, @@ -3399,6 +3410,7 @@ 2697A39515E404BA003E682C /* OptionValueArch.h in Headers */, 2698699D15E6CBD0002415FF /* OperatingSystemPython.h in Headers */, 260D9B2715EC369500960137 /* ModuleSpec.h in Headers */, + 947A1D651616476B0017C8D1 /* CommandObjectPlugin.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3758,6 +3770,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9456F2241616671900656F91 /* DynamicLibrary.cpp in Sources */, 49C8507C1384A786007DB519 /* ProcessDataAllocator.cpp in Sources */, 2689FFDA13353D9D00698AC0 /* lldb.cpp in Sources */, 2689FFDB13353DA300698AC0 /* lldb-log.cpp in Sources */, @@ -4119,6 +4132,7 @@ 94EA1D5C15E6C9B400D4171A /* PythonDataObjects.cpp in Sources */, 2698699B15E6CBD0002415FF /* OperatingSystemPython.cpp in Sources */, 94CDEB9D15F0258500DD2A7A /* CXXFormatterFunctions.cpp in Sources */, + 947A1D641616476B0017C8D1 /* CommandObjectPlugin.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/lldb/scripts/Python/build-swig-Python.sh b/lldb/scripts/Python/build-swig-Python.sh index 20547647282..386dde6d342 100755 --- a/lldb/scripts/Python/build-swig-Python.sh +++ b/lldb/scripts/Python/build-swig-Python.sh @@ -104,7 +104,7 @@ HEADER_FILES="${SRC_ROOT}/include/lldb/lldb.h"\ " ${SRC_ROOT}/include/lldb/API/SBTypeSynthetic.h"\ " ${SRC_ROOT}/include/lldb/API/SBValue.h"\ " ${SRC_ROOT}/include/lldb/API/SBValueList.h"\ -" ${SRC_ROOT}/include/lldb/API/SBWatchpoint.h"\ +" ${SRC_ROOT}/include/lldb/API/SBWatchpoint.h" INTERFACE_FILES="${SRC_ROOT}/scripts/Python/interface/SBAddress.i"\ " ${SRC_ROOT}/scripts/Python/interface/SBBlock.i"\ diff --git a/lldb/scripts/Python/interface/SBCommandInterpreter.i b/lldb/scripts/Python/interface/SBCommandInterpreter.i index 62aaf8c48aa..4cf3d22f5d0 100644 --- a/lldb/scripts/Python/interface/SBCommandInterpreter.i +++ b/lldb/scripts/Python/interface/SBCommandInterpreter.i @@ -101,6 +101,9 @@ public: lldb::SBProcess GetProcess (); + + lldb::SBDebugger + GetDebugger (); void SourceInitFileInHomeDirectory (lldb::SBCommandReturnObject &result); diff --git a/lldb/scripts/Python/interface/SBCommandReturnObject.i b/lldb/scripts/Python/interface/SBCommandReturnObject.i index aed02eac64b..82c07ee434d 100644 --- a/lldb/scripts/Python/interface/SBCommandReturnObject.i +++ b/lldb/scripts/Python/interface/SBCommandReturnObject.i @@ -65,6 +65,9 @@ public: void AppendMessage (const char *message); + void + AppendWarning (const char *message); + bool GetDescription (lldb::SBStream &description); 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; } |