LLDB  mainline
netbsd/Host.cpp
Go to the documentation of this file.
1 //===-- source/Host/netbsd/Host.cpp -----------------------------*- C++ -*-===//
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 <dlfcn.h>
10 #include <execinfo.h>
11 #include <stdio.h>
12 #include <sys/proc.h>
13 #include <sys/sysctl.h>
14 #include <sys/types.h>
15 
16 #include <limits.h>
17 
18 #include <elf.h>
19 #include <kvm.h>
20 #include <sys/exec.h>
21 #include <sys/ptrace.h>
22 
23 #include "lldb/Host/Host.h"
24 #include "lldb/Host/HostInfo.h"
27 #include "lldb/Utility/Endian.h"
28 #include "lldb/Utility/Log.h"
31 #include "lldb/Utility/Status.h"
33 
34 #include "llvm/Support/Host.h"
35 
36 extern "C" {
37 extern char **environ;
38 }
39 
40 using namespace lldb;
41 using namespace lldb_private;
42 
43 namespace lldb_private {
44 class ProcessLaunchInfo;
45 }
46 
47 Environment Host::GetEnvironment() { return Environment(environ); }
48 
49 static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
50  ProcessInstanceInfo &process_info) {
51  if (!process_info.ProcessIDIsValid())
52  return false;
53 
54  int pid = process_info.GetProcessID();
55 
56  int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV};
57 
58  char arg_data[8192];
59  size_t arg_data_size = sizeof(arg_data);
60  if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) != 0)
61  return false;
62 
63  DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(),
64  sizeof(void *));
65  lldb::offset_t offset = 0;
66  const char *cstr;
67 
68  cstr = data.GetCStr(&offset);
69  if (!cstr)
70  return false;
71 
72  process_info.GetExecutableFile().SetFile(cstr,
73  FileSpec::Style::native);
74 
75  if (!(match_info_ptr == NULL ||
77  match_info_ptr->GetNameMatchType(),
78  match_info_ptr->GetProcessInfo().GetName())))
79  return false;
80 
81  Args &proc_args = process_info.GetArguments();
82  while (1) {
83  const uint8_t *p = data.PeekData(offset, 1);
84  while ((p != NULL) && (*p == '\0') && offset < arg_data_size) {
85  ++offset;
86  p = data.PeekData(offset, 1);
87  }
88  if (p == NULL || offset >= arg_data_size)
89  break;
90 
91  cstr = data.GetCStr(&offset);
92  if (!cstr)
93  break;
94 
95  proc_args.AppendArgument(llvm::StringRef(cstr));
96  }
97 
98  return true;
99 }
100 
101 static bool GetNetBSDProcessCPUType(ProcessInstanceInfo &process_info) {
102  if (process_info.ProcessIDIsValid()) {
103  process_info.GetArchitecture() =
104  HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
105  return true;
106  }
107  process_info.GetArchitecture().Clear();
108  return false;
109 }
110 
112  ::kvm_t *kdp;
113  char errbuf[_POSIX2_LINE_MAX]; /* XXX: error string unused */
114 
115  struct ::kinfo_proc2 *proc_kinfo;
116  const int pid = process_info.GetProcessID();
117  int nproc;
118 
119  if (!process_info.ProcessIDIsValid())
120  goto error;
121 
122  if ((kdp = ::kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL)
123  goto error;
124 
125  if ((proc_kinfo = ::kvm_getproc2(kdp, KERN_PROC_PID, pid,
126  sizeof(struct ::kinfo_proc2), &nproc)) ==
127  NULL) {
128  ::kvm_close(kdp);
129  goto error;
130  }
131 
132  if (nproc < 1) {
133  ::kvm_close(kdp); /* XXX: we don't check for error here */
134  goto error;
135  }
136 
137  process_info.SetParentProcessID(proc_kinfo->p_ppid);
138  process_info.SetUserID(proc_kinfo->p_ruid);
139  process_info.SetGroupID(proc_kinfo->p_rgid);
140  process_info.SetEffectiveUserID(proc_kinfo->p_uid);
141  process_info.SetEffectiveGroupID(proc_kinfo->p_gid);
142 
143  ::kvm_close(kdp); /* XXX: we don't check for error here */
144 
145  return true;
146 
147 error:
149  process_info.SetUserID(UINT32_MAX);
150  process_info.SetGroupID(UINT32_MAX);
151  process_info.SetEffectiveUserID(UINT32_MAX);
152  process_info.SetEffectiveGroupID(UINT32_MAX);
153  return false;
154 }
155 
156 uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
157  ProcessInstanceInfoList &process_infos) {
158  const ::pid_t our_pid = ::getpid();
159  const ::uid_t our_uid = ::getuid();
160 
161  const bool all_users =
162  match_info.GetMatchAllUsers() ||
163  // Special case, if lldb is being run as root we can attach to anything
164  (our_uid == 0);
165 
166  kvm_t *kdp;
167  char errbuf[_POSIX2_LINE_MAX]; /* XXX: error string unused */
168  if ((kdp = ::kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL)
169  return 0;
170 
171  struct ::kinfo_proc2 *proc_kinfo;
172  int nproc;
173  if ((proc_kinfo = ::kvm_getproc2(kdp, KERN_PROC_ALL, 0,
174  sizeof(struct ::kinfo_proc2), &nproc)) ==
175  NULL) {
176  ::kvm_close(kdp);
177  return 0;
178  }
179 
180  for (int i = 0; i < nproc; i++) {
181  if (proc_kinfo[i].p_pid < 1)
182  continue; /* not valid */
183  /* Make sure the user is acceptable */
184  if (!all_users && proc_kinfo[i].p_ruid != our_uid)
185  continue;
186 
187  if (proc_kinfo[i].p_pid == our_pid || // Skip this process
188  proc_kinfo[i].p_pid == 0 || // Skip kernel (kernel pid is 0)
189  proc_kinfo[i].p_stat == LSZOMB || // Zombies are bad
190  proc_kinfo[i].p_flag & P_TRACED || // Being debugged?
191  proc_kinfo[i].p_flag & P_WEXIT) // Working on exiting
192  continue;
193 
194  // Every thread is a process in NetBSD, but all the threads of a single
195  // process have the same pid. Do not store the process info in the result
196  // list if a process with given identifier is already registered there.
197  if (proc_kinfo[i].p_nlwps > 1) {
198  bool already_registered = false;
199  for (size_t pi = 0; pi < process_infos.GetSize(); pi++) {
200  if (process_infos.GetProcessIDAtIndex(pi) == proc_kinfo[i].p_pid) {
201  already_registered = true;
202  break;
203  }
204  }
205 
206  if (already_registered)
207  continue;
208  }
209  ProcessInstanceInfo process_info;
210  process_info.SetProcessID(proc_kinfo[i].p_pid);
211  process_info.SetParentProcessID(proc_kinfo[i].p_ppid);
212  process_info.SetUserID(proc_kinfo[i].p_ruid);
213  process_info.SetGroupID(proc_kinfo[i].p_rgid);
214  process_info.SetEffectiveUserID(proc_kinfo[i].p_uid);
215  process_info.SetEffectiveGroupID(proc_kinfo[i].p_gid);
216  // Make sure our info matches before we go fetch the name and cpu type
217  if (match_info.Matches(process_info) &&
218  GetNetBSDProcessArgs(&match_info, process_info)) {
219  GetNetBSDProcessCPUType(process_info);
220  if (match_info.Matches(process_info))
221  process_infos.Append(process_info);
222  }
223  }
224 
225  kvm_close(kdp); /* XXX: we don't check for error here */
226 
227  return process_infos.GetSize();
228 }
229 
230 bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
231  process_info.SetProcessID(pid);
232 
233  if (GetNetBSDProcessArgs(NULL, process_info)) {
234  GetNetBSDProcessCPUType(process_info);
235  GetNetBSDProcessUserAndGroup(process_info);
236  return true;
237  }
238 
239  process_info.Clear();
240  return false;
241 }
242 
243 Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
244  return Status("unimplemented");
245 }
ConstString & GetFilename()
Filename string get accessor.
Definition: FileSpec.cpp:369
An data extractor class.
Definition: DataExtractor.h:47
bool NameMatches(llvm::StringRef name, NameMatch match_type, llvm::StringRef match)
Definition: NameMatches.cpp:15
A command line argument class.
Definition: Args.h:32
bool ProcessIDIsValid() const
Definition: ProcessInfo.h:72
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
void SetGroupID(uint32_t gid)
Definition: ProcessInfo.h:60
const char * GetCStr(lldb::offset_t *offset_ptr) const
Extract a C string from *offset_ptr.
#define LLDB_INVALID_PROCESS_ID
Definition: lldb-defines.h:92
void Append(const ProcessInstanceInfo &info)
Definition: ProcessInfo.h:166
ProcessInstanceInfo & GetProcessInfo()
Definition: ProcessInfo.h:216
void SetProcessID(lldb::pid_t pid)
Definition: ProcessInfo.h:70
char ** environ
static bool GetNetBSDProcessCPUType(ProcessInstanceInfo &process_info)
bool Matches(const ProcessInstanceInfo &proc_info) const
const char * GetName() const
Definition: ProcessInfo.cpp:41
void Clear()
Clears the object state.
Definition: ArchSpec.cpp:580
#define UINT32_MAX
Definition: lldb-defines.h:31
uint64_t offset_t
Definition: lldb-types.h:87
void SetEffectiveUserID(uint32_t uid)
Definition: ProcessInfo.h:133
void SetEffectiveGroupID(uint32_t gid)
Definition: ProcessInfo.h:135
void SetParentProcessID(lldb::pid_t pid)
Definition: ProcessInfo.h:139
static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, ProcessInstanceInfo &process_info)
Definition: netbsd/Host.cpp:49
FileSpec & GetExecutableFile()
Definition: ProcessInfo.h:43
ArchSpec & GetArchitecture()
Definition: ProcessInfo.h:62
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:247
Definition: SBAddress.h:15
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:321
uint64_t pid_t
Definition: lldb-types.h:85
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
Definition: FileSpec.cpp:198
lldb::ByteOrder InlHostByteOrder()
Definition: Endian.h:25
void SetUserID(uint32_t uid)
Definition: ProcessInfo.h:58
lldb::pid_t GetProcessID() const
Definition: ProcessInfo.h:68
static bool GetNetBSDProcessUserAndGroup(ProcessInstanceInfo &process_info)
lldb::pid_t GetProcessIDAtIndex(size_t idx)
Definition: ProcessInfo.h:176
An error handling class.
Definition: Status.h:44
const uint8_t * PeekData(lldb::offset_t offset, lldb::offset_t length) const
Peek at a bytes at offset.