203 lines · cpp
1//===-- source/Host/openbsd/Host.cpp --------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include <sys/types.h>10 11#include <sys/signal.h>12#include <sys/exec.h>13#include <sys/proc.h>14#include <sys/ptrace.h>15#include <sys/sysctl.h>16#include <sys/user.h>17 18#include <cstdio>19 20#include "lldb/Host/Host.h"21#include "lldb/Host/HostInfo.h"22#include "lldb/Utility/DataBufferHeap.h"23#include "lldb/Utility/DataExtractor.h"24#include "lldb/Utility/Endian.h"25#include "lldb/Utility/Log.h"26#include "lldb/Utility/NameMatches.h"27#include "lldb/Utility/ProcessInfo.h"28#include "lldb/Utility/Status.h"29#include "lldb/Utility/StreamString.h"30 31#include "llvm/TargetParser/Host.h"32 33using namespace lldb;34using namespace lldb_private;35 36namespace lldb_private {37class ProcessLaunchInfo;38}39 40static bool41GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,42 ProcessInstanceInfo &process_info) {43 if (process_info.ProcessIDIsValid()) {44 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS,45 (int)process_info.GetProcessID()};46 47 char arg_data[8192];48 size_t arg_data_size = sizeof(arg_data);49 if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) == 0) {50 DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(),51 sizeof(void *));52 lldb::offset_t offset = 0;53 const char *cstr;54 55 cstr = data.GetCStr(&offset);56 if (cstr) {57 process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native);58 59 if (!(match_info_ptr == NULL ||60 NameMatches(61 process_info.GetExecutableFile().GetFilename().GetCString(),62 match_info_ptr->GetNameMatchType(),63 match_info_ptr->GetProcessInfo().GetName())))64 return false;65 66 Args &proc_args = process_info.GetArguments();67 while (1) {68 const uint8_t *p = data.PeekData(offset, 1);69 while ((p != NULL) && (*p == '\0') && offset < arg_data_size) {70 ++offset;71 p = data.PeekData(offset, 1);72 }73 if (p == NULL || offset >= arg_data_size)74 return true;75 76 cstr = data.GetCStr(&offset);77 if (cstr)78 proc_args.AppendArgument(llvm::StringRef(cstr));79 else80 return true;81 }82 }83 }84 }85 return false;86}87 88static bool GetOpenBSDProcessCPUType(ProcessInstanceInfo &process_info) {89 if (process_info.ProcessIDIsValid()) {90 process_info.GetArchitecture() =91 HostInfo::GetArchitecture(HostInfo::eArchKindDefault);92 return true;93 }94 process_info.GetArchitecture().Clear();95 return false;96}97 98static bool GetOpenBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) {99 struct kinfo_proc proc_kinfo;100 size_t proc_kinfo_size;101 102 if (process_info.ProcessIDIsValid()) {103 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID,104 (int)process_info.GetProcessID()};105 proc_kinfo_size = sizeof(struct kinfo_proc);106 107 if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {108 if (proc_kinfo_size > 0) {109 process_info.SetParentProcessID(proc_kinfo.p_ppid);110 process_info.SetUserID(proc_kinfo.p_ruid);111 process_info.SetGroupID(proc_kinfo.p_rgid);112 process_info.SetEffectiveUserID(proc_kinfo.p_uid);113 process_info.SetEffectiveGroupID(proc_kinfo.p_gid);114 return true;115 }116 }117 }118 process_info.SetParentProcessID(LLDB_INVALID_PROCESS_ID);119 process_info.SetUserID(UINT32_MAX);120 process_info.SetGroupID(UINT32_MAX);121 process_info.SetEffectiveUserID(UINT32_MAX);122 process_info.SetEffectiveGroupID(UINT32_MAX);123 return false;124}125 126uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info,127 ProcessInstanceInfoList &process_infos) {128 std::vector<struct kinfo_proc> kinfos;129 130 int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};131 132 size_t pid_data_size = 0;133 if (::sysctl(mib, 3, NULL, &pid_data_size, NULL, 0) != 0)134 return 0;135 136 // Add a few extra in case a few more show up137 const size_t estimated_pid_count =138 (pid_data_size / sizeof(struct kinfo_proc)) + 10;139 140 kinfos.resize(estimated_pid_count);141 pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);142 143 if (::sysctl(mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0)144 return 0;145 146 const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));147 148 bool all_users = match_info.GetMatchAllUsers();149 const ::pid_t our_pid = getpid();150 const uid_t our_uid = getuid();151 for (size_t i = 0; i < actual_pid_count; i++) {152 const struct kinfo_proc &kinfo = kinfos[i];153 const bool kinfo_user_matches = (all_users || (kinfo.p_ruid == our_uid) ||154 // Special case, if lldb is being run as155 // root we can attach to anything.156 (our_uid == 0));157 158 if (kinfo_user_matches == false || // Make sure the user is acceptable159 kinfo.p_pid == our_pid || // Skip this process160 kinfo.p_pid == 0 || // Skip kernel (kernel pid is zero)161 kinfo.p_stat == SZOMB || // Zombies are bad, they like brains...162 kinfo.p_psflags & PS_TRACED || // Being debugged?163 kinfo.p_flag & P_WEXIT) // Working on exiting164 continue;165 166 ProcessInstanceInfo process_info;167 process_info.SetProcessID(kinfo.p_pid);168 process_info.SetParentProcessID(kinfo.p_ppid);169 process_info.SetUserID(kinfo.p_ruid);170 process_info.SetGroupID(kinfo.p_rgid);171 process_info.SetEffectiveUserID(kinfo.p_svuid);172 process_info.SetEffectiveGroupID(kinfo.p_svgid);173 174 // Make sure our info matches before we go fetch the name and cpu type175 if (match_info.Matches(process_info) &&176 GetOpenBSDProcessArgs(&match_info, process_info)) {177 GetOpenBSDProcessCPUType(process_info);178 if (match_info.Matches(process_info))179 process_infos.push_back(process_info);180 }181 }182 183 return process_infos.size();184}185 186bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {187 process_info.SetProcessID(pid);188 189 if (GetOpenBSDProcessArgs(NULL, process_info)) {190 // should use libprocstat instead of going right into sysctl?191 GetOpenBSDProcessCPUType(process_info);192 GetOpenBSDProcessUserAndGroup(process_info);193 return true;194 }195 196 process_info.Clear();197 return false;198}199 200Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {201 return Status::FromErrorString("unimplemented");202}203