[Lldb-commits] [lldb] [llvm] [lldb] [lldb-server] Introduce Host/qnx and NativeProcessQNX (PR #97630)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Jul 3 13:21:04 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Ayush Sahay (ayushsahay1837)
<details>
<summary>Changes</summary>
This change provisions the _QNX_ host and process plugins, and is the fifth and final in a series of changes that look to facilitate remote debug of _AArch64_ targets on _QNX_.
_QNX Neutrino Real-Time Operating System_ is a commercial Unix-like real-time operating system primarily targeting the embedded systems market including automotive, medical devices, robotics, transportation, and industrial embedded systems.
The series of changes in question looks to provision support for –
- Launching a debuggee
- Attaching to a debuggee
- Having the debuggee come up stopped at the entry point
- Setting breakpoints
- Stopping at breakpoints
- Reading/writing contents of/to the debuggee's memory
- Reading/writing contents of/to the debuggee's registers
- Reading/writing contents of/to the debuggee's variables
- Resuming the debuggee's execution
- Single-stepping the debuggee's execution
- Interrupting the debuggee's execution
- Dumping information pertaining to the debuggee's stack trace
Kindly note that _ptrace_ isn't available on _QNX_. Instead, _devctl_ can be leveraged to observe and control the execution of a process under debug on _QNX_.
Any additional support (including the facilitation of execution of tests) will be the subject of future work.
---
Patch is 109.15 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/97630.diff
34 Files Affected:
- (modified) lldb/cmake/modules/LLDBConfig.cmake (+1-1)
- (modified) lldb/include/lldb/Host/HostInfo.h (+3)
- (modified) lldb/include/lldb/Host/posix/MainLoopPosix.h (+19-1)
- (added) lldb/include/lldb/Host/qnx/HostInfoQNX.h (+24)
- (added) lldb/include/lldb/Host/qnx/Support.h (+33)
- (modified) lldb/source/Host/CMakeLists.txt (+7)
- (modified) lldb/source/Host/common/ProcessLaunchInfo.cpp (+3)
- (modified) lldb/source/Host/common/PseudoTerminal.cpp (+24)
- (modified) lldb/source/Host/common/TCPSocket.cpp (+3)
- (modified) lldb/source/Host/posix/MainLoopPosix.cpp (+51-7)
- (modified) lldb/source/Host/posix/ProcessLauncherPosixFork.cpp (+191-1)
- (added) lldb/source/Host/qnx/Host.cpp (+183)
- (added) lldb/source/Host/qnx/HostInfoQNX.cpp (+22)
- (added) lldb/source/Host/qnx/Support.cpp (+41)
- (modified) lldb/source/Plugins/Process/CMakeLists.txt (+3)
- (added) lldb/source/Plugins/Process/QNX/CMakeLists.txt (+16)
- (added) lldb/source/Plugins/Process/QNX/NativeProcessQNX.cpp (+1066)
- (added) lldb/source/Plugins/Process/QNX/NativeProcessQNX.h (+157)
- (added) lldb/source/Plugins/Process/QNX/NativeRegisterContextQNX.cpp (+12)
- (added) lldb/source/Plugins/Process/QNX/NativeRegisterContextQNX.h (+37)
- (added) lldb/source/Plugins/Process/QNX/NativeRegisterContextQNX_arm64.cpp (+344)
- (added) lldb/source/Plugins/Process/QNX/NativeRegisterContextQNX_arm64.h (+66)
- (added) lldb/source/Plugins/Process/QNX/NativeThreadQNX.cpp (+141)
- (added) lldb/source/Plugins/Process/QNX/NativeThreadQNX.h (+73)
- (modified) lldb/source/Plugins/Process/Utility/CMakeLists.txt (+1)
- (added) lldb/source/Plugins/Process/Utility/QNXSignals.cpp (+140)
- (added) lldb/source/Plugins/Process/Utility/QNXSignals.h (+27)
- (modified) lldb/source/Target/UnixSignals.cpp (+3)
- (modified) lldb/source/Utility/CMakeLists.txt (+4)
- (modified) lldb/tools/lldb-server/CMakeLists.txt (+4)
- (modified) lldb/tools/lldb-server/lldb-gdbserver.cpp (+4)
- (modified) llvm/include/llvm/Support/ExitCodes.h (+5-5)
- (modified) llvm/lib/Support/Unix/Path.inc (+11-1)
- (modified) llvm/lib/Support/Unix/Signals.inc (+6)
``````````diff
diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake
index a60921990cf77..139f1c98bd5a1 100644
--- a/lldb/cmake/modules/LLDBConfig.cmake
+++ b/lldb/cmake/modules/LLDBConfig.cmake
@@ -299,7 +299,7 @@ endif()
# Figure out if lldb could use lldb-server. If so, then we'll
# ensure we build lldb-server when an lldb target is being built.
-if (CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|FreeBSD|Linux|NetBSD|Windows")
+if (CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|FreeBSD|Linux|NetBSD|Windows|QNX")
set(LLDB_CAN_USE_LLDB_SERVER ON)
else()
set(LLDB_CAN_USE_LLDB_SERVER OFF)
diff --git a/lldb/include/lldb/Host/HostInfo.h b/lldb/include/lldb/Host/HostInfo.h
index b7010d69d88e7..82fa911ff1204 100644
--- a/lldb/include/lldb/Host/HostInfo.h
+++ b/lldb/include/lldb/Host/HostInfo.h
@@ -55,6 +55,9 @@
#elif defined(__APPLE__)
#include "lldb/Host/macosx/HostInfoMacOSX.h"
#define HOST_INFO_TYPE HostInfoMacOSX
+#elif defined(__QNX__)
+#include "lldb/Host/qnx/HostInfoQNX.h"
+#define HOST_INFO_TYPE HostInfoQNX
#else
#include "lldb/Host/posix/HostInfoPosix.h"
#define HOST_INFO_TYPE HostInfoPosix
diff --git a/lldb/include/lldb/Host/posix/MainLoopPosix.h b/lldb/include/lldb/Host/posix/MainLoopPosix.h
index 07497b7b8c259..6ff1c71f4d0c0 100644
--- a/lldb/include/lldb/Host/posix/MainLoopPosix.h
+++ b/lldb/include/lldb/Host/posix/MainLoopPosix.h
@@ -63,15 +63,30 @@ class MainLoopPosix : public MainLoopBase {
class SignalHandle {
public:
~SignalHandle() { m_mainloop.UnregisterSignal(m_signo, m_callback_it); }
+#if defined(__QNX__)
+ std::weak_ptr<siginfo_t> GetSiginfo() const { return m_siginfo; }
+#endif
private:
SignalHandle(MainLoopPosix &mainloop, int signo,
+#if defined(__QNX__)
+ std::list<Callback>::iterator callback_it,
+ std::weak_ptr<siginfo_t> siginfo)
+ : m_mainloop(mainloop), m_signo(signo), m_callback_it(callback_it),
+ m_siginfo(siginfo) {
+ }
+#else
std::list<Callback>::iterator callback_it)
- : m_mainloop(mainloop), m_signo(signo), m_callback_it(callback_it) {}
+ : m_mainloop(mainloop), m_signo(signo), m_callback_it(callback_it) {
+ }
+#endif
MainLoopPosix &m_mainloop;
int m_signo;
std::list<Callback>::iterator m_callback_it;
+#if defined(__QNX__)
+ std::weak_ptr<siginfo_t> m_siginfo;
+#endif
friend class MainLoopPosix;
SignalHandle(const SignalHandle &) = delete;
@@ -81,6 +96,9 @@ class MainLoopPosix : public MainLoopBase {
struct SignalInfo {
std::list<Callback> callbacks;
struct sigaction old_action;
+#if defined(__QNX__)
+ std::shared_ptr<siginfo_t> siginfo;
+#endif
bool was_blocked : 1;
};
class RunImpl;
diff --git a/lldb/include/lldb/Host/qnx/HostInfoQNX.h b/lldb/include/lldb/Host/qnx/HostInfoQNX.h
new file mode 100644
index 0000000000000..94fd51279ed53
--- /dev/null
+++ b/lldb/include/lldb/Host/qnx/HostInfoQNX.h
@@ -0,0 +1,24 @@
+//===-- HostInfoQNX.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 lldb_Host_qnx_HostInfoQNX_h_
+#define lldb_Host_qnx_HostInfoQNX_h_
+
+#include "lldb/Host/posix/HostInfoPosix.h"
+
+namespace lldb_private {
+
+class HostInfoQNX : public HostInfoPosix {
+public:
+ static llvm::VersionTuple GetOSVersion();
+ static std::optional<std::string> GetOSBuildString();
+ static FileSpec GetProgramFileSpec();
+};
+} // namespace lldb_private
+
+#endif
diff --git a/lldb/include/lldb/Host/qnx/Support.h b/lldb/include/lldb/Host/qnx/Support.h
new file mode 100644
index 0000000000000..975c45c4d2ba6
--- /dev/null
+++ b/lldb/include/lldb/Host/qnx/Support.h
@@ -0,0 +1,33 @@
+//===-- Support.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 LLDB_HOST_QNX_SUPPORT_H
+#define LLDB_HOST_QNX_SUPPORT_H
+
+#include <memory>
+
+#include "lldb/Host/File.h"
+#include "lldb/lldb-forward.h"
+
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace lldb_private {
+
+llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+getProcFile(::pid_t pid, const llvm::Twine &file);
+
+llvm::Expected<lldb::FileUP>
+openProcFile(::pid_t pid, const llvm::Twine &file, File::OpenOptions options,
+ uint32_t permissions = lldb::eFilePermissionsFileDefault,
+ bool should_close_fd = true);
+
+} // namespace lldb_private
+
+#endif // #ifndef LLDB_HOST_QNX_SUPPORT_H
diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt
index c2e091ee8555b..205705a9a28df 100644
--- a/lldb/source/Host/CMakeLists.txt
+++ b/lldb/source/Host/CMakeLists.txt
@@ -133,6 +133,13 @@ else()
openbsd/Host.cpp
openbsd/HostInfoOpenBSD.cpp
)
+
+ elseif (CMAKE_SYSTEM_NAME MATCHES "QNX")
+ add_host_subdirectory(qnx
+ qnx/Host.cpp
+ qnx/HostInfoQNX.cpp
+ qnx/Support.cpp
+ )
endif()
endif()
diff --git a/lldb/source/Host/common/ProcessLaunchInfo.cpp b/lldb/source/Host/common/ProcessLaunchInfo.cpp
index a1866b2a99fd8..d43b55ba0b3e6 100644
--- a/lldb/source/Host/common/ProcessLaunchInfo.cpp
+++ b/lldb/source/Host/common/ProcessLaunchInfo.cpp
@@ -213,7 +213,10 @@ llvm::Error ProcessLaunchInfo::SetUpPtyRedirection() {
// We really shouldn't be specifying platform specific flags that are
// intended for a system call in generic code. But this will have to
// do for now.
+#if !defined(__QNX__)
+ // O_CLOEXEC is NOT a valid flag for posix_openpt on QNX.
open_flags |= O_CLOEXEC;
+#endif
#endif
if (llvm::Error Err = m_pty->OpenFirstAvailablePrimary(open_flags))
return Err;
diff --git a/lldb/source/Host/common/PseudoTerminal.cpp b/lldb/source/Host/common/PseudoTerminal.cpp
index d53327973eb27..bd183679655d2 100644
--- a/lldb/source/Host/common/PseudoTerminal.cpp
+++ b/lldb/source/Host/common/PseudoTerminal.cpp
@@ -72,6 +72,24 @@ llvm::Error PseudoTerminal::OpenFirstAvailablePrimary(int oflag) {
std::error_code(errno, std::generic_category()));
}
+#if defined(FD_CLOEXEC)
+ // Enable the close-on-exec flag for the primary file descriptor if it hasn't
+ // already been enabled.
+ // NB: In multithreaded programs, using fcntl to set the close-on-exec flag at
+ // the same time as another thread performs a fork plus execve risks a race
+ // condition that may unintentionally leak the file descriptor to the program
+ // executed in the child process but, apparently, we don't launch processes
+ // for debugging from within multithreaded contexts at the moment.
+ int flags = ::fcntl(m_primary_fd, F_GETFD);
+ if (flags == -1)
+ return llvm::errorCodeToError(
+ std::error_code(errno, std::generic_category()));
+ if (!(flags & FD_CLOEXEC))
+ if (::fcntl(m_primary_fd, F_SETFD, flags | FD_CLOEXEC) == -1)
+ return llvm::errorCodeToError(
+ std::error_code(errno, std::generic_category()));
+#endif
+
// Grant access to the secondary pseudo terminal
if (::grantpt(m_primary_fd) < 0) {
std::error_code EC(errno, std::generic_category());
@@ -124,7 +142,13 @@ std::string PseudoTerminal::GetSecondaryName() const {
buf[0] = '\0';
int r = ptsname_r(m_primary_fd, buf, sizeof(buf));
UNUSED_IF_ASSERT_DISABLED(r);
+#if defined(__QNX__)
+ // ptsname_r returns a pointer to a null-terminated string containing the
+ // pathname of the corresponding slave device on success on QNX.
+ assert(r != 0);
+#else
assert(r == 0);
+#endif
return buf;
#if defined(__APPLE__)
} else {
diff --git a/lldb/source/Host/common/TCPSocket.cpp b/lldb/source/Host/common/TCPSocket.cpp
index df4737216ed3a..5efcffbb29d0f 100644
--- a/lldb/source/Host/common/TCPSocket.cpp
+++ b/lldb/source/Host/common/TCPSocket.cpp
@@ -26,6 +26,9 @@
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
+#if defined(__QNX__)
+#include <sys/select.h>
+#endif
#endif
#if defined(_WIN32)
diff --git a/lldb/source/Host/posix/MainLoopPosix.cpp b/lldb/source/Host/posix/MainLoopPosix.cpp
index 5fe4d015251c8..37edc016e99b8 100644
--- a/lldb/source/Host/posix/MainLoopPosix.cpp
+++ b/lldb/source/Host/posix/MainLoopPosix.cpp
@@ -20,12 +20,14 @@
#include <vector>
// Multiplexing is implemented using kqueue on systems that support it (BSD
-// variants including OSX). On linux we use ppoll, while android uses pselect
-// (ppoll is present but not implemented properly). On windows we use WSApoll
-// (which does not support signals).
+// variants including OSX). On linux we use ppoll, while android and QNX use
+// pselect (ppoll is present on Android but not implemented properly). On
+// windows we use WSApoll (which does not support signals).
#if HAVE_SYS_EVENT_H
#include <sys/event.h>
+#elif defined(__QNX__)
+#include <sys/select.h>
#elif defined(__ANDROID__)
#include <sys/syscall.h>
#else
@@ -36,10 +38,17 @@ using namespace lldb;
using namespace lldb_private;
static sig_atomic_t g_signal_flags[NSIG];
+#if defined(__QNX__)
+static llvm::DenseMap<int, siginfo_t> g_signal_info;
+#endif
static void SignalHandler(int signo, siginfo_t *info, void *) {
assert(signo < NSIG);
g_signal_flags[signo] = 1;
+#if defined(__QNX__)
+ siginfo_t siginfo(*info);
+ g_signal_info.insert({signo, siginfo});
+#endif
}
class MainLoopPosix::RunImpl {
@@ -59,7 +68,7 @@ class MainLoopPosix::RunImpl {
int num_events = -1;
#else
-#ifdef __ANDROID__
+#if defined(__ANDROID__) || defined(__QNX__)
fd_set read_fd_set;
#else
std::vector<struct pollfd> read_fds;
@@ -113,7 +122,7 @@ void MainLoopPosix::RunImpl::ProcessEvents() {
}
#else
MainLoopPosix::RunImpl::RunImpl(MainLoopPosix &loop) : loop(loop) {
-#ifndef __ANDROID__
+#if !defined(__ANDROID__) && !defined(__QNX__)
read_fds.reserve(loop.m_read_fds.size());
#endif
}
@@ -129,7 +138,7 @@ sigset_t MainLoopPosix::RunImpl::get_sigmask() {
return sigmask;
}
-#ifdef __ANDROID__
+#if defined(__ANDROID__) || defined(__QNX__)
Status MainLoopPosix::RunImpl::Poll() {
// ppoll(2) is not supported on older all android versions. Also, older
// versions android (API <= 19) implemented pselect in a non-atomic way, as a
@@ -144,6 +153,7 @@ Status MainLoopPosix::RunImpl::Poll() {
nfds = std::max(nfds, fd.first + 1);
}
+#if defined(__ANDROID__)
union {
sigset_t set;
uint64_t pad;
@@ -157,6 +167,11 @@ Status MainLoopPosix::RunImpl::Poll() {
} extra_data = {&kernel_sigset, sizeof(kernel_sigset)};
if (syscall(__NR_pselect6, nfds, &read_fd_set, nullptr, nullptr, nullptr,
&extra_data) == -1) {
+#else
+ // QNX.
+ sigset_t sigmask = get_sigmask();
+ if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == -1) {
+#endif
if (errno != EINTR)
return Status(errno, eErrorTypePOSIX);
else
@@ -188,7 +203,7 @@ Status MainLoopPosix::RunImpl::Poll() {
#endif
void MainLoopPosix::RunImpl::ProcessEvents() {
-#ifdef __ANDROID__
+#if defined(__ANDROID__) || defined(__QNX__)
// Collect first all readable file descriptors into a separate vector and
// then iterate over it to invoke callbacks. Iterating directly over
// loop.m_read_fds is not possible because the callbacks can modify the
@@ -213,14 +228,28 @@ void MainLoopPosix::RunImpl::ProcessEvents() {
std::vector<int> signals;
for (const auto &entry : loop.m_signals)
+#if defined(__QNX__)
+ if (g_signal_flags[entry.first] != 0) {
+ signals.push_back(entry.first);
+ *(entry.second.siginfo.get()) = g_signal_info.find(entry.first)->second;
+ }
+#else
if (g_signal_flags[entry.first] != 0)
signals.push_back(entry.first);
+#endif
for (const auto &signal : signals) {
if (loop.m_terminate_request)
return;
g_signal_flags[signal] = 0;
+#if defined(__QNX__)
+ g_signal_info.erase(signal);
+#endif
loop.ProcessSignal(signal);
+#if defined(__QNX__)
+ memset(loop.m_signals.find(signal)->second.siginfo.get(), 0,
+ sizeof(siginfo_t));
+#endif
}
}
#endif
@@ -282,7 +311,12 @@ MainLoopPosix::RegisterSignal(int signo, const Callback &callback,
if (signal_it != m_signals.end()) {
auto callback_it = signal_it->second.callbacks.insert(
signal_it->second.callbacks.end(), callback);
+#if defined(__QNX__)
+ std::weak_ptr<siginfo_t> siginfo = signal_it->second.siginfo;
+ return SignalHandleUP(new SignalHandle(*this, signo, callback_it, siginfo));
+#else
return SignalHandleUP(new SignalHandle(*this, signo, callback_it));
+#endif
}
SignalInfo info;
@@ -315,11 +349,21 @@ MainLoopPosix::RegisterSignal(int signo, const Callback &callback,
ret = pthread_sigmask(HAVE_SYS_EVENT_H ? SIG_UNBLOCK : SIG_BLOCK,
&new_action.sa_mask, &old_set);
assert(ret == 0 && "pthread_sigmask failed");
+#if defined(__QNX__)
+ info.siginfo = std::make_shared<siginfo_t>();
+#endif
info.was_blocked = sigismember(&old_set, signo);
auto insert_ret = m_signals.insert({signo, info});
+#if defined(__QNX__)
+ std::weak_ptr<siginfo_t> siginfo = info.siginfo;
+#endif
return SignalHandleUP(new SignalHandle(
+#if defined(__QNX__)
+ *this, signo, insert_ret.first->second.callbacks.begin(), siginfo));
+#else
*this, signo, insert_ret.first->second.callbacks.begin()));
+#endif
}
void MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) {
diff --git a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp
index 0a832ebad13a7..b539dedcb8bcf 100644
--- a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp
+++ b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp
@@ -17,7 +17,11 @@
#include "llvm/Support/Errno.h"
#include <climits>
+#if defined(__QNX__)
+#include <spawn.h>
+#else
#include <sys/ptrace.h>
+#endif
#include <sys/wait.h>
#include <unistd.h>
@@ -35,6 +39,10 @@
#include <sys/personality.h>
#endif
+#if !defined(EOK)
+#define EOK 0 /* No error */
+#endif
+
using namespace lldb;
using namespace lldb_private;
@@ -193,7 +201,9 @@ struct ForkLaunchInfo {
}
// Start tracing this child that is about to exec.
+#if !defined(__QNX__)
if (ptrace(PT_TRACE_ME, 0, nullptr, 0) == -1)
+#endif
ExitWithError(error_fd, "ptrace");
}
@@ -222,6 +232,148 @@ struct ForkLaunchInfo {
// End of code running in the child process.
+#if defined(__QNX__)
+static ::pid_t PosixSpawn(const ForkLaunchInfo &info,
+ posix_spawn_file_actions_t &file_actions,
+ posix_spawnattr_t &attr, Status &error) {
+ uint32_t flags = 0;
+ sigset_t set;
+ ::pid_t pid;
+ int ret;
+
+ if (info.separate_process_group) {
+ flags |= POSIX_SPAWN_SETPGROUP;
+ if (::posix_spawnattr_setpgroup(&attr, 0) != EOK) {
+ error.SetErrorStringWithFormatv("posix_spawnattr_setpgroup failed with "
+ "error message: {0}",
+ llvm::sys::StrError());
+ return LLDB_INVALID_PROCESS_ID;
+ }
+ }
+
+ for (const ForkFileAction &action : info.actions) {
+ switch (action.action) {
+ case FileAction::eFileActionClose:
+ if (::posix_spawn_file_actions_addclose(&file_actions, action.fd) !=
+ EOK) {
+ error.SetErrorStringWithFormatv("posix_spawn_file_actions_addclose "
+ "failed with error message: {0}",
+ llvm::sys::StrError());
+ return LLDB_INVALID_PROCESS_ID;
+ }
+ break;
+ case FileAction::eFileActionDuplicate:
+ if (::posix_spawn_file_actions_adddup2(&file_actions, action.fd,
+ action.arg) != EOK) {
+ error.SetErrorStringWithFormatv("posix_spawn_file_actions_adddup2 "
+ "failed with error message: {0}",
+ llvm::sys::StrError());
+ return LLDB_INVALID_PROCESS_ID;
+ }
+ break;
+ case FileAction::eFileActionOpen:
+ if (::posix_spawn_file_actions_addopen(&file_actions, action.fd,
+ action.path.c_str(), action.arg,
+ 0666) != EOK) {
+ error.SetErrorStringWithFormatv("posix_spawn_file_actions_addopen "
+ "failed with error message: {0}",
+ llvm::sys::StrError());
+ return LLDB_INVALID_PROCESS_ID;
+ }
+ break;
+ case FileAction::eFileActionNone:
+ break;
+ }
+ }
+
+ // Change the working directory.
+ if (!info.wd.empty()) {
+ flags |= POSIX_SPAWN_SETCWD;
+
+ int dirfd =
+ llvm::sys::RetryAfterSignal(-1, ::open, info.wd.c_str(), O_DIRECTORY);
+
+ if (dirfd == -1) {
+ error.SetErrorStringWithFormatv("open failed with error message: {0}",
+ llvm::sys::StrError());
+ return LLDB_INVALID_PROCESS_ID;
+ }
+
+ if (::posix_spawnattr_setcwd_np(&attr, dirfd) != EOK) {
+ error.SetErrorStringWithFormatv("posix_spawnattr_setcwd_np failed with "
+ "error message: {0}",
+ llvm::sys::StrError());
+ return LLDB_INVALID_PROCESS_ID;
+ }
+ }
+
+ if (info.disable_aslr) {
+ if (::posix_spawnattr_setaslr(&attr, POSIX_SPAWN_ASLR_DISABLE) != EOK) {
+ error.SetErrorStringWithFormatv("posix_spawnattr_setaslr failed with "
+ "error message: {0}",
+ llvm::sys::StrError());
+ return LLDB_INVALID_PROCESS_ID;
+ }
+ }
+
+ // Clear the signal mask to prevent the child from being affected by any
+ // masking done by the parent.
+ flags |= POSIX_SPAWN_SETSIGMASK;
+
+ if (sigemptyset(&set) != 0) {
+ error.SetErrorStringWithFormatv("sigemptyset failed with error message: "
+ "{0}",
+ llvm::sys::StrError());
+ return LLDB_INVALID_PROCESS_ID;
+ }
+
+ if (::posix_spawnattr_setsigmask(&attr, &set) != EOK) {
+ error.SetErrorStringWithFormatv("posix_spawnattr_setsigmask failed with "
+ "error message: {0}",
+ llvm::sys::StrError());
+ return LLDB_INVALID_PROCESS_ID;
+ }
+
+ if (info.debug) {
+ // Hold the child process as if it had received a SIGSTOP as soon as it was
+ // spawned.
+ flags |= POSIX_SPAWN_HOLD;
+
+ // Do not inherit setgid powers.
+ flags |= POSIX_SPAWN_RESETIDS;
+
+ // posix_spawn returns EBADF when requested to close all open file
+ // descriptors other than STDIN, STDOUT, and STDERR.
+ // TODO: Close everything besides STDIN, STDOUT, and STDERR that doesn't
+ // have any file action to avoid leaking descriptors.
+ }
+
+ if (::posix_spawnattr_setxflags(&attr, flags) != EOK) {
+ error.SetErrorStringWithFormatv("posix_spawnattr_setxflags failed with "
+ "error message: {0}",
+ llvm::sys::StrError());
+ return LLDB_INVALID_PROCESS_ID;
+ }
+
+ ret = ::posix_spawn(&pid, info.argv[0], &file_actions, &attr,
+ const_cast<char *const *>(info.argv), info.envp);
+
+ if (ret != EOK) {
+ // posix_spawn failed.
+ error.SetErrorStringWithFormatv("posix_spawn failed with error message: "
+ "{0}",
+ llvm::sys::StrError());
+ return LLDB_INVALID_PROCESS_ID;
+ }
+
+ // If an error occurs after posix_spawn returns successfully, then the child
+ // process exits with status 127.
+ // TODO: Wait for the child process if it exits on account of any error.
+
+ return pid; // No error. We're done.
+}
+#endif
+
Fo...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/97630
More information about the lldb-commits
mailing list