blob: adef97f5a24016a4634f745910c8b95196a0861b [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- Host.mm -------------------------------------------------*- 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#include <dlfcn.h>
11#include <libgen.h>
12#include <mach/mach.h>
13#include <mach-o/dyld.h>
14#include <signal.h>
15#include <stddef.h>
16#include <sys/sysctl.h>
17#include <unistd.h>
Jim Ingham7508e732010-08-09 23:31:02 +000018#include <libproc.h>
19#include <sys/proc_info.h>
Chris Lattner24943d22010-06-08 16:52:24 +000020
21#include <map>
22#include <string>
23
24#include <objc/objc-auto.h>
25
26#include <Foundation/Foundation.h>
27
Greg Clayton54e7afa2010-07-09 20:39:50 +000028#include "cfcpp/CFCBundle.h"
29#include "cfcpp/CFCReleaser.h"
30#include "cfcpp/CFCString.h"
Chris Lattner24943d22010-06-08 16:52:24 +000031
32#include "lldb/Host/Host.h"
33#include "lldb/Core/ArchSpec.h"
34#include "lldb/Core/ConstString.h"
35#include "lldb/Core/Error.h"
36#include "lldb/Core/FileSpec.h"
37#include "lldb/Core/Log.h"
38#include "lldb/Core/StreamString.h"
39#include "lldb/Host/Mutex.h"
40#include "lldb/Target/Process.h"
41#include "lldb/Target/Target.h"
42#include "lldb/Target/TargetList.h"
43#include "lldb/lldb-private-log.h"
44
45using namespace lldb;
46using namespace lldb_private;
47
48//------------------------------------------------------------------
49// Return the size in bytes of a page on the host system
50//------------------------------------------------------------------
51size_t
52Host::GetPageSize()
53{
54 return ::getpagesize();
55}
56
57
58//------------------------------------------------------------------
59// Returns true if the host system is Big Endian.
60//------------------------------------------------------------------
61ByteOrder
62Host::GetByteOrder()
63{
64 union EndianTest
65 {
66 uint32_t num;
67 uint8_t bytes[sizeof(uint32_t)];
68 } endian = { (uint16_t)0x11223344 };
69 switch (endian.bytes[0])
70 {
71 case 0x11: return eByteOrderLittle;
72 case 0x44: return eByteOrderBig;
73 case 0x33: return eByteOrderPDP;
74 }
75 return eByteOrderInvalid;
76}
77
78lldb::pid_t
79Host::GetCurrentProcessID()
80{
81 return ::getpid();
82}
83
84lldb::pid_t
85Host::GetCurrentThreadID()
86{
87 return ::mach_thread_self();
88}
89
90
91const ArchSpec &
92Host::GetArchitecture ()
93{
94 static ArchSpec g_host_arch;
95 if (!g_host_arch.IsValid())
96 {
97 uint32_t cputype, cpusubtype;
98 uint32_t is_64_bit_capable;
99 size_t len = sizeof(cputype);
100 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
101 {
102 len = sizeof(cpusubtype);
103 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
104 g_host_arch.SetArch(cputype, cpusubtype);
105
106 len = sizeof (is_64_bit_capable);
107 if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
108 {
109 if (is_64_bit_capable)
110 {
111 if (cputype == CPU_TYPE_I386 && cpusubtype == CPU_SUBTYPE_486)
112 cpusubtype = CPU_SUBTYPE_I386_ALL;
113
114 cputype |= CPU_ARCH_ABI64;
115 }
116 }
117 }
118 }
119 return g_host_arch;
120}
121
122const ConstString &
123Host::GetVendorString()
124{
125 static ConstString g_vendor;
126 if (!g_vendor)
127 {
128 char ostype[64];
129 size_t len = sizeof(ostype);
130 if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
131 g_vendor.SetCString (ostype);
132 }
133 return g_vendor;
134}
135
136const ConstString &
137Host::GetOSString()
138{
139 static ConstString g_os_string("apple");
140 return g_os_string;
141}
142
143const ConstString &
144Host::GetTargetTriple()
145{
146 static ConstString g_host_triple;
147 if (!(g_host_triple))
148 {
149 StreamString triple;
150 triple.Printf("%s-%s-%s",
151 GetArchitecture ().AsCString(),
152 GetVendorString().AsCString("apple"),
153 GetOSString().AsCString("darwin"));
154
155 std::transform (triple.GetString().begin(),
156 triple.GetString().end(),
157 triple.GetString().begin(),
158 ::tolower);
159
160 g_host_triple.SetCString(triple.GetString().c_str());
161 }
162 return g_host_triple;
163}
164
165class MacOSXDarwinThread
166{
167public:
168 MacOSXDarwinThread(const char *thread_name) :
169 m_pool (nil)
170 {
171 // Register our thread with the collector if garbage collection is enabled.
172 if (objc_collectingEnabled())
173 {
174#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
175 // On Leopard and earlier there is no way objc_registerThreadWithCollector
176 // function, so we do it manually.
177 auto_zone_register_thread(auto_zone());
178#else
179 // On SnowLoepard and later we just call the thread registration function.
180 objc_registerThreadWithCollector();
181#endif
182 }
183 else
184 {
185 m_pool = [[NSAutoreleasePool alloc] init];
186 }
187
188
189 Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name);
190 }
191
192 ~MacOSXDarwinThread()
193 {
194 if (m_pool)
195 [m_pool release];
196 }
197
198 static void PThreadDestructor (void *v)
199 {
200 delete (MacOSXDarwinThread*)v;
201 }
202
203protected:
204 NSAutoreleasePool * m_pool;
205private:
206 DISALLOW_COPY_AND_ASSIGN (MacOSXDarwinThread);
207};
208
209static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT;
210static pthread_key_t g_thread_create_key = 0;
211
212static void
213InitThreadCreated()
214{
215 ::pthread_key_create (&g_thread_create_key, MacOSXDarwinThread::PThreadDestructor);
216}
217
Greg Claytonc0418152010-07-07 17:07:17 +0000218struct HostThreadCreateInfo
Chris Lattner24943d22010-06-08 16:52:24 +0000219{
220 std::string thread_name;
221 thread_func_t thread_fptr;
222 thread_arg_t thread_arg;
223
224 HostThreadCreateInfo (const char *name, thread_func_t fptr, thread_arg_t arg) :
225 thread_name (name ? name : ""),
226 thread_fptr (fptr),
227 thread_arg (arg)
228 {
229 }
230};
231
232static thread_result_t
233ThreadCreateTrampoline (thread_arg_t arg)
234{
235 HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg;
236 Host::ThreadCreated (info->thread_name.c_str());
237 thread_func_t thread_fptr = info->thread_fptr;
238 thread_arg_t thread_arg = info->thread_arg;
239
240 Log * log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);
241 if (log)
242 log->Printf("thread created");
243
244 delete info;
245 return thread_fptr (thread_arg);
246}
247
248lldb::thread_t
249Host::ThreadCreate
250(
251 const char *thread_name,
252 thread_func_t thread_fptr,
253 thread_arg_t thread_arg,
254 Error *error
255)
256{
257 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
258
259 // Host::ThreadCreateTrampoline will delete this pointer for us.
260 HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg);
261
262 int err = ::pthread_create (&thread, NULL, ThreadCreateTrampoline, info_ptr);
263 if (err == 0)
264 {
265 if (error)
266 error->Clear();
267 return thread;
268 }
269
270 if (error)
271 error->SetError (err, eErrorTypePOSIX);
272
273 return LLDB_INVALID_HOST_THREAD;
274}
275
276bool
277Host::ThreadCancel (lldb::thread_t thread, Error *error)
278{
279
280 int err = ::pthread_cancel (thread);
281 if (error)
282 error->SetError(err, eErrorTypePOSIX);
283 return err == 0;
284}
285
286bool
287Host::ThreadDetach (lldb::thread_t thread, Error *error)
288{
289 int err = ::pthread_detach (thread);
290 if (error)
291 error->SetError(err, eErrorTypePOSIX);
292 return err == 0;
293}
294
295bool
296Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error)
297{
298 int err = ::pthread_join (thread, thread_result_ptr);
299 if (error)
300 error->SetError(err, eErrorTypePOSIX);
301 return err == 0;
302}
303
304void
305Host::ThreadCreated (const char *thread_name)
306{
307 ::pthread_once (&g_thread_create_once, InitThreadCreated);
308 if (g_thread_create_key)
309 {
310 ::pthread_setspecific (g_thread_create_key, new MacOSXDarwinThread(thread_name));
311 }
312}
313
314//------------------------------------------------------------------
315// Control access to a static file thread name map using a single
316// static function to avoid a static constructor.
317//------------------------------------------------------------------
318static const char *
319ThreadNameAccessor (bool get, lldb::pid_t pid, lldb::tid_t tid, const char *name)
320{
321
322 uint64_t pid_tid = ((uint64_t)pid << 32) | (uint64_t)tid;
323
324 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
325 Mutex::Locker locker(&g_mutex);
326
327 typedef std::map<uint64_t, std::string> thread_name_map;
328 static thread_name_map g_thread_names;
329
330 if (get)
331 {
332 // See if the thread name exists in our thread name pool
333 thread_name_map::iterator pos = g_thread_names.find(pid_tid);
334 if (pos != g_thread_names.end())
335 return pos->second.c_str();
336 }
337 else
338 {
339 // Set the thread name
340 g_thread_names[pid_tid] = name;
341 }
342 return NULL;
343}
344
345
346
347const char *
348Host::GetSignalAsCString (int signo)
349{
350 switch (signo)
351 {
352 case SIGHUP: return "SIGHUP"; // 1 hangup
353 case SIGINT: return "SIGINT"; // 2 interrupt
354 case SIGQUIT: return "SIGQUIT"; // 3 quit
355 case SIGILL: return "SIGILL"; // 4 illegal instruction (not reset when caught)
356 case SIGTRAP: return "SIGTRAP"; // 5 trace trap (not reset when caught)
357 case SIGABRT: return "SIGABRT"; // 6 abort()
358#if defined(_POSIX_C_SOURCE)
359 case SIGPOLL: return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported)
360#else // !_POSIX_C_SOURCE
361 case SIGEMT: return "SIGEMT"; // 7 EMT instruction
362#endif // !_POSIX_C_SOURCE
363 case SIGFPE: return "SIGFPE"; // 8 floating point exception
364 case SIGKILL: return "SIGKILL"; // 9 kill (cannot be caught or ignored)
365 case SIGBUS: return "SIGBUS"; // 10 bus error
366 case SIGSEGV: return "SIGSEGV"; // 11 segmentation violation
367 case SIGSYS: return "SIGSYS"; // 12 bad argument to system call
368 case SIGPIPE: return "SIGPIPE"; // 13 write on a pipe with no one to read it
369 case SIGALRM: return "SIGALRM"; // 14 alarm clock
370 case SIGTERM: return "SIGTERM"; // 15 software termination signal from kill
371 case SIGURG: return "SIGURG"; // 16 urgent condition on IO channel
372 case SIGSTOP: return "SIGSTOP"; // 17 sendable stop signal not from tty
373 case SIGTSTP: return "SIGTSTP"; // 18 stop signal from tty
374 case SIGCONT: return "SIGCONT"; // 19 continue a stopped process
375 case SIGCHLD: return "SIGCHLD"; // 20 to parent on child stop or exit
376 case SIGTTIN: return "SIGTTIN"; // 21 to readers pgrp upon background tty read
377 case SIGTTOU: return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local&LTOSTOP)
378#if !defined(_POSIX_C_SOURCE)
379 case SIGIO: return "SIGIO"; // 23 input/output possible signal
380#endif
381 case SIGXCPU: return "SIGXCPU"; // 24 exceeded CPU time limit
382 case SIGXFSZ: return "SIGXFSZ"; // 25 exceeded file size limit
383 case SIGVTALRM: return "SIGVTALRM"; // 26 virtual time alarm
384 case SIGPROF: return "SIGPROF"; // 27 profiling time alarm
385#if !defined(_POSIX_C_SOURCE)
386 case SIGWINCH: return "SIGWINCH"; // 28 window size changes
387 case SIGINFO: return "SIGINFO"; // 29 information request
388#endif
389 case SIGUSR1: return "SIGUSR1"; // 30 user defined signal 1
390 case SIGUSR2: return "SIGUSR2"; // 31 user defined signal 2
391 default:
392 break;
393 }
394 return NULL;
395}
396
397const char *
398Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
399{
400 const char *name = ThreadNameAccessor (true, pid, tid, NULL);
401 if (name == NULL)
402 {
403 // We currently can only get the name of a thread in the current process.
404#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
405 if (pid == Host::GetCurrentProcessID())
406 {
407 char pthread_name[1024];
408 if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0)
409 {
410 if (pthread_name[0])
411 {
412 // Set the thread in our string pool
413 ThreadNameAccessor (false, pid, tid, pthread_name);
414 // Get our copy of the thread name string
415 name = ThreadNameAccessor (true, pid, tid, NULL);
416 }
417 }
418 }
419#endif
420 }
421 return name;
422}
423
424void
425Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name)
426{
427 lldb::pid_t curr_pid = Host::GetCurrentProcessID();
428 lldb::tid_t curr_tid = Host::GetCurrentThreadID();
429 if (pid == LLDB_INVALID_PROCESS_ID)
430 pid = curr_pid;
431
432 if (tid == LLDB_INVALID_THREAD_ID)
433 tid = curr_tid;
434
435#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
436 // Set the pthread name if possible
437 if (pid == curr_pid && tid == curr_tid)
438 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000439 ::pthread_setname_np (name);
Chris Lattner24943d22010-06-08 16:52:24 +0000440 }
441#endif
442 ThreadNameAccessor (false, pid, tid, name);
443}
444
445FileSpec
446Host::GetProgramFileSpec ()
447{
448 static FileSpec g_program_filepsec;
449 if (!g_program_filepsec)
450 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000451 char program_fullpath[PATH_MAX];
Chris Lattner24943d22010-06-08 16:52:24 +0000452 // If DST is NULL, then return the number of bytes needed.
Greg Clayton54e7afa2010-07-09 20:39:50 +0000453 uint32_t len = sizeof(program_fullpath);
454 int err = _NSGetExecutablePath (program_fullpath, &len);
Chris Lattner24943d22010-06-08 16:52:24 +0000455 if (err == 0)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000456 g_program_filepsec.SetFile (program_fullpath);
457 else if (err == -1)
458 {
459 char *large_program_fullpath = (char *)::malloc (len + 1);
460
461 err = _NSGetExecutablePath (large_program_fullpath, &len);
462 if (err == 0)
463 g_program_filepsec.SetFile (large_program_fullpath);
464
465 ::free (large_program_fullpath);
466 }
Chris Lattner24943d22010-06-08 16:52:24 +0000467 }
468 return g_program_filepsec;
469}
470
471
472FileSpec
473Host::GetModuleFileSpecForHostAddress (const void *host_addr)
474{
475 FileSpec module_filespec;
476 Dl_info info;
477 if (::dladdr (host_addr, &info))
478 {
479 if (info.dli_fname)
480 module_filespec.SetFile(info.dli_fname);
481 }
482 return module_filespec;
483}
484
485
486bool
487Host::ResolveExecutableInBundle (FileSpec *file)
488{
489 if (file->GetFileType () == FileSpec::eFileTypeDirectory)
490 {
491 char path[PATH_MAX];
492 if (file->GetPath(path, sizeof(path)))
493 {
494 CFCBundle bundle (path);
495 CFCReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
496 if (url.get())
497 {
498 if (::CFURLGetFileSystemRepresentation (url.get(), YES, (UInt8*)path, sizeof(path)))
499 {
500 file->SetFile(path);
501 return true;
502 }
503 }
504 }
505 }
506 return false;
507}
508
Greg Claytonc0418152010-07-07 17:07:17 +0000509struct MonitorInfo
Chris Lattner24943d22010-06-08 16:52:24 +0000510{
Greg Clayton75ccf502010-08-21 02:22:51 +0000511 lldb::pid_t pid; // The process ID to monitor
512 Host::MonitorChildProcessCallback callback; // The callback function to call when "pid" exits or signals
513 void *callback_baton; // The callback baton for the callback function
514 bool monitor_signals; // If true, call the callback when "pid" gets signaled.
Chris Lattner24943d22010-06-08 16:52:24 +0000515};
516
Chris Lattner24943d22010-06-08 16:52:24 +0000517static void *
518MonitorChildProcessThreadFunction (void *arg);
519
Greg Clayton75ccf502010-08-21 02:22:51 +0000520lldb::thread_t
Chris Lattner24943d22010-06-08 16:52:24 +0000521Host::StartMonitoringChildProcess
522(
Greg Clayton75ccf502010-08-21 02:22:51 +0000523 Host::MonitorChildProcessCallback callback,
Chris Lattner24943d22010-06-08 16:52:24 +0000524 void *callback_baton,
525 lldb::pid_t pid,
526 bool monitor_signals
527)
528{
Greg Clayton75ccf502010-08-21 02:22:51 +0000529
530 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
Chris Lattner24943d22010-06-08 16:52:24 +0000531 if (callback)
532 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000533 std::auto_ptr<MonitorInfo> info_ap(new MonitorInfo);
534
535 info_ap->pid = pid;
536 info_ap->callback = callback;
537 info_ap->callback_baton = callback_baton;
538 info_ap->monitor_signals = monitor_signals;
539
540 char thread_name[256];
541 ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%i)>", pid);
542 thread = ThreadCreate (thread_name,
543 MonitorChildProcessThreadFunction,
544 info_ap.get(),
545 NULL);
546
547 if (thread != LLDB_INVALID_HOST_THREAD)
548 info_ap.release();
Chris Lattner24943d22010-06-08 16:52:24 +0000549 }
Greg Clayton75ccf502010-08-21 02:22:51 +0000550 return thread;
Chris Lattner24943d22010-06-08 16:52:24 +0000551}
552
Chris Lattner24943d22010-06-08 16:52:24 +0000553//------------------------------------------------------------------
554// Scoped class that will disable thread canceling when it is
555// constructed, and exception safely restore the previous value it
556// when it goes out of scope.
557//------------------------------------------------------------------
558class ScopedPThreadCancelDisabler
559{
560public:
561
562 ScopedPThreadCancelDisabler()
563 {
564 // Disable the ability for this thread to be cancelled
565 int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state);
566 if (err != 0)
567 m_old_state = -1;
568
569 }
570
571 ~ScopedPThreadCancelDisabler()
572 {
573 // Restore the ability for this thread to be cancelled to what it
574 // previously was.
575 if (m_old_state != -1)
576 ::pthread_setcancelstate (m_old_state, 0);
577 }
578private:
579 int m_old_state; // Save the old cancelability state.
580};
581
582
583
584static void *
585MonitorChildProcessThreadFunction (void *arg)
586{
587 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
588 const char *function = __FUNCTION__;
589 if (log)
590 log->Printf ("%s (arg = %p) thread starting...", function, arg);
591
Greg Clayton75ccf502010-08-21 02:22:51 +0000592 MonitorInfo *info = (MonitorInfo *)arg;
593
594 const Host::MonitorChildProcessCallback callback = info->callback;
595 void * const callback_baton = info->callback_baton;
596 const lldb::pid_t pid = info->pid;
597 const bool monitor_signals = info->monitor_signals;
598
599 delete info;
600
Chris Lattner24943d22010-06-08 16:52:24 +0000601 int status = -1;
602 const int options = 0;
603 struct rusage *rusage = NULL;
604 while (1)
605 {
606 if (log)
Greg Clayton75ccf502010-08-21 02:22:51 +0000607 log->Printf("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p)...", function, pid, options, rusage);
Chris Lattner24943d22010-06-08 16:52:24 +0000608
609 // Wait for all child processes
610 ::pthread_testcancel ();
Greg Clayton75ccf502010-08-21 02:22:51 +0000611 const lldb::pid_t wait_pid = ::wait4 (pid, &status, options, rusage);
Chris Lattner24943d22010-06-08 16:52:24 +0000612 ::pthread_testcancel ();
613
Greg Clayton75ccf502010-08-21 02:22:51 +0000614 if (wait_pid == -1)
Chris Lattner24943d22010-06-08 16:52:24 +0000615 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000616 if (errno == EINTR)
617 continue;
618 else
619 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000620 }
Greg Clayton75ccf502010-08-21 02:22:51 +0000621 else if (wait_pid == pid)
Chris Lattner24943d22010-06-08 16:52:24 +0000622 {
Chris Lattner24943d22010-06-08 16:52:24 +0000623 bool exited = false;
624 int signal = 0;
625 int exit_status = 0;
626 const char *status_cstr = NULL;
627 if (WIFSTOPPED(status))
628 {
629 signal = WSTOPSIG(status);
630 status_cstr = "STOPPED";
631 }
632 else if (WIFEXITED(status))
633 {
634 exit_status = WEXITSTATUS(status);
635 status_cstr = "EXITED";
636 exited = true;
637 }
638 else if (WIFSIGNALED(status))
639 {
640 signal = WTERMSIG(status);
641 status_cstr = "SIGNALED";
642 exited = true;
643 exit_status = -1;
644 }
645 else
646 {
647 status_cstr = "(???)";
648 }
649
Greg Clayton75ccf502010-08-21 02:22:51 +0000650 // Scope for pthread_cancel_disabler
Chris Lattner24943d22010-06-08 16:52:24 +0000651 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000652 ScopedPThreadCancelDisabler pthread_cancel_disabler;
653
654 if (log)
655 log->Printf ("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_state = %i",
656 function,
657 wait_pid,
658 options,
659 rusage,
660 pid,
661 status,
662 status_cstr,
663 signal,
664 exit_status);
665
666 if (exited || (signal != 0 && monitor_signals))
Chris Lattner24943d22010-06-08 16:52:24 +0000667 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000668 bool callback_return = callback (callback_baton, pid, signal, exit_status);
669
670 // If our process exited, then this thread should exit
671 if (exited)
672 break;
673 // If the callback returns true, it means this process should
674 // exit
675 if (callback_return)
676 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000677 }
678 }
679 }
680 }
681
682 if (log)
Greg Clayton75ccf502010-08-21 02:22:51 +0000683 log->Printf ("%s (arg = %p) thread exiting...", __FUNCTION__, arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000684
Chris Lattner24943d22010-06-08 16:52:24 +0000685 return NULL;
686}
687
688void
689Host::WillTerminate ()
690{
Chris Lattner24943d22010-06-08 16:52:24 +0000691}
692
Jim Ingham7508e732010-08-09 23:31:02 +0000693uint32_t
694Host::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
695{
696
697 int num_pids;
698 int size_of_pids;
699 int *pid_list;
700 uint32_t num_matches = 0;
701
702 size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
703 if (size_of_pids == -1)
704 return 0;
705
706 num_pids = size_of_pids/sizeof(int);
707 pid_list = (int *) malloc(size_of_pids);
708 size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, pid_list, size_of_pids);
709 if (size_of_pids == -1)
710 return 0;
711
Benjamin Kramer410f7212010-08-10 13:22:03 +0000712 lldb::pid_t our_pid = getpid();
Jim Ingham7508e732010-08-09 23:31:02 +0000713
714 for (int i = 0; i < num_pids; i++)
715 {
716 struct proc_bsdinfo bsd_info;
717 int error = proc_pidinfo (pid_list[i], PROC_PIDTBSDINFO, (uint64_t) 0, &bsd_info, PROC_PIDTBSDINFO_SIZE);
718 if (error == 0)
719 continue;
720
721 // Don't offer to attach to zombie processes, already traced or exiting
722 // processes, and of course, ourselves... It looks like passing the second arg of
723 // 0 to proc_listpids will exclude zombies anyway, but that's not documented so...
Benjamin Kramer410f7212010-08-10 13:22:03 +0000724 if (((bsd_info.pbi_flags & (PROC_FLAG_TRACED | PROC_FLAG_INEXIT)) != 0)
Jim Ingham7508e732010-08-09 23:31:02 +0000725 || (bsd_info.pbi_status == SZOMB)
726 || (bsd_info.pbi_pid == our_pid))
727 continue;
728 char pid_name[MAXCOMLEN * 2 + 1];
729 int name_len;
730 name_len = proc_name(bsd_info.pbi_pid, pid_name, MAXCOMLEN * 2);
731 if (name_len == 0)
732 continue;
733
734 if (strstr(pid_name, name) != pid_name)
735 continue;
736 matches.AppendString (pid_name);
737 pids.push_back (bsd_info.pbi_pid);
738 num_matches++;
739 }
740
741 return num_matches;
742}
743
744ArchSpec
745Host::GetArchSpecForExistingProcess (lldb::pid_t pid)
746{
747 ArchSpec return_spec;
748
749 struct proc_bsdinfo bsd_info;
750 int error = proc_pidinfo (pid, PROC_PIDTBSDINFO, (uint64_t) 0, &bsd_info, PROC_PIDTBSDINFO_SIZE);
751 if (error == 0)
752 return return_spec;
753 if (bsd_info.pbi_flags & PROC_FLAG_LP64)
754 return_spec.SetArch(LLDB_ARCH_DEFAULT_64BIT);
755 else
756 return_spec.SetArch(LLDB_ARCH_DEFAULT_32BIT);
757
758 return return_spec;
759}
760
761ArchSpec
762Host::GetArchSpecForExistingProcess (const char *process_name)
763{
764 ArchSpec returnSpec;
765 StringList matches;
766 std::vector<lldb::pid_t> pids;
767 if (ListProcessesMatchingName(process_name, matches, pids))
768 {
769 if (matches.GetSize() == 1)
770 {
771 return GetArchSpecForExistingProcess(pids[0]);
772 }
773 }
774 return returnSpec;
775}