Index: include/lldb/API/SBLaunchInfo.h =================================================================== --- /dev/null +++ include/lldb/API/SBLaunchInfo.h @@ -0,0 +1,186 @@ +//===-- SBLaunchInfo.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SBLaunchInfo_h_ +#define LLDB_SBLaunchInfo_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBPlatform; +class SBTarget; + +class SBLaunchInfo +{ +public: + SBLaunchInfo (const char **argv); + + ~SBLaunchInfo(); + + lldb::pid_t + GetProcessID(); + + uint32_t + GetUserID(); + + uint32_t + GetGroupID(); + + bool + UserIDIsValid (); + + bool + GroupIDIsValid (); + + void + SetUserID (uint32_t uid); + + void + SetGroupID (uint32_t gid); + + SBFileSpec + GetExecutableFile (); + + //---------------------------------------------------------------------- + /// Set the executable file that will be used to launch the process and + /// optionally set it as the first argument in the argument vector. + /// + /// This only needs to be specified if clients wish to carefully control + /// the exact path will be used to launch a binary. If you create a + /// target with a symlink, that symlink will get resolved in the target + /// and the resolved path will get used to launch the process. Calling + /// this function can help you still launch your process using the + /// path of your choice. + /// + /// If this function is not called prior to launching with + /// SBTarget::Launch(...), the target will use the resolved executable + /// path that was used to create the target. + /// + /// @param[in] exe_file + /// The override path to use when launching the executable. + /// + /// @param[in] add_as_first_arg + /// If true, then the path will be inserted into the argument vector + /// prior to launching. Otherwise the argument vector will be left + /// alone. + //---------------------------------------------------------------------- + void + SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg); + + + //---------------------------------------------------------------------- + /// Get the listener that will be used to receive process events. + /// + /// If no listener has been set via a call to + /// SBLaunchInfo::SetListener(), then an invalid SBListener will be + /// returned (SBListener::IsValid() will return false). If a listener + /// has been set, then the valid listener object will be returned. + //---------------------------------------------------------------------- + SBListener + GetListener (); + + //---------------------------------------------------------------------- + /// Set the listener that will be used to receive process events. + /// + /// By default the SBDebugger, which has a listener, that the SBTarget + /// belongs to will listen for the process events. Calling this function + /// allows a different listener to be used to listen for process events. + //---------------------------------------------------------------------- + void + SetListener (SBListener &listener); + + uint32_t + GetNumArguments (); + + const char * + GetArgumentAtIndex (uint32_t idx); + + void + SetArguments (const char **argv, bool append); + + uint32_t + GetNumEnvironmentEntries (); + + const char * + GetEnvironmentEntryAtIndex (uint32_t idx); + + void + SetEnvironmentEntries (const char **envp, bool append); + + void + Clear (); + + const char * + GetWorkingDirectory () const; + + void + SetWorkingDirectory (const char *working_dir); + + uint32_t + GetLaunchFlags (); + + void + SetLaunchFlags (uint32_t flags); + + const char * + GetProcessPluginName (); + + void + SetProcessPluginName (const char *plugin_name); + + const char * + GetShell (); + + void + SetShell (const char * path); + + uint32_t + GetResumeCount (); + + void + SetResumeCount (uint32_t c); + + bool + AddCloseFileAction (int fd); + + bool + AddDuplicateFileAction (int fd, int dup_fd); + + bool + AddOpenFileAction (int fd, const char *path, bool read, bool write); + + bool + AddSuppressFileAction (int fd, bool read, bool write); + + void + SetLaunchEventData (const char *data); + + const char * + GetLaunchEventData () const; + + bool + GetDetachOnError() const; + + void + SetDetachOnError(bool enable); + +protected: + friend class SBPlatform; + friend class SBTarget; + + lldb_private::ProcessLaunchInfo & + ref (); + + ProcessLaunchInfoSP m_opaque_sp; +}; + +} // namespace lldb + +#endif // LLDB_SBLaunchInfo_h_ Index: include/lldb/API/SBPlatform.h =================================================================== --- include/lldb/API/SBPlatform.h +++ include/lldb/API/SBPlatform.h @@ -17,6 +17,8 @@ namespace lldb { + class SBLaunchInfo; + class SBPlatformConnectOptions { public: @@ -171,6 +173,12 @@ Run (SBPlatformShellCommand &shell_command); SBError + Launch (SBLaunchInfo &launch_info); + + SBError + Kill (const lldb::pid_t pid); + + SBError MakeDirectory (const char *path, uint32_t file_permissions = eFilePermissionsDirectoryDefault); uint32_t @@ -190,6 +198,9 @@ void SetSP (const lldb::PlatformSP& platform_sp); + SBError + ExecuteConnected (const std::function& func); + lldb::PlatformSP m_opaque_sp; }; Index: include/lldb/API/SBTarget.h =================================================================== --- include/lldb/API/SBTarget.h +++ include/lldb/API/SBTarget.h @@ -15,6 +15,7 @@ #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBFileSpecList.h" +#include "lldb/API/SBLaunchInfo.h" #include "lldb/API/SBSymbolContextList.h" #include "lldb/API/SBType.h" #include "lldb/API/SBValue.h" @@ -24,166 +25,6 @@ class SBPlatform; -class SBLaunchInfo -{ -public: - SBLaunchInfo (const char **argv); - - ~SBLaunchInfo(); - - uint32_t - GetUserID(); - - uint32_t - GetGroupID(); - - bool - UserIDIsValid (); - - bool - GroupIDIsValid (); - - void - SetUserID (uint32_t uid); - - void - SetGroupID (uint32_t gid); - - SBFileSpec - GetExecutableFile (); - - //---------------------------------------------------------------------- - /// Set the executable file that will be used to launch the process and - /// optionally set it as the first argument in the argument vector. - /// - /// This only needs to be specified if clients wish to carefully control - /// the exact path will be used to launch a binary. If you create a - /// target with a symlink, that symlink will get resolved in the target - /// and the resolved path will get used to launch the process. Calling - /// this function can help you still launch your process using the - /// path of your choice. - /// - /// If this function is not called prior to launching with - /// SBTarget::Launch(...), the target will use the resolved executable - /// path that was used to create the target. - /// - /// @param[in] exe_file - /// The override path to use when launching the executable. - /// - /// @param[in] add_as_first_arg - /// If true, then the path will be inserted into the argument vector - /// prior to launching. Otherwise the argument vector will be left - /// alone. - //---------------------------------------------------------------------- - void - SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg); - - - //---------------------------------------------------------------------- - /// Get the listener that will be used to receive process events. - /// - /// If no listener has been set via a call to - /// SBLaunchInfo::SetListener(), then an invalid SBListener will be - /// returned (SBListener::IsValid() will return false). If a listener - /// has been set, then the valid listener object will be returned. - //---------------------------------------------------------------------- - SBListener - GetListener (); - - //---------------------------------------------------------------------- - /// Set the listener that will be used to receive process events. - /// - /// By default the SBDebugger, which has a listener, that the SBTarget - /// belongs to will listen for the process events. Calling this function - /// allows a different listener to be used to listen for process events. - //---------------------------------------------------------------------- - void - SetListener (SBListener &listener); - - uint32_t - GetNumArguments (); - - const char * - GetArgumentAtIndex (uint32_t idx); - - void - SetArguments (const char **argv, bool append); - - uint32_t - GetNumEnvironmentEntries (); - - const char * - GetEnvironmentEntryAtIndex (uint32_t idx); - - void - SetEnvironmentEntries (const char **envp, bool append); - - void - Clear (); - - const char * - GetWorkingDirectory () const; - - void - SetWorkingDirectory (const char *working_dir); - - uint32_t - GetLaunchFlags (); - - void - SetLaunchFlags (uint32_t flags); - - const char * - GetProcessPluginName (); - - void - SetProcessPluginName (const char *plugin_name); - - const char * - GetShell (); - - void - SetShell (const char * path); - - uint32_t - GetResumeCount (); - - void - SetResumeCount (uint32_t c); - - bool - AddCloseFileAction (int fd); - - bool - AddDuplicateFileAction (int fd, int dup_fd); - - bool - AddOpenFileAction (int fd, const char *path, bool read, bool write); - - bool - AddSuppressFileAction (int fd, bool read, bool write); - - void - SetLaunchEventData (const char *data); - - const char * - GetLaunchEventData () const; - - bool - GetDetachOnError() const; - - void - SetDetachOnError(bool enable); - -protected: - friend class SBTarget; - - lldb_private::ProcessLaunchInfo & - ref (); - - ProcessLaunchInfoSP m_opaque_sp; -}; - class SBAttachInfo { public: Index: include/lldb/Target/Platform.h =================================================================== --- include/lldb/Target/Platform.h +++ include/lldb/Target/Platform.h @@ -380,6 +380,12 @@ LaunchProcess (ProcessLaunchInfo &launch_info); //------------------------------------------------------------------ + /// Kill process on a platform. + //------------------------------------------------------------------ + virtual Error + KillProcess (const lldb::pid_t pid); + + //------------------------------------------------------------------ /// Lets a platform answer if it is compatible with a given /// architecture and the target triple contained within. //------------------------------------------------------------------ Index: lldb.xcodeproj/project.pbxproj =================================================================== --- lldb.xcodeproj/project.pbxproj +++ lldb.xcodeproj/project.pbxproj @@ -92,6 +92,8 @@ 23F4034D1926E0F60046DC9B /* NativeRegisterContextRegisterInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23F403481926CC250046DC9B /* NativeRegisterContextRegisterInfo.cpp */; }; 25420ECD1A6490B8009ADBCB /* OptionValueChar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25420ECC1A6490B8009ADBCB /* OptionValueChar.cpp */; }; 25420ED21A649D88009ADBCB /* PipeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25420ED11A649D88009ADBCB /* PipeBase.cpp */; }; + 254FBB951A81AA7F00BD6378 /* SBLaunchInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 254FBB941A81AA7F00BD6378 /* SBLaunchInfo.cpp */; }; + 254FBB971A81B03100BD6378 /* SBLaunchInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 254FBB961A81B03100BD6378 /* SBLaunchInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; 260157C61885F51C00F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; 260157C71885F52500F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; 260157C81885F53100F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; @@ -1165,6 +1167,9 @@ 25420ECC1A6490B8009ADBCB /* OptionValueChar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueChar.cpp; path = source/Interpreter/OptionValueChar.cpp; sourceTree = ""; }; 25420ECE1A64911B009ADBCB /* OptionValueChar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionValueChar.h; path = include/lldb/Interpreter/OptionValueChar.h; sourceTree = ""; }; 25420ED11A649D88009ADBCB /* PipeBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PipeBase.cpp; sourceTree = ""; }; + 254FBB921A81AA5200BD6378 /* SBLaunchInfo.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBLaunchInfo.i; sourceTree = ""; }; + 254FBB941A81AA7F00BD6378 /* SBLaunchInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBLaunchInfo.cpp; path = source/API/SBLaunchInfo.cpp; sourceTree = ""; }; + 254FBB961A81B03100BD6378 /* SBLaunchInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBLaunchInfo.h; path = include/lldb/API/SBLaunchInfo.h; sourceTree = ""; }; 260157C41885F4FF00F875CF /* libpanel.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpanel.dylib; path = /usr/lib/libpanel.dylib; sourceTree = ""; }; 260223E7115F06D500A601A2 /* SBCommunication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBCommunication.h; path = include/lldb/API/SBCommunication.h; sourceTree = ""; }; 260223E8115F06E500A601A2 /* SBCommunication.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBCommunication.cpp; path = source/API/SBCommunication.cpp; sourceTree = ""; }; @@ -3021,6 +3026,7 @@ 2611FEEE142D83060017FEA3 /* interface */ = { isa = PBXGroup; children = ( + 254FBB921A81AA5200BD6378 /* SBLaunchInfo.i */, 2611FEEF142D83060017FEA3 /* SBAddress.i */, 2611FEF0142D83060017FEA3 /* SBBlock.i */, 2611FEF1142D83060017FEA3 /* SBBreakpoint.i */, @@ -3090,6 +3096,8 @@ 262D3190111B4341004E6F88 /* API */ = { isa = PBXGroup; children = ( + 254FBB961A81B03100BD6378 /* SBLaunchInfo.h */, + 254FBB941A81AA7F00BD6378 /* SBLaunchInfo.cpp */, 2611FEEE142D83060017FEA3 /* interface */, 26BC7C2510F1B3BC00F91463 /* lldb-defines.h */, 26BC7C2610F1B3BC00F91463 /* lldb-enumerations.h */, @@ -5029,6 +5037,7 @@ 9AC7038E117674FB0086C050 /* SBInstruction.h in Headers */, 9AC70390117675270086C050 /* SBInstructionList.h in Headers */, 26DE205911618FE700A093E2 /* SBLineEntry.h in Headers */, + 254FBB971A81B03100BD6378 /* SBLaunchInfo.h in Headers */, AF0EBBED185941360059E52F /* SBQueueItem.h in Headers */, 26680227115FD13D008E1FE4 /* SBListener.h in Headers */, 26DE204F11618E9800A093E2 /* SBModule.h in Headers */, @@ -5632,6 +5641,7 @@ 9452573A16262D0200325455 /* SBDeclaration.cpp in Sources */, 4CE4F675162C973F00F75CB3 /* SBExpressionOptions.cpp in Sources */, AF9107EE168570D200DBCD3C /* RegisterContextDarwin_arm64.cpp in Sources */, + 254FBB951A81AA7F00BD6378 /* SBLaunchInfo.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; Index: scripts/Python/build-swig-Python.sh =================================================================== --- scripts/Python/build-swig-Python.sh +++ scripts/Python/build-swig-Python.sh @@ -99,6 +99,7 @@ " ${SRC_ROOT}/include/lldb/API/SBHostOS.h"\ " ${SRC_ROOT}/include/lldb/API/SBInstruction.h"\ " ${SRC_ROOT}/include/lldb/API/SBInstructionList.h"\ +" ${SRC_ROOT}/include/lldb/API/SBLaunchInfo.h"\ " ${SRC_ROOT}/include/lldb/API/SBLineEntry.h"\ " ${SRC_ROOT}/include/lldb/API/SBListener.h"\ " ${SRC_ROOT}/include/lldb/API/SBModule.h"\ @@ -150,6 +151,7 @@ " ${SRC_ROOT}/scripts/Python/interface/SBHostOS.i"\ " ${SRC_ROOT}/scripts/Python/interface/SBInstruction.i"\ " ${SRC_ROOT}/scripts/Python/interface/SBInstructionList.i"\ +" ${SRC_ROOT}/scripts/Python/interface/SBLaunchInfo.i"\ " ${SRC_ROOT}/scripts/Python/interface/SBLineEntry.i"\ " ${SRC_ROOT}/scripts/Python/interface/SBListener.i"\ " ${SRC_ROOT}/scripts/Python/interface/SBModule.i"\ Index: scripts/Python/buildSwigPython.py =================================================================== --- scripts/Python/buildSwigPython.py +++ scripts/Python/buildSwigPython.py @@ -101,6 +101,7 @@ "/include/lldb/API/SBInputReader.h", "/include/lldb/API/SBInstruction.h", "/include/lldb/API/SBInstructionList.h", + "/include/lldb/API/SBLaunchInfo.h", "/include/lldb/API/SBLineEntry.h", "/include/lldb/API/SBListener.h", "/include/lldb/API/SBModule.h", @@ -177,6 +178,7 @@ "/scripts/Python/interface/SBInputReader.i", "/scripts/Python/interface/SBInstruction.i", "/scripts/Python/interface/SBInstructionList.i", + "/scripts/Python/interface/SBLaunchInfo.i", "/scripts/Python/interface/SBLineEntry.i", "/scripts/Python/interface/SBListener.i", "/scripts/Python/interface/SBModule.i", Index: scripts/Python/interface/SBLaunchInfo.i =================================================================== --- /dev/null +++ scripts/Python/interface/SBLaunchInfo.i @@ -0,0 +1,126 @@ +//===-- SWIG Interface for SBLaunchInfo--------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +namespace lldb { + +class SBLaunchInfo +{ +public: + SBLaunchInfo (const char **argv); + + pid_t + GetProcessID(); + + uint32_t + GetUserID(); + + uint32_t + GetGroupID(); + + bool + UserIDIsValid (); + + bool + GroupIDIsValid (); + + void + SetUserID (uint32_t uid); + + void + SetGroupID (uint32_t gid); + + lldb::SBFileSpec + GetExecutableFile (); + + void + SetExecutableFile (lldb::SBFileSpec exe_file, bool add_as_first_arg); + + lldb::SBListener + GetListener (); + + void + SetListener (lldb::SBListener &listener); + + uint32_t + GetNumArguments (); + + const char * + GetArgumentAtIndex (uint32_t idx); + + void + SetArguments (const char **argv, bool append); + + uint32_t + GetNumEnvironmentEntries (); + + const char * + GetEnvironmentEntryAtIndex (uint32_t idx); + + void + SetEnvironmentEntries (const char **envp, bool append); + + void + Clear (); + + const char * + GetWorkingDirectory () const; + + void + SetWorkingDirectory (const char *working_dir); + + uint32_t + GetLaunchFlags (); + + void + SetLaunchFlags (uint32_t flags); + + const char * + GetProcessPluginName (); + + void + SetProcessPluginName (const char *plugin_name); + + const char * + GetShell (); + + void + SetShell (const char * path); + + uint32_t + GetResumeCount (); + + void + SetResumeCount (uint32_t c); + + bool + AddCloseFileAction (int fd); + + bool + AddDuplicateFileAction (int fd, int dup_fd); + + bool + AddOpenFileAction (int fd, const char *path, bool read, bool write); + + bool + AddSuppressFileAction (int fd, bool read, bool write); + + void + SetLaunchEventData (const char *data); + + const char * + GetLaunchEventData () const; + + bool + GetDetachOnError() const; + + void + SetDetachOnError(bool enable); +}; + +} // namespace lldb Index: scripts/Python/interface/SBPlatform.i =================================================================== --- scripts/Python/interface/SBPlatform.i +++ scripts/Python/interface/SBPlatform.i @@ -174,6 +174,12 @@ Run (lldb::SBPlatformShellCommand &shell_command); lldb::SBError + Launch (lldb::SBLaunchInfo &launch_info); + + lldb::SBError + Kill (const lldb::pid_t pid); + + lldb::SBError MakeDirectory (const char *path, uint32_t file_permissions = lldb::eFilePermissionsDirectoryDefault); uint32_t Index: scripts/Python/interface/SBTarget.i =================================================================== --- scripts/Python/interface/SBTarget.i +++ scripts/Python/interface/SBTarget.i @@ -9,117 +9,6 @@ namespace lldb { -class SBLaunchInfo -{ -public: - SBLaunchInfo (const char **argv); - - uint32_t - GetUserID(); - - uint32_t - GetGroupID(); - - bool - UserIDIsValid (); - - bool - GroupIDIsValid (); - - void - SetUserID (uint32_t uid); - - void - SetGroupID (uint32_t gid); - - lldb::SBFileSpec - GetExecutableFile (); - - void - SetExecutableFile (lldb::SBFileSpec exe_file, bool add_as_first_arg); - - lldb::SBListener - GetListener (); - - void - SetListener (lldb::SBListener &listener); - - uint32_t - GetNumArguments (); - - const char * - GetArgumentAtIndex (uint32_t idx); - - void - SetArguments (const char **argv, bool append); - - uint32_t - GetNumEnvironmentEntries (); - - const char * - GetEnvironmentEntryAtIndex (uint32_t idx); - - void - SetEnvironmentEntries (const char **envp, bool append); - - void - Clear (); - - const char * - GetWorkingDirectory () const; - - void - SetWorkingDirectory (const char *working_dir); - - uint32_t - GetLaunchFlags (); - - void - SetLaunchFlags (uint32_t flags); - - const char * - GetProcessPluginName (); - - void - SetProcessPluginName (const char *plugin_name); - - const char * - GetShell (); - - void - SetShell (const char * path); - - uint32_t - GetResumeCount (); - - void - SetResumeCount (uint32_t c); - - bool - AddCloseFileAction (int fd); - - bool - AddDuplicateFileAction (int fd, int dup_fd); - - bool - AddOpenFileAction (int fd, const char *path, bool read, bool write); - - bool - AddSuppressFileAction (int fd, bool read, bool write); - - void - SetLaunchEventData (const char *data); - - const char * - GetLaunchEventData () const; - - bool - GetDetachOnError() const; - - void - SetDetachOnError(bool enable); -}; - class SBAttachInfo { public: Index: scripts/lldb.swig =================================================================== --- scripts/lldb.swig +++ scripts/lldb.swig @@ -75,6 +75,7 @@ #include "lldb/API/SBHostOS.h" #include "lldb/API/SBInstruction.h" #include "lldb/API/SBInstructionList.h" +#include "lldb/API/SBLaunchInfo.h" #include "lldb/API/SBLineEntry.h" #include "lldb/API/SBListener.h" #include "lldb/API/SBModule.h" @@ -149,6 +150,7 @@ %include "./Python/interface/SBHostOS.i" %include "./Python/interface/SBInstruction.i" %include "./Python/interface/SBInstructionList.i" +%include "./Python/interface/SBLaunchInfo.i" %include "./Python/interface/SBLineEntry.i" %include "./Python/interface/SBListener.i" %include "./Python/interface/SBModule.i" Index: source/API/CMakeLists.txt =================================================================== --- source/API/CMakeLists.txt +++ source/API/CMakeLists.txt @@ -27,6 +27,7 @@ SBHostOS.cpp SBInstruction.cpp SBInstructionList.cpp + SBLaunchInfo.cpp SBLineEntry.cpp SBListener.cpp SBModule.cpp Index: source/API/SBLaunchInfo.cpp =================================================================== --- /dev/null +++ source/API/SBLaunchInfo.cpp @@ -0,0 +1,278 @@ +//===-- SBLaunchInfo.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/lldb-python.h" + +#include "lldb/API/SBLaunchInfo.h" + +#include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBListener.h" +#include "lldb/Target/ProcessLaunchInfo.h" + +using namespace lldb; +using namespace lldb_private; + +SBLaunchInfo::SBLaunchInfo (const char **argv) : + m_opaque_sp(new ProcessLaunchInfo()) +{ + m_opaque_sp->GetFlags().Reset (eLaunchFlagDebug | eLaunchFlagDisableASLR); + if (argv && argv[0]) + m_opaque_sp->GetArguments().SetArguments(argv); +} + +SBLaunchInfo::~SBLaunchInfo() +{ +} + +lldb_private::ProcessLaunchInfo & +SBLaunchInfo::ref () +{ + return *m_opaque_sp; +} + +lldb::pid_t +SBLaunchInfo::GetProcessID() +{ + return m_opaque_sp->GetProcessID(); +} + +uint32_t +SBLaunchInfo::GetUserID() +{ + return m_opaque_sp->GetUserID(); +} + +uint32_t +SBLaunchInfo::GetGroupID() +{ + return m_opaque_sp->GetGroupID(); +} + +bool +SBLaunchInfo::UserIDIsValid () +{ + return m_opaque_sp->UserIDIsValid(); +} + +bool +SBLaunchInfo::GroupIDIsValid () +{ + return m_opaque_sp->GroupIDIsValid(); +} + +void +SBLaunchInfo::SetUserID (uint32_t uid) +{ + m_opaque_sp->SetUserID (uid); +} + +void +SBLaunchInfo::SetGroupID (uint32_t gid) +{ + m_opaque_sp->SetGroupID (gid); +} + +SBFileSpec +SBLaunchInfo::GetExecutableFile () +{ + return SBFileSpec (m_opaque_sp->GetExecutableFile()); +} + +void +SBLaunchInfo::SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg) +{ + m_opaque_sp->SetExecutableFile(exe_file.ref(), add_as_first_arg); +} + +SBListener +SBLaunchInfo::GetListener () +{ + return SBListener(m_opaque_sp->GetListener()); +} + +void +SBLaunchInfo::SetListener (SBListener &listener) +{ + m_opaque_sp->SetListener(listener.GetSP()); +} + +uint32_t +SBLaunchInfo::GetNumArguments () +{ + return m_opaque_sp->GetArguments().GetArgumentCount(); +} + +const char * +SBLaunchInfo::GetArgumentAtIndex (uint32_t idx) +{ + return m_opaque_sp->GetArguments().GetArgumentAtIndex(idx); +} + +void +SBLaunchInfo::SetArguments (const char **argv, bool append) +{ + if (append) + { + if (argv) + m_opaque_sp->GetArguments().AppendArguments(argv); + } + else + { + if (argv) + m_opaque_sp->GetArguments().SetArguments(argv); + else + m_opaque_sp->GetArguments().Clear(); + } +} + +uint32_t +SBLaunchInfo::GetNumEnvironmentEntries () +{ + return m_opaque_sp->GetEnvironmentEntries().GetArgumentCount(); +} + +const char * +SBLaunchInfo::GetEnvironmentEntryAtIndex (uint32_t idx) +{ + return m_opaque_sp->GetEnvironmentEntries().GetArgumentAtIndex(idx); +} + +void +SBLaunchInfo::SetEnvironmentEntries (const char **envp, bool append) +{ + if (append) + { + if (envp) + m_opaque_sp->GetEnvironmentEntries().AppendArguments(envp); + } + else + { + if (envp) + m_opaque_sp->GetEnvironmentEntries().SetArguments(envp); + else + m_opaque_sp->GetEnvironmentEntries().Clear(); + } +} + +void +SBLaunchInfo::Clear () +{ + m_opaque_sp->Clear(); +} + +const char * +SBLaunchInfo::GetWorkingDirectory () const +{ + return m_opaque_sp->GetWorkingDirectory(); +} + +void +SBLaunchInfo::SetWorkingDirectory (const char *working_dir) +{ + m_opaque_sp->SetWorkingDirectory(working_dir); +} + +uint32_t +SBLaunchInfo::GetLaunchFlags () +{ + return m_opaque_sp->GetFlags().Get(); +} + +void +SBLaunchInfo::SetLaunchFlags (uint32_t flags) +{ + m_opaque_sp->GetFlags().Reset(flags); +} + +const char * +SBLaunchInfo::GetProcessPluginName () +{ + return m_opaque_sp->GetProcessPluginName(); +} + +void +SBLaunchInfo::SetProcessPluginName (const char *plugin_name) +{ + return m_opaque_sp->SetProcessPluginName (plugin_name); +} + +const char * +SBLaunchInfo::GetShell () +{ + // Constify this string so that it is saved in the string pool. Otherwise + // it would be freed when this function goes out of scope. + ConstString shell(m_opaque_sp->GetShell().GetPath().c_str()); + return shell.AsCString(); +} + +void +SBLaunchInfo::SetShell (const char * path) +{ + m_opaque_sp->SetShell (FileSpec(path, false)); +} + +uint32_t +SBLaunchInfo::GetResumeCount () +{ + return m_opaque_sp->GetResumeCount(); +} + +void +SBLaunchInfo::SetResumeCount (uint32_t c) +{ + m_opaque_sp->SetResumeCount (c); +} + +bool +SBLaunchInfo::AddCloseFileAction (int fd) +{ + return m_opaque_sp->AppendCloseFileAction(fd); +} + +bool +SBLaunchInfo::AddDuplicateFileAction (int fd, int dup_fd) +{ + return m_opaque_sp->AppendDuplicateFileAction(fd, dup_fd); +} + +bool +SBLaunchInfo::AddOpenFileAction (int fd, const char *path, bool read, bool write) +{ + return m_opaque_sp->AppendOpenFileAction(fd, path, read, write); +} + +bool +SBLaunchInfo::AddSuppressFileAction (int fd, bool read, bool write) +{ + return m_opaque_sp->AppendSuppressFileAction(fd, read, write); +} + +void +SBLaunchInfo::SetLaunchEventData (const char *data) +{ + m_opaque_sp->SetLaunchEventData (data); +} + +const char * +SBLaunchInfo::GetLaunchEventData () const +{ + return m_opaque_sp->GetLaunchEventData (); +} + +void +SBLaunchInfo::SetDetachOnError (bool enable) +{ + m_opaque_sp->SetDetachOnError (enable); +} + +bool +SBLaunchInfo::GetDetachOnError () const +{ + return m_opaque_sp->GetDetachOnError (); +} Index: source/API/SBPlatform.cpp =================================================================== --- source/API/SBPlatform.cpp +++ source/API/SBPlatform.cpp @@ -10,6 +10,7 @@ #include "lldb/API/SBPlatform.h" #include "lldb/API/SBError.h" #include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBLaunchInfo.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Error.h" #include "lldb/Host/File.h" @@ -17,6 +18,8 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Platform.h" +#include + using namespace lldb; using namespace lldb_private; @@ -484,104 +487,108 @@ SBPlatform::Put (SBFileSpec &src, SBFileSpec &dst) { - SBError sb_error; - - PlatformSP platform_sp(GetSP()); - if (platform_sp) - { - if (src.Exists()) + return ExecuteConnected( + [&](const lldb::PlatformSP& platform_sp) + { + if (src.Exists()) + { + uint32_t permissions = src.ref().GetPermissions(); + if (permissions == 0) + { + if (src.ref().GetFileType() == FileSpec::eFileTypeDirectory) + permissions = eFilePermissionsDirectoryDefault; + else + permissions = eFilePermissionsFileDefault; + } + + return platform_sp->PutFile(src.ref(), dst.ref(), permissions); + } + + Error error; + error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str()); + return error; + }); +} + +SBError +SBPlatform::Install (SBFileSpec &src, + SBFileSpec &dst) +{ + return ExecuteConnected( + [&](const lldb::PlatformSP& platform_sp) + { + if (src.Exists()) + return platform_sp->Install(src.ref(), dst.ref()); + + Error error; + error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str()); + return error; + }); +} + + +SBError +SBPlatform::Run (SBPlatformShellCommand &shell_command) +{ + return ExecuteConnected( + [&](const lldb::PlatformSP& platform_sp) { - uint32_t permissions = src.ref().GetPermissions(); - if (permissions == 0) + const char *command = shell_command.GetCommand(); + if (!command) + return Error("invalid shell command (empty)"); + + const char *working_dir = shell_command.GetWorkingDirectory(); + if (working_dir == NULL) { - if (src.ref().GetFileType() == FileSpec::eFileTypeDirectory) - permissions = eFilePermissionsDirectoryDefault; - else - permissions = eFilePermissionsFileDefault; + working_dir = platform_sp->GetWorkingDirectory().GetCString(); + if (working_dir) + shell_command.SetWorkingDirectory(working_dir); } + return platform_sp->RunShellCommand(command, + working_dir, + &shell_command.m_opaque_ptr->m_status, + &shell_command.m_opaque_ptr->m_signo, + &shell_command.m_opaque_ptr->m_output, + shell_command.m_opaque_ptr->m_timeout_sec); + }); +} - sb_error.ref() = platform_sp->PutFile(src.ref(), - dst.ref(), - permissions); - } - else +SBError +SBPlatform::Launch (SBLaunchInfo &launch_info) +{ + return ExecuteConnected( + [&](const lldb::PlatformSP& platform_sp) { - sb_error.ref().SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str()); - } - } - else - { - sb_error.SetErrorString("invalid platform"); - } - return sb_error; + return platform_sp->LaunchProcess(launch_info.ref()); + }); } SBError -SBPlatform::Install (SBFileSpec &src, - SBFileSpec &dst) +SBPlatform::Kill (const lldb::pid_t pid) { - SBError sb_error; - PlatformSP platform_sp(GetSP()); - if (platform_sp) - { - if (src.Exists()) - { - sb_error.ref() = platform_sp->Install(src.ref(), dst.ref()); - } - else + return ExecuteConnected( + [&](const lldb::PlatformSP& platform_sp) { - sb_error.ref().SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str()); - } - } - else - { - sb_error.SetErrorString("invalid platform"); - } - return sb_error; + return platform_sp->KillProcess(pid); + }); } - SBError -SBPlatform::Run (SBPlatformShellCommand &shell_command) +SBPlatform::ExecuteConnected (const std::function& func) { SBError sb_error; - PlatformSP platform_sp(GetSP()); + const auto platform_sp(GetSP()); if (platform_sp) { if (platform_sp->IsConnected()) - { - const char *command = shell_command.GetCommand(); - if (command) - { - const char *working_dir = shell_command.GetWorkingDirectory(); - if (working_dir == NULL) - { - working_dir = platform_sp->GetWorkingDirectory().GetCString(); - if (working_dir) - shell_command.SetWorkingDirectory(working_dir); - } - sb_error.ref() = platform_sp->RunShellCommand(command, - working_dir, - &shell_command.m_opaque_ptr->m_status, - &shell_command.m_opaque_ptr->m_signo, - &shell_command.m_opaque_ptr->m_output, - shell_command.m_opaque_ptr->m_timeout_sec); - } - else - { - sb_error.SetErrorString("invalid shell command (empty)"); - } - } + sb_error.ref() = func(platform_sp); else - { sb_error.SetErrorString("not connected"); - } } else - { sb_error.SetErrorString("invalid platform"); - } - return sb_error; + + return sb_error; } SBError Index: source/API/SBTarget.cpp =================================================================== --- source/API/SBTarget.cpp +++ source/API/SBTarget.cpp @@ -66,259 +66,6 @@ #define DEFAULT_DISASM_BYTE_SIZE 32 -SBLaunchInfo::SBLaunchInfo (const char **argv) : - m_opaque_sp(new ProcessLaunchInfo()) -{ - m_opaque_sp->GetFlags().Reset (eLaunchFlagDebug | eLaunchFlagDisableASLR); - if (argv && argv[0]) - m_opaque_sp->GetArguments().SetArguments(argv); -} - -SBLaunchInfo::~SBLaunchInfo() -{ -} - -lldb_private::ProcessLaunchInfo & -SBLaunchInfo::ref () -{ - return *m_opaque_sp; -} - - -uint32_t -SBLaunchInfo::GetUserID() -{ - return m_opaque_sp->GetUserID(); -} - -uint32_t -SBLaunchInfo::GetGroupID() -{ - return m_opaque_sp->GetGroupID(); -} - -bool -SBLaunchInfo::UserIDIsValid () -{ - return m_opaque_sp->UserIDIsValid(); -} - -bool -SBLaunchInfo::GroupIDIsValid () -{ - return m_opaque_sp->GroupIDIsValid(); -} - -void -SBLaunchInfo::SetUserID (uint32_t uid) -{ - m_opaque_sp->SetUserID (uid); -} - -void -SBLaunchInfo::SetGroupID (uint32_t gid) -{ - m_opaque_sp->SetGroupID (gid); -} - -SBFileSpec -SBLaunchInfo::GetExecutableFile () -{ - return SBFileSpec (m_opaque_sp->GetExecutableFile()); -} - -void -SBLaunchInfo::SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg) -{ - m_opaque_sp->SetExecutableFile(exe_file.ref(), add_as_first_arg); -} - -SBListener -SBLaunchInfo::GetListener () -{ - return SBListener(m_opaque_sp->GetListener()); -} - -void -SBLaunchInfo::SetListener (SBListener &listener) -{ - m_opaque_sp->SetListener(listener.GetSP()); -} - -uint32_t -SBLaunchInfo::GetNumArguments () -{ - return m_opaque_sp->GetArguments().GetArgumentCount(); -} - -const char * -SBLaunchInfo::GetArgumentAtIndex (uint32_t idx) -{ - return m_opaque_sp->GetArguments().GetArgumentAtIndex(idx); -} - -void -SBLaunchInfo::SetArguments (const char **argv, bool append) -{ - if (append) - { - if (argv) - m_opaque_sp->GetArguments().AppendArguments(argv); - } - else - { - if (argv) - m_opaque_sp->GetArguments().SetArguments(argv); - else - m_opaque_sp->GetArguments().Clear(); - } -} - -uint32_t -SBLaunchInfo::GetNumEnvironmentEntries () -{ - return m_opaque_sp->GetEnvironmentEntries().GetArgumentCount(); -} - -const char * -SBLaunchInfo::GetEnvironmentEntryAtIndex (uint32_t idx) -{ - return m_opaque_sp->GetEnvironmentEntries().GetArgumentAtIndex(idx); -} - -void -SBLaunchInfo::SetEnvironmentEntries (const char **envp, bool append) -{ - if (append) - { - if (envp) - m_opaque_sp->GetEnvironmentEntries().AppendArguments(envp); - } - else - { - if (envp) - m_opaque_sp->GetEnvironmentEntries().SetArguments(envp); - else - m_opaque_sp->GetEnvironmentEntries().Clear(); - } -} - -void -SBLaunchInfo::Clear () -{ - m_opaque_sp->Clear(); -} - -const char * -SBLaunchInfo::GetWorkingDirectory () const -{ - return m_opaque_sp->GetWorkingDirectory(); -} - -void -SBLaunchInfo::SetWorkingDirectory (const char *working_dir) -{ - m_opaque_sp->SetWorkingDirectory(working_dir); -} - -uint32_t -SBLaunchInfo::GetLaunchFlags () -{ - return m_opaque_sp->GetFlags().Get(); -} - -void -SBLaunchInfo::SetLaunchFlags (uint32_t flags) -{ - m_opaque_sp->GetFlags().Reset(flags); -} - -const char * -SBLaunchInfo::GetProcessPluginName () -{ - return m_opaque_sp->GetProcessPluginName(); -} - -void -SBLaunchInfo::SetProcessPluginName (const char *plugin_name) -{ - return m_opaque_sp->SetProcessPluginName (plugin_name); -} - -const char * -SBLaunchInfo::GetShell () -{ - // Constify this string so that it is saved in the string pool. Otherwise - // it would be freed when this function goes out of scope. - ConstString shell(m_opaque_sp->GetShell().GetPath().c_str()); - return shell.AsCString(); -} - -void -SBLaunchInfo::SetShell (const char * path) -{ - m_opaque_sp->SetShell (FileSpec(path, false)); -} - -uint32_t -SBLaunchInfo::GetResumeCount () -{ - return m_opaque_sp->GetResumeCount(); -} - -void -SBLaunchInfo::SetResumeCount (uint32_t c) -{ - m_opaque_sp->SetResumeCount (c); -} - -bool -SBLaunchInfo::AddCloseFileAction (int fd) -{ - return m_opaque_sp->AppendCloseFileAction(fd); -} - -bool -SBLaunchInfo::AddDuplicateFileAction (int fd, int dup_fd) -{ - return m_opaque_sp->AppendDuplicateFileAction(fd, dup_fd); -} - -bool -SBLaunchInfo::AddOpenFileAction (int fd, const char *path, bool read, bool write) -{ - return m_opaque_sp->AppendOpenFileAction(fd, path, read, write); -} - -bool -SBLaunchInfo::AddSuppressFileAction (int fd, bool read, bool write) -{ - return m_opaque_sp->AppendSuppressFileAction(fd, read, write); -} - -void -SBLaunchInfo::SetLaunchEventData (const char *data) -{ - m_opaque_sp->SetLaunchEventData (data); -} - -const char * -SBLaunchInfo::GetLaunchEventData () const -{ - return m_opaque_sp->GetLaunchEventData (); -} - -void -SBLaunchInfo::SetDetachOnError (bool enable) -{ - m_opaque_sp->SetDetachOnError (enable); -} - -bool -SBLaunchInfo::GetDetachOnError () const -{ - return m_opaque_sp->GetDetachOnError (); -} SBAttachInfo::SBAttachInfo () : m_opaque_sp (new ProcessAttachInfo()) Index: source/CMakeLists.txt =================================================================== --- source/CMakeLists.txt +++ source/CMakeLists.txt @@ -81,6 +81,7 @@ API/SBHostOS.cpp API/SBInstruction.cpp API/SBInstructionList.cpp + API/SBLaunchInfo.cpp API/SBLineEntry.cpp API/SBListener.cpp API/SBModule.cpp Index: source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h =================================================================== --- source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -86,7 +86,10 @@ virtual lldb_private::Error LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info); - + + virtual lldb_private::Error + KillProcess (const lldb::pid_t pid); + virtual lldb::ProcessSP DebugProcess (lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger, Index: source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp =================================================================== --- source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -430,14 +430,30 @@ { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); Error error; - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; if (log) log->Printf ("PlatformRemoteGDBServer::%s() called", __FUNCTION__); - m_gdb_client.SetSTDIN ("/dev/null"); - m_gdb_client.SetSTDOUT ("/dev/null"); - m_gdb_client.SetSTDERR ("/dev/null"); + auto num_file_actions = launch_info.GetNumFileActions (); + for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) + { + const auto file_action = launch_info.GetFileActionAtIndex (i); + if (file_action->GetAction () != FileAction::eFileActionOpen) + continue; + switch(file_action->GetFD()) + { + case STDIN_FILENO: + m_gdb_client.SetSTDIN (file_action->GetPath()); + break; + case STDOUT_FILENO: + m_gdb_client.SetSTDOUT (file_action->GetPath()); + break; + case STDERR_FILENO: + m_gdb_client.SetSTDERR (file_action->GetPath()); + break; + } + } + m_gdb_client.SetDisableASLR (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)); m_gdb_client.SetDetachOnError (launch_info.GetFlags().Test (eLaunchFlagDetachOnError)); @@ -475,7 +491,7 @@ std::string error_str; if (m_gdb_client.GetLaunchSuccess (error_str)) { - pid = m_gdb_client.GetCurrentProcessID (); + const auto pid = m_gdb_client.GetCurrentProcessID (false); if (pid != LLDB_INVALID_PROCESS_ID) { launch_info.SetProcessID (pid); @@ -486,7 +502,7 @@ { if (log) log->Printf ("PlatformRemoteGDBServer::%s() launch succeeded but we didn't get a valid process id back!", __FUNCTION__); - // FIXME isn't this an error condition? Do we need to set an error here? Check with Greg. + error.SetErrorString ("failed to get PID"); } } else @@ -503,6 +519,14 @@ return error; } +Error +PlatformRemoteGDBServer::KillProcess (const lldb::pid_t pid) +{ + if (!m_gdb_client.KillSpawnedProcess(pid)) + return Error("failed to kill remote spawned process"); + return Error(); +} + lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger, Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -100,7 +100,7 @@ bool &timed_out); lldb::pid_t - GetCurrentProcessID (); + GetCurrentProcessID (bool allow_lazy = true); bool GetLaunchSuccess (std::string &error_str); @@ -525,7 +525,7 @@ StringExtractorGDBRemote &response); bool - GetCurrentProcessInfo (); + GetCurrentProcessInfo (bool allow_lazy_pid = true); bool GetGDBServerVersion(); Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1211,13 +1211,13 @@ } lldb::pid_t -GDBRemoteCommunicationClient::GetCurrentProcessID () +GDBRemoteCommunicationClient::GetCurrentProcessID (bool allow_lazy) { - if (m_curr_pid_is_valid == eLazyBoolYes) + if (allow_lazy && m_curr_pid_is_valid == eLazyBoolYes) return m_curr_pid; // First try to retrieve the pid via the qProcessInfo request. - GetCurrentProcessInfo (); + GetCurrentProcessInfo (allow_lazy); if (m_curr_pid_is_valid == eLazyBoolYes) { // We really got it. @@ -2409,14 +2409,17 @@ } bool -GDBRemoteCommunicationClient::GetCurrentProcessInfo () +GDBRemoteCommunicationClient::GetCurrentProcessInfo (bool allow_lazy) { Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - if (m_qProcessInfo_is_valid == eLazyBoolYes) - return true; - if (m_qProcessInfo_is_valid == eLazyBoolNo) - return false; + if (allow_lazy) + { + if (m_qProcessInfo_is_valid == eLazyBoolYes) + return true; + if (m_qProcessInfo_is_valid == eLazyBoolNo) + return false; + } GetHostInfo (); Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -607,14 +607,12 @@ // add to list of spawned processes. On an lldb-gdbserver, we // would expect there to be only one. - lldb::pid_t pid; - if ( (pid = m_process_launch_info.GetProcessID()) != LLDB_INVALID_PROCESS_ID ) + const auto pid = m_process_launch_info.GetProcessID(); + if (pid != LLDB_INVALID_PROCESS_ID) { // add to spawned pids - { - Mutex::Locker locker (m_spawned_pids_mutex); - m_spawned_pids.insert(pid); - } + Mutex::Locker locker (m_spawned_pids_mutex); + m_spawned_pids.insert(pid); } return error; @@ -1437,23 +1435,33 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::Handle_qProcessInfo (StringExtractorGDBRemote &packet) { - // Only the gdb server handles this. - if (!IsGdbServer ()) - return SendUnimplementedResponse (packet.GetStringRef ().c_str ()); - - // Fail if we don't have a current process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - return SendErrorResponse (68); - - ProcessInstanceInfo proc_info; - if (Host::GetProcessInfo (m_debugged_process_sp->GetID (), proc_info)) + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + + if (IsGdbServer ()) { - StreamString response; - CreateProcessInfoResponse_DebugServerStyle(proc_info, response); - return SendPacketNoLock (response.GetData (), response.GetSize ()); + // Fail if we don't have a current process. + if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse (68); + + pid = m_debugged_process_sp->GetID (); } - - return SendErrorResponse (1); + else if (m_is_platform) + { + pid = m_process_launch_info.GetProcessID (); + } + else + return SendUnimplementedResponse (packet.GetStringRef ().c_str ()); + + if (pid == LLDB_INVALID_PROCESS_ID) + return SendErrorResponse (1); + + ProcessInstanceInfo proc_info; + if (!Host::GetProcessInfo (pid, proc_info)) + return SendErrorResponse (1); + + StreamString response; + CreateProcessInfoResponse_DebugServerStyle(proc_info, response); + return SendPacketNoLock (response.GetData (), response.GetSize ()); } GDBRemoteCommunication::PacketResult Index: source/Target/Platform.cpp =================================================================== --- source/Target/Platform.cpp +++ source/Target/Platform.cpp @@ -1103,6 +1103,20 @@ return error; } +Error +Platform::KillProcess (const lldb::pid_t pid) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf ("Platform::%s, pid %" PRIu64, __FUNCTION__, pid); + + if (!IsHost ()) + return Error ("base lldb_private::Platform class can't launch remote processes"); + + Host::Kill (pid, SIGTERM); + return Error(); +} + lldb::ProcessSP Platform::DebugProcess (ProcessLaunchInfo &launch_info, Debugger &debugger, Index: test/lldbtest.py =================================================================== --- test/lldbtest.py +++ test/lldbtest.py @@ -31,6 +31,7 @@ $ """ +import abc import os, sys, traceback import os.path import re @@ -41,6 +42,7 @@ import types import unittest2 import lldb +from _pyio import __metaclass__ # See also dotest.parseOptionsAndInitTestdirs(), where the environment variables # LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' options. @@ -233,6 +235,78 @@ print >> self.session, self.getvalue() self.close() +class _BaseProcess(object): + __metaclass__ = abc.ABCMeta + + @abc.abstractproperty + def pid(self): + """Returns process PID if has been launched already.""" + + @abc.abstractmethod + def launch(self, executable, args): + """Launches new process with given executable and args.""" + + @abc.abstractmethod + def terminate(self): + """Terminates previously launched process..""" + +class _LocalProcess(_BaseProcess): + + def __init__(self, trace_on): + self._proc = None + self._trace_on = trace_on + + @property + def pid(self): + return self._proc.pid + + def launch(self, executable, args): + self._proc = Popen([executable] + args, + stdout = open(os.devnull) if not self._trace_on else None, + stdin = PIPE) + + def terminate(self): + if self._proc.poll() == None: + self._proc.terminate() + +class _RemoteProcess(_BaseProcess): + + def __init__(self): + self._pid = None + + @property + def pid(self): + return self._pid + + def launch(self, executable, args): + remote_work_dir = lldb.remote_platform.GetWorkingDirectory() + src_path = executable + dst_path = os.path.join(remote_work_dir, os.path.basename(executable)) + + dst_file_spec = lldb.SBFileSpec(dst_path, False) + err = lldb.remote_platform.Install(lldb.SBFileSpec(src_path, True), + dst_file_spec) + if err.Fail(): + raise Exception("remote_platform.Install('%s', '%s') failed: %s" % (src_path, dst_path, err)) + + launch_info = lldb.SBLaunchInfo(args) + launch_info.SetExecutableFile(dst_file_spec, True) + launch_info.SetWorkingDirectory(remote_work_dir) + + # Redirect stdout and stderr to /dev/null + launch_info.AddSuppressFileAction(1, False, True) + launch_info.AddSuppressFileAction(2, False, True) + + err = lldb.remote_platform.Launch(launch_info) + if err.Fail(): + raise Exception("remote_platform.Launch('%s', '%s') failed: %s" % (dst_path, args, err)) + self._pid = launch_info.GetProcessID() + + def terminate(self): + err = lldb.remote_platform.Kill(self._pid) + if err.Fail(): + raise Exception("remote_platform.Kill(%d) failed: %s" % (self._pid, err)) + # From 2.7's subprocess.check_output() convenience function. # Return a tuple (stdoutdata, stderrdata). def system(commands, **kwargs): @@ -961,8 +1035,7 @@ def cleanupSubprocesses(self): # Ensure any subprocesses are cleaned up for p in self.subprocesses: - if p.poll() == None: - p.terminate() + p.terminate() del p del self.subprocesses[:] # Ensure any forked processes are cleaned up @@ -979,11 +1052,8 @@ otherwise the test suite will leak processes. """ - - # Don't display the stdout if not in TraceOn() mode. - proc = Popen([executable] + args, - stdout = open(os.devnull) if not self.TraceOn() else None, - stdin = PIPE) + proc = _RemoteProcess() if lldb.remote_platform else _LocalProcess(self.TraceOn()) + proc.launch(executable, args) self.subprocesses.append(proc) return proc