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