Index: include/lldb/Target/Process.h =================================================================== --- include/lldb/Target/Process.h +++ include/lldb/Target/Process.h @@ -3180,6 +3180,7 @@ lldb::IOHandlerSP m_process_input_reader; Communication m_stdio_communication; Mutex m_stdio_communication_mutex; + bool m_stdio_disable; /// Remember process launch setting std::string m_stdout_data; std::string m_stderr_data; Mutex m_profile_data_comm_mutex; Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -175,6 +175,23 @@ //------------------------------------------------------------------ + /// Sends a GDB remote protocol 'I' packet that delivers stdin + /// data to the remote process. + /// + /// @param[in] data + /// A pointer to stdin data. + /// + /// @param[in] data_len + /// The number of bytes available at \a data. + /// + /// @return + /// Zero if the attach was successful, or an error indicating + /// an error code. + //------------------------------------------------------------------ + int + SendStdinNotification(const char* data, size_t data_len); + + //------------------------------------------------------------------ /// Sets the path to use for stdin/out/err for a process /// that will be launched with the 'A' packet. /// Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1866,6 +1866,21 @@ return -1; } +int +GDBRemoteCommunicationClient::SendStdinNotification (const char* data, size_t data_len) +{ + StreamString packet; + packet.PutCString("I"); + packet.PutBytesAsRawHex8(data, data_len); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) + { + return 0; + } + return response.GetError(); + +} + const lldb_private::ArchSpec & GDBRemoteCommunicationClient::GetHostArchitecture () { Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -415,6 +415,9 @@ Handle_H (StringExtractorGDBRemote &packet); PacketResult + Handle_I (StringExtractorGDBRemote &packet); + + PacketResult Handle_interrupt (StringExtractorGDBRemote &packet); PacketResult Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -370,6 +370,10 @@ packet_result = Handle_H (packet); break; + case StringExtractorGDBRemote::eServerPacketType_I: + packet_result = Handle_I (packet); + break; + case StringExtractorGDBRemote::eServerPacketType_m: packet_result = Handle_m (packet); break; @@ -3422,6 +3426,46 @@ } GDBRemoteCommunicationServer::PacketResult +GDBRemoteCommunicationServer::Handle_I (StringExtractorGDBRemote &packet) +{ + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + // Ensure we're llgs. + if (!IsGdbServer()) + return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_I() unimplemented"); + + // Fail if we don't have a current process. + if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) + { + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__); + return SendErrorResponse (0x15); + } + + packet.SetFilePos (::strlen("I")); + char tmp[4096]; + for (;;) + { + size_t read = packet.GetHexBytesAvail(tmp, sizeof(tmp)); + if (read == 0) + { + break; + } + // write directly to stdin *this might block if stdin buffer is full* + // TODO: enqueue this block in circular buffer and send window size to remote host + ConnectionStatus status; + Error error; + m_stdio_communication.Write(tmp, read, status, &error); + if (error.Fail()) + { + return SendErrorResponse (0x15); + } + } + + return SendOKResponse(); +} + +GDBRemoteCommunicationServer::PacketResult GDBRemoteCommunicationServer::Handle_interrupt (StringExtractorGDBRemote &packet) { Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -942,6 +942,7 @@ SetPrivateState (SetThreadStopInfo (m_last_stop_packet)); + m_stdio_disable = disable_stdio; if (!disable_stdio) { if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd) @@ -2477,6 +2478,10 @@ ConnectionStatus status; m_stdio_communication.Write(src, src_len, status, NULL); } + else if (!m_stdio_disable) + { + m_gdb_comm.SendStdinNotification(src, src_len); + } return 0; } Index: source/Target/Process.cpp =================================================================== --- source/Target/Process.cpp +++ source/Target/Process.cpp @@ -720,6 +720,7 @@ m_process_input_reader (), m_stdio_communication ("process.stdio"), m_stdio_communication_mutex (Mutex::eMutexTypeRecursive), + m_stdio_disable(true), m_stdout_data (), m_stderr_data (), m_profile_data_comm_mutex (Mutex::eMutexTypeRecursive), @@ -3906,6 +3907,7 @@ } m_stdio_communication.StopReadThread(); m_stdio_communication.Disconnect(); + m_stdio_disable = true; if (m_process_input_reader) { Index: source/Utility/StringExtractorGDBRemote.h =================================================================== --- source/Utility/StringExtractorGDBRemote.h +++ source/Utility/StringExtractorGDBRemote.h @@ -130,6 +130,7 @@ eServerPacketType_g, eServerPacketType_G, eServerPacketType_H, + eServerPacketType_I, // stdin notification eServerPacketType_k, eServerPacketType_m, eServerPacketType_M, Index: source/Utility/StringExtractorGDBRemote.cpp =================================================================== --- source/Utility/StringExtractorGDBRemote.cpp +++ source/Utility/StringExtractorGDBRemote.cpp @@ -265,6 +265,9 @@ case 'H': return eServerPacketType_H; + case 'I': + return eServerPacketType_I; + case 'k': if (packet_size == 1) return eServerPacketType_k; break;