[Lldb-commits] [lldb] [lldb-dap] Implement `runInTerminal` for Windows (PR #121269)
https://github.com/SuibianP updated https://github.com/llvm/llvm-project/pull/121269 >From b980d11a234138a2c5a3f1509ee9d0dee51ccae0 Mon Sep 17 00:00:00 2001 From: Hu Jialun Date: Sat, 28 Dec 2024 22:39:33 +0800 Subject: [PATCH] [lldb-dap] Implement runInTerminal for Windows Currently, the named pipe is passed by name and a transient ofstream is constructed at each I/O request. This assumes, - Blocking semantics: FIFO I/O waits for the other side to connect. - Buffered semantics: Closing one side does not discard existing data. The former can be replaced by WaitNamedPipe/ConnectNamedPipe on Win32, but the second cannot be easily worked around. It is also impossible to have another "keep-alive" pipe server instance, as server-client pairs are fixed on connection on Win32 and the client may get connected to it instead of the real one. Refactor FifoFile[IO] to use an open file handles rather than file name. --- lldb/tools/lldb-dap/FifoFiles.cpp | 110 +- lldb/tools/lldb-dap/FifoFiles.h | 31 lldb/tools/lldb-dap/RunInTerminal.cpp | 27 +-- lldb/tools/lldb-dap/RunInTerminal.h | 4 +- lldb/tools/lldb-dap/lldb-dap.cpp | 13 ++- 5 files changed, 138 insertions(+), 47 deletions(-) diff --git a/lldb/tools/lldb-dap/FifoFiles.cpp b/lldb/tools/lldb-dap/FifoFiles.cpp index 1f1bba80bd3b11..f2544cfe974a54 100644 --- a/lldb/tools/lldb-dap/FifoFiles.cpp +++ b/lldb/tools/lldb-dap/FifoFiles.cpp @@ -9,7 +9,13 @@ #include "FifoFiles.h" #include "JSONUtils.h" -#if !defined(_WIN32) +#include "llvm/Support/FileSystem.h" + +#if defined(_WIN32) +#include +#include +#include +#else #include #include #include @@ -24,26 +30,65 @@ using namespace llvm; namespace lldb_dap { -FifoFile::FifoFile(StringRef path) : m_path(path) {} +std::error_code EC; +FifoFile::FifoFile(StringRef path) +: m_path(path), m_file(fopen(path.data(), "r+")) { + if (m_file == nullptr) { +EC = std::error_code(errno, std::generic_category()); +llvm::errs() << "Failed to open fifo file: " << path << EC.message() + << "\n"; +return; + } + if (setvbuf(m_file, NULL, _IONBF, 0)) +llvm::errs() << "Error setting unbuffered mode on C FILE\n"; +} +FifoFile::FifoFile(StringRef path, FILE *f) : m_path(path), m_file(f) {} FifoFile::~FifoFile() { + fclose(m_file); #if !defined(_WIN32) unlink(m_path.c_str()); #endif + // Unreferenced named pipes are deleted automatically on Win32 } -Expected> CreateFifoFile(StringRef path) { -#if defined(_WIN32) - return createStringError(inconvertibleErrorCode(), "Unimplemented"); +// This probably belongs to llvm::sys::fs as another FSEntity type +std::error_code createNamedPipe(const Twine &Prefix, StringRef Suffix, +int &ResultFd, +SmallVectorImpl &ResultPath) { + const char *Middle = Suffix.empty() ? "-%%" : "-%%."; + auto EC = sys::fs::getPotentiallyUniqueFileName( +#ifdef _WIN32 + ".\\pipe\\LOCAL\\" +#else + "/tmp/" +#endif + + Prefix + Middle + Suffix, + ResultPath); + if (EC) +return EC; + ResultPath.push_back(0); + const char *path = ResultPath.data(); +#ifdef _WIN32 + HANDLE h = ::CreateNamedPipeA( + path, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, 0, NULL); + if (h == INVALID_HANDLE_VALUE) +return std::error_code(::GetLastError(), std::system_category()); + ResultFd = _open_osfhandle((intptr_t)h, _O_TEXT | _O_RDWR); + if (ResultFd == -1) +return std::error_code(::GetLastError(), std::system_category()); #else - if (int err = mkfifo(path.data(), 0600)) -return createStringError(std::error_code(err, std::generic_category()), - "Couldn't create fifo file: %s", path.data()); - return std::make_shared(path); + if (mkfifo(path, 0600) == -1) +return std::error_code(errno, std::generic_category()); + EC = openFileForWrite(ResultPath, ResultFd, sys::fs::CD_OpenExisting, sys::fs::OF_None, 0600); + if (EC) +return EC; #endif + return std::error_code(); } -FifoFileIO::FifoFileIO(StringRef fifo_file, StringRef other_endpoint_name) +FifoFileIO::FifoFileIO(FifoFile fifo_file, StringRef other_endpoint_name) : m_fifo_file(fifo_file), m_other_endpoint_name(other_endpoint_name) {} Expected FifoFileIO::ReadJSON(std::chrono::milliseconds timeout) { @@ -52,13 +97,20 @@ Expected FifoFileIO::ReadJSON(std::chrono::milliseconds timeout) { std::optional line; std::future *future = new std::future(std::async(std::launch::async, [&]() { -std::ifstream reader(m_fifo_file, std::ifstream::in); -std::string buffer; -std::getline(reader, buffer); -if (!buffer.empty()) - line = buffer; +rewind(m_fifo_file.m_file); +constexpr size_t buffer_size = 2048; +char buffer[buffer_size]; +cha
[Lldb-commits] [lldb] [lldb-dap] Implement `runInTerminal` for Windows (PR #121269)
https://github.com/SuibianP created https://github.com/llvm/llvm-project/pull/121269 Currently, the named pipe is passed by name and a transient `ofstream` is constructed at each I/O request. This assumes, - Blocking semantics: FIFO I/O waits for the other side to connect. - Buffered semantics: Closing one side does not discard existing data. The former can be replaced by `WaitNamedPipe`/`ConnectNamedPipe` on Win32, but the second cannot be easily worked around. It is also impossible to have another "keep-alive" pipe server instance, as server-client pairs are fixed on connection on Win32 and the client may get connected to it instead of the real one. Refactor `FifoFile[IO]` to use an open file handles rather than file name. >From 4c8c18c8c54308b945d6c78e2c71ebabf29cb554 Mon Sep 17 00:00:00 2001 From: Hu Jialun Date: Sat, 28 Dec 2024 22:39:33 +0800 Subject: [PATCH] [lldb-dap] Implement runInTerminal for Windows Currently, the named pipe is passed by name and a transient ofstream is constructed at each I/O request. This assumes, - Blocking semantics: FIFO I/O waits for the other side to connect. - Buffered semantics: Closing one side does not discard existing data. The former can be replaced by WaitNamedPipe/ConnectNamedPipe on Win32, but the second cannot be easily worked around. It is also impossible to have another "keep-alive" pipe server instance, as server-client pairs are fixed on connection on Win32 and the client may get connected to it instead of the real one. Refactor FifoFile[IO] to use an open file handles rather than file name. --- lldb/tools/lldb-dap/FifoFiles.cpp | 110 +- lldb/tools/lldb-dap/FifoFiles.h | 31 lldb/tools/lldb-dap/RunInTerminal.cpp | 27 +-- lldb/tools/lldb-dap/RunInTerminal.h | 4 +- lldb/tools/lldb-dap/lldb-dap.cpp | 13 ++- 5 files changed, 138 insertions(+), 47 deletions(-) diff --git a/lldb/tools/lldb-dap/FifoFiles.cpp b/lldb/tools/lldb-dap/FifoFiles.cpp index 1f1bba80bd3b11..80e358532ecee4 100644 --- a/lldb/tools/lldb-dap/FifoFiles.cpp +++ b/lldb/tools/lldb-dap/FifoFiles.cpp @@ -9,7 +9,13 @@ #include "FifoFiles.h" #include "JSONUtils.h" -#if !defined(_WIN32) +#include "llvm/Support/FileSystem.h" + +#if defined(_WIN32) +#include +#include +#include +#else #include #include #include @@ -24,26 +30,65 @@ using namespace llvm; namespace lldb_dap { -FifoFile::FifoFile(StringRef path) : m_path(path) {} +std::error_code EC; +FifoFile::FifoFile(StringRef path) +: m_path(path), m_file(fopen(path.data(), "r+")) { + if (m_file == nullptr) { +EC = std::error_code(errno, std::generic_category()); +llvm::errs() << "Failed to open fifo file: " << path << EC.message() + << "\n"; +return; + } + if (setvbuf(m_file, NULL, _IONBF, 0)) +llvm::errs() << "Error setting unbuffered mode on C FILE\n"; +} +FifoFile::FifoFile(StringRef path, FILE *f) : m_path(path), m_file(f) {} FifoFile::~FifoFile() { + fclose(m_file); #if !defined(_WIN32) unlink(m_path.c_str()); #endif + // Unreferenced named pipes are deleted automatically on Win32 } -Expected> CreateFifoFile(StringRef path) { -#if defined(_WIN32) - return createStringError(inconvertibleErrorCode(), "Unimplemented"); +// This probably belongs to llvm::sys::fs as another FSEntity type +std::error_code createNamedPipe(const Twine &Prefix, StringRef Suffix, +int &ResultFd, +SmallVectorImpl &ResultPath) { + const char *Middle = Suffix.empty() ? "-%%" : "-%%."; + auto EC = sys::fs::getPotentiallyUniqueFileName( +#ifdef _WIN32 + ".\\pipe\\LOCAL\\" +#else + "/tmp/" +#endif + + Prefix + Middle + Suffix, + ResultPath); + if (EC) +return EC; + ResultPath.push_back(0); + const char *path = ResultPath.data(); +#ifdef _WIN32 + HANDLE h = ::CreateNamedPipeA( + path, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, 0, NULL); + if (h == INVALID_HANDLE_VALUE) +return std::error_code(::GetLastError(), std::system_category()); + ResultFd = _open_osfhandle((intptr_t)h, _O_TEXT | _O_RDWR); + if (ResultFd == -1) +return std::error_code(::GetLastError(), std::system_category()); #else - if (int err = mkfifo(path.data(), 0600)) -return createStringError(std::error_code(err, std::generic_category()), - "Couldn't create fifo file: %s", path.data()); - return std::make_shared(path); + if (mkfifo(path, 0600) == -1) +return std::error_code(errno, std::generic_category()); + EC = openFileForWrite(ResultPath, ResultFd, CD_OpenExisting, OF_None, 0600); + if (EC) +return EC; #endif + return std::error_code(); } -FifoFileIO::FifoFileIO(StringRef fifo_file, StringRef other_endpoint_name) +FifoFileIO::FifoFileIO(FifoFile fifo_file, StringRef other_endpoint_name) : m_fifo_file(
[Lldb-commits] [lldb] [lldb-dap] Implement `runInTerminal` for Windows (PR #121269)
github-actions[bot] wrote: Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). You can also ask questions in a comment on this PR, on the [LLVM Discord](https://discord.com/invite/xS7Z362) or on the [forums](https://discourse.llvm.org/). https://github.com/llvm/llvm-project/pull/121269 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Implement `runInTerminal` for Windows (PR #121269)
SuibianP wrote: The patch currently suffers from a critical issue that I cannot diagnose. Help is much appreciated. When the debug adapter attempts to attach to the launcher, https://github.com/llvm/llvm-project/blob/4c8c18c8c54308b945d6c78e2c71ebabf29cb554/lldb/tools/lldb-dap/lldb-dap.cpp#L2039 it blocks at https://github.com/llvm/llvm-project/blob/4c8c18c8c54308b945d6c78e2c71ebabf29cb554/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp#L580-L581 although adding the following snippet at the front of `RunInTerminalLauncherCommChannel::WaitUntilDebugAdaptorAttaches` indicates that the launcher process does get paused and never resumed. ```cpp for (int i = 0; !::IsDebuggerPresent(); ++i) LLVM_LOGV(log, "Waiting to be attached... {0}", i); LLVM_LOGV(log, "Attached"); ``` https://github.com/llvm/llvm-project/pull/121269 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][AIX] Added PlatformAIX plugin (PR #121273)
https://github.com/DhruvSrivastavaX created https://github.com/llvm/llvm-project/pull/121273 This PR is in reference to porting LLDB on AIX. Link to discussions on llvm discourse and github: 1. https://discourse.llvm.org/t/port-lldb-to-ibm-aix/80640 2. https://github.com/llvm/llvm-project/issues/101657 The complete changes for porting are present in this draft PR: https://github.com/llvm/llvm-project/pull/102601 Details: -- Adding PlatformAIX plugin for a basic lldb build support. The 1st commit is the original version as in the draft PR which is a PlatformLinux copy. I have removed some of the code in the next commits. Please let me know all the other changes required to push the PlatformAIX changes and avoid any duplication. Review Request: @labath @DavidSpickett >From 16107a423e30cc339b7529db35a75c3c26924146 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Sat, 28 Dec 2024 13:19:21 -0600 Subject: [PATCH 1/3] Introducing PlatformAIX from PlatformLinux --- .../Plugins/Platform/AIX/CMakeLists.txt | 13 + .../Plugins/Platform/AIX/PlatformAIX.cpp | 471 ++ .../source/Plugins/Platform/AIX/PlatformAIX.h | 74 +++ lldb/source/Plugins/Platform/CMakeLists.txt | 1 + 4 files changed, 559 insertions(+) create mode 100644 lldb/source/Plugins/Platform/AIX/CMakeLists.txt create mode 100644 lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp create mode 100644 lldb/source/Plugins/Platform/AIX/PlatformAIX.h diff --git a/lldb/source/Plugins/Platform/AIX/CMakeLists.txt b/lldb/source/Plugins/Platform/AIX/CMakeLists.txt new file mode 100644 index 00..85ff0a315eabd5 --- /dev/null +++ b/lldb/source/Plugins/Platform/AIX/CMakeLists.txt @@ -0,0 +1,13 @@ +add_definitions("-D_ALL_SOURCE") + +add_lldb_library(lldbPluginPlatformAIX PLUGIN + PlatformAIX.cpp + + LINK_LIBS +lldbBreakpoint +lldbCore +lldbHost +lldbInterpreter +lldbTarget +lldbPluginPlatformPOSIX + ) diff --git a/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp b/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp new file mode 100644 index 00..5c944770029789 --- /dev/null +++ b/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp @@ -0,0 +1,471 @@ +//===-- PlatformAIX.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 "PlatformAIX.h" +#include "lldb/Host/Config.h" + +#include +#if LLDB_ENABLE_POSIX +#include +#endif + +#include "Utility/ARM64_DWARF_Registers.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/State.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/StreamString.h" + +// Define these constants from AIX mman.h for use when targeting remote aix +// systems even when host has different values. + +#if defined(_AIX) +#include +#endif + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::platform_aix; + +LLDB_PLUGIN_DEFINE(PlatformAIX) + +static uint32_t g_initialize_count = 0; + + +PlatformSP PlatformAIX::CreateInstance(bool force, const ArchSpec *arch) { + Log *log = GetLog(LLDBLog::Platform); + LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force, + arch ? arch->GetArchitectureName() : "", + arch ? arch->GetTriple().getTriple() : ""); + + bool create = force; + if (!create && arch && arch->IsValid()) { +const llvm::Triple &triple = arch->GetTriple(); +switch (triple.getOS()) { +case llvm::Triple::AIX: + create = true; + break; + +default: + break; +} + } + + LLDB_LOG(log, "create = {0}", create); + if (create) { +return PlatformSP(new PlatformAIX(false)); + } + return PlatformSP(); +} + +llvm::StringRef PlatformAIX::GetPluginDescriptionStatic(bool is_host) { + if (is_host) +return "Local AIX user platform plug-in."; + return "Remote AIX user platform plug-in."; +} + +void PlatformAIX::Initialize() { + PlatformPOSIX::Initialize(); + + if (g_initialize_count++ == 0) { +#if defined(_AIX) +PlatformSP default_platform_sp(new PlatformAIX(true)); +default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); +Platform::SetHostPlatform(default_platform_sp); +#endif +PluginManager::RegisterPlugin( +PlatformAIX::GetPluginNameStatic(false), +PlatformAIX::GetPluginDescriptionStatic(false), +PlatformAIX::CreateInstance, nullptr); + } +} + +void PlatformAIX::Terminate() { + if (g_initialize_count > 0
[Lldb-commits] [lldb] [lldb][AIX] Added PlatformAIX plugin (PR #121273)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Dhruv Srivastava (DhruvSrivastavaX) Changes This PR is in reference to porting LLDB on AIX. Link to discussions on llvm discourse and github: 1. https://discourse.llvm.org/t/port-lldb-to-ibm-aix/80640 2. https://github.com/llvm/llvm-project/issues/101657 The complete changes for porting are present in this draft PR: https://github.com/llvm/llvm-project/pull/102601 Details: -- Adding PlatformAIX plugin for a basic lldb build support. The 1st commit is the original version as in the draft PR which is a PlatformLinux copy. I have removed some of the code in the next commits. Please let me know all the other changes required to push the PlatformAIX changes and avoid any duplication. Review Request: @labath @DavidSpickett --- Full diff: https://github.com/llvm/llvm-project/pull/121273.diff 4 Files Affected: - (added) lldb/source/Plugins/Platform/AIX/CMakeLists.txt (+13) - (added) lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp (+368) - (added) lldb/source/Plugins/Platform/AIX/PlatformAIX.h (+74) - (modified) lldb/source/Plugins/Platform/CMakeLists.txt (+1) ``diff diff --git a/lldb/source/Plugins/Platform/AIX/CMakeLists.txt b/lldb/source/Plugins/Platform/AIX/CMakeLists.txt new file mode 100644 index 00..85ff0a315eabd5 --- /dev/null +++ b/lldb/source/Plugins/Platform/AIX/CMakeLists.txt @@ -0,0 +1,13 @@ +add_definitions("-D_ALL_SOURCE") + +add_lldb_library(lldbPluginPlatformAIX PLUGIN + PlatformAIX.cpp + + LINK_LIBS +lldbBreakpoint +lldbCore +lldbHost +lldbInterpreter +lldbTarget +lldbPluginPlatformPOSIX + ) diff --git a/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp b/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp new file mode 100644 index 00..36d02be5642293 --- /dev/null +++ b/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp @@ -0,0 +1,368 @@ +//===-- PlatformAIX.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 "PlatformAIX.h" +#include "lldb/Host/Config.h" +#include +#if LLDB_ENABLE_POSIX +#include +#endif +#include "Utility/ARM64_DWARF_Registers.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/State.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/StreamString.h" + +// Use defined constants from AIX mman.h for use when targeting remote aix +// systems even when host has different values. + +#if defined(_AIX) +#include +#endif + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::platform_aix; + +LLDB_PLUGIN_DEFINE(PlatformAIX) + +static uint32_t g_initialize_count = 0; + +PlatformSP PlatformAIX::CreateInstance(bool force, const ArchSpec *arch) { + Log *log = GetLog(LLDBLog::Platform); + LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force, + arch ? arch->GetArchitectureName() : "", + arch ? arch->GetTriple().getTriple() : ""); + + bool create = force; + if (!create && arch && arch->IsValid()) { +const llvm::Triple &triple = arch->GetTriple(); +switch (triple.getOS()) { +case llvm::Triple::AIX: + create = true; + break; + +default: + break; +} + } + + LLDB_LOG(log, "create = {0}", create); + if (create) { +return PlatformSP(new PlatformAIX(false)); + } + return PlatformSP(); +} + +llvm::StringRef PlatformAIX::GetPluginDescriptionStatic(bool is_host) { + if (is_host) +return "Local AIX user platform plug-in."; + return "Remote AIX user platform plug-in."; +} + +void PlatformAIX::Initialize() { + PlatformPOSIX::Initialize(); + + if (g_initialize_count++ == 0) { +PlatformSP default_platform_sp(new PlatformAIX(true)); +default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); +Platform::SetHostPlatform(default_platform_sp); +PluginManager::RegisterPlugin( +PlatformAIX::GetPluginNameStatic(false), +PlatformAIX::GetPluginDescriptionStatic(false), +PlatformAIX::CreateInstance, nullptr); + } +} + +void PlatformAIX::Terminate() { + if (g_initialize_count > 0) { +if (--g_initialize_count == 0) { + PluginManager::UnregisterPlugin(PlatformAIX::CreateInstance); +} + } + + PlatformPOSIX::Terminate(); +} + +/// Default Constructor +PlatformAIX::PlatformAIX(bool is_host) +: PlatformPOSIX(is_host) // This is the local host platform +{ + if (is_host) { +ArchSpec hostArch = HostInfo