[lldb] [llvm] [DRAFT][lldb][windows] add Windows Virtual Console support (PR #168729)
Charles Zablit via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 19 08:06:15 PST 2025
https://github.com/charles-zablit created https://github.com/llvm/llvm-project/pull/168729
None
>From 8792764ad14dba22c4817a6b463d504c429b0d11 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Wed, 19 Nov 2025 16:03:17 +0000
Subject: [PATCH] [lldb][windows] add Windows Virtual Console support
---
lldb/include/lldb/Host/ProcessLaunchInfo.h | 2 +-
lldb/include/lldb/Host/PseudoTerminal.h | 40 +++-
.../windows/ConnectionPseudoTerminalWindows.h | 61 ++++++
.../Host/windows/ProcessLauncherWindows.h | 29 +++
.../lldb/Host/windows/PseudoTerminalWindows.h | 37 ++++
lldb/include/lldb/Host/windows/windows.h | 5 +-
lldb/include/lldb/Target/Process.h | 30 +++
lldb/source/Host/CMakeLists.txt | 2 +
lldb/source/Host/common/ProcessLaunchInfo.cpp | 19 +-
lldb/source/Host/common/PseudoTerminal.cpp | 12 +-
.../ConnectionPseudoTerminalWindows.cpp | 191 ++++++++++++++++++
.../Host/windows/ProcessLauncherWindows.cpp | 164 ++++++++-------
.../Host/windows/PseudoTerminalWindows.cpp | 68 +++++++
lldb/source/Interpreter/ScriptInterpreter.cpp | 2 +-
.../MacOSX/PlatformAppleSimulator.cpp | 2 +-
...latformiOSSimulatorCoreSimulatorSupport.mm | 10 +-
.../Plugins/Platform/POSIX/PlatformPOSIX.cpp | 2 +-
.../Platform/QemuUser/PlatformQemuUser.cpp | 4 +-
.../Platform/Windows/PlatformWindows.cpp | 12 +-
.../Plugins/Process/AIX/NativeProcessAIX.cpp | 5 +-
.../Process/FreeBSD/NativeProcessFreeBSD.cpp | 4 +-
.../Process/Linux/NativeProcessLinux.cpp | 4 +-
.../Process/NetBSD/NativeProcessNetBSD.cpp | 4 +-
.../Windows/Common/NativeProcessWindows.cpp | 6 +-
.../Process/Windows/Common/ProcessWindows.cpp | 33 +--
.../Process/Windows/Common/ProcessWindows.h | 8 +-
lldb/source/Target/Platform.cpp | 2 +-
lldb/source/Target/Process.cpp | 17 +-
.../platform/basic/TestPlatformCommand.py | 1 +
.../tools/lldb-dap/launch/TestDAP_launch.py | 1 -
lldb/tools/lldb-dap/tool/lldb-dap.cpp | 3 +
.../GDBRemoteCommunicationClientTest.cpp | 34 ++--
.../gn/secondary/lldb/source/Host/BUILD.gn | 2 +
33 files changed, 652 insertions(+), 164 deletions(-)
create mode 100644 lldb/include/lldb/Host/windows/ConnectionPseudoTerminalWindows.h
create mode 100644 lldb/include/lldb/Host/windows/PseudoTerminalWindows.h
create mode 100644 lldb/source/Host/windows/ConnectionPseudoTerminalWindows.cpp
create mode 100644 lldb/source/Host/windows/PseudoTerminalWindows.cpp
diff --git a/lldb/include/lldb/Host/ProcessLaunchInfo.h b/lldb/include/lldb/Host/ProcessLaunchInfo.h
index 25762bc65295d..50a5af604ee26 100644
--- a/lldb/include/lldb/Host/ProcessLaunchInfo.h
+++ b/lldb/include/lldb/Host/ProcessLaunchInfo.h
@@ -118,7 +118,7 @@ class ProcessLaunchInfo : public ProcessInfo {
bool MonitorProcess() const;
- PseudoTerminal &GetPTY() { return *m_pty; }
+ std::shared_ptr<PseudoTerminal> GetPTY() const { return m_pty; }
void SetLaunchEventData(const char *data) { m_event_data.assign(data); }
diff --git a/lldb/include/lldb/Host/PseudoTerminal.h b/lldb/include/lldb/Host/PseudoTerminal.h
index bd1e2f56241b2..b61c213e138cb 100644
--- a/lldb/include/lldb/Host/PseudoTerminal.h
+++ b/lldb/include/lldb/Host/PseudoTerminal.h
@@ -35,11 +35,14 @@ class PseudoTerminal {
/// Destructor
///
- /// The destructor will close the primary and secondary file descriptors if
- /// they are valid and ownership has not been released using one of: @li
- /// PseudoTerminal::ReleasePrimaryFileDescriptor() @li
- /// PseudoTerminal::ReleaseSaveFileDescriptor()
- ~PseudoTerminal();
+ /// The destructor will close the primary and secondary file
+ /// descriptor/HANDLEs if they are valid and ownership has not been released
+ /// using PseudoTerminal::Close().
+ virtual ~PseudoTerminal();
+
+ /// Close all the file descriptors or Handles of the PseudoTerminal if they
+ /// are valid.
+ virtual void Close();
/// Close the primary file descriptor if it is valid.
void ClosePrimaryFileDescriptor();
@@ -59,8 +62,7 @@ class PseudoTerminal {
///
/// This class will close the file descriptors for the primary/secondary when
/// the destructor is called. The file handles can be released using either:
- /// @li PseudoTerminal::ReleasePrimaryFileDescriptor() @li
- /// PseudoTerminal::ReleaseSaveFileDescriptor()
+ /// @li PseudoTerminal::ReleasePrimaryFileDescriptor()
///
/// \return
/// \b Parent process: a child process ID that is greater
@@ -82,6 +84,16 @@ class PseudoTerminal {
/// \see PseudoTerminal::ReleasePrimaryFileDescriptor()
int GetPrimaryFileDescriptor() const;
+ /// The primary HANDLE accessor.
+ ///
+ /// This object retains ownership of the primary HANDLE when this
+ /// accessor is used.
+ ///
+ /// \return
+ /// The primary HANDLE, or INVALID_HANDLE_VALUE if the primary HANDLE is
+ /// not currently valid.
+ virtual void *GetPrimaryHandle() const { return ((void *)(long long)-1); };
+
/// The secondary file descriptor accessor.
///
/// This object retains ownership of the secondary file descriptor when this
@@ -105,7 +117,17 @@ class PseudoTerminal {
/// The name of the secondary pseudo terminal.
///
/// \see PseudoTerminal::OpenFirstAvailablePrimary()
- std::string GetSecondaryName() const;
+ virtual std::string GetSecondaryName() const;
+
+ /// The underlying Windows Pseudo Terminal HANDLE's accessor.
+ ///
+ /// This object retains ownership of the ConPTY's HANDLE when this
+ /// accessor is used.
+ ///
+ /// \return
+ /// The primary HANDLE, or INVALID_HANDLE_VALUE if the primary HANDLE is
+ /// not currently valid.
+ virtual void *GetPseudoTerminalHandle() { return ((void *)(long long)-1); };
/// Open the first available pseudo terminal.
///
@@ -126,7 +148,7 @@ class PseudoTerminal {
///
/// \see PseudoTerminal::GetPrimaryFileDescriptor() @see
/// PseudoTerminal::ReleasePrimaryFileDescriptor()
- llvm::Error OpenFirstAvailablePrimary(int oflag);
+ virtual llvm::Error OpenFirstAvailablePrimary(int oflag);
/// Open the secondary for the current primary pseudo terminal.
///
diff --git a/lldb/include/lldb/Host/windows/ConnectionPseudoTerminalWindows.h b/lldb/include/lldb/Host/windows/ConnectionPseudoTerminalWindows.h
new file mode 100644
index 0000000000000..6283312db7b8d
--- /dev/null
+++ b/lldb/include/lldb/Host/windows/ConnectionPseudoTerminalWindows.h
@@ -0,0 +1,61 @@
+//===-- ConnectionPseudoTerminalWindows.h ------------------------*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Host_windows_ConnectionPseudoConsoleWindows_h_
+#define liblldb_Host_windows_ConnectionPseudoConsoleWindows_h_
+
+#include "lldb/Host/windows/PseudoTerminalWindows.h"
+#include "lldb/Host/windows/windows.h"
+#include "lldb/Utility/Connection.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-types.h"
+
+namespace lldb_private {
+
+class ConnectionPseudoTerminal : public lldb_private::Connection {
+public:
+ ConnectionPseudoTerminal();
+
+ ConnectionPseudoTerminal(std::shared_ptr<PseudoTerminal> pty, bool owns_file);
+
+ ~ConnectionPseudoTerminal() override;
+
+ bool IsConnected() const override;
+
+ lldb::ConnectionStatus Connect(llvm::StringRef url,
+ Status *error_ptr) override;
+
+ lldb::ConnectionStatus Disconnect(Status *error_ptr) override;
+
+ size_t Read(void *dst, size_t dst_len, const Timeout<std::micro> &timeout,
+ lldb::ConnectionStatus &status, Status *error_ptr) override;
+
+ size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status,
+ Status *error_ptr) override;
+
+ std::string GetURI() override { return ""; };
+
+ bool InterruptRead() override;
+
+protected:
+ std::shared_ptr<PseudoTerminal> m_pty;
+ OVERLAPPED m_overlapped;
+ bool m_owns_file;
+ HANDLE m_event_handles[2];
+
+ enum { kBytesAvailableEvent, kInterruptEvent };
+
+private:
+ ConnectionPseudoTerminal(const ConnectionPseudoTerminal &) = delete;
+ const ConnectionPseudoTerminal &
+ operator=(const ConnectionPseudoTerminal &) = delete;
+};
+} // namespace lldb_private
+
+#endif
diff --git a/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h b/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
index 81aea5b2022a5..a04077a5e1d03 100644
--- a/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
+++ b/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
@@ -11,6 +11,9 @@
#include "lldb/Host/ProcessLauncher.h"
#include "lldb/Host/windows/windows.h"
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/Environment.h"
+#include "llvm/Support/ErrorOr.h"
namespace lldb_private {
@@ -23,6 +26,32 @@ class ProcessLauncherWindows : public ProcessLauncher {
protected:
HANDLE GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd);
+
+ /// Create a UTF-16 environment block to use with CreateProcessW.
+ ///
+ /// The buffer is a sequence of null-terminated UTF-16 strings, followed by an
+ /// extra L'\0' (two bytes of 0). An empty environment must have one
+ /// empty string, followed by an extra L'\0'.
+ ///
+ /// The keys are sorted to comply with the CreateProcess' calling convention.
+ ///
+ /// Ensure that the resulting buffer is used in conjunction with
+ /// CreateProcessW and be sure that dwCreationFlags includes
+ /// CREATE_UNICODE_ENVIRONMENT.
+ ///
+ /// \param env The Environment object to convert.
+ /// \returns The sorted sequence of environment variables and their values,
+ /// separated by null terminators.
+ static std::vector<wchar_t> CreateEnvironmentBufferW(const Environment &env);
+
+ /// Flattens an Args object into a Windows command-line wide string.
+ ///
+ /// Returns an empty string if args is empty.
+ ///
+ /// \param args The Args object to flatten.
+ /// \returns A wide string containing the flattened command line.
+ static llvm::ErrorOr<std::wstring>
+ GetFlattenedWindowsCommandStringW(Args args);
};
}
diff --git a/lldb/include/lldb/Host/windows/PseudoTerminalWindows.h b/lldb/include/lldb/Host/windows/PseudoTerminalWindows.h
new file mode 100644
index 0000000000000..8698ae2f8b804
--- /dev/null
+++ b/lldb/include/lldb/Host/windows/PseudoTerminalWindows.h
@@ -0,0 +1,37 @@
+//===-- PseudoTerminalWindows.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Host_Windows_PseudoTerminalWindows_H_
+#define liblldb_Host_Windows_PseudoTerminalWindows_H_
+
+#include "lldb/Host/PseudoTerminal.h"
+#include "lldb/Host/windows/windows.h"
+
+namespace lldb_private {
+
+class PseudoTerminalWindows : public PseudoTerminal {
+
+public:
+ void Close() override;
+
+ HPCON GetPseudoTerminalHandle() override { return m_conpty_handle; };
+
+ HANDLE GetPrimaryHandle() const override { return m_conpty_output; };
+
+ std::string GetSecondaryName() const override { return ""; };
+
+ llvm::Error OpenFirstAvailablePrimary(int oflag) override;
+
+protected:
+ HANDLE m_conpty_handle = INVALID_HANDLE_VALUE;
+ HANDLE m_conpty_output = INVALID_HANDLE_VALUE;
+ HANDLE m_conpty_input = INVALID_HANDLE_VALUE;
+};
+}; // namespace lldb_private
+
+#endif // liblldb_Host_Windows_PseudoTerminalWindows_H_
\ No newline at end of file
diff --git a/lldb/include/lldb/Host/windows/windows.h b/lldb/include/lldb/Host/windows/windows.h
index d53d4b9967268..2047e602291fc 100644
--- a/lldb/include/lldb/Host/windows/windows.h
+++ b/lldb/include/lldb/Host/windows/windows.h
@@ -9,9 +9,9 @@
#ifndef LLDB_lldb_windows_h_
#define LLDB_lldb_windows_h_
-#define NTDDI_VERSION NTDDI_VISTA
+// #define NTDDI_VERSION NTDDI_VISTA
#undef _WIN32_WINNT // undef a previous definition to avoid warning
-#define _WIN32_WINNT _WIN32_WINNT_VISTA
+// #define _WIN32_WINNT _WIN32_WINNT_VISTA
#define WIN32_LEAN_AND_MEAN
#define NOGDI
#undef NOMINMAX // undef a previous definition to avoid warning
@@ -26,6 +26,7 @@
#undef near
#undef FAR
#undef NEAR
+#undef WIN32_MEMORY_INFORMATION_CLASS
#define FAR
#define NEAR
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index c1f9785e76f90..17a8ce713302a 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -2534,8 +2534,38 @@ void PruneThreadPlans();
void CalculateExecutionContext(ExecutionContext &exe_ctx) override;
+ /// Associates a file descriptor with the process's STDIO handling
+ /// and configures an asynchronous reading of that descriptor.
+ ///
+ /// This method installs a ConnectionFileDescriptor for the passed file
+ /// descriptor and starts a dedicated read thread. If the read thread starts
+ /// successfully, the method also ensures that an IOHandlerProcessSTDIO is
+ /// created to manage user input to the process.
+ ///
+ /// The descriptor's ownership is transferred to the underlying
+ /// ConnectionFileDescriptor.
+ ///
+ /// \param[in] fd
+ /// The file descriptor to use for process STDIO communication. It's
+ /// assumed to be valid and will be managed by the newly created
+ /// connection.
+ ///
+ /// \see lldb_private::Process::STDIOReadThreadBytesReceived()
+ /// \see lldb_private::IOHandlerProcessSTDIO
+ /// \see lldb_private::ConnectionFileDescriptor
void SetSTDIOFileDescriptor(int file_descriptor);
+ /// Windows equivalent of Process::SetSTDIOFileDescriptor, with a
+ /// PseudoTerminalWindows instead of a file descriptor.
+ ///
+ /// \param pty
+ /// The PseudoTerminal to use for process STDIO communication. It is not
+ /// managed by the created read thread.
+ ///
+ /// \see lldb_private::ConnectionPseudoTerminalWindows
+ virtual void
+ SetPseudoTerminalHandle(const std::shared_ptr<PseudoTerminal> &pty) {};
+
// Add a permanent region of memory that should never be read or written to.
// This can be used to ensure that memory reads or writes to certain areas of
// memory never end up being sent to the DoReadMemory or DoWriteMemory
diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt
index c9e8afe48fcde..1657dadf5ffe7 100644
--- a/lldb/source/Host/CMakeLists.txt
+++ b/lldb/source/Host/CMakeLists.txt
@@ -66,6 +66,7 @@ add_host_subdirectory(posix
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
add_host_subdirectory(windows
windows/ConnectionGenericFileWindows.cpp
+ windows/ConnectionPseudoTerminalWindows.cpp
windows/FileSystem.cpp
windows/Host.cpp
windows/HostInfoWindows.cpp
@@ -75,6 +76,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows")
windows/MainLoopWindows.cpp
windows/PipeWindows.cpp
windows/ProcessLauncherWindows.cpp
+ windows/PseudoTerminalWindows.cpp
windows/ProcessRunLock.cpp
)
else()
diff --git a/lldb/source/Host/common/ProcessLaunchInfo.cpp b/lldb/source/Host/common/ProcessLaunchInfo.cpp
index 49159cca9c57c..c3beef7031f18 100644
--- a/lldb/source/Host/common/ProcessLaunchInfo.cpp
+++ b/lldb/source/Host/common/ProcessLaunchInfo.cpp
@@ -20,7 +20,9 @@
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/FileSystem.h"
-#if !defined(_WIN32)
+#ifdef _WIN32
+#include "lldb/Host/windows/PseudoTerminalWindows.h"
+#else
#include <climits>
#endif
@@ -31,7 +33,12 @@ using namespace lldb_private;
ProcessLaunchInfo::ProcessLaunchInfo()
: ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(0),
- m_file_actions(), m_pty(new PseudoTerminal), m_monitor_callback(nullptr) {
+ m_file_actions(), m_monitor_callback(nullptr) {
+#ifdef _WIN32
+ m_pty = std::make_shared<PseudoTerminalWindows>();
+#else
+ m_pty = std::make_shared<PseudoTerminal>();
+#endif
}
ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec,
@@ -40,7 +47,13 @@ ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec,
const FileSpec &working_directory,
uint32_t launch_flags)
: ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags),
- m_file_actions(), m_pty(new PseudoTerminal) {
+ m_file_actions() {
+#ifdef _WIN32
+ m_pty = std::make_shared<PseudoTerminalWindows>();
+#else
+ m_pty = std::make_shared<PseudoTerminal>();
+#endif
+
if (stdin_file_spec) {
FileAction file_action;
const bool read = true;
diff --git a/lldb/source/Host/common/PseudoTerminal.cpp b/lldb/source/Host/common/PseudoTerminal.cpp
index 53e91aff212a4..4d062c3618523 100644
--- a/lldb/source/Host/common/PseudoTerminal.cpp
+++ b/lldb/source/Host/common/PseudoTerminal.cpp
@@ -9,6 +9,7 @@
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/windows/windows.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Errno.h"
#include <cassert>
@@ -29,16 +30,11 @@
using namespace lldb_private;
-// PseudoTerminal constructor
PseudoTerminal::PseudoTerminal() = default;
-// Destructor
-//
-// The destructor will close the primary and secondary file descriptors if they
-// are valid and ownership has not been released using the
-// ReleasePrimaryFileDescriptor() or the ReleaseSaveFileDescriptor() member
-// functions.
-PseudoTerminal::~PseudoTerminal() {
+PseudoTerminal::~PseudoTerminal() { Close(); }
+
+void PseudoTerminal::Close() {
ClosePrimaryFileDescriptor();
CloseSecondaryFileDescriptor();
}
diff --git a/lldb/source/Host/windows/ConnectionPseudoTerminalWindows.cpp b/lldb/source/Host/windows/ConnectionPseudoTerminalWindows.cpp
new file mode 100644
index 0000000000000..b00fd745bc409
--- /dev/null
+++ b/lldb/source/Host/windows/ConnectionPseudoTerminalWindows.cpp
@@ -0,0 +1,191 @@
+//===-- ConnectionPseudoConsoleWindowsWindows.cpp
+//----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/windows/ConnectionPseudoTerminalWindows.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/Utility/Timeout.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ConvertUTF.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class ReturnInfo {
+public:
+ void Set(size_t bytes, ConnectionStatus status, DWORD error_code) {
+ m_error = Status(error_code, eErrorTypeWin32);
+ m_bytes = bytes;
+ m_status = status;
+ }
+
+ void Set(size_t bytes, ConnectionStatus status, llvm::StringRef error_msg) {
+ m_error = Status::FromErrorString(error_msg.data());
+ m_bytes = bytes;
+ m_status = status;
+ }
+
+ size_t GetBytes() const { return m_bytes; }
+ ConnectionStatus GetStatus() const { return m_status; }
+ const Status &GetError() const { return m_error; }
+
+private:
+ Status m_error;
+ size_t m_bytes;
+ ConnectionStatus m_status;
+};
+
+ConnectionPseudoTerminal::ConnectionPseudoTerminal()
+ : m_pty(nullptr), m_owns_file(false) {
+ ::ZeroMemory(&m_overlapped, sizeof(m_overlapped));
+}
+
+ConnectionPseudoTerminal::ConnectionPseudoTerminal(
+ std::shared_ptr<PseudoTerminal> pty, bool owns_file)
+ : m_pty(pty), m_owns_file(owns_file) {
+ ::ZeroMemory(&m_overlapped, sizeof(m_overlapped));
+}
+
+ConnectionPseudoTerminal::~ConnectionPseudoTerminal() {}
+
+lldb::ConnectionStatus ConnectionPseudoTerminal::Connect(llvm::StringRef url,
+ Status *error_ptr) {
+ if (IsConnected())
+ return eConnectionStatusSuccess;
+ return eConnectionStatusNoConnection;
+}
+
+bool ConnectionPseudoTerminal::IsConnected() const {
+ return m_pty && (m_pty->GetPrimaryHandle() != INVALID_HANDLE_VALUE);
+}
+
+lldb::ConnectionStatus ConnectionPseudoTerminal::Disconnect(Status *error_ptr) {
+ Log *log = GetLog(LLDBLog::Connection);
+ LLDB_LOGF(log, "%p ConnectionPseudoTerminal::Disconnect ()",
+ static_cast<void *>(this));
+
+ if (!IsConnected())
+ return eConnectionStatusSuccess;
+
+ m_pty->Close();
+ return eConnectionStatusSuccess;
+}
+
+size_t ConnectionPseudoTerminal::Read(void *dst, size_t dst_len,
+ const Timeout<std::micro> &timeout,
+ lldb::ConnectionStatus &status,
+ Status *error_ptr) {
+ ReturnInfo return_info;
+ DWORD bytes_read = 0;
+ BOOL result = false;
+
+ if (error_ptr)
+ error_ptr->Clear();
+
+ HANDLE hInput = m_pty->GetPrimaryHandle();
+
+ if (!IsConnected()) {
+ return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE);
+ goto finish;
+ }
+
+ // Setup OVERLAPPED event
+ m_overlapped.hEvent = m_event_handles[kBytesAvailableEvent];
+
+ result =
+ ::ReadFile(hInput, dst, static_cast<DWORD>(dst_len), NULL, &m_overlapped);
+ if (result || ::GetLastError() == ERROR_IO_PENDING) {
+ if (!result) {
+ // Operation pending: wait for completion or interrupt
+ DWORD milliseconds =
+ timeout ? static_cast<DWORD>(
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ *timeout)
+ .count())
+ : INFINITE;
+
+ DWORD wait_result = ::WaitForMultipleObjects(
+ static_cast<DWORD>(std::size(m_event_handles)), m_event_handles,
+ FALSE, milliseconds);
+
+ switch (wait_result) {
+ case WAIT_OBJECT_0 + kBytesAvailableEvent:
+ break; // Data ready
+ case WAIT_OBJECT_0 + kInterruptEvent:
+ return_info.Set(0, eConnectionStatusInterrupted, 0);
+ goto finish;
+ case WAIT_TIMEOUT:
+ return_info.Set(0, eConnectionStatusTimedOut, 0);
+ goto finish;
+ case WAIT_FAILED:
+ return_info.Set(0, eConnectionStatusError, ::GetLastError());
+ goto finish;
+ }
+ }
+
+ // Get actual number of bytes read
+ if (!::GetOverlappedResult(hInput, &m_overlapped, &bytes_read, FALSE)) {
+ DWORD err = ::GetLastError();
+ if (err == ERROR_HANDLE_EOF || err == ERROR_OPERATION_ABORTED ||
+ err == ERROR_BROKEN_PIPE)
+ return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0);
+ else
+ return_info.Set(bytes_read, eConnectionStatusError, err);
+ } else if (bytes_read == 0) {
+ return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0);
+ } else {
+ return_info.Set(bytes_read, eConnectionStatusSuccess, 0);
+ }
+ goto finish;
+ } else if (::GetLastError() == ERROR_BROKEN_PIPE) {
+ return_info.Set(0, eConnectionStatusEndOfFile, 0);
+ } else {
+ return_info.Set(0, eConnectionStatusError, ::GetLastError());
+ }
+
+finish:
+ status = return_info.GetStatus();
+ if (error_ptr)
+ *error_ptr = return_info.GetError().Clone();
+
+ // Reset manual-reset event for next read
+ ResetEvent(m_event_handles[kBytesAvailableEvent]);
+
+ // IncrementFilePointer(return_info.GetBytes());
+
+ Log *log = GetLog(LLDBLog::Connection);
+ LLDB_LOGF(log,
+ "%p ConnectionPseudoTerminal::Read() handle=%p, dst=%p, "
+ "dst_len=%zu => %zu, error=%s",
+ static_cast<void *>(this), hInput, dst, dst_len,
+ return_info.GetBytes(), return_info.GetError().AsCString());
+
+ return return_info.GetBytes();
+}
+
+size_t ConnectionPseudoTerminal::Write(const void *src, size_t src_len,
+ lldb::ConnectionStatus &status,
+ Status *error_ptr) {
+ // TODO:
+ DWORD bytes_written = 0;
+
+ if (error_ptr)
+ error_ptr->Clear();
+
+ if (!IsConnected()) {
+ }
+ return 0;
+}
+
+bool ConnectionPseudoTerminal::InterruptRead() {
+ return ::SetEvent(m_event_handles[kInterruptEvent]);
+}
\ No newline at end of file
diff --git a/lldb/source/Host/windows/ProcessLauncherWindows.cpp b/lldb/source/Host/windows/ProcessLauncherWindows.cpp
index f5adadaf061bf..dc7f864b0543d 100644
--- a/lldb/source/Host/windows/ProcessLauncherWindows.cpp
+++ b/lldb/source/Host/windows/ProcessLauncherWindows.cpp
@@ -21,42 +21,41 @@
using namespace lldb;
using namespace lldb_private;
-static void CreateEnvironmentBuffer(const Environment &env,
- std::vector<char> &buffer) {
- // The buffer is a list of null-terminated UTF-16 strings, followed by an
- // extra L'\0' (two bytes of 0). An empty environment must have one
- // empty string, followed by an extra L'\0'.
+std::vector<wchar_t>
+ProcessLauncherWindows::CreateEnvironmentBufferW(const Environment &env) {
+ std::vector<std::wstring> env_entries;
for (const auto &KV : env) {
- std::wstring warg;
- if (llvm::ConvertUTF8toWide(Environment::compose(KV), warg)) {
- buffer.insert(
- buffer.end(), reinterpret_cast<const char *>(warg.c_str()),
- reinterpret_cast<const char *>(warg.c_str() + warg.size() + 1));
+ std::wstring wentry;
+ if (llvm::ConvertUTF8toWide(Environment::compose(KV), wentry)) {
+ env_entries.push_back(std::move(wentry));
}
}
- // One null wchar_t (to end the block) is two null bytes
- buffer.push_back(0);
- buffer.push_back(0);
- // Insert extra two bytes, just in case the environment was empty.
- buffer.push_back(0);
- buffer.push_back(0);
+ std::sort(env_entries.begin(), env_entries.end(),
+ [](const std::wstring &a, const std::wstring &b) {
+ return _wcsicmp(a.c_str(), b.c_str()) < 0;
+ });
+
+ std::vector<wchar_t> buffer;
+ buffer.clear();
+ for (const auto &env_entry : env_entries) {
+ buffer.insert(buffer.end(), env_entry.begin(), env_entry.end());
+ buffer.push_back(L'\0');
+ }
+ buffer.push_back(L'\0');
+
+ return buffer;
}
-static bool GetFlattenedWindowsCommandString(Args args, std::wstring &command) {
+llvm::ErrorOr<std::wstring>
+ProcessLauncherWindows::GetFlattenedWindowsCommandStringW(Args args) {
if (args.empty())
- return false;
+ return L"";
std::vector<llvm::StringRef> args_ref;
for (auto &entry : args.entries())
args_ref.push_back(entry.ref());
- llvm::ErrorOr<std::wstring> result =
- llvm::sys::flattenWindowsCommandLine(args_ref);
- if (result.getError())
- return false;
-
- command = *result;
- return true;
+ return llvm::sys::flattenWindowsCommandLine(args_ref);
}
HostProcess
@@ -64,12 +63,13 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
Status &error) {
error.Clear();
- std::string executable;
- std::vector<char> environment;
- STARTUPINFOEX startupinfoex = {};
- STARTUPINFO &startupinfo = startupinfoex.StartupInfo;
+ std::vector<HANDLE> inherited_handles;
+ STARTUPINFOEXW startupinfoex = {};
+ STARTUPINFOW &startupinfo = startupinfoex.StartupInfo;
PROCESS_INFORMATION pi = {};
+ HPCON hPC = launch_info.GetPTY()->GetPseudoTerminalHandle();
+
HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO);
HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO);
HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO);
@@ -82,32 +82,34 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
::CloseHandle(stderr_handle);
});
- startupinfo.cb = sizeof(startupinfoex);
+ startupinfo.cb = sizeof(STARTUPINFOEXW);
startupinfo.dwFlags |= STARTF_USESTDHANDLES;
- startupinfo.hStdError =
- stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE);
- startupinfo.hStdInput =
- stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE);
- startupinfo.hStdOutput =
- stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE);
- std::vector<HANDLE> inherited_handles;
- if (startupinfo.hStdError)
- inherited_handles.push_back(startupinfo.hStdError);
- if (startupinfo.hStdInput)
- inherited_handles.push_back(startupinfo.hStdInput);
- if (startupinfo.hStdOutput)
- inherited_handles.push_back(startupinfo.hStdOutput);
+ if (hPC == INVALID_HANDLE_VALUE) {
+ startupinfo.hStdError =
+ stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE);
+ startupinfo.hStdInput =
+ stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE);
+ startupinfo.hStdOutput =
+ stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE);
+
+ if (startupinfo.hStdError)
+ inherited_handles.push_back(startupinfo.hStdError);
+ if (startupinfo.hStdInput)
+ inherited_handles.push_back(startupinfo.hStdInput);
+ if (startupinfo.hStdOutput)
+ inherited_handles.push_back(startupinfo.hStdOutput);
+ }
SIZE_T attributelist_size = 0;
InitializeProcThreadAttributeList(/*lpAttributeList=*/nullptr,
/*dwAttributeCount=*/1, /*dwFlags=*/0,
&attributelist_size);
- startupinfoex.lpAttributeList =
- static_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(attributelist_size));
- auto free_attributelist =
- llvm::make_scope_exit([&] { free(startupinfoex.lpAttributeList); });
+ startupinfoex.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(
+ GetProcessHeap(), 0, attributelist_size);
+ auto free_attributelist = llvm::make_scope_exit(
+ [&] { HeapFree(GetProcessHeap(), 0, startupinfoex.lpAttributeList); });
if (!InitializeProcThreadAttributeList(startupinfoex.lpAttributeList,
/*dwAttributeCount=*/1, /*dwFlags=*/0,
&attributelist_size)) {
@@ -116,21 +118,31 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
}
auto delete_attributelist = llvm::make_scope_exit(
[&] { DeleteProcThreadAttributeList(startupinfoex.lpAttributeList); });
- for (size_t i = 0; i < launch_info.GetNumFileActions(); ++i) {
- const FileAction *act = launch_info.GetFileActionAtIndex(i);
- if (act->GetAction() == FileAction::eFileActionDuplicate &&
- act->GetFD() == act->GetActionArgument())
- inherited_handles.push_back(reinterpret_cast<HANDLE>(act->GetFD()));
- }
- if (!inherited_handles.empty()) {
- if (!UpdateProcThreadAttribute(
- startupinfoex.lpAttributeList, /*dwFlags=*/0,
- PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data(),
- inherited_handles.size() * sizeof(HANDLE),
- /*lpPreviousValue=*/nullptr, /*lpReturnSize=*/nullptr)) {
+
+ if (hPC != INVALID_HANDLE_VALUE) {
+ if (!UpdateProcThreadAttribute(startupinfoex.lpAttributeList, 0,
+ PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, hPC,
+ sizeof(hPC), NULL, NULL)) {
error = Status(::GetLastError(), eErrorTypeWin32);
return HostProcess();
}
+ } else {
+ for (size_t i = 0; i < launch_info.GetNumFileActions(); ++i) {
+ const FileAction *act = launch_info.GetFileActionAtIndex(i);
+ if (act->GetAction() == FileAction::eFileActionDuplicate &&
+ act->GetFD() == act->GetActionArgument())
+ inherited_handles.push_back(reinterpret_cast<HANDLE>(act->GetFD()));
+ }
+ if (!inherited_handles.empty()) {
+ if (!UpdateProcThreadAttribute(
+ startupinfoex.lpAttributeList, /*dwFlags=*/0,
+ PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data(),
+ inherited_handles.size() * sizeof(HANDLE),
+ /*lpPreviousValue=*/nullptr, /*lpReturnSize=*/nullptr)) {
+ error = Status(::GetLastError(), eErrorTypeWin32);
+ return HostProcess();
+ }
+ }
}
const char *hide_console_var =
@@ -146,31 +158,37 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
if (launch_info.GetFlags().Test(eLaunchFlagDebug))
flags |= DEBUG_ONLY_THIS_PROCESS;
- if (launch_info.GetFlags().Test(eLaunchFlagDisableSTDIO))
+ if (launch_info.GetFlags().Test(eLaunchFlagDisableSTDIO) ||
+ hPC != INVALID_HANDLE_VALUE)
flags &= ~CREATE_NEW_CONSOLE;
- LPVOID env_block = nullptr;
- ::CreateEnvironmentBuffer(launch_info.GetEnvironment(), environment);
- env_block = environment.data();
+ std::vector<wchar_t> environment =
+ CreateEnvironmentBufferW(launch_info.GetEnvironment());
+ LPVOID env_block = environment.empty() ? nullptr : environment.data();
- executable = launch_info.GetExecutableFile().GetPath();
- std::wstring wcommandLine;
- GetFlattenedWindowsCommandString(launch_info.GetArguments(), wcommandLine);
-
- std::wstring wexecutable, wworkingDirectory;
- llvm::ConvertUTF8toWide(executable, wexecutable);
- llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetPath(),
- wworkingDirectory);
+ auto wcommandLineOrErr =
+ GetFlattenedWindowsCommandStringW(launch_info.GetArguments());
+ if (!wcommandLineOrErr) {
+ error = Status(wcommandLineOrErr.getError());
+ return HostProcess();
+ }
+ std::wstring wcommandLine = *wcommandLineOrErr;
// If the command line is empty, it's best to pass a null pointer to tell
// CreateProcessW to use the executable name as the command line. If the
// command line is not empty, its contents may be modified by CreateProcessW.
WCHAR *pwcommandLine = wcommandLine.empty() ? nullptr : &wcommandLine[0];
+ std::wstring wexecutable, wworkingDirectory;
+ llvm::ConvertUTF8toWide(launch_info.GetExecutableFile().GetPath(),
+ wexecutable);
+ llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetPath(),
+ wworkingDirectory);
+
BOOL result = ::CreateProcessW(
wexecutable.c_str(), pwcommandLine, NULL, NULL,
/*bInheritHandles=*/!inherited_handles.empty(), flags, env_block,
wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(),
- reinterpret_cast<STARTUPINFO *>(&startupinfoex), &pi);
+ reinterpret_cast<STARTUPINFOW *>(&startupinfoex), &pi);
if (!result) {
// Call GetLastError before we make any other system calls.
@@ -223,4 +241,4 @@ ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info,
HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create,
flags, NULL);
return (result == INVALID_HANDLE_VALUE) ? NULL : result;
-}
+}
\ No newline at end of file
diff --git a/lldb/source/Host/windows/PseudoTerminalWindows.cpp b/lldb/source/Host/windows/PseudoTerminalWindows.cpp
new file mode 100644
index 0000000000000..38ebbbce84cfe
--- /dev/null
+++ b/lldb/source/Host/windows/PseudoTerminalWindows.cpp
@@ -0,0 +1,68 @@
+#include "lldb/Host/windows/PseudoTerminalWindows.h"
+
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Errno.h"
+
+using namespace lldb_private;
+
+void PseudoTerminalWindows::Close() {
+ if (m_conpty_handle != INVALID_HANDLE_VALUE)
+ ClosePseudoConsole(m_conpty_handle);
+ CloseHandle(m_conpty_input);
+ CloseHandle(m_conpty_output);
+ m_conpty_handle = INVALID_HANDLE_VALUE;
+ m_conpty_input = INVALID_HANDLE_VALUE;
+ m_conpty_output = INVALID_HANDLE_VALUE;
+}
+
+llvm::Error PseudoTerminalWindows::OpenFirstAvailablePrimary(int oflag) {
+ HRESULT hr;
+ HANDLE hInputRead = INVALID_HANDLE_VALUE;
+ HANDLE hInputWrite = INVALID_HANDLE_VALUE;
+ HANDLE hOutputRead = INVALID_HANDLE_VALUE;
+ HANDLE hOutputWrite = INVALID_HANDLE_VALUE;
+
+ wchar_t pipe_name[MAX_PATH];
+ swprintf(pipe_name, MAX_PATH, L"\\\\.\\pipe\\conpty-%d-%p",
+ GetCurrentProcessId(), this);
+
+ hOutputRead =
+ CreateNamedPipeW(pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_BYTE | PIPE_WAIT, 1, 4096, 4096, 0, NULL);
+ hOutputWrite = CreateFileW(pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (!CreatePipe(&hInputRead, &hInputWrite, NULL, 0))
+ return llvm::errorCodeToError(
+ std::error_code(GetLastError(), std::system_category()));
+
+ // if (!CreatePipe(&hOutputRead, &hOutputWrite, NULL, 0)) {
+ // CloseHandle(hInputRead);
+ // CloseHandle(hInputWrite);
+ // return llvm::errorCodeToError(
+ // std::error_code(GetLastError(), std::system_category()));
+ // }
+
+ COORD consoleSize{80, 25};
+ HPCON hPC = INVALID_HANDLE_VALUE;
+ hr = CreatePseudoConsole(consoleSize, hInputRead, hOutputWrite, 0, &hPC);
+ CloseHandle(hInputRead);
+ CloseHandle(hOutputWrite);
+
+ if (FAILED(hr)) {
+ CloseHandle(hInputWrite);
+ CloseHandle(hOutputRead);
+ return llvm::make_error<llvm::StringError>(
+ "Failed to create Windows ConPTY pseudo terminal",
+ llvm::errc::io_error);
+ }
+
+ DWORD mode = PIPE_NOWAIT;
+ SetNamedPipeHandleState(hOutputRead, &mode, NULL, NULL);
+
+ m_conpty_handle = hPC;
+ m_conpty_output = hOutputRead;
+ m_conpty_input = hInputWrite;
+
+ return llvm::Error::success();
+}
\ No newline at end of file
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp
index 211868b51facb..d2fd372bfe9e3 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -136,7 +136,7 @@ SymbolContext ScriptInterpreter::GetOpaqueTypeFromSBSymbolContext(
return {};
}
-std::optional<MemoryRegionInfo>
+std::optional<lldb_private::MemoryRegionInfo>
ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo(
const lldb::SBMemoryRegionInfo &mem_region) const {
if (!mem_region.m_opaque_up)
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
index 47111c97927c1..8eeb3d61ba78b 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
@@ -215,7 +215,7 @@ PlatformAppleSimulator::DebugProcess(ProcessLaunchInfo &launch_info,
// been used where the secondary side was given as the file to open for
// stdin/out/err after we have already opened the primary so we can
// read/write stdin/out/err.
- int pty_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor();
+ int pty_fd = launch_info.GetPTY()->ReleasePrimaryFileDescriptor();
if (pty_fd != PseudoTerminal::invalid_fd) {
process_sp->SetSTDIOFileDescriptor(pty_fd);
}
diff --git a/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm b/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
index f3e79d3d56154..297fcd9b17f0a 100644
--- a/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
+++ b/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
@@ -399,18 +399,18 @@ static Status HandleFileAction(ProcessLaunchInfo &launch_info,
case FileAction::eFileActionOpen: {
FileSpec file_spec = file_action->GetFileSpec();
if (file_spec) {
- const int primary_fd = launch_info.GetPTY().GetPrimaryFileDescriptor();
+ const int primary_fd = launch_info.GetPTY()->GetPrimaryFileDescriptor();
if (primary_fd != PseudoTerminal::invalid_fd) {
// Check in case our file action open wants to open the secondary
- FileSpec secondary_spec(launch_info.GetPTY().GetSecondaryName());
+ FileSpec secondary_spec(launch_info.GetPTY()->GetSecondaryName());
if (file_spec == secondary_spec) {
int secondary_fd =
- launch_info.GetPTY().GetSecondaryFileDescriptor();
+ launch_info.GetPTY()->GetSecondaryFileDescriptor();
if (secondary_fd == PseudoTerminal::invalid_fd) {
- if (llvm::Error Err = launch_info.GetPTY().OpenSecondary(O_RDWR))
+ if (llvm::Error Err = launch_info.GetPTY()->OpenSecondary(O_RDWR))
return Status::FromError(std::move(Err));
}
- secondary_fd = launch_info.GetPTY().GetSecondaryFileDescriptor();
+ secondary_fd = launch_info.GetPTY()->GetSecondaryFileDescriptor();
assert(secondary_fd != PseudoTerminal::invalid_fd);
[options setValue:[NSNumber numberWithInteger:secondary_fd]
forKey:key];
diff --git a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index befc28b09d185..193ea3ca5d219 100644
--- a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -488,7 +488,7 @@ lldb::ProcessSP PlatformPOSIX::DebugProcess(ProcessLaunchInfo &launch_info,
if (error.Success()) {
// Hook up process PTY if we have one (which we should for local debugging
// with llgs).
- int pty_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor();
+ int pty_fd = launch_info.GetPTY()->ReleasePrimaryFileDescriptor();
if (pty_fd != PseudoTerminal::invalid_fd) {
process_sp->SetSTDIOFileDescriptor(pty_fd);
LLDB_LOG(log, "hooked up STDIO pty to process");
diff --git a/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp
index c182d3d862269..ced709aef6f8d 100644
--- a/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp
+++ b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp
@@ -235,10 +235,10 @@ lldb::ProcessSP PlatformQemuUser::DebugProcess(ProcessLaunchInfo &launch_info,
if (error.Fail())
return nullptr;
- if (launch_info.GetPTY().GetPrimaryFileDescriptor() !=
+ if (launch_info.GetPTY()->GetPrimaryFileDescriptor() !=
PseudoTerminal::invalid_fd)
process_sp->SetSTDIOFileDescriptor(
- launch_info.GetPTY().ReleasePrimaryFileDescriptor());
+ launch_info.GetPTY()->ReleasePrimaryFileDescriptor());
return process_sp;
}
diff --git a/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp b/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
index c0c26cc5f1954..917e8be9ea60a 100644
--- a/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
+++ b/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
@@ -496,6 +496,7 @@ ProcessSP PlatformWindows::DebugProcess(ProcessLaunchInfo &launch_info,
// plugin, and PlatformWindows::DebugProcess is just a pass-through to get to
// the process plugin.
+ Log *log = GetLog(LLDBLog::Platform);
if (IsRemote()) {
if (m_remote_platform_sp)
return m_remote_platform_sp->DebugProcess(launch_info, debugger, target,
@@ -519,8 +520,15 @@ ProcessSP PlatformWindows::DebugProcess(ProcessLaunchInfo &launch_info,
// We need to launch and attach to the process.
launch_info.GetFlags().Set(eLaunchFlagDebug);
- if (process_sp)
- error = process_sp->Launch(launch_info);
+ if (!process_sp)
+ return process_sp;
+ error = process_sp->Launch(launch_info);
+ int zzzz = 1;
+ if (error.Success() && zzzz)
+ process_sp->SetPseudoTerminalHandle(launch_info.GetPTY());
+ else
+ LLDB_LOGF(log, "Platform::%s LaunchProcess() failed: %s", __FUNCTION__,
+ error.AsCString());
return process_sp;
}
diff --git a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
index cd5e3458e60e8..bbf10960f55ae 100644
--- a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
+++ b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
@@ -86,8 +86,9 @@ NativeProcessAIX::Manager::Launch(ProcessLaunchInfo &launch_info,
LLDB_LOG(log, "inferior started, now in stopped state");
return std::unique_ptr<NativeProcessAIX>(new NativeProcessAIX(
- pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
- HostInfo::GetArchitecture(HostInfo::eArchKind64), *this, {pid}));
+ pid, launch_info.GetPTY()->ReleasePrimaryFileDescriptor(),
+ native_delegate, HostInfo::GetArchitecture(HostInfo::eArchKind64), *this,
+ {pid}));
}
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
index a22083a8a0903..1b63b01693840 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
@@ -108,8 +108,8 @@ NativeProcessFreeBSD::Manager::Launch(ProcessLaunchInfo &launch_info,
Info.GetArchitecture().GetArchitectureName());
std::unique_ptr<NativeProcessFreeBSD> process_up(new NativeProcessFreeBSD(
- pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
- Info.GetArchitecture(), m_mainloop));
+ pid, launch_info.GetPTY()->ReleasePrimaryFileDescriptor(),
+ native_delegate, Info.GetArchitecture(), m_mainloop));
status = process_up->SetupTrace();
if (status.Fail())
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 7ef50da3641b4..c603c42cf09bf 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -304,8 +304,8 @@ NativeProcessLinux::Manager::Launch(ProcessLaunchInfo &launch_info,
return arch_or.takeError();
return std::unique_ptr<NativeProcessLinux>(new NativeProcessLinux(
- pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
- *arch_or, *this, {pid}));
+ pid, launch_info.GetPTY()->ReleasePrimaryFileDescriptor(),
+ native_delegate, *arch_or, *this, {pid}));
}
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 8fb15d83117f4..4f874d33f361a 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -94,8 +94,8 @@ NativeProcessNetBSD::Manager::Launch(ProcessLaunchInfo &launch_info,
Info.GetArchitecture().GetArchitectureName());
std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
- pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
- Info.GetArchitecture(), m_mainloop));
+ pid, launch_info.GetPTY()->ReleasePrimaryFileDescriptor(),
+ native_delegate, Info.GetArchitecture(), m_mainloop));
status = process_up->SetupTrace();
if (status.Fail())
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index 79dd46ba319d6..600f2203c63e1 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -47,9 +47,9 @@ namespace lldb_private {
NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info,
NativeDelegate &delegate,
llvm::Error &E)
- : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID,
- launch_info.GetPTY().ReleasePrimaryFileDescriptor(),
- delegate),
+ : NativeProcessProtocol(
+ LLDB_INVALID_PROCESS_ID,
+ launch_info.GetPTY()->ReleasePrimaryFileDescriptor(), delegate),
ProcessDebugger(), m_arch(launch_info.GetArchitecture()) {
ErrorAsOutParameter EOut(&E);
DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this));
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
index 0fecefe23b88e..d25ac7ada5d43 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -21,6 +21,9 @@
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/HostNativeProcessBase.h"
#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/PseudoTerminal.h"
+#include "lldb/Host/windows/ConnectionGenericFileWindows.h"
+#include "lldb/Host/windows/ConnectionPseudoTerminalWindows.h"
#include "lldb/Host/windows/HostThreadWindows.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
@@ -121,22 +124,6 @@ ProcessWindows::ProcessWindows(lldb::TargetSP target_sp,
ProcessWindows::~ProcessWindows() {}
-size_t ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Status &error) {
- error = Status::FromErrorString("GetSTDOUT unsupported on Windows");
- return 0;
-}
-
-size_t ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Status &error) {
- error = Status::FromErrorString("GetSTDERR unsupported on Windows");
- return 0;
-}
-
-size_t ProcessWindows::PutSTDIN(const char *buf, size_t buf_size,
- Status &error) {
- error = Status::FromErrorString("PutSTDIN unsupported on Windows");
- return 0;
-}
-
Status ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) {
if (bp_site->HardwareRequired())
return Status::FromErrorString("Hardware breakpoints are not supported.");
@@ -659,6 +646,7 @@ void ProcessWindows::OnExitProcess(uint32_t exit_code) {
LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code);
TargetSP target = CalculateTarget();
+ target->GetProcessLaunchInfo().GetPTY()->Close();
if (target) {
ModuleSP executable_module = target->GetExecutableModule();
ModuleList unloaded_modules;
@@ -954,4 +942,17 @@ Status ProcessWindows::DisableWatchpoint(WatchpointSP wp_sp, bool notify) {
return error;
}
+
+void ProcessWindows::SetPseudoTerminalHandle(
+ const std::shared_ptr<PseudoTerminal> &pty) {
+ m_stdio_communication.SetConnection(
+ std::make_unique<ConnectionGenericFile>(pty->GetPrimaryHandle(), false));
+ if (m_stdio_communication.IsConnected()) {
+ m_stdio_communication.SetReadThreadBytesReceivedCallback(
+ STDIOReadThreadBytesReceived, this);
+ m_stdio_communication.StartReadThread();
+
+ // TODO: Now read thread is set up, set up input reader.
+ }
+}
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
index 97284b7cd1436..49596e49a9f82 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
@@ -9,6 +9,7 @@
#ifndef liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_
#define liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_
+#include "lldb/Host/windows/PseudoTerminalWindows.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-forward.h"
@@ -38,10 +39,6 @@ class ProcessWindows : public Process, public ProcessDebugger {
~ProcessWindows();
- size_t GetSTDOUT(char *buf, size_t buf_size, Status &error) override;
- size_t GetSTDERR(char *buf, size_t buf_size, Status &error) override;
- size_t PutSTDIN(const char *buf, size_t buf_size, Status &error) override;
-
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
Status EnableBreakpointSite(BreakpointSite *bp_site) override;
@@ -101,6 +98,9 @@ class ProcessWindows : public Process, public ProcessDebugger {
Status DisableWatchpoint(lldb::WatchpointSP wp_sp,
bool notify = true) override;
+ void
+ SetPseudoTerminalHandle(const std::shared_ptr<PseudoTerminal> &pty) override;
+
protected:
ProcessWindows(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index 5b0930cf26b77..2c569039624e6 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -1054,7 +1054,7 @@ lldb::ProcessSP Platform::DebugProcess(ProcessLaunchInfo &launch_info,
// been used where the secondary side was given as the file to open for
// stdin/out/err after we have already opened the primary so we can
// read/write stdin/out/err.
- int pty_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor();
+ int pty_fd = launch_info.GetPTY()->ReleasePrimaryFileDescriptor();
if (pty_fd != PseudoTerminal::invalid_fd) {
process_sp->SetSTDIOFileDescriptor(pty_fd);
}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 69edea503002e..7059726671e05 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -6545,7 +6545,7 @@ Status Process::WriteMemoryTags(lldb::addr_t addr, size_t len,
// Create a CoreFileMemoryRange from a MemoryRegionInfo
static CoreFileMemoryRange
-CreateCoreFileMemoryRange(const MemoryRegionInfo ®ion) {
+CreateCoreFileMemoryRange(const lldb_private::MemoryRegionInfo ®ion) {
const addr_t addr = region.GetRange().GetRangeBase();
llvm::AddressRange range(addr, addr + region.GetRange().GetByteSize());
return {range, region.GetLLDBPermissions()};
@@ -6554,7 +6554,7 @@ CreateCoreFileMemoryRange(const MemoryRegionInfo ®ion) {
// Add dirty pages to the core file ranges and return true if dirty pages
// were added. Return false if the dirty page information is not valid or in
// the region.
-static bool AddDirtyPages(const MemoryRegionInfo ®ion,
+static bool AddDirtyPages(const lldb_private::MemoryRegionInfo ®ion,
CoreFileMemoryRanges &ranges) {
const auto &dirty_page_list = region.GetDirtyPageList();
if (!dirty_page_list)
@@ -6593,8 +6593,8 @@ static bool AddDirtyPages(const MemoryRegionInfo ®ion,
// given region. If the region has dirty page information, only dirty pages
// will be added to \a ranges, else the entire range will be added to \a
// ranges.
-static void AddRegion(const MemoryRegionInfo ®ion, bool try_dirty_pages,
- CoreFileMemoryRanges &ranges) {
+static void AddRegion(const lldb_private::MemoryRegionInfo ®ion,
+ bool try_dirty_pages, CoreFileMemoryRanges &ranges) {
// Don't add empty ranges.
if (region.GetRange().GetByteSize() == 0)
return;
@@ -6617,7 +6617,7 @@ static void SaveDynamicLoaderSections(Process &process,
if (!dyld)
return;
- std::vector<MemoryRegionInfo> dynamic_loader_mem_regions;
+ std::vector<lldb_private::MemoryRegionInfo> dynamic_loader_mem_regions;
std::function<bool(const lldb_private::Thread &)> save_thread_predicate =
[&](const lldb_private::Thread &t) -> bool {
return options.ShouldThreadBeSaved(t.GetID());
@@ -6742,10 +6742,11 @@ static void GetCoreFileSaveRangesStackOnly(Process &process,
// TODO: We should refactor CoreFileMemoryRanges to use the lldb range type, and
// then add an intersect method on it, or MemoryRegionInfo.
-static MemoryRegionInfo Intersect(const MemoryRegionInfo &lhs,
- const MemoryRegionInfo::RangeType &rhs) {
+static lldb_private::MemoryRegionInfo
+Intersect(const lldb_private::MemoryRegionInfo &lhs,
+ const MemoryRegionInfo::RangeType &rhs) {
- MemoryRegionInfo region_info;
+ lldb_private::MemoryRegionInfo region_info;
region_info.SetLLDBPermissions(lhs.GetLLDBPermissions());
region_info.GetRange() = lhs.GetRange().Intersect(rhs);
diff --git a/lldb/test/API/commands/platform/basic/TestPlatformCommand.py b/lldb/test/API/commands/platform/basic/TestPlatformCommand.py
index 1e1a476c44a92..9becd03438c68 100644
--- a/lldb/test/API/commands/platform/basic/TestPlatformCommand.py
+++ b/lldb/test/API/commands/platform/basic/TestPlatformCommand.py
@@ -100,6 +100,7 @@ def test_shell_timeout(self):
def test_host_shell_interpreter(self):
"""Test the host platform shell with a different interpreter"""
self.build()
+ breakpoint()
exe = self.getBuildArtifact("a.out")
self.expect(
"platform shell -h -s " + exe + " -- 'echo $0'",
diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
index ca881f1d817c5..4196c8be24fc8 100644
--- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
+++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
@@ -16,7 +16,6 @@
class TestDAP_launch(lldbdap_testcase.DAPTestCaseBase):
- @skipIfWindows
def test_default(self):
"""
Tests the default launch of a simple program. No arguments,
diff --git a/lldb/tools/lldb-dap/tool/lldb-dap.cpp b/lldb/tools/lldb-dap/tool/lldb-dap.cpp
index f10ed12344cbd..dc016638d4223 100644
--- a/lldb/tools/lldb-dap/tool/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/tool/lldb-dap.cpp
@@ -542,6 +542,9 @@ static llvm::Error serveConnection(
}
int main(int argc, char *argv[]) {
+ int zzz = 0;
+ while (zzz) {
+ }
llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false);
#if !defined(__APPLE__)
llvm::setBugReportMsg("PLEASE submit a bug report to " LLDB_BUG_REPORT_URL
diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
index 012eae02d5857..966b37e09ee55 100644
--- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
+++ b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
@@ -326,7 +326,7 @@ TEST_F(GDBRemoteCommunicationClientTest, SendSignalsToIgnore) {
TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfo) {
const lldb::addr_t addr = 0xa000;
- MemoryRegionInfo region_info;
+ lldb_private::MemoryRegionInfo region_info;
std::future<Status> result = std::async(std::launch::async, [&] {
return client.GetMemoryRegionInfo(addr, region_info);
});
@@ -343,13 +343,16 @@ TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfo) {
EXPECT_TRUE(result.get().Success());
EXPECT_EQ(addr, region_info.GetRange().GetRangeBase());
EXPECT_EQ(0x2000u, region_info.GetRange().GetByteSize());
- EXPECT_EQ(MemoryRegionInfo::eYes, region_info.GetReadable());
- EXPECT_EQ(MemoryRegionInfo::eNo, region_info.GetWritable());
- EXPECT_EQ(MemoryRegionInfo::eYes, region_info.GetExecutable());
+ EXPECT_EQ(lldb_private::MemoryRegionInfo::eYes, region_info.GetReadable());
+ EXPECT_EQ(lldb_private::MemoryRegionInfo::eNo, region_info.GetWritable());
+ EXPECT_EQ(lldb_private::MemoryRegionInfo::eYes, region_info.GetExecutable());
EXPECT_EQ("/foo/bar.so", region_info.GetName().GetStringRef());
- EXPECT_EQ(MemoryRegionInfo::eDontKnow, region_info.GetMemoryTagged());
- EXPECT_EQ(MemoryRegionInfo::eDontKnow, region_info.IsStackMemory());
- EXPECT_EQ(MemoryRegionInfo::eDontKnow, region_info.IsShadowStack());
+ EXPECT_EQ(lldb_private::MemoryRegionInfo::eDontKnow,
+ region_info.GetMemoryTagged());
+ EXPECT_EQ(lldb_private::MemoryRegionInfo::eDontKnow,
+ region_info.IsStackMemory());
+ EXPECT_EQ(lldb_private::MemoryRegionInfo::eDontKnow,
+ region_info.IsShadowStack());
result = std::async(std::launch::async, [&] {
return client.GetMemoryRegionInfo(addr, region_info);
@@ -358,9 +361,9 @@ TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfo) {
HandlePacket(server, "qMemoryRegionInfo:a000",
"start:a000;size:2000;flags:;type:stack;");
EXPECT_TRUE(result.get().Success());
- EXPECT_EQ(MemoryRegionInfo::eNo, region_info.GetMemoryTagged());
- EXPECT_EQ(MemoryRegionInfo::eYes, region_info.IsStackMemory());
- EXPECT_EQ(MemoryRegionInfo::eNo, region_info.IsShadowStack());
+ EXPECT_EQ(lldb_private::MemoryRegionInfo::eNo, region_info.GetMemoryTagged());
+ EXPECT_EQ(lldb_private::MemoryRegionInfo::eYes, region_info.IsStackMemory());
+ EXPECT_EQ(lldb_private::MemoryRegionInfo::eNo, region_info.IsShadowStack());
result = std::async(std::launch::async, [&] {
return client.GetMemoryRegionInfo(addr, region_info);
@@ -369,9 +372,10 @@ TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfo) {
HandlePacket(server, "qMemoryRegionInfo:a000",
"start:a000;size:2000;flags: mt zz mt ss ;type:ha,ha,stack;");
EXPECT_TRUE(result.get().Success());
- EXPECT_EQ(MemoryRegionInfo::eYes, region_info.GetMemoryTagged());
- EXPECT_EQ(MemoryRegionInfo::eYes, region_info.IsStackMemory());
- EXPECT_EQ(MemoryRegionInfo::eYes, region_info.IsShadowStack());
+ EXPECT_EQ(lldb_private::MemoryRegionInfo::eYes,
+ region_info.GetMemoryTagged());
+ EXPECT_EQ(lldb_private::MemoryRegionInfo::eYes, region_info.IsStackMemory());
+ EXPECT_EQ(lldb_private::MemoryRegionInfo::eYes, region_info.IsShadowStack());
result = std::async(std::launch::async, [&] {
return client.GetMemoryRegionInfo(addr, region_info);
@@ -380,12 +384,12 @@ TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfo) {
HandlePacket(server, "qMemoryRegionInfo:a000",
"start:a000;size:2000;type:heap;");
EXPECT_TRUE(result.get().Success());
- EXPECT_EQ(MemoryRegionInfo::eNo, region_info.IsStackMemory());
+ EXPECT_EQ(lldb_private::MemoryRegionInfo::eNo, region_info.IsStackMemory());
}
TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfoInvalidResponse) {
const lldb::addr_t addr = 0x4000;
- MemoryRegionInfo region_info;
+ lldb_private::MemoryRegionInfo region_info;
std::future<Status> result = std::async(std::launch::async, [&] {
return client.GetMemoryRegionInfo(addr, region_info);
});
diff --git a/llvm/utils/gn/secondary/lldb/source/Host/BUILD.gn b/llvm/utils/gn/secondary/lldb/source/Host/BUILD.gn
index 10c5f95edf5fd..40bad5afe5beb 100644
--- a/llvm/utils/gn/secondary/lldb/source/Host/BUILD.gn
+++ b/llvm/utils/gn/secondary/lldb/source/Host/BUILD.gn
@@ -65,6 +65,7 @@ static_library("Host") {
if (current_os == "win") {
sources += [
"windows/ConnectionGenericFileWindows.cpp",
+ "windows/ConnectionPseudoTerminalWindows.cpp",
"windows/FileSystem.cpp",
"windows/Host.cpp",
"windows/HostInfoWindows.cpp",
@@ -74,6 +75,7 @@ static_library("Host") {
"windows/MainLoopWindows.cpp",
"windows/PipeWindows.cpp",
"windows/ProcessLauncherWindows.cpp",
+ "windows/PseudoTerminalWindows.cpp",
"windows/ProcessRunLock.cpp",
]
} else {
More information about the llvm-commits
mailing list