tberghammer created this revision. tberghammer added reviewers: labath, clayborg. tberghammer added a subscriber: lldb-commits. Herald added subscribers: srhines, danalbert, tberghammer, emaste.
Create new "platform process connect" command The standard remote debugging workflow with gdb is to start the application on the remote host under gdbserver (e.g.: gdbserver :5039 a.out) and then connect to it with gdb. The same workflow is supported by debugserver/lldb-gdbserver with a very similar syntax but to access all features of lldb we need to be connected also to an lldb-platform instance running on the target. Before this change this had to be done manually with starting a separate lldb-platform on the target machine and then connecting to it with lldb before connecting to the process. This change add a new command to lldb called "lldb platform connect" what makes it possible to connect to a platform and a process instance with a single command with specifying only a single connection port. With this command replacing gdbserver in a gdb based worflow is usually as simple as replacing the command to execute gdbserver with executing lldb-platform. Example for the new workflow: * On the target: lldb-server platform --listen localhost:5432 -- a.out arg1 arg2 * On the host: (lldb) platform select remote-android (lldb) platform process connect connect://localhost:5432 http://reviews.llvm.org/D14952 Files: include/lldb/Target/Platform.h source/Commands/CommandObjectPlatform.cpp source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h source/Plugins/Platform/POSIX/PlatformPOSIX.cpp source/Plugins/Platform/POSIX/PlatformPOSIX.h source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h tools/lldb-server/lldb-platform.cpp
Index: tools/lldb-server/lldb-platform.cpp =================================================================== --- tools/lldb-server/lldb-platform.cpp +++ tools/lldb-server/lldb-platform.cpp @@ -285,6 +285,12 @@ exit(option_error); } + // Skip any options we consumed with getopt_long_only. + argc -= optind; + argv += optind; + lldb_private::Args inferior_arguments; + inferior_arguments.SetArguments(argc, const_cast<const char**>(argv)); + const bool children_inherit_listen_socket = false; // the test suite makes many connections in parallel, let's not miss any. // The highest this should get reasonably is a function of the number @@ -317,7 +323,9 @@ do { GDBRemoteCommunicationServerPlatform platform(acceptor_up->GetSocketProtocol(), acceptor_up->GetSocketScheme()); - + if (inferior_arguments.GetArgumentCount() > 0) + platform.SetInferiorArguments(inferior_arguments); + if (port_offset > 0) platform.SetPortOffset(port_offset); Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h @@ -66,6 +66,9 @@ void SetPortOffset (uint16_t port_offset); + void + SetInferiorArguments (const lldb_private::Args& args); + protected: const Socket::SocketProtocol m_socket_protocol; const std::string m_socket_scheme; @@ -75,6 +78,7 @@ PortMap m_port_map; uint16_t m_port_offset; + lldb_private::Args m_inferior_arguments; PacketResult Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet); Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -165,7 +165,8 @@ Error error = StartDebugserverProcess (url.str().c_str(), nullptr, debugserver_launch_info, - port_ptr); + port_ptr, + m_inferior_arguments); lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID(); @@ -553,7 +554,13 @@ } void -GDBRemoteCommunicationServerPlatform::SetPortOffset (uint16_t port_offset) +GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) { m_port_offset = port_offset; } + +void +GDBRemoteCommunicationServerPlatform::SetInferiorArguments(const Args& args) +{ + m_inferior_arguments = args; +} Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -25,6 +25,7 @@ #include "lldb/Host/Mutex.h" #include "lldb/Host/Predicate.h" #include "lldb/Host/TimeValue.h" +#include "lldb/Interpreter/Args.h" #include "Utility/StringExtractorGDBRemote.h" @@ -168,7 +169,8 @@ StartDebugserverProcess(const char *url, Platform *platform, // If non nullptr, then check with the platform for the GDB server binary if it can't be located ProcessLaunchInfo &launch_info, - uint16_t *port); + uint16_t *port, + const Args& inferior_args = Args()); void DumpHistory(Stream &strm); Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -1115,7 +1115,8 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *url, Platform *platform, ProcessLaunchInfo &launch_info, - uint16_t *port) + uint16_t *port, + const Args& inferior_args) { Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); if (log) @@ -1328,6 +1329,20 @@ } } while (has_env_var); + if (inferior_args.GetArgumentCount() > 0) + { + debugserver_args.AppendArgument ("--"); + debugserver_args.AppendArguments (inferior_args); + } + + // Copy the current environment to the gdbserver/debugserver instance + StringList env; + if (Host::GetEnvironment(env)) + { + for (size_t i = 0; i < env.GetSize(); ++i) + launch_info.GetEnvironmentEntries().AppendArgument(env[i].c_str()); + } + // Close STDIN, STDOUT and STDERR. launch_info.AppendCloseFileAction (STDIN_FILENO); launch_info.AppendCloseFileAction (STDOUT_FILENO); Index: source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h =================================================================== --- source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -217,20 +217,21 @@ const lldb::UnixSignalsSP & GetRemoteUnixSignals() override; + // Launch the debug server on the remote host - caller connects to launched + // debug server using connect_url. + // Subclasses should override this method if they want to do extra actions before or + // after launching the debug server. + Error + LaunchRemoteGdbServer (lldb::pid_t &pid, std::string &connect_url) override; + protected: process_gdb_remote::GDBRemoteCommunicationClient m_gdb_client; std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to std::string m_platform_scheme; std::string m_platform_hostname; lldb::UnixSignalsSP m_remote_signals_sp; - // Launch the debug server on the remote host - caller connects to launched - // debug server using connect_url. - // Subclasses should override this method if they want to do extra actions before or - // after launching the debug server. - virtual bool - LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url); virtual bool KillSpawnedProcess (lldb::pid_t pid); Index: source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp =================================================================== --- source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -574,7 +574,7 @@ { lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; std::string connect_url; - if (!LaunchGDBServer(debugserver_pid, connect_url)) + if (LaunchRemoteGdbServer(debugserver_pid, connect_url).Fail()) { error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ()); } @@ -629,8 +629,8 @@ } -bool -PlatformRemoteGDBServer::LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url) +Error +PlatformRemoteGDBServer::LaunchRemoteGdbServer (lldb::pid_t &pid, std::string &connect_url) { ArchSpec remote_arch = GetRemoteSystemArchitecture (); llvm::Triple &remote_triple = remote_arch.GetTriple (); @@ -652,13 +652,13 @@ } if (!launch_result) - return false; + return Error("Failed to launch gdbserver on the remote host"); connect_url = MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port, (socket_name.empty()) ? nullptr : socket_name.c_str()); - return true; + return Error(); } bool @@ -680,7 +680,7 @@ { lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; std::string connect_url; - if (!LaunchGDBServer(debugserver_pid, connect_url)) + if (LaunchRemoteGdbServer(debugserver_pid, connect_url).Fail()) { error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ()); } Index: source/Plugins/Platform/POSIX/PlatformPOSIX.h =================================================================== --- source/Plugins/Platform/POSIX/PlatformPOSIX.h +++ source/Plugins/Platform/POSIX/PlatformPOSIX.h @@ -173,11 +173,14 @@ lldb_private::Error DisconnectRemote () override; + lldb_private::Error + LaunchRemoteGdbServer(lldb::pid_t &pid, std::string &connect_url) override; + protected: std::unique_ptr<lldb_private::OptionGroupOptions> m_options; - + lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote POSIX-compliant OS - + private: DISALLOW_COPY_AND_ASSIGN (PlatformPOSIX); }; Index: source/Plugins/Platform/POSIX/PlatformPOSIX.cpp =================================================================== --- source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -846,6 +846,16 @@ void PlatformPOSIX::CalculateTrapHandlerSymbolNames () -{ +{ m_trap_handlers.push_back (ConstString ("_sigtramp")); -} +} + +Error +PlatformPOSIX::LaunchRemoteGdbServer (lldb::pid_t &pid, std::string &connect_url) +{ + if (IsHost()) + return Error("Not supported during local debugging"); + if (!m_remote_platform_sp) + return Error("The platform currently isn't connected"); + return m_remote_platform_sp->LaunchRemoteGdbServer(pid, connect_url); +} Index: source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h =================================================================== --- source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h +++ source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h @@ -44,8 +44,8 @@ std::map<lldb::pid_t, uint16_t> m_port_forwards; llvm::Optional<AdbClient::UnixSocketNamespace> m_socket_namespace; - bool - LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url) override; + Error + LaunchRemoteGdbServer (lldb::pid_t &pid, std::string &connect_url) override; bool KillSpawnedProcess (lldb::pid_t pid) override; Index: source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp =================================================================== --- source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp +++ source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp @@ -88,13 +88,13 @@ DeleteForwardPortWithAdb(it.second, m_device_id); } -bool -PlatformAndroidRemoteGDBServer::LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url) +Error +PlatformAndroidRemoteGDBServer::LaunchRemoteGdbServer (lldb::pid_t &pid, std::string &connect_url) { uint16_t remote_port = 0; std::string socket_name; if (!m_gdb_client.LaunchGDBServer ("127.0.0.1", pid, remote_port, socket_name)) - return false; + return Error("Failed to launch gdbserver on the remote host"); Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); @@ -105,7 +105,7 @@ if (error.Success() && log) log->Printf("gdbserver connect URL: %s", connect_url.c_str()); - return error.Success(); + return error; } bool Index: source/Commands/CommandObjectPlatform.cpp =================================================================== --- source/Commands/CommandObjectPlatform.cpp +++ source/Commands/CommandObjectPlatform.cpp @@ -1248,6 +1248,77 @@ }; //---------------------------------------------------------------------- +// "platform process connect <connect-url>" +//---------------------------------------------------------------------- +class CommandObjectPlatformProcessConnect : public CommandObjectParsed +{ +public: + CommandObjectPlatformProcessConnect (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "platform process connect", + "Connect to a remote platform with a pre-specified inferior launch config.", + "platform process connect <connect-url>", + 0) + { + } + + ~CommandObjectPlatformProcessConnect () override = default; + +protected: + bool + DoExecute (Args& args, CommandReturnObject &result) override + { + Stream &ostrm = result.GetOutputStream(); + + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (!platform_sp) + { + result.AppendError ("no platform is currently selected\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + + Error error (platform_sp->ConnectRemote (args)); + if (error.Fail()) + { + result.AppendErrorWithFormat ("%s\n", error.AsCString()); + result.SetStatus (eReturnStatusFailed); + return false; + } + + platform_sp->GetStatus (ostrm); + + lldb::pid_t pid = 0; + std::string connect_url; + error = platform_sp->LaunchRemoteGdbServer(pid, connect_url); + if (error.Fail()) + { + result.AppendErrorWithFormat ("%s\n", error.AsCString()); + result.SetStatus (eReturnStatusFailed); + return false; + } + + StreamString command; + command.Printf("process connect %s", connect_url.c_str()); + return m_interpreter.HandleCommand(command.GetData(), LazyBool::eLazyBoolNo, result); + } + + Options * + GetOptions () override + { + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + OptionGroupOptions* m_platform_options = NULL; + if (platform_sp) + { + m_platform_options = platform_sp->GetConnectionOptions(m_interpreter); + if (m_platform_options != NULL && !m_platform_options->m_did_finalize) + m_platform_options->Finalize(); + } + return m_platform_options; + } +}; + +//---------------------------------------------------------------------- // "platform process launch" //---------------------------------------------------------------------- class CommandObjectPlatformProcessLaunch : public CommandObjectParsed @@ -1969,17 +2040,15 @@ "A set of commands to query, launch and attach to platform processes", "platform process [attach|launch|list] ...") { - LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter))); - LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter))); - LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter))); - LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter))); - - } - - ~CommandObjectPlatformProcess () override - { + LoadSubCommand ("attach" , CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter))); + LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformProcessConnect (interpreter))); + LoadSubCommand ("launch" , CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter))); + LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter))); + LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter))); } - + + ~CommandObjectPlatformProcess () override = default; + private: //------------------------------------------------------------------ // For CommandObjectPlatform only Index: include/lldb/Target/Platform.h =================================================================== --- include/lldb/Target/Platform.h +++ include/lldb/Target/Platform.h @@ -987,6 +987,12 @@ virtual uint32_t GetDefaultMemoryCacheLineSize() { return 0; } + virtual Error + LaunchRemoteGdbServer(lldb::pid_t &pid, std::string &connect_url) + { + return Error ("Not implemented"); + } + protected: bool m_is_host; // Set to true when we are able to actually set the OS version while
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits