[Lldb-commits] [lldb] [lldb] Add native process support for OpenBSD (PR #236288)

Brad Smith via lldb-commits lldb-commits at lists.llvm.org
Mon Nov 2 16:52:42 PST 2026


================
@@ -0,0 +1,723 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "NativeProcessOpenBSD.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#define _DYN_LOADER
+#include <elf.h>
+#include <util.h>
+
+#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/common/NativeRegisterContext.h"
+#include "lldb/Host/posix/ProcessLauncherPosixFork.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/State.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Errno.h"
+
+#include <cstring>
+
+// System includes - They have to be included after framework includes because
+// they define some macros which collide with variable names in other modules
+// clang-format off
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+#include <unistd.h>
+// clang-format on
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_openbsd;
+using namespace llvm;
+
+// Simple helper function to ensure flags are enabled on the given file
+// descriptor.
+static Status EnsureFDFlags(int fd, int flags) {
+  int status = fcntl(fd, F_GETFL);
+  if (status == -1)
+    return Status::FromErrno();
+
+  if (fcntl(fd, F_SETFL, status | flags) == -1)
+    return Status::FromErrno();
+
+  return Status();
+}
+
+// No architecture has a register context yet.
+static llvm::Error CheckArchitectureSupported() {
+  return llvm::createStringError(
+      "debugging is not supported on this architecture");
+}
+
+// Whether kern.global_ptrace allows attaching to processes that are not
+// children of the debugger.
+static bool IsGlobalPtraceEnabled() {
+  int mib[2] = {CTL_KERN, KERN_GLOBAL_PTRACE};
+  int value = 0;
+  size_t len = sizeof(value);
+  return ::sysctl(mib, 2, &value, &len, nullptr, 0) == 0 && value != 0;
+}
+
+// Public Static Methods
+
+llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
+NativeProcessOpenBSD::Manager::Launch(ProcessLaunchInfo &launch_info,
+                                      NativeDelegate &native_delegate) {
+  Log *log = GetLog(POSIXLog::Process);
+
+  if (llvm::Error error = CheckArchitectureSupported())
+    return std::move(error);
+
+  Status status;
+  ::pid_t pid = ProcessLauncherPosixFork()
+                    .LaunchProcess(launch_info, status)
+                    .GetProcessId();
+  LLDB_LOG(log, "pid = {0:x}", pid);
+  if (status.Fail()) {
+    LLDB_LOG(log, "failed to launch process: {0}", status);
+    return status.ToError();
+  }
+
+  // Wait for the child process to trap on its call to execve.
+  int wstatus;
+  ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
+  assert(wpid == pid);
+  UNUSED_IF_ASSERT_DISABLED(wpid);
+  if (!WIFSTOPPED(wstatus)) {
+    LLDB_LOG(log, "Could not sync with inferior process: wstatus={0}",
+             WaitStatus::Decode(wstatus));
+    return llvm::createStringError("could not sync with inferior process");
+  }
+  LLDB_LOG(log, "inferior started, now in stopped state");
+
+  ProcessInstanceInfo Info;
+  if (!Host::GetProcessInfo(pid, Info)) {
+    return llvm::createStringError("cannot get process architecture");
+  }
+
+  // Set the architecture to the exe architecture.
+  LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
+           Info.GetArchitecture().GetArchitectureName());
+
+  std::unique_ptr<NativeProcessOpenBSD> process_up(new NativeProcessOpenBSD(
+      pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
+      Info.GetArchitecture(), m_mainloop));
+
+  status = process_up->RefreshThreads();
+  if (status.Fail())
+    return status.ToError();
+
+  process_up->m_trapped_tid = process_up->GetTrappedThreadID();
+  for (const auto &thread : process_up->m_threads)
+    static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
+  process_up->SetState(StateType::eStateStopped, false);
+
+  return std::move(process_up);
+}
+
+llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
+NativeProcessOpenBSD::Manager::Attach(
+    lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate) {
+
+  Log *log = GetLog(POSIXLog::Process);
+  LLDB_LOG(log, "pid = {0:x}", pid);
+
+  if (llvm::Error error = CheckArchitectureSupported())
+    return std::move(error);
+
+  // Retrieve the architecture for the running process.
+  ProcessInstanceInfo Info;
+  if (!Host::GetProcessInfo(pid, Info)) {
+    return llvm::createStringError("cannot get process architecture");
+  }
+
+  std::unique_ptr<NativeProcessOpenBSD> process_up(new NativeProcessOpenBSD(
+      pid, -1, native_delegate, Info.GetArchitecture(), m_mainloop));
+
+  Status status = process_up->Attach();
+  if (!status.Success())
+    return status.ToError();
+
+  return std::move(process_up);
+}
+
+NativeProcessOpenBSD::Extension
+NativeProcessOpenBSD::Manager::GetSupportedExtensions() const {
+  Extension supported =
+      Extension::pass_signals | Extension::auxv | Extension::libraries_svr4;
----------------
brad0 wrote:

> So if I'm understanding correctly, OpenBSD only supports limited set of extensions compared to FreeBSD?

Yes, it’s a subset, but only part of that is permanent.

- pass_signals, auxv and libraries_svr4 match FreeBSD.
- fork and multiprocess are coming in the follow-up change (fork following + memory regions). OpenBSD does report fork through PT_SET_EVENT_MASK/PTRACE_FORK, and that patch advertises both. I left them out of this PR to keep the core small.
- vfork is not possible. PTRACE_FORK is the only event OpenBSD has; there’s no vfork, exec or thread event.
- siginfo_read is not possible. FreeBSD gets the siginfo from PT_LWPINFO, and OpenBSD has no ptrace request that returns a traced process’s siginfo.
- savecore is not possible. OpenBSD has nothing like FreeBSD’s PT_COREDUMP.

https://github.com/llvm/llvm-project/pull/236288


More information about the lldb-commits mailing list