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.SetParentProcessID(proc_kinfo.p_ppid);
107 process_info.SetUserID(proc_kinfo.p_ruid);
108 process_info.SetGroupID(proc_kinfo.p_rgid);
109 process_info.SetEffectiveUserID(proc_kinfo.p_uid);
110 process_info.SetEffectiveGroupID(proc_kinfo.p_gid);
111 return true;
112 }
113 }
114 }
116 process_info.SetUserID(UINT32_MAX);
117 process_info.SetGroupID(UINT32_MAX);
118 process_info.SetEffectiveUserID(UINT32_MAX);
119 process_info.SetEffectiveGroupID(UINT32_MAX);
120 return false;
121}
122
123uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info,
124 ProcessInstanceInfoList &process_infos) {
125 std::vector<struct kinfo_proc> kinfos;
126
127 int mib[6] = {
128 CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), 0};
129
130 size_t pid_data_size = 0;
131 if (::sysctl(mib, 6, NULL, &pid_data_size, NULL, 0) != 0)
132 return 0;
133
134 // Add a few extra in case a few more show up
135 const size_t estimated_pid_count =
136 (pid_data_size / sizeof(struct kinfo_proc)) + 10;
137
138 kinfos.resize(estimated_pid_count);
139 mib[5] = estimated_pid_count;
140 pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);
141
142 if (::sysctl(mib, 6, &kinfos[0], &pid_data_size, NULL, 0) != 0)
143 return 0;
144
145 const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));
146
147 bool all_users = match_info.GetMatchAllUsers();
148 const ::pid_t our_pid = getpid();
149 const uid_t our_uid = getuid();
150 for (size_t i = 0; i < actual_pid_count; i++) {
151 const struct kinfo_proc &kinfo = kinfos[i];
152 const bool kinfo_user_matches = (all_users || (kinfo.p_ruid == our_uid) ||
153 // Special case, if lldb is being run as
154 // root we can attach to anything.
155 (our_uid == 0));
156
157 if (kinfo_user_matches == false || // Make sure the user is acceptable
158 kinfo.p_pid == our_pid || // Skip this process
159 kinfo.p_pid == 0 || // Skip kernel (kernel pid is zero)
160 kinfo.p_stat == SZOMB || // Zombies are bad, they like brains...
161 kinfo.p_psflags & PS_TRACED || // Being debugged?
162 kinfo.p_flag & P_WEXIT) // Working on exiting
163 continue;
164
165 ProcessInstanceInfo process_info;
166 process_info.SetProcessID(kinfo.p_pid);
167 process_info.SetParentProcessID(kinfo.p_ppid);
168 process_info.SetUserID(kinfo.p_ruid);
169 process_info.SetGroupID(kinfo.p_rgid);
170 process_info.SetEffectiveUserID(kinfo.p_svuid);
171 process_info.SetEffectiveGroupID(kinfo.p_svgid);
172
173 // Make sure our info matches before we go fetch the name and cpu type
174 if (match_info.Matches(process_info) &&
175 GetOpenBSDProcessArgs(&match_info, process_info)) {
176 GetOpenBSDProcessCPUType(process_info);
177 if (match_info.Matches(process_info))
178 process_infos.push_back(process_info);
179 }
180 }
181
182 return process_infos.size();
183}
184
185bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
186 process_info.SetProcessID(pid);
187
188 if (GetOpenBSDProcessArgs(NULL, process_info)) {
189 // should use libprocstat instead of going right into sysctl?
190 GetOpenBSDProcessCPUType(process_info);
191 GetOpenBSDProcessUserAndGroup(process_info);
192 return true;
193 }
194
195 process_info.Clear();
196 return false;
197}
198
199Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info,
200 const Timeout<std::micro> &timeout) {
201 return Status::FromErrorString("unimplemented");
202}
void Clear()
Clears the object state.
Definition ArchSpec.cpp:735
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
ProcessInstanceInfo & GetProcessInfo()
void SetEffectiveGroupID(uint32_t gid)
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)