LLDB mainline
openbsd/Host.cpp
Go to the documentation of this file.
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-exception
6//
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#include <cstdlib>
20
21#include "lldb/Host/Host.h"
22#include "lldb/Host/HostInfo.h"
24#include "lldb/Utility/Log.h"
27#include "lldb/Utility/Status.h"
29
30#include "llvm/ADT/ScopeExit.h"
31#include "llvm/TargetParser/Host.h"
32
33using namespace lldb;
34using namespace lldb_private;
35
36namespace lldb_private {
38}
39
40static bool
42 ProcessInstanceInfo &process_info) {
43 if (!process_info.ProcessIDIsValid())
44 return false;
45
46 int pid = process_info.GetProcessID();
47
48 int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV};
49 size_t kern_proc_args_size = 0;
50
51 // On OpenBSD, this will just fill ARG_MAX all the time
52 if (::sysctl(mib, 4, NULL, &kern_proc_args_size, NULL, 0) == -1)
53 return false;
54
55 void *arg_data = ::malloc(kern_proc_args_size);
56 if (!arg_data)
57 return false;
58 auto free_arg_data = llvm::scope_exit([&] { ::free(arg_data); });
59
60 if (::sysctl(mib, 4, arg_data, &kern_proc_args_size, NULL, 0) == -1)
61 return false;
62
63 // arg_data is a NULL terminated list of pointers, where the pointers
64 // point within arg_data to the location of the arg string
65 char **argv = static_cast<char **>(arg_data);
66 if (!argv[0])
67 return false;
68
69 process_info.GetExecutableFile().SetFile(argv[0], FileSpec::Style::native);
70
71 if (match_info_ptr != NULL &&
73 match_info_ptr->GetNameMatchType(),
74 match_info_ptr->GetProcessInfo().GetName())) {
75 return false;
76 }
77
78 Args &proc_args = process_info.GetArguments();
79 for (char **arg = argv + 1; *arg != NULL; ++arg)
80 proc_args.AppendArgument(*arg);
81
82 return true;
83}
84
86 if (process_info.ProcessIDIsValid()) {
87 process_info.GetArchitecture() =
88 HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
89 return true;
90 }
91 process_info.GetArchitecture().Clear();
92 return false;
93}
94
96
97 if (process_info.ProcessIDIsValid()) {
98 struct kinfo_proc proc_kinfo = {};
99 size_t proc_kinfo_size = sizeof(proc_kinfo);
100 int mib[6] = {CTL_KERN, KERN_PROC,
101 KERN_PROC_PID, (int)process_info.GetProcessID(),
102 sizeof(proc_kinfo), 1};
103
104 if (::sysctl(mib, 6, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {
105 if (proc_kinfo_size > 0) {
106 process_info.SetProcessGroupID(proc_kinfo.p__pgid);
107 process_info.SetProcessSessionID(proc_kinfo.p_sid);
108 process_info.SetParentProcessID(proc_kinfo.p_ppid);
109 process_info.SetUserID(proc_kinfo.p_ruid);
110 process_info.SetGroupID(proc_kinfo.p_rgid);
111 process_info.SetEffectiveUserID(proc_kinfo.p_uid);
112 process_info.SetEffectiveGroupID(proc_kinfo.p_gid);
113 return true;
114 }
115 }
116 }
120 process_info.SetUserID(UINT32_MAX);
121 process_info.SetGroupID(UINT32_MAX);
122 process_info.SetEffectiveUserID(UINT32_MAX);
123 process_info.SetEffectiveGroupID(UINT32_MAX);
124 return false;
125}
126
127uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info,
128 ProcessInstanceInfoList &process_infos) {
129 std::vector<struct kinfo_proc> kinfos;
130
131 // The name is only known after GetOpenBSDProcessArgs(), so leave it out of
132 // the first check.
133 ProcessInstanceInfoMatch match_info_noname{match_info};
134 match_info_noname.SetNameMatchType(NameMatch::Ignore);
135
136 int mib[6] = {
137 CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), 0};
138
139 size_t pid_data_size = 0;
140 if (::sysctl(mib, 6, NULL, &pid_data_size, NULL, 0) != 0)
141 return 0;
142
143 // Add a few extra in case a few more show up
144 const size_t estimated_pid_count =
145 (pid_data_size / sizeof(struct kinfo_proc)) + 10;
146
147 kinfos.resize(estimated_pid_count);
148 mib[5] = estimated_pid_count;
149 pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);
150
151 if (::sysctl(mib, 6, &kinfos[0], &pid_data_size, NULL, 0) != 0)
152 return 0;
153
154 const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));
155
156 bool all_users = match_info.GetMatchAllUsers();
157 const ::pid_t our_pid = getpid();
158 const uid_t our_uid = getuid();
159 for (size_t i = 0; i < actual_pid_count; i++) {
160 const struct kinfo_proc &kinfo = kinfos[i];
161 const bool kinfo_user_matches = (all_users || (kinfo.p_ruid == our_uid) ||
162 // Special case, if lldb is being run as
163 // root we can attach to anything.
164 (our_uid == 0));
165
166 if (kinfo_user_matches == false || // Make sure the user is acceptable
167 kinfo.p_pid == our_pid || // Skip this process
168 kinfo.p_pid == 0 || // Skip kernel (kernel pid is zero)
169 kinfo.p_stat == SZOMB || // Zombies are bad, they like brains...
170 kinfo.p_psflags & PS_TRACED || // Being debugged?
171 kinfo.p_flag & P_WEXIT) // Working on exiting
172 continue;
173
174 ProcessInstanceInfo process_info;
175 process_info.SetProcessID(kinfo.p_pid);
176 process_info.SetProcessGroupID(kinfo.p__pgid);
177 process_info.SetProcessSessionID(kinfo.p_sid);
178 process_info.SetParentProcessID(kinfo.p_ppid);
179 process_info.SetUserID(kinfo.p_ruid);
180 process_info.SetGroupID(kinfo.p_rgid);
181 process_info.SetEffectiveUserID(kinfo.p_svuid);
182 process_info.SetEffectiveGroupID(kinfo.p_svgid);
183
184 // Make sure our info matches before we go fetch the name and cpu type
185 if (match_info_noname.Matches(process_info) &&
186 GetOpenBSDProcessArgs(&match_info, process_info)) {
187 GetOpenBSDProcessCPUType(process_info);
188 if (match_info.Matches(process_info))
189 process_infos.push_back(process_info);
190 }
191 }
192
193 return process_infos.size();
194}
195
196bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
197 process_info.SetProcessID(pid);
198
199 if (GetOpenBSDProcessArgs(NULL, process_info)) {
200 GetOpenBSDProcessCPUType(process_info);
201 GetOpenBSDProcessUserAndGroup(process_info);
202 return true;
203 }
204
205 process_info.Clear();
206 return false;
207}
208
209Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info,
210 const Timeout<std::micro> &timeout) {
211 return Status::FromErrorString("unimplemented");
212}
void Clear()
Clears the object state.
Definition ArchSpec.cpp:558
A command line argument class.
Definition Args.h:33
void AppendArgument(llvm::StringRef arg_str, char quote_char='\0')
Appends a new argument to the end of the list argument list.
Definition Args.cpp:332
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
Definition FileSpec.cpp:174
llvm::StringRef GetFilename() const
Filename string const get accessor.
Definition FileSpec.h:248
static Status ShellExpandArguments(ProcessLaunchInfo &launch_info, const Timeout< std::micro > &timeout)
Perform expansion of the command-line for this launch info This can potentially involve wildcard expa...
Definition aix/Host.cpp:216
static uint32_t FindProcessesImpl(const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &proc_infos)
Definition aix/Host.cpp:169
static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info)
Definition aix/Host.cpp:211
void SetGroupID(uint32_t gid)
Definition ProcessInfo.h:58
bool ProcessIDIsValid() const
Definition ProcessInfo.h:70
lldb::pid_t GetProcessID() const
Definition ProcessInfo.h:66
void SetProcessID(lldb::pid_t pid)
Definition ProcessInfo.h:68
FileSpec & GetExecutableFile()
Definition ProcessInfo.h:41
llvm::StringRef GetName() const
void SetUserID(uint32_t uid)
Definition ProcessInfo.h:56
ArchSpec & GetArchitecture()
Definition ProcessInfo.h:60
bool Matches(const ProcessInstanceInfo &proc_info) const
void SetNameMatchType(NameMatch name_match_type)
ProcessInstanceInfo & GetProcessInfo()
void SetEffectiveGroupID(uint32_t gid)
void SetProcessGroupID(lldb::pid_t pgrp)
void SetProcessSessionID(lldb::pid_t session)
void SetParentProcessID(lldb::pid_t pid)
void SetEffectiveUserID(uint32_t uid)
static Status FromErrorString(const char *str)
Definition Status.h:141
#define UINT32_MAX
#define LLDB_INVALID_PROCESS_ID
A class that represents a running process on the host machine.
bool NameMatches(llvm::StringRef name, NameMatch match_type, llvm::StringRef match)
std::vector< ProcessInstanceInfo > ProcessInstanceInfoList
Definition Host.h:32
uint64_t pid_t
Definition lldb-types.h:84
static bool GetOpenBSDProcessUserAndGroup(ProcessInstanceInfo &process_info)
static bool GetOpenBSDProcessCPUType(ProcessInstanceInfo &process_info)
static bool GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, ProcessInstanceInfo &process_info)