blob: 579b43fde6cb2cc8654139cba03c03f7cc644770 [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 Clayton54e7afa2010-07-09 20:39:50 +0000511 uint32_t handle;
Chris Lattner24943d22010-06-08 16:52:24 +0000512 pthread_t thread;
513 Host::MonitorChildProcessCallback callback;
514 void *callback_baton;
515 bool monitor_signals;
516};
517
518typedef std::multimap<lldb::pid_t, MonitorInfo> MonitorInfoMap;
519static pthread_mutex_t g_monitor_map_mutex = PTHREAD_MUTEX_INITIALIZER;
520typedef lldb::SharedPtr<MonitorInfoMap>::Type MonitorInfoMapSP;
521
522static MonitorInfoMapSP&
523GetMonitorMap (bool can_create)
524{
525 static MonitorInfoMapSP g_monitor_map_sp;
526 if (can_create && g_monitor_map_sp.get() == NULL)
527 {
528 g_monitor_map_sp.reset (new MonitorInfoMap);
529 }
530 return g_monitor_map_sp;
531}
532
533static Predicate<bool>&
534GetChildProcessPredicate ()
535{
536 static Predicate<bool> g_has_child_processes;
537 return g_has_child_processes;
538}
539
540static void *
541MonitorChildProcessThreadFunction (void *arg);
542
543static pthread_t g_monitor_thread;
544
545uint32_t
546Host::StartMonitoringChildProcess
547(
548 MonitorChildProcessCallback callback,
549 void *callback_baton,
550 lldb::pid_t pid,
551 bool monitor_signals
552)
553{
554 static uint32_t g_handle = 0;
555 if (callback)
556 {
557 Mutex::Locker locker(&g_monitor_map_mutex);
558 if (!g_monitor_thread)
559 {
Greg Claytonf2a4d2e2010-07-06 20:27:00 +0000560 lldb::pid_t wait_pid = -1;
Chris Lattner24943d22010-06-08 16:52:24 +0000561 g_monitor_thread = ThreadCreate ("<lldb.host.wait4>",
562 MonitorChildProcessThreadFunction,
563 &wait_pid,
564 NULL);
565 if (g_monitor_thread)
566 {
567 //Host::ThreadDetach (g_monitor_thread, NULL);
568 }
569 }
570
571 if (g_monitor_thread)
572 {
573 MonitorInfo info = { ++g_handle, 0, callback, callback_baton, monitor_signals };
574 MonitorInfoMapSP monitor_map_sp (GetMonitorMap (true));
575 if (monitor_map_sp)
576 {
577 monitor_map_sp->insert(std::make_pair(pid, info));
578 GetChildProcessPredicate ().SetValue (true, eBroadcastOnChange);
579 return info.handle;
580 }
581 }
582 }
583 return 0;
584}
585
586bool
587Host::StopMonitoringChildProcess (uint32_t handle)
588{
589 Mutex::Locker locker(&g_monitor_map_mutex);
590 MonitorInfoMapSP monitor_map_sp (GetMonitorMap (false));
591 if (monitor_map_sp)
592 {
593 MonitorInfoMap::iterator pos, end = monitor_map_sp->end();
594 for (pos = monitor_map_sp->end(); pos != end; ++pos)
595 {
596 if (pos->second.handle == handle)
597 {
598 monitor_map_sp->erase(pos);
599 return true;
600 }
601 }
602 }
603 return false;
604}
605
606
607//------------------------------------------------------------------
608// Scoped class that will disable thread canceling when it is
609// constructed, and exception safely restore the previous value it
610// when it goes out of scope.
611//------------------------------------------------------------------
612class ScopedPThreadCancelDisabler
613{
614public:
615
616 ScopedPThreadCancelDisabler()
617 {
618 // Disable the ability for this thread to be cancelled
619 int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state);
620 if (err != 0)
621 m_old_state = -1;
622
623 }
624
625 ~ScopedPThreadCancelDisabler()
626 {
627 // Restore the ability for this thread to be cancelled to what it
628 // previously was.
629 if (m_old_state != -1)
630 ::pthread_setcancelstate (m_old_state, 0);
631 }
632private:
633 int m_old_state; // Save the old cancelability state.
634};
635
636
637
638static void *
639MonitorChildProcessThreadFunction (void *arg)
640{
641 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
642 const char *function = __FUNCTION__;
643 if (log)
644 log->Printf ("%s (arg = %p) thread starting...", function, arg);
645
Greg Claytonf2a4d2e2010-07-06 20:27:00 +0000646 const lldb::pid_t wait_pid = -1;//*((pid_t*)arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000647 int status = -1;
648 const int options = 0;
649 struct rusage *rusage = NULL;
650 while (1)
651 {
652 if (log)
653 log->Printf("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p)...", function, wait_pid, options, rusage);
654
655 // Wait for all child processes
656 ::pthread_testcancel ();
657 lldb::pid_t pid = ::wait4 (wait_pid, &status, options, rusage);
658 ::pthread_testcancel ();
659
660 if (pid < 0)
661 {
662 // No child processes to watch wait for the mutex to be cleared
663
664 // Scope for "locker"
665 {
666 ScopedPThreadCancelDisabler pthread_cancel_disabler;
667
668 // First clear out all monitor entries since we have no processes
669 // to watch.
670 Mutex::Locker locker(&g_monitor_map_mutex);
671 // Since we don't have any child processes, we can safely clear
672 // anyone with a valid pid.
673 MonitorInfoMapSP monitor_map_sp(GetMonitorMap (false));
674 if (monitor_map_sp)
675 {
676 MonitorInfoMap::iterator pos = monitor_map_sp->begin();
677 while (pos != monitor_map_sp->end())
678 {
679 // pid value of 0 and -1 are special (see man page on wait4...)
680 if (pos->first > 0)
681 {
682 MonitorInfoMap::iterator next_pos = pos; ++next_pos;
683 monitor_map_sp->erase (pos, next_pos);
684 pos = next_pos;
685 }
686 else
687 ++pos;
688 }
689 }
690 }
691
692 if (log)
693 log->Printf("%s no child processes, wait for some...", function);
694 GetChildProcessPredicate ().SetValue (false, eBroadcastNever);
695 ::pthread_testcancel();
696 GetChildProcessPredicate ().WaitForValueEqualTo (true);
697 if (log)
698 log->Printf("%s resuming monitoring of child processes.", function);
699
700 }
701 else
702 {
703 ScopedPThreadCancelDisabler pthread_cancel_disabler;
704 bool exited = false;
705 int signal = 0;
706 int exit_status = 0;
707 const char *status_cstr = NULL;
708 if (WIFSTOPPED(status))
709 {
710 signal = WSTOPSIG(status);
711 status_cstr = "STOPPED";
712 }
713 else if (WIFEXITED(status))
714 {
715 exit_status = WEXITSTATUS(status);
716 status_cstr = "EXITED";
717 exited = true;
718 }
719 else if (WIFSIGNALED(status))
720 {
721 signal = WTERMSIG(status);
722 status_cstr = "SIGNALED";
723 exited = true;
724 exit_status = -1;
725 }
726 else
727 {
728 status_cstr = "(???)";
729 }
730
731 if (log)
732 log->Printf ("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_state = %i",
733 function,
734 wait_pid,
735 options,
736 rusage,
737 pid,
738 status,
739 status_cstr,
740 signal,
741 exit_status);
742
743 // Scope for mutex locker
744 {
745 // Notify anyone listening to this process
746 Mutex::Locker locker(&g_monitor_map_mutex);
747 MonitorInfoMapSP monitor_map_sp(GetMonitorMap (false));
748 if (monitor_map_sp)
749 {
750 std::pair<MonitorInfoMap::iterator, MonitorInfoMap::iterator> range;
751 range = monitor_map_sp->equal_range(pid);
752 MonitorInfoMap::iterator pos;
753 for (pos = range.first; pos != range.second; ++pos)
754 {
755 if (exited || (signal != 0 && pos->second.monitor_signals))
756 {
757 bool callback_return = pos->second.callback (pos->second.callback_baton, pid, signal, exit_status);
758
759 if (exited || callback_return)
760 {
761 // Make this entry as needing to be removed by
762 // setting its handle to zero
763 pos->second.handle = 0;
764 }
765 }
766 }
767
768 // Remove any entries that requested to be removed or any
769 // entries for child processes that did exit. We know this
770 // because we changed the handles to an invalid value.
771 pos = monitor_map_sp->begin();
772 while (pos != monitor_map_sp->end())
773 {
774 if (pos->second.handle == 0)
775 {
776 MonitorInfoMap::iterator next_pos = pos; ++next_pos;
777 monitor_map_sp->erase (pos, next_pos);
778 pos = next_pos;
779 }
780 else
781 ++pos;
782 }
783 }
784 }
785 }
786 }
787
788 if (log)
789 log->Printf ("ProcessMacOSX::%s (arg = %p) thread exiting...", __FUNCTION__, arg);
790
791 g_monitor_thread = NULL;
792 return NULL;
793}
794
795void
796Host::WillTerminate ()
797{
798 if (g_monitor_thread != NULL)
799 {
800 ThreadCancel (g_monitor_thread, NULL);
801 GetChildProcessPredicate ().SetValue (true, eBroadcastAlways);
802 ThreadJoin(g_monitor_thread, NULL, NULL);
803 g_monitor_thread = NULL;
804 }
805}
806
Jim Ingham7508e732010-08-09 23:31:02 +0000807uint32_t
808Host::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
809{
810
811 int num_pids;
812 int size_of_pids;
813 int *pid_list;
814 uint32_t num_matches = 0;
815
816 size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
817 if (size_of_pids == -1)
818 return 0;
819
820 num_pids = size_of_pids/sizeof(int);
821 pid_list = (int *) malloc(size_of_pids);
822 size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, pid_list, size_of_pids);
823 if (size_of_pids == -1)
824 return 0;
825
Benjamin Kramer410f7212010-08-10 13:22:03 +0000826 lldb::pid_t our_pid = getpid();
Jim Ingham7508e732010-08-09 23:31:02 +0000827
828 for (int i = 0; i < num_pids; i++)
829 {
830 struct proc_bsdinfo bsd_info;
831 int error = proc_pidinfo (pid_list[i], PROC_PIDTBSDINFO, (uint64_t) 0, &bsd_info, PROC_PIDTBSDINFO_SIZE);
832 if (error == 0)
833 continue;
834
835 // Don't offer to attach to zombie processes, already traced or exiting
836 // processes, and of course, ourselves... It looks like passing the second arg of
837 // 0 to proc_listpids will exclude zombies anyway, but that's not documented so...
Benjamin Kramer410f7212010-08-10 13:22:03 +0000838 if (((bsd_info.pbi_flags & (PROC_FLAG_TRACED | PROC_FLAG_INEXIT)) != 0)
Jim Ingham7508e732010-08-09 23:31:02 +0000839 || (bsd_info.pbi_status == SZOMB)
840 || (bsd_info.pbi_pid == our_pid))
841 continue;
842 char pid_name[MAXCOMLEN * 2 + 1];
843 int name_len;
844 name_len = proc_name(bsd_info.pbi_pid, pid_name, MAXCOMLEN * 2);
845 if (name_len == 0)
846 continue;
847
848 if (strstr(pid_name, name) != pid_name)
849 continue;
850 matches.AppendString (pid_name);
851 pids.push_back (bsd_info.pbi_pid);
852 num_matches++;
853 }
854
855 return num_matches;
856}
857
858ArchSpec
859Host::GetArchSpecForExistingProcess (lldb::pid_t pid)
860{
861 ArchSpec return_spec;
862
863 struct proc_bsdinfo bsd_info;
864 int error = proc_pidinfo (pid, PROC_PIDTBSDINFO, (uint64_t) 0, &bsd_info, PROC_PIDTBSDINFO_SIZE);
865 if (error == 0)
866 return return_spec;
867 if (bsd_info.pbi_flags & PROC_FLAG_LP64)
868 return_spec.SetArch(LLDB_ARCH_DEFAULT_64BIT);
869 else
870 return_spec.SetArch(LLDB_ARCH_DEFAULT_32BIT);
871
872 return return_spec;
873}
874
875ArchSpec
876Host::GetArchSpecForExistingProcess (const char *process_name)
877{
878 ArchSpec returnSpec;
879 StringList matches;
880 std::vector<lldb::pid_t> pids;
881 if (ListProcessesMatchingName(process_name, matches, pids))
882 {
883 if (matches.GetSize() == 1)
884 {
885 return GetArchSpecForExistingProcess(pids[0]);
886 }
887 }
888 return returnSpec;
889}