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