https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/201638
>From 68a6ea7ab9f0dd75ba85c0651b5b7168673c9157 Mon Sep 17 00:00:00 2001 From: Charles Zablit <[email protected]> Date: Thu, 4 Jun 2026 18:09:30 +0100 Subject: [PATCH 1/2] [lldb][Windows] add stdin support to lldb-server --- .../lldb/Host/common/NativeProcessProtocol.h | 6 ++++- .../Host/windows/ConnectionConPTYWindows.cpp | 27 ++++++++++++++++++- .../Windows/Common/NativeProcessWindows.cpp | 15 +++++++++++ .../Windows/Common/NativeProcessWindows.h | 7 +++++ .../Process/Windows/Common/ProcessWindows.cpp | 1 + .../GDBRemoteCommunicationServerLLGS.cpp | 9 ++++++- .../Process/gdb-remote/ProcessGDBRemote.cpp | 16 ++++++++++- 7 files changed, 77 insertions(+), 4 deletions(-) diff --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h index 4e4804623b1d8..435185a38f3f9 100644 --- a/lldb/include/lldb/Host/common/NativeProcessProtocol.h +++ b/lldb/include/lldb/Host/common/NativeProcessProtocol.h @@ -247,8 +247,12 @@ class NativeProcessProtocol { // Access to inferior stdio virtual int GetTerminalFileDescriptor() { return m_terminal_fd; } - // Stop id interface + /// Write up to \p len bytes from \p buf to the inferior's stdin. + virtual size_t WriteStdin(const void *buf, size_t len, Status &error) { + return 0; + } + // Stop id interface uint32_t GetStopID() const; // Callbacks for low-level process state changes diff --git a/lldb/source/Host/windows/ConnectionConPTYWindows.cpp b/lldb/source/Host/windows/ConnectionConPTYWindows.cpp index e9d026fc7dc9f..f7e90421653e3 100644 --- a/lldb/source/Host/windows/ConnectionConPTYWindows.cpp +++ b/lldb/source/Host/windows/ConnectionConPTYWindows.cpp @@ -61,5 +61,30 @@ size_t ConnectionConPTY::Read(void *dst, size_t dst_len, size_t ConnectionConPTY::Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, Status *error_ptr) { - llvm_unreachable("not implemented"); + if (!m_pty || !m_pty->IsConnected()) { + status = eConnectionStatusNoConnection; + if (error_ptr) + *error_ptr = Status::FromErrorString("ConPTY not connected"); + return 0; + } + HANDLE stdin_handle = m_pty->GetSTDINHandle(); + if (stdin_handle == INVALID_HANDLE_VALUE || stdin_handle == nullptr) { + status = eConnectionStatusNoConnection; + if (error_ptr) + *error_ptr = Status::FromErrorString("ConPTY STDIN handle is invalid"); + return 0; + } + DWORD written = 0; + if (!::WriteFile(stdin_handle, src, static_cast<DWORD>(src_len), &written, + nullptr)) { + DWORD err = ::GetLastError(); + status = (err == ERROR_BROKEN_PIPE || err == ERROR_NO_DATA) + ? eConnectionStatusEndOfFile + : eConnectionStatusError; + if (error_ptr) + *error_ptr = Status(err, lldb::eErrorTypeWin32); + return written; + } + status = eConnectionStatusSuccess; + return written; } diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp index b235ab281bad6..bf447c9ea81f5 100644 --- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp @@ -749,4 +749,19 @@ void NativeProcessWindows::STDIOReadThreadBytesReceived(void *baton, self->m_delegate.NewProcessOutput( self, llvm::StringRef(static_cast<const char *>(src), src_len)); } + +size_t NativeProcessWindows::WriteStdin(const void *buf, size_t len, + Status &error) { + if (!m_stdio_communication.HasConnection()) { + error = Status::FromErrorString( + "no ConPTY connection on this NativeProcessWindows"); + return 0; + } + ConnectionStatus status; + size_t written = m_stdio_communication.Write(buf, len, status, &error); + if (status != eConnectionStatusSuccess && error.Success()) + error = Status::FromErrorStringWithFormatv( + "ConPTY stdin write returned status {0}", static_cast<int>(status)); + return written; +} } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h index 95b85754ebdeb..cac3920d82aa9 100644 --- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h +++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h @@ -107,6 +107,13 @@ class NativeProcessWindows : public NativeProcessProtocol, bool HasPendingLibraryEvents() override; + /// Forward bytes from the gdb-remote `I` packet into the inferior's + /// ConPTY-backed stdin via `m_stdio_communication.Write` → + /// `ConnectionConPTY::Write` → `WriteFile` on the parent-side STDIN + /// HANDLE. Returns the number of bytes written (0 if the PTY is + /// disconnected or write fails). + size_t WriteStdin(const void *buf, size_t len, Status &error) override; + // ProcessDebugger Overrides void OnExitProcess(uint32_t exit_code) override; void OnDebuggerConnected(lldb::addr_t image_base) override; diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp index 30a1610ee5a17..143f779d0b15b 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp @@ -46,6 +46,7 @@ #include "ExceptionRecord.h" #include "ForwardDecl.h" #include "LocalDebugDelegate.h" +#include "Plugins/Process/Utility/IOHandlerProcessSTDIOWindows.h" #include "ProcessWindowsLog.h" #include "TargetThreadWindows.h" diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index d56026e011564..077144f94227d 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -2569,12 +2569,19 @@ GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) { // 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; Status error; + +#if defined(_WIN32) + // On Windows the inferior's stdio is owned by NativeProcessWindows. + if (m_current_process->WriteStdin(tmp, read, error) != read || error.Fail()) + return SendErrorResponse(0x15); +#else + ConnectionStatus status; m_stdio_communication.WriteAll(tmp, read, status, &error); if (error.Fail()) { return SendErrorResponse(0x15); } +#endif } return SendOKResponse(); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 77506275d3e13..68f3eb0752973 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -101,6 +101,10 @@ #include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" +#ifdef _WIN32 +#include "Plugins/Process/Windows/Common/IOHandlerProcessSTDIOWindows.h" +#endif + #if defined(__APPLE__) #define DEBUGSERVER_BASENAME "debugserver" #elif defined(_WIN32) @@ -879,8 +883,18 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, SetPrivateState(SetThreadStopInfo(response)); if (!disable_stdio) { - if (pty.GetPrimaryFileDescriptor() != PseudoTerminal::invalid_fd) + if (pty.GetPrimaryFileDescriptor() != PseudoTerminal::invalid_fd) { SetSTDIOFileDescriptor(pty.ReleasePrimaryFileDescriptor()); + } +#ifdef _WIN32 + else if (m_stdin_forward) { + // No client-side PTY FD on Windows. + std::lock_guard<std::mutex> guard(m_process_input_reader_mutex); + if (!m_process_input_reader) + m_process_input_reader = + std::make_shared<IOHandlerProcessSTDIOWindows>(this); + } +#endif } } } else { >From 0194f0dc723e7289bf744c1e3300e2699bedc931 Mon Sep 17 00:00:00 2001 From: Charles Zablit <[email protected]> Date: Fri, 5 Jun 2026 17:38:51 +0100 Subject: [PATCH 2/2] fixup! [lldb][Windows] add stdin support to lldb-server --- .../source/Plugins/Process/Windows/Common/ProcessWindows.cpp | 1 - lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 5 +---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp index 143f779d0b15b..30a1610ee5a17 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp @@ -46,7 +46,6 @@ #include "ExceptionRecord.h" #include "ForwardDecl.h" #include "LocalDebugDelegate.h" -#include "Plugins/Process/Utility/IOHandlerProcessSTDIOWindows.h" #include "ProcessWindowsLog.h" #include "TargetThreadWindows.h" diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 68f3eb0752973..16284f0052f5e 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -59,6 +59,7 @@ #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Target/ProcessIOHandler.h" #include "lldb/Target/RegisterFlags.h" #include "lldb/Target/SystemRuntime.h" #include "lldb/Target/Target.h" @@ -101,10 +102,6 @@ #include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" -#ifdef _WIN32 -#include "Plugins/Process/Windows/Common/IOHandlerProcessSTDIOWindows.h" -#endif - #if defined(__APPLE__) #define DEBUGSERVER_BASENAME "debugserver" #elif defined(_WIN32) _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
