blob: b748cdfa4dafa54f8d8d1e2fa5883beac584c712 [file] [log] [blame]
Johnny Chen8f3d8382011-08-02 20:52:42 +00001//===-- source/Host/freebsd/Host.cpp ------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// C Includes
11#include <stdio.h>
Johnny Chen30213ff2012-01-05 19:17:38 +000012#include <dlfcn.h>
Johnny Chen8f3d8382011-08-02 20:52:42 +000013#include <execinfo.h>
14#include <sys/types.h>
15#include <sys/user.h>
16#include <sys/utsname.h>
17#include <sys/sysctl.h>
Daniel Maleae0f8f572013-08-26 23:57:52 +000018#include <sys/proc.h>
Johnny Chen8f3d8382011-08-02 20:52:42 +000019
Johnny Chen30213ff2012-01-05 19:17:38 +000020#include <sys/ptrace.h>
21#include <sys/exec.h>
22#include <machine/elf.h>
23
Daniel Maleae0f8f572013-08-26 23:57:52 +000024#include <spawn.h>
Johnny Chen30213ff2012-01-05 19:17:38 +000025
Johnny Chen8f3d8382011-08-02 20:52:42 +000026// C++ Includes
27// Other libraries and framework includes
28// Project includes
29#include "lldb/Core/Error.h"
30#include "lldb/Host/Endian.h"
31#include "lldb/Host/Host.h"
Daniel Maleae0f8f572013-08-26 23:57:52 +000032#include "lldb/Core/Module.h"
Johnny Chen8f3d8382011-08-02 20:52:42 +000033#include "lldb/Core/DataExtractor.h"
34#include "lldb/Core/StreamFile.h"
35#include "lldb/Core/StreamString.h"
36#include "lldb/Target/Process.h"
Daniel Maleae0f8f572013-08-26 23:57:52 +000037#include "lldb/Target/Platform.h"
Johnny Chen8f3d8382011-08-02 20:52:42 +000038
Johnny Chen30213ff2012-01-05 19:17:38 +000039#include "lldb/Core/DataBufferHeap.h"
40#include "lldb/Core/DataExtractor.h"
Daniel Maleae0f8f572013-08-26 23:57:52 +000041#include "lldb/Utility/CleanUp.h"
42
Johnny Chen8f3d8382011-08-02 20:52:42 +000043#include "llvm/Support/Host.h"
44
Johnny Chen30213ff2012-01-05 19:17:38 +000045
Johnny Chen8f3d8382011-08-02 20:52:42 +000046extern "C" {
Johnny Chen30213ff2012-01-05 19:17:38 +000047 extern char **environ;
Johnny Chen8f3d8382011-08-02 20:52:42 +000048}
49
50using namespace lldb;
51using namespace lldb_private;
52
53class FreeBSDThread
54{
55public:
56 FreeBSDThread(const char *thread_name)
57 {
58 Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name);
59 }
60 static void PThreadDestructor (void *v)
61 {
62 delete (FreeBSDThread*)v;
63 }
64};
65
66static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT;
67static pthread_key_t g_thread_create_key = 0;
68
69static void
70InitThreadCreated()
71{
72 ::pthread_key_create (&g_thread_create_key, FreeBSDThread::PThreadDestructor);
73}
74
75void
76Host::ThreadCreated (const char *thread_name)
77{
78 ::pthread_once (&g_thread_create_once, InitThreadCreated);
79 if (g_thread_create_key)
80 {
81 ::pthread_setspecific (g_thread_create_key, new FreeBSDThread(thread_name));
82 }
Ed Maste02983be2013-07-25 19:10:32 +000083
84 Host::SetShortThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name, 16);
Johnny Chen8f3d8382011-08-02 20:52:42 +000085}
86
Ed Maste889865f2013-07-11 14:12:16 +000087std::string
88Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
89{
90 std::string thread_name;
91 return thread_name;
92}
93
Johnny Chen8f3d8382011-08-02 20:52:42 +000094void
95Host::Backtrace (Stream &strm, uint32_t max_frames)
96{
97 char backtrace_path[] = "/tmp/lldb-backtrace-tmp-XXXXXX";
98 int backtrace_fd = ::mkstemp (backtrace_path);
99 if (backtrace_fd != -1)
100 {
101 std::vector<void *> frame_buffer (max_frames, NULL);
102 int count = ::backtrace (&frame_buffer[0], frame_buffer.size());
103 ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd);
Johnny Chen30213ff2012-01-05 19:17:38 +0000104
Johnny Chen8f3d8382011-08-02 20:52:42 +0000105 const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR);
106
107 if (::lseek(backtrace_fd, 0, SEEK_SET) == 0)
108 {
109 char *buffer = (char *)::malloc (buffer_size);
110 if (buffer)
111 {
112 ssize_t bytes_read = ::read (backtrace_fd, buffer, buffer_size);
113 if (bytes_read > 0)
114 strm.Write(buffer, bytes_read);
115 ::free (buffer);
116 }
117 }
118 ::close (backtrace_fd);
119 ::unlink (backtrace_path);
120 }
121}
122
123size_t
124Host::GetEnvironment (StringList &env)
125{
126 char *v;
127 char **var = environ;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000128 for (; var != NULL && *var != NULL; ++var)
129 {
Johnny Chen8f3d8382011-08-02 20:52:42 +0000130 v = strchr(*var, (int)'-');
131 if (v == NULL)
132 continue;
133 env.AppendString(v);
134 }
135 return env.GetSize();
136}
137
138bool
Ed Maste5d34af32013-06-24 15:09:18 +0000139Host::GetOSVersion(uint32_t &major,
140 uint32_t &minor,
Johnny Chen8f3d8382011-08-02 20:52:42 +0000141 uint32_t &update)
142{
143 struct utsname un;
Johnny Chen8f3d8382011-08-02 20:52:42 +0000144
Daniel Maleae0f8f572013-08-26 23:57:52 +0000145 ::memset(&un, 0, sizeof(utsname));
Johnny Chen8f3d8382011-08-02 20:52:42 +0000146 if (uname(&un) < 0)
147 return false;
148
Ed Maste2f0d5902013-06-25 20:50:07 +0000149 status = sscanf(un.release, "%u.%u", &major, &minor);
Ed Maste2f0d5902013-06-25 20:50:07 +0000150 return status == 2;
Johnny Chen8f3d8382011-08-02 20:52:42 +0000151}
152
Daniel Maleae0f8f572013-08-26 23:57:52 +0000153// The posix_spawn() and posix_spawnp() functions first appeared in FreeBSD 8.0.
154static Error
155LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid)
156{
157 Error error;
158 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
159
160 assert(exe_path);
161 assert(!launch_info.GetFlags().Test (eLaunchFlagDebug));
162
163 posix_spawnattr_t attr;
164
165 error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);
166 error.LogIfError(log.get(), "::posix_spawnattr_init ( &attr )");
167 if (error.Fail())
168 return error;
169
170 // Make a quick class that will cleanup the posix spawn attributes in case
171 // we return in the middle of this function.
172 lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy);
173
174 sigset_t no_signals;
175 sigset_t all_signals;
176 sigemptyset (&no_signals);
177 sigfillset (&all_signals);
178 ::posix_spawnattr_setsigmask(&attr, &all_signals);
179 ::posix_spawnattr_setsigdefault(&attr, &no_signals);
180
181 short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
182
183 error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX);
184 error.LogIfError(log.get(), "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags);
185 if (error.Fail())
186 return error;
187
188 const size_t num_file_actions = launch_info.GetNumFileActions ();
189 posix_spawn_file_actions_t file_actions, *file_action_ptr = NULL;
190 // Make a quick class that will cleanup the posix spawn attributes in case
191 // we return in the middle of this function.
192 lldb_utility::CleanUp <posix_spawn_file_actions_t *, int>
193 posix_spawn_file_actions_cleanup (file_action_ptr, NULL, posix_spawn_file_actions_destroy);
194
195 if (num_file_actions > 0)
196 {
197 error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
198 error.LogIfError(log.get(), "::posix_spawn_file_actions_init ( &file_actions )");
199 if (error.Fail())
200 return error;
201
202 file_action_ptr = &file_actions;
203 posix_spawn_file_actions_cleanup.set(file_action_ptr);
204
205 for (size_t i = 0; i < num_file_actions; ++i)
206 {
207 const ProcessLaunchInfo::FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i);
208 if (launch_file_action &&
209 !ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (&file_actions,
210 launch_file_action,
211 log.get(),
212 error))
213 return error;
214 }
215 }
216
217 // Change working directory if neccessary.
218 char current_dir[PATH_MAX];
219 current_dir[0] = '\0';
220
221 const char *working_dir = launch_info.GetWorkingDirectory();
222 if (working_dir != NULL)
223 {
224 if (::getcwd(current_dir, sizeof(current_dir)) == NULL)
225 {
226 error.SetError(errno, eErrorTypePOSIX);
227 error.LogIfError(log.get(), "unable to save the current directory");
228 return error;
229 }
230
231 if (::chdir(working_dir) == -1)
232 {
233 error.SetError(errno, eErrorTypePOSIX);
234 error.LogIfError(log.get(), "unable to change working directory to %s", working_dir);
235 return error;
236 }
237 }
238
239 const char *tmp_argv[2];
240 char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector();
241 char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector();
242
243 // Prepare minimal argument list if we didn't get it from the launch_info structure.
244 // We must pass argv into posix_spawnp and it must contain at least two items -
245 // pointer to an executable and NULL.
246 if (argv == NULL)
247 {
248 tmp_argv[0] = exe_path;
249 tmp_argv[1] = NULL;
250 argv = (char * const*)tmp_argv;
251 }
252
253 error.SetError (::posix_spawnp (&pid,
254 exe_path,
255 (num_file_actions > 0) ? &file_actions : NULL,
256 &attr,
257 argv,
258 envp),
259 eErrorTypePOSIX);
260
261 error.LogIfError(log.get(), "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )",
262 pid, exe_path, file_action_ptr, &attr, argv, envp);
263
264 // Change back the current directory.
265 // NOTE: do not override previously established error from posix_spawnp.
266 if (working_dir != NULL && ::chdir(current_dir) == -1 && error.Success())
267 {
268 error.SetError(errno, eErrorTypePOSIX);
269 error.LogIfError(log.get(), "unable to change current directory back to %s",
270 current_dir);
271 }
272
273 return error;
274}
275
276
Johnny Chen8f3d8382011-08-02 20:52:42 +0000277Error
278Host::LaunchProcess (ProcessLaunchInfo &launch_info)
279{
280 Error error;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000281 char exe_path[PATH_MAX];
282
283 PlatformSP host_platform_sp (Platform::GetDefaultPlatform ());
284
285 const ArchSpec &arch_spec = launch_info.GetArchitecture();
286
287 FileSpec exe_spec(launch_info.GetExecutableFile());
288
289 FileSpec::FileType file_type = exe_spec.GetFileType();
290 if (file_type != FileSpec::eFileTypeRegular)
291 {
292 lldb::ModuleSP exe_module_sp;
293 error = host_platform_sp->ResolveExecutable (exe_spec,
294 arch_spec,
295 exe_module_sp,
296 NULL);
297
298 if (error.Fail())
299 return error;
300
301 if (exe_module_sp)
302 exe_spec = exe_module_sp->GetFileSpec();
303}
304
305 if (exe_spec.Exists())
306 {
307 exe_spec.GetPath (exe_path, sizeof(exe_path));
308 }
309 else
310 {
311 launch_info.GetExecutableFile().GetPath (exe_path, sizeof(exe_path));
312 error.SetErrorStringWithFormat ("executable doesn't exist: '%s'", exe_path);
313 return error;
314 }
315
316 assert(!launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY));
317
318 ::pid_t pid = LLDB_INVALID_PROCESS_ID;
319
320 error = LaunchProcessPosixSpawn(exe_path, launch_info, pid);
321
322 if (pid != LLDB_INVALID_PROCESS_ID)
323 {
324 // If all went well, then set the process ID into the launch info
325 launch_info.SetProcessID(pid);
326
327 // Make sure we reap any processes we spawn or we will have zombies.
328 if (!launch_info.MonitorProcess())
329 {
330 const bool monitor_signals = false;
331 StartMonitoringChildProcess (Process::SetProcessExitStatus,
332 NULL,
333 pid,
334 monitor_signals);
335 }
336 }
337 else
338 {
339 // Invalid process ID, something didn't go well
340 if (error.Success())
341 error.SetErrorString ("process launch failed for unknown reasons");
342 }
Johnny Chen8f3d8382011-08-02 20:52:42 +0000343 return error;
344}
345
346bool
347Host::GetOSBuildString (std::string &s)
348{
349 int mib[2] = { CTL_KERN, KERN_OSREV };
Daniel Maleae0f8f572013-08-26 23:57:52 +0000350 char osrev_str[12];
351 uint32_t osrev = 0;
352 size_t osrev_len = sizeof(osrev);
353
354 if (::sysctl (mib, 2, &osrev, &osrev_len, NULL, 0) == 0)
Johnny Chen8f3d8382011-08-02 20:52:42 +0000355 {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000356 ::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev);
357 s.assign (osrev_str);
Johnny Chen8f3d8382011-08-02 20:52:42 +0000358 return true;
359 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000360
Johnny Chen8f3d8382011-08-02 20:52:42 +0000361 s.clear();
362 return false;
363}
364
365bool
366Host::GetOSKernelDescription (std::string &s)
367{
Daniel Maleae0f8f572013-08-26 23:57:52 +0000368 struct utsname un;
369
370 ::memset(&un, 0, sizeof(utsname));
Johnny Chen8f3d8382011-08-02 20:52:42 +0000371 s.clear();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000372
373 if (uname(&un) < 0)
Johnny Chen8f3d8382011-08-02 20:52:42 +0000374 return false;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000375
376 s.assign (un.version);
377
378 return true;
Johnny Chen8f3d8382011-08-02 20:52:42 +0000379}
380
381static bool
382GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr,
383 ProcessInstanceInfo &process_info)
384{
Daniel Maleae0f8f572013-08-26 23:57:52 +0000385 if (process_info.ProcessIDIsValid())
386 {
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000387 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() };
Johnny Chen8f3d8382011-08-02 20:52:42 +0000388
389 char arg_data[8192];
390 size_t arg_data_size = sizeof(arg_data);
Johnny Chen30213ff2012-01-05 19:17:38 +0000391 if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0)
Johnny Chen8f3d8382011-08-02 20:52:42 +0000392 {
393 DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *));
Ashok Thirumurthi0f3b9b82013-05-01 20:38:19 +0000394 lldb::offset_t offset = 0;
Johnny Chen8f3d8382011-08-02 20:52:42 +0000395 const char *cstr;
Johnny Chen30213ff2012-01-05 19:17:38 +0000396
Johnny Chen8f3d8382011-08-02 20:52:42 +0000397 cstr = data.GetCStr (&offset);
398 if (cstr)
399 {
400 process_info.GetExecutableFile().SetFile(cstr, false);
401
Ed Maste5d34af32013-06-24 15:09:18 +0000402 if (!(match_info_ptr == NULL ||
Johnny Chen8f3d8382011-08-02 20:52:42 +0000403 NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(),
404 match_info_ptr->GetNameMatchType(),
Johnny Chen30213ff2012-01-05 19:17:38 +0000405 match_info_ptr->GetProcessInfo().GetName())))
406 return false;
407
408 Args &proc_args = process_info.GetArguments();
409 while (1)
Johnny Chen8f3d8382011-08-02 20:52:42 +0000410 {
Johnny Chen30213ff2012-01-05 19:17:38 +0000411 const uint8_t *p = data.PeekData(offset, 1);
412 while ((p != NULL) && (*p == '\0') && offset < arg_data_size)
Johnny Chen8f3d8382011-08-02 20:52:42 +0000413 {
Johnny Chen8f3d8382011-08-02 20:52:42 +0000414 ++offset;
Johnny Chen30213ff2012-01-05 19:17:38 +0000415 p = data.PeekData(offset, 1);
Johnny Chen8f3d8382011-08-02 20:52:42 +0000416 }
Johnny Chen30213ff2012-01-05 19:17:38 +0000417 if (p == NULL || offset >= arg_data_size)
418 return true;
419
420 cstr = data.GetCStr(&offset);
421 if (cstr)
422 proc_args.AppendArgument(cstr);
423 else
424 return true;
Johnny Chen8f3d8382011-08-02 20:52:42 +0000425 }
426 }
Ed Maste5d34af32013-06-24 15:09:18 +0000427 }
Johnny Chen8f3d8382011-08-02 20:52:42 +0000428 }
429 return false;
430}
431
432static bool
433GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info)
434{
Daniel Maleae0f8f572013-08-26 23:57:52 +0000435 if (process_info.ProcessIDIsValid())
436 {
Johnny Chen30213ff2012-01-05 19:17:38 +0000437 process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
438 return true;
Johnny Chen8f3d8382011-08-02 20:52:42 +0000439 }
440 process_info.GetArchitecture().Clear();
441 return false;
442}
443
444static bool
445GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info)
446{
447 struct kinfo_proc proc_kinfo;
448 size_t proc_kinfo_size;
449
Ed Maste5d34af32013-06-24 15:09:18 +0000450 if (process_info.ProcessIDIsValid())
Johnny Chen8f3d8382011-08-02 20:52:42 +0000451 {
452 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID,
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000453 (int)process_info.GetProcessID() };
Johnny Chen8f3d8382011-08-02 20:52:42 +0000454 proc_kinfo_size = sizeof(struct kinfo_proc);
455
456 if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
457 {
458 if (proc_kinfo_size > 0)
459 {
460 process_info.SetParentProcessID (proc_kinfo.ki_ppid);
461 process_info.SetUserID (proc_kinfo.ki_ruid);
462 process_info.SetGroupID (proc_kinfo.ki_rgid);
463 process_info.SetEffectiveUserID (proc_kinfo.ki_uid);
464 if (proc_kinfo.ki_ngroups > 0)
465 process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]);
466 else
Johnny Chen30213ff2012-01-05 19:17:38 +0000467 process_info.SetEffectiveGroupID (UINT32_MAX);
Johnny Chen8f3d8382011-08-02 20:52:42 +0000468 return true;
469 }
470 }
471 }
472 process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID);
473 process_info.SetUserID (UINT32_MAX);
474 process_info.SetGroupID (UINT32_MAX);
475 process_info.SetEffectiveUserID (UINT32_MAX);
Johnny Chen30213ff2012-01-05 19:17:38 +0000476 process_info.SetEffectiveGroupID (UINT32_MAX);
Johnny Chen8f3d8382011-08-02 20:52:42 +0000477 return false;
478}
479
Daniel Maleae0f8f572013-08-26 23:57:52 +0000480uint32_t
481Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
482{
483 std::vector<struct kinfo_proc> kinfos;
484
485 int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
486
487 size_t pid_data_size = 0;
488 if (::sysctl (mib, 3, NULL, &pid_data_size, NULL, 0) != 0)
489 return 0;
490
491 // Add a few extra in case a few more show up
492 const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10;
493
494 kinfos.resize (estimated_pid_count);
495 pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);
496
497 if (::sysctl (mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0)
498 return 0;
499
500 const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));
501
502 bool all_users = match_info.GetMatchAllUsers();
503 const lldb::pid_t our_pid = getpid();
504 const uid_t our_uid = getuid();
505 for (int i = 0; i < actual_pid_count; i++)
506 {
507 const struct kinfo_proc &kinfo = kinfos[i];
508 const bool kinfo_user_matches = (all_users ||
509 (kinfo.ki_ruid == our_uid) ||
510 // Special case, if lldb is being run as root we can attach to anything.
511 (our_uid == 0)
512 );
513
514 if (kinfo_user_matches == false || // Make sure the user is acceptable
515 kinfo.ki_pid == our_pid || // Skip this process
516 kinfo.ki_pid == 0 || // Skip kernel (kernel pid is zero)
517 kinfo.ki_stat == SZOMB || // Zombies are bad, they like brains...
518 kinfo.ki_flag & P_TRACED || // Being debugged?
519 kinfo.ki_flag & P_WEXIT) // Working on exiting
520 continue;
521
522 // Every thread is a process in FreeBSD, but all the threads of a single process
523 // have the same pid. Do not store the process info in the result list if a process
524 // with given identifier is already registered there.
525 bool already_registered = false;
526 for (uint32_t pi = 0;
527 !already_registered &&
528 (const int)kinfo.ki_numthreads > 1 &&
529 pi < (const uint32_t)process_infos.GetSize(); pi++)
530 already_registered = (process_infos.GetProcessIDAtIndex(pi) == (uint32_t)kinfo.ki_pid);
531
532 if (already_registered)
533 continue;
534
535 ProcessInstanceInfo process_info;
536 process_info.SetProcessID (kinfo.ki_pid);
537 process_info.SetParentProcessID (kinfo.ki_ppid);
538 process_info.SetUserID (kinfo.ki_ruid);
539 process_info.SetGroupID (kinfo.ki_rgid);
540 process_info.SetEffectiveUserID (kinfo.ki_svuid);
541 process_info.SetEffectiveGroupID (kinfo.ki_svgid);
542
543 // Make sure our info matches before we go fetch the name and cpu type
544 if (match_info.Matches (process_info) &&
545 GetFreeBSDProcessArgs (&match_info, process_info))
546 {
547 GetFreeBSDProcessCPUType (process_info);
548 if (match_info.Matches (process_info))
549 process_infos.Append (process_info);
550 }
551 }
552
553 return process_infos.GetSize();
554}
555
Johnny Chen8f3d8382011-08-02 20:52:42 +0000556bool
557Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
558{
559 process_info.SetProcessID(pid);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000560
561 if (GetFreeBSDProcessArgs(NULL, process_info))
562 {
Johnny Chen8f3d8382011-08-02 20:52:42 +0000563 // should use libprocstat instead of going right into sysctl?
564 GetFreeBSDProcessCPUType(process_info);
565 GetFreeBSDProcessUserAndGroup(process_info);
566 return true;
567 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000568
Johnny Chen8f3d8382011-08-02 20:52:42 +0000569 process_info.Clear();
570 return false;
571}
Johnny Chen30213ff2012-01-05 19:17:38 +0000572
573lldb::DataBufferSP
574Host::GetAuxvData(lldb_private::Process *process)
575{
576 int mib[2] = { CTL_KERN, KERN_PS_STRINGS };
577 void *ps_strings_addr, *auxv_addr;
578 size_t ps_strings_size = sizeof(void *);
579 Elf_Auxinfo aux_info[AT_COUNT];
580 struct ps_strings ps_strings;
581 struct ptrace_io_desc pid;
582 DataBufferSP buf_sp;
Greg Clayton7b0992d2013-04-18 22:45:39 +0000583 std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
Johnny Chen30213ff2012-01-05 19:17:38 +0000584
585 if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) {
586 pid.piod_op = PIOD_READ_D;
587 pid.piod_addr = &ps_strings;
588 pid.piod_offs = ps_strings_addr;
589 pid.piod_len = sizeof(ps_strings);
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000590 if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
Johnny Chen30213ff2012-01-05 19:17:38 +0000591 perror("failed to fetch ps_strings");
592 buf_ap.release();
593 goto done;
594 }
595
596 auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1;
597
598 pid.piod_addr = aux_info;
599 pid.piod_offs = auxv_addr;
600 pid.piod_len = sizeof(aux_info);
Filipe Cabecinhasd0b87d82012-09-11 18:11:16 +0000601 if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
Johnny Chen30213ff2012-01-05 19:17:38 +0000602 perror("failed to fetch aux_info");
603 buf_ap.release();
604 goto done;
605 }
606 memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len);
607 buf_sp.reset(buf_ap.release());
608 } else {
609 perror("sysctl failed on ps_strings");
610 }
611
612 done:
613 return buf_sp;
614}