Path: blob/main/contrib/llvm-project/lldb/source/Host/openbsd/Host.cpp
39606 views
//===-- source/Host/openbsd/Host.cpp --------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include <sys/types.h>910#include <sys/signal.h>11#include <sys/exec.h>12#include <sys/proc.h>13#include <sys/ptrace.h>14#include <sys/sysctl.h>15#include <sys/user.h>1617#include <cstdio>1819#include "lldb/Host/Host.h"20#include "lldb/Host/HostInfo.h"21#include "lldb/Utility/DataBufferHeap.h"22#include "lldb/Utility/DataExtractor.h"23#include "lldb/Utility/Endian.h"24#include "lldb/Utility/Log.h"25#include "lldb/Utility/NameMatches.h"26#include "lldb/Utility/ProcessInfo.h"27#include "lldb/Utility/Status.h"28#include "lldb/Utility/StreamString.h"2930#include "llvm/TargetParser/Host.h"3132extern "C" {33extern char **environ;34}3536using namespace lldb;37using namespace lldb_private;3839namespace lldb_private {40class ProcessLaunchInfo;41}4243Environment Host::GetEnvironment() {44Environment env;45char *v;46char **var = environ;47for (; var != NULL && *var != NULL; ++var) {48v = strchr(*var, (int)'-');49if (v == NULL)50continue;51env.insert(v);52}53return env;54}5556static bool57GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,58ProcessInstanceInfo &process_info) {59if (process_info.ProcessIDIsValid()) {60int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS,61(int)process_info.GetProcessID()};6263char arg_data[8192];64size_t arg_data_size = sizeof(arg_data);65if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) == 0) {66DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(),67sizeof(void *));68lldb::offset_t offset = 0;69const char *cstr;7071cstr = data.GetCStr(&offset);72if (cstr) {73process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native);7475if (!(match_info_ptr == NULL ||76NameMatches(77process_info.GetExecutableFile().GetFilename().GetCString(),78match_info_ptr->GetNameMatchType(),79match_info_ptr->GetProcessInfo().GetName())))80return false;8182Args &proc_args = process_info.GetArguments();83while (1) {84const uint8_t *p = data.PeekData(offset, 1);85while ((p != NULL) && (*p == '\0') && offset < arg_data_size) {86++offset;87p = data.PeekData(offset, 1);88}89if (p == NULL || offset >= arg_data_size)90return true;9192cstr = data.GetCStr(&offset);93if (cstr)94proc_args.AppendArgument(llvm::StringRef(cstr));95else96return true;97}98}99}100}101return false;102}103104static bool GetOpenBSDProcessCPUType(ProcessInstanceInfo &process_info) {105if (process_info.ProcessIDIsValid()) {106process_info.GetArchitecture() =107HostInfo::GetArchitecture(HostInfo::eArchKindDefault);108return true;109}110process_info.GetArchitecture().Clear();111return false;112}113114static bool GetOpenBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) {115struct kinfo_proc proc_kinfo;116size_t proc_kinfo_size;117118if (process_info.ProcessIDIsValid()) {119int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID,120(int)process_info.GetProcessID()};121proc_kinfo_size = sizeof(struct kinfo_proc);122123if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {124if (proc_kinfo_size > 0) {125process_info.SetParentProcessID(proc_kinfo.p_ppid);126process_info.SetUserID(proc_kinfo.p_ruid);127process_info.SetGroupID(proc_kinfo.p_rgid);128process_info.SetEffectiveUserID(proc_kinfo.p_uid);129process_info.SetEffectiveGroupID(proc_kinfo.p_gid);130return true;131}132}133}134process_info.SetParentProcessID(LLDB_INVALID_PROCESS_ID);135process_info.SetUserID(UINT32_MAX);136process_info.SetGroupID(UINT32_MAX);137process_info.SetEffectiveUserID(UINT32_MAX);138process_info.SetEffectiveGroupID(UINT32_MAX);139return false;140}141142uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info,143ProcessInstanceInfoList &process_infos) {144std::vector<struct kinfo_proc> kinfos;145146int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};147148size_t pid_data_size = 0;149if (::sysctl(mib, 3, NULL, &pid_data_size, NULL, 0) != 0)150return 0;151152// Add a few extra in case a few more show up153const size_t estimated_pid_count =154(pid_data_size / sizeof(struct kinfo_proc)) + 10;155156kinfos.resize(estimated_pid_count);157pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);158159if (::sysctl(mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0)160return 0;161162const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));163164bool all_users = match_info.GetMatchAllUsers();165const ::pid_t our_pid = getpid();166const uid_t our_uid = getuid();167for (size_t i = 0; i < actual_pid_count; i++) {168const struct kinfo_proc &kinfo = kinfos[i];169const bool kinfo_user_matches = (all_users || (kinfo.p_ruid == our_uid) ||170// Special case, if lldb is being run as171// root we can attach to anything.172(our_uid == 0));173174if (kinfo_user_matches == false || // Make sure the user is acceptable175kinfo.p_pid == our_pid || // Skip this process176kinfo.p_pid == 0 || // Skip kernel (kernel pid is zero)177kinfo.p_stat == SZOMB || // Zombies are bad, they like brains...178kinfo.p_psflags & PS_TRACED || // Being debugged?179kinfo.p_flag & P_WEXIT) // Working on exiting180continue;181182ProcessInstanceInfo process_info;183process_info.SetProcessID(kinfo.p_pid);184process_info.SetParentProcessID(kinfo.p_ppid);185process_info.SetUserID(kinfo.p_ruid);186process_info.SetGroupID(kinfo.p_rgid);187process_info.SetEffectiveUserID(kinfo.p_svuid);188process_info.SetEffectiveGroupID(kinfo.p_svgid);189190// Make sure our info matches before we go fetch the name and cpu type191if (match_info.Matches(process_info) &&192GetOpenBSDProcessArgs(&match_info, process_info)) {193GetOpenBSDProcessCPUType(process_info);194if (match_info.Matches(process_info))195process_infos.push_back(process_info);196}197}198199return process_infos.size();200}201202bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {203process_info.SetProcessID(pid);204205if (GetOpenBSDProcessArgs(NULL, process_info)) {206// should use libprocstat instead of going right into sysctl?207GetOpenBSDProcessCPUType(process_info);208GetOpenBSDProcessUserAndGroup(process_info);209return true;210}211212process_info.Clear();213return false;214}215216Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {217return Status("unimplemented");218}219220221