From bdeee0d0397c5843aef0f7c254de934076edce2e Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Wed, 21 Oct 2026 06:29:40 -0400 Subject: [PATCH] [lldb][OpenBSD] Fix sysctl usage for process info (#122534) The OpenBSD Host code used FreeBSD-style sysctl MIBs, which don't match OpenBSD's interface, so process lookups failed. - GetOpenBSDProcessArgs: use {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV}. OpenBSD returns a NULL-terminated argv array whose pointers point into the returned buffer, so iterate it directly. - GetOpenBSDProcessUserAndGroup, FindProcessesImpl: KERN_PROC takes a 6-element MIB on OpenBSD, with the kinfo_proc element size and element count as the last two entries. (cherry picked from commit b880f44cbad751b0784a5fbbfbdaacea25e167f8) --- lldb/source/Host/openbsd/Host.cpp | 95 +++++++++++++++---------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/lldb/source/Host/openbsd/Host.cpp b/lldb/source/Host/openbsd/Host.cpp index 2b66a3c8696b..586d76de3a06 100644 --- a/lldb/source/Host/openbsd/Host.cpp +++ b/lldb/source/Host/openbsd/Host.cpp @@ -16,18 +16,18 @@ #include #include +#include #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/DataExtractor.h" -#include "lldb/Utility/Endian.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/NameMatches.h" #include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/TargetParser/Host.h" using namespace lldb; @@ -40,49 +40,46 @@ class ProcessLaunchInfo; static bool GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, ProcessInstanceInfo &process_info) { - if (process_info.ProcessIDIsValid()) { - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS, - (int)process_info.GetProcessID()}; + if (!process_info.ProcessIDIsValid()) + return false; - char arg_data[8192]; - size_t arg_data_size = sizeof(arg_data); - if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) == 0) { - DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(), - sizeof(void *)); - lldb::offset_t offset = 0; - const char *cstr; + int pid = process_info.GetProcessID(); - cstr = data.GetCStr(&offset); - if (cstr) { - process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native); + int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV}; + size_t kern_proc_args_size = 0; - if (!(match_info_ptr == NULL || - NameMatches( - process_info.GetExecutableFile().GetFilename().GetCString(), - match_info_ptr->GetNameMatchType(), - match_info_ptr->GetProcessInfo().GetName()))) - return false; + // On OpenBSD, this will just fill ARG_MAX all the time + if (::sysctl(mib, 4, NULL, &kern_proc_args_size, NULL, 0) == -1) + return false; - Args &proc_args = process_info.GetArguments(); - while (1) { - const uint8_t *p = data.PeekData(offset, 1); - while ((p != NULL) && (*p == '\0') && offset < arg_data_size) { - ++offset; - p = data.PeekData(offset, 1); - } - if (p == NULL || offset >= arg_data_size) - return true; + void *arg_data = ::malloc(kern_proc_args_size); + if (!arg_data) + return false; + auto free_arg_data = llvm::scope_exit([&] { ::free(arg_data); }); - cstr = data.GetCStr(&offset); - if (cstr) - proc_args.AppendArgument(llvm::StringRef(cstr)); - else - return true; - } - } - } + if (::sysctl(mib, 4, arg_data, &kern_proc_args_size, NULL, 0) == -1) + return false; + + // arg_data is a NULL terminated list of pointers, where the pointers + // point within arg_data to the location of the arg string + char **argv = static_cast(arg_data); + if (!argv[0]) + return false; + + process_info.GetExecutableFile().SetFile(argv[0], FileSpec::Style::native); + + if (match_info_ptr != NULL && + !NameMatches(process_info.GetExecutableFile().GetFilename(), + match_info_ptr->GetNameMatchType(), + match_info_ptr->GetProcessInfo().GetName())) { + return false; } - return false; + + Args &proc_args = process_info.GetArguments(); + for (char **arg = argv + 1; *arg != NULL; ++arg) + proc_args.AppendArgument(*arg); + + return true; } static bool GetOpenBSDProcessCPUType(ProcessInstanceInfo &process_info) { @@ -96,15 +93,15 @@ static bool GetOpenBSDProcessCPUType(ProcessInstanceInfo &process_info) { } static bool GetOpenBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) { - struct kinfo_proc proc_kinfo; - size_t proc_kinfo_size; if (process_info.ProcessIDIsValid()) { - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, - (int)process_info.GetProcessID()}; - proc_kinfo_size = sizeof(struct kinfo_proc); + struct kinfo_proc proc_kinfo = {}; + size_t proc_kinfo_size = sizeof(proc_kinfo); + int mib[6] = {CTL_KERN, KERN_PROC, + KERN_PROC_PID, (int)process_info.GetProcessID(), + sizeof(proc_kinfo), 1}; - if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) { + if (::sysctl(mib, 6, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) { if (proc_kinfo_size > 0) { process_info.SetParentProcessID(proc_kinfo.p_ppid); process_info.SetUserID(proc_kinfo.p_ruid); @@ -127,10 +124,11 @@ uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) { std::vector kinfos; - int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; + int mib[6] = { + CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), 0}; size_t pid_data_size = 0; - if (::sysctl(mib, 3, NULL, &pid_data_size, NULL, 0) != 0) + if (::sysctl(mib, 6, NULL, &pid_data_size, NULL, 0) != 0) return 0; // Add a few extra in case a few more show up @@ -138,9 +136,10 @@ uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info, (pid_data_size / sizeof(struct kinfo_proc)) + 10; kinfos.resize(estimated_pid_count); + mib[5] = estimated_pid_count; pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); - if (::sysctl(mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0) + if (::sysctl(mib, 6, &kinfos[0], &pid_data_size, NULL, 0) != 0) return 0; const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));