1 //===-- source/Host/openbsd/Host.cpp --------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
11 #include <sys/signal.h>
14 #include <sys/ptrace.h>
15 #include <sys/sysctl.h>
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"
31 #include "llvm/TargetParser/Host.h"
34 extern char **environ
;
38 using namespace lldb_private
;
40 namespace lldb_private
{
41 class ProcessLaunchInfo
;
44 Environment
Host::GetEnvironment() {
48 for (; var
!= NULL
&& *var
!= NULL
; ++var
) {
49 v
= strchr(*var
, (int)'-');
58 GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch
*match_info_ptr
,
59 ProcessInstanceInfo
&process_info
) {
60 if (process_info
.ProcessIDIsValid()) {
61 int mib
[4] = {CTL_KERN
, KERN_PROC
, KERN_PROC_ARGS
,
62 (int)process_info
.GetProcessID()};
65 size_t arg_data_size
= sizeof(arg_data
);
66 if (::sysctl(mib
, 4, arg_data
, &arg_data_size
, NULL
, 0) == 0) {
67 DataExtractor
data(arg_data
, arg_data_size
, endian::InlHostByteOrder(),
69 lldb::offset_t offset
= 0;
72 cstr
= data
.GetCStr(&offset
);
74 process_info
.GetExecutableFile().SetFile(cstr
, FileSpec::Style::native
);
76 if (!(match_info_ptr
== NULL
||
78 process_info
.GetExecutableFile().GetFilename().GetCString(),
79 match_info_ptr
->GetNameMatchType(),
80 match_info_ptr
->GetProcessInfo().GetName())))
83 Args
&proc_args
= process_info
.GetArguments();
85 const uint8_t *p
= data
.PeekData(offset
, 1);
86 while ((p
!= NULL
) && (*p
== '\0') && offset
< arg_data_size
) {
88 p
= data
.PeekData(offset
, 1);
90 if (p
== NULL
|| offset
>= arg_data_size
)
93 cstr
= data
.GetCStr(&offset
);
95 proc_args
.AppendArgument(llvm::StringRef(cstr
));
105 static bool GetOpenBSDProcessCPUType(ProcessInstanceInfo
&process_info
) {
106 if (process_info
.ProcessIDIsValid()) {
107 process_info
.GetArchitecture() =
108 HostInfo::GetArchitecture(HostInfo::eArchKindDefault
);
111 process_info
.GetArchitecture().Clear();
115 static bool GetOpenBSDProcessUserAndGroup(ProcessInstanceInfo
&process_info
) {
116 struct kinfo_proc proc_kinfo
;
117 size_t proc_kinfo_size
;
119 if (process_info
.ProcessIDIsValid()) {
120 int mib
[4] = {CTL_KERN
, KERN_PROC
, KERN_PROC_PID
,
121 (int)process_info
.GetProcessID()};
122 proc_kinfo_size
= sizeof(struct kinfo_proc
);
124 if (::sysctl(mib
, 4, &proc_kinfo
, &proc_kinfo_size
, NULL
, 0) == 0) {
125 if (proc_kinfo_size
> 0) {
126 process_info
.SetParentProcessID(proc_kinfo
.p_ppid
);
127 process_info
.SetUserID(proc_kinfo
.p_ruid
);
128 process_info
.SetGroupID(proc_kinfo
.p_rgid
);
129 process_info
.SetEffectiveUserID(proc_kinfo
.p_uid
);
130 process_info
.SetEffectiveGroupID(proc_kinfo
.p_gid
);
135 process_info
.SetParentProcessID(LLDB_INVALID_PROCESS_ID
);
136 process_info
.SetUserID(UINT32_MAX
);
137 process_info
.SetGroupID(UINT32_MAX
);
138 process_info
.SetEffectiveUserID(UINT32_MAX
);
139 process_info
.SetEffectiveGroupID(UINT32_MAX
);
143 uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch
&match_info
,
144 ProcessInstanceInfoList
&process_infos
) {
145 std::vector
<struct kinfo_proc
> kinfos
;
147 int mib
[3] = {CTL_KERN
, KERN_PROC
, KERN_PROC_ALL
};
149 size_t pid_data_size
= 0;
150 if (::sysctl(mib
, 3, NULL
, &pid_data_size
, NULL
, 0) != 0)
153 // Add a few extra in case a few more show up
154 const size_t estimated_pid_count
=
155 (pid_data_size
/ sizeof(struct kinfo_proc
)) + 10;
157 kinfos
.resize(estimated_pid_count
);
158 pid_data_size
= kinfos
.size() * sizeof(struct kinfo_proc
);
160 if (::sysctl(mib
, 3, &kinfos
[0], &pid_data_size
, NULL
, 0) != 0)
163 const size_t actual_pid_count
= (pid_data_size
/ sizeof(struct kinfo_proc
));
165 bool all_users
= match_info
.GetMatchAllUsers();
166 const ::pid_t our_pid
= getpid();
167 const uid_t our_uid
= getuid();
168 for (size_t i
= 0; i
< actual_pid_count
; i
++) {
169 const struct kinfo_proc
&kinfo
= kinfos
[i
];
170 const bool kinfo_user_matches
= (all_users
|| (kinfo
.p_ruid
== our_uid
) ||
171 // Special case, if lldb is being run as
172 // root we can attach to anything.
175 if (kinfo_user_matches
== false || // Make sure the user is acceptable
176 kinfo
.p_pid
== our_pid
|| // Skip this process
177 kinfo
.p_pid
== 0 || // Skip kernel (kernel pid is zero)
178 kinfo
.p_stat
== SZOMB
|| // Zombies are bad, they like brains...
179 kinfo
.p_psflags
& PS_TRACED
|| // Being debugged?
180 kinfo
.p_flag
& P_WEXIT
) // Working on exiting
183 ProcessInstanceInfo process_info
;
184 process_info
.SetProcessID(kinfo
.p_pid
);
185 process_info
.SetParentProcessID(kinfo
.p_ppid
);
186 process_info
.SetUserID(kinfo
.p_ruid
);
187 process_info
.SetGroupID(kinfo
.p_rgid
);
188 process_info
.SetEffectiveUserID(kinfo
.p_svuid
);
189 process_info
.SetEffectiveGroupID(kinfo
.p_svgid
);
191 // Make sure our info matches before we go fetch the name and cpu type
192 if (match_info
.Matches(process_info
) &&
193 GetOpenBSDProcessArgs(&match_info
, process_info
)) {
194 GetOpenBSDProcessCPUType(process_info
);
195 if (match_info
.Matches(process_info
))
196 process_infos
.push_back(process_info
);
200 return process_infos
.size();
203 bool Host::GetProcessInfo(lldb::pid_t pid
, ProcessInstanceInfo
&process_info
) {
204 process_info
.SetProcessID(pid
);
206 if (GetOpenBSDProcessArgs(NULL
, process_info
)) {
207 // should use libprocstat instead of going right into sysctl?
208 GetOpenBSDProcessCPUType(process_info
);
209 GetOpenBSDProcessUserAndGroup(process_info
);
213 process_info
.Clear();
217 Status
Host::ShellExpandArguments(ProcessLaunchInfo
&launch_info
) {
218 return Status("unimplemented");