blob: 4bd78df1b513c9b86093e9e77451015e413834bb [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;
Johnny Chen99343352010-08-23 17:13:12 +0000328 // rdar://problem/8153284
329 // Fixed a crasher where during shutdown, loggings attempted to access the
330 // thread name but the static map instance had already been destructed.
331 // Another approach is to introduce a static guard object which monitors its
332 // own destruction and raises a flag, but this incurs more overhead.
333 static thread_name_map *g_thread_names_ptr = new thread_name_map();
334 thread_name_map &g_thread_names = *g_thread_names_ptr;
Chris Lattner24943d22010-06-08 16:52:24 +0000335
336 if (get)
337 {
338 // See if the thread name exists in our thread name pool
339 thread_name_map::iterator pos = g_thread_names.find(pid_tid);
340 if (pos != g_thread_names.end())
341 return pos->second.c_str();
342 }
343 else
344 {
345 // Set the thread name
346 g_thread_names[pid_tid] = name;
347 }
348 return NULL;
349}
350
351
352
353const char *
354Host::GetSignalAsCString (int signo)
355{
356 switch (signo)
357 {
358 case SIGHUP: return "SIGHUP"; // 1 hangup
359 case SIGINT: return "SIGINT"; // 2 interrupt
360 case SIGQUIT: return "SIGQUIT"; // 3 quit
361 case SIGILL: return "SIGILL"; // 4 illegal instruction (not reset when caught)
362 case SIGTRAP: return "SIGTRAP"; // 5 trace trap (not reset when caught)
363 case SIGABRT: return "SIGABRT"; // 6 abort()
364#if defined(_POSIX_C_SOURCE)
365 case SIGPOLL: return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported)
366#else // !_POSIX_C_SOURCE
367 case SIGEMT: return "SIGEMT"; // 7 EMT instruction
368#endif // !_POSIX_C_SOURCE
369 case SIGFPE: return "SIGFPE"; // 8 floating point exception
370 case SIGKILL: return "SIGKILL"; // 9 kill (cannot be caught or ignored)
371 case SIGBUS: return "SIGBUS"; // 10 bus error
372 case SIGSEGV: return "SIGSEGV"; // 11 segmentation violation
373 case SIGSYS: return "SIGSYS"; // 12 bad argument to system call
374 case SIGPIPE: return "SIGPIPE"; // 13 write on a pipe with no one to read it
375 case SIGALRM: return "SIGALRM"; // 14 alarm clock
376 case SIGTERM: return "SIGTERM"; // 15 software termination signal from kill
377 case SIGURG: return "SIGURG"; // 16 urgent condition on IO channel
378 case SIGSTOP: return "SIGSTOP"; // 17 sendable stop signal not from tty
379 case SIGTSTP: return "SIGTSTP"; // 18 stop signal from tty
380 case SIGCONT: return "SIGCONT"; // 19 continue a stopped process
381 case SIGCHLD: return "SIGCHLD"; // 20 to parent on child stop or exit
382 case SIGTTIN: return "SIGTTIN"; // 21 to readers pgrp upon background tty read
383 case SIGTTOU: return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local&LTOSTOP)
384#if !defined(_POSIX_C_SOURCE)
385 case SIGIO: return "SIGIO"; // 23 input/output possible signal
386#endif
387 case SIGXCPU: return "SIGXCPU"; // 24 exceeded CPU time limit
388 case SIGXFSZ: return "SIGXFSZ"; // 25 exceeded file size limit
389 case SIGVTALRM: return "SIGVTALRM"; // 26 virtual time alarm
390 case SIGPROF: return "SIGPROF"; // 27 profiling time alarm
391#if !defined(_POSIX_C_SOURCE)
392 case SIGWINCH: return "SIGWINCH"; // 28 window size changes
393 case SIGINFO: return "SIGINFO"; // 29 information request
394#endif
395 case SIGUSR1: return "SIGUSR1"; // 30 user defined signal 1
396 case SIGUSR2: return "SIGUSR2"; // 31 user defined signal 2
397 default:
398 break;
399 }
400 return NULL;
401}
402
403const char *
404Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
405{
406 const char *name = ThreadNameAccessor (true, pid, tid, NULL);
407 if (name == NULL)
408 {
409 // We currently can only get the name of a thread in the current process.
410#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
411 if (pid == Host::GetCurrentProcessID())
412 {
413 char pthread_name[1024];
414 if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0)
415 {
416 if (pthread_name[0])
417 {
418 // Set the thread in our string pool
419 ThreadNameAccessor (false, pid, tid, pthread_name);
420 // Get our copy of the thread name string
421 name = ThreadNameAccessor (true, pid, tid, NULL);
422 }
423 }
424 }
425#endif
426 }
427 return name;
428}
429
430void
431Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name)
432{
433 lldb::pid_t curr_pid = Host::GetCurrentProcessID();
434 lldb::tid_t curr_tid = Host::GetCurrentThreadID();
435 if (pid == LLDB_INVALID_PROCESS_ID)
436 pid = curr_pid;
437
438 if (tid == LLDB_INVALID_THREAD_ID)
439 tid = curr_tid;
440
441#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
442 // Set the pthread name if possible
443 if (pid == curr_pid && tid == curr_tid)
444 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000445 ::pthread_setname_np (name);
Chris Lattner24943d22010-06-08 16:52:24 +0000446 }
447#endif
448 ThreadNameAccessor (false, pid, tid, name);
449}
450
451FileSpec
452Host::GetProgramFileSpec ()
453{
454 static FileSpec g_program_filepsec;
455 if (!g_program_filepsec)
456 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000457 char program_fullpath[PATH_MAX];
Chris Lattner24943d22010-06-08 16:52:24 +0000458 // If DST is NULL, then return the number of bytes needed.
Greg Clayton54e7afa2010-07-09 20:39:50 +0000459 uint32_t len = sizeof(program_fullpath);
460 int err = _NSGetExecutablePath (program_fullpath, &len);
Chris Lattner24943d22010-06-08 16:52:24 +0000461 if (err == 0)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000462 g_program_filepsec.SetFile (program_fullpath);
463 else if (err == -1)
464 {
465 char *large_program_fullpath = (char *)::malloc (len + 1);
466
467 err = _NSGetExecutablePath (large_program_fullpath, &len);
468 if (err == 0)
469 g_program_filepsec.SetFile (large_program_fullpath);
470
471 ::free (large_program_fullpath);
472 }
Chris Lattner24943d22010-06-08 16:52:24 +0000473 }
474 return g_program_filepsec;
475}
476
477
478FileSpec
479Host::GetModuleFileSpecForHostAddress (const void *host_addr)
480{
481 FileSpec module_filespec;
482 Dl_info info;
483 if (::dladdr (host_addr, &info))
484 {
485 if (info.dli_fname)
486 module_filespec.SetFile(info.dli_fname);
487 }
488 return module_filespec;
489}
490
491
492bool
493Host::ResolveExecutableInBundle (FileSpec *file)
494{
495 if (file->GetFileType () == FileSpec::eFileTypeDirectory)
496 {
497 char path[PATH_MAX];
498 if (file->GetPath(path, sizeof(path)))
499 {
500 CFCBundle bundle (path);
501 CFCReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
502 if (url.get())
503 {
504 if (::CFURLGetFileSystemRepresentation (url.get(), YES, (UInt8*)path, sizeof(path)))
505 {
506 file->SetFile(path);
507 return true;
508 }
509 }
510 }
511 }
512 return false;
513}
514
Greg Claytonc0418152010-07-07 17:07:17 +0000515struct MonitorInfo
Chris Lattner24943d22010-06-08 16:52:24 +0000516{
Greg Clayton75ccf502010-08-21 02:22:51 +0000517 lldb::pid_t pid; // The process ID to monitor
518 Host::MonitorChildProcessCallback callback; // The callback function to call when "pid" exits or signals
519 void *callback_baton; // The callback baton for the callback function
520 bool monitor_signals; // If true, call the callback when "pid" gets signaled.
Chris Lattner24943d22010-06-08 16:52:24 +0000521};
522
Chris Lattner24943d22010-06-08 16:52:24 +0000523static void *
524MonitorChildProcessThreadFunction (void *arg);
525
Greg Clayton75ccf502010-08-21 02:22:51 +0000526lldb::thread_t
Chris Lattner24943d22010-06-08 16:52:24 +0000527Host::StartMonitoringChildProcess
528(
Greg Clayton75ccf502010-08-21 02:22:51 +0000529 Host::MonitorChildProcessCallback callback,
Chris Lattner24943d22010-06-08 16:52:24 +0000530 void *callback_baton,
531 lldb::pid_t pid,
532 bool monitor_signals
533)
534{
Greg Clayton75ccf502010-08-21 02:22:51 +0000535
536 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
Chris Lattner24943d22010-06-08 16:52:24 +0000537 if (callback)
538 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000539 std::auto_ptr<MonitorInfo> info_ap(new MonitorInfo);
540
541 info_ap->pid = pid;
542 info_ap->callback = callback;
543 info_ap->callback_baton = callback_baton;
544 info_ap->monitor_signals = monitor_signals;
545
546 char thread_name[256];
547 ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%i)>", pid);
548 thread = ThreadCreate (thread_name,
549 MonitorChildProcessThreadFunction,
550 info_ap.get(),
551 NULL);
552
553 if (thread != LLDB_INVALID_HOST_THREAD)
554 info_ap.release();
Chris Lattner24943d22010-06-08 16:52:24 +0000555 }
Greg Clayton75ccf502010-08-21 02:22:51 +0000556 return thread;
Chris Lattner24943d22010-06-08 16:52:24 +0000557}
558
Chris Lattner24943d22010-06-08 16:52:24 +0000559//------------------------------------------------------------------
560// Scoped class that will disable thread canceling when it is
561// constructed, and exception safely restore the previous value it
562// when it goes out of scope.
563//------------------------------------------------------------------
564class ScopedPThreadCancelDisabler
565{
566public:
567
568 ScopedPThreadCancelDisabler()
569 {
570 // Disable the ability for this thread to be cancelled
571 int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state);
572 if (err != 0)
573 m_old_state = -1;
574
575 }
576
577 ~ScopedPThreadCancelDisabler()
578 {
579 // Restore the ability for this thread to be cancelled to what it
580 // previously was.
581 if (m_old_state != -1)
582 ::pthread_setcancelstate (m_old_state, 0);
583 }
584private:
585 int m_old_state; // Save the old cancelability state.
586};
587
588
589
590static void *
591MonitorChildProcessThreadFunction (void *arg)
592{
593 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
594 const char *function = __FUNCTION__;
595 if (log)
596 log->Printf ("%s (arg = %p) thread starting...", function, arg);
597
Greg Clayton75ccf502010-08-21 02:22:51 +0000598 MonitorInfo *info = (MonitorInfo *)arg;
599
600 const Host::MonitorChildProcessCallback callback = info->callback;
601 void * const callback_baton = info->callback_baton;
602 const lldb::pid_t pid = info->pid;
603 const bool monitor_signals = info->monitor_signals;
604
605 delete info;
606
Chris Lattner24943d22010-06-08 16:52:24 +0000607 int status = -1;
608 const int options = 0;
609 struct rusage *rusage = NULL;
610 while (1)
611 {
612 if (log)
Greg Clayton75ccf502010-08-21 02:22:51 +0000613 log->Printf("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p)...", function, pid, options, rusage);
Chris Lattner24943d22010-06-08 16:52:24 +0000614
615 // Wait for all child processes
616 ::pthread_testcancel ();
Greg Clayton75ccf502010-08-21 02:22:51 +0000617 const lldb::pid_t wait_pid = ::wait4 (pid, &status, options, rusage);
Chris Lattner24943d22010-06-08 16:52:24 +0000618 ::pthread_testcancel ();
619
Greg Clayton75ccf502010-08-21 02:22:51 +0000620 if (wait_pid == -1)
Chris Lattner24943d22010-06-08 16:52:24 +0000621 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000622 if (errno == EINTR)
623 continue;
624 else
625 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000626 }
Greg Clayton75ccf502010-08-21 02:22:51 +0000627 else if (wait_pid == pid)
Chris Lattner24943d22010-06-08 16:52:24 +0000628 {
Chris Lattner24943d22010-06-08 16:52:24 +0000629 bool exited = false;
630 int signal = 0;
631 int exit_status = 0;
632 const char *status_cstr = NULL;
633 if (WIFSTOPPED(status))
634 {
635 signal = WSTOPSIG(status);
636 status_cstr = "STOPPED";
637 }
638 else if (WIFEXITED(status))
639 {
640 exit_status = WEXITSTATUS(status);
641 status_cstr = "EXITED";
642 exited = true;
643 }
644 else if (WIFSIGNALED(status))
645 {
646 signal = WTERMSIG(status);
647 status_cstr = "SIGNALED";
648 exited = true;
649 exit_status = -1;
650 }
651 else
652 {
653 status_cstr = "(???)";
654 }
655
Greg Clayton75ccf502010-08-21 02:22:51 +0000656 // Scope for pthread_cancel_disabler
Chris Lattner24943d22010-06-08 16:52:24 +0000657 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000658 ScopedPThreadCancelDisabler pthread_cancel_disabler;
659
660 if (log)
661 log->Printf ("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_state = %i",
662 function,
663 wait_pid,
664 options,
665 rusage,
666 pid,
667 status,
668 status_cstr,
669 signal,
670 exit_status);
671
672 if (exited || (signal != 0 && monitor_signals))
Chris Lattner24943d22010-06-08 16:52:24 +0000673 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000674 bool callback_return = callback (callback_baton, pid, signal, exit_status);
675
676 // If our process exited, then this thread should exit
677 if (exited)
678 break;
679 // If the callback returns true, it means this process should
680 // exit
681 if (callback_return)
682 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000683 }
684 }
685 }
686 }
687
688 if (log)
Greg Clayton75ccf502010-08-21 02:22:51 +0000689 log->Printf ("%s (arg = %p) thread exiting...", __FUNCTION__, arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000690
Chris Lattner24943d22010-06-08 16:52:24 +0000691 return NULL;
692}
693
694void
695Host::WillTerminate ()
696{
Chris Lattner24943d22010-06-08 16:52:24 +0000697}
698
Jim Ingham7508e732010-08-09 23:31:02 +0000699uint32_t
700Host::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
701{
702
703 int num_pids;
704 int size_of_pids;
705 int *pid_list;
706 uint32_t num_matches = 0;
707
708 size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
709 if (size_of_pids == -1)
710 return 0;
711
712 num_pids = size_of_pids/sizeof(int);
713 pid_list = (int *) malloc(size_of_pids);
714 size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, pid_list, size_of_pids);
715 if (size_of_pids == -1)
716 return 0;
717
Benjamin Kramer410f7212010-08-10 13:22:03 +0000718 lldb::pid_t our_pid = getpid();
Jim Ingham7508e732010-08-09 23:31:02 +0000719
720 for (int i = 0; i < num_pids; i++)
721 {
722 struct proc_bsdinfo bsd_info;
723 int error = proc_pidinfo (pid_list[i], PROC_PIDTBSDINFO, (uint64_t) 0, &bsd_info, PROC_PIDTBSDINFO_SIZE);
724 if (error == 0)
725 continue;
726
727 // Don't offer to attach to zombie processes, already traced or exiting
728 // processes, and of course, ourselves... It looks like passing the second arg of
729 // 0 to proc_listpids will exclude zombies anyway, but that's not documented so...
Benjamin Kramer410f7212010-08-10 13:22:03 +0000730 if (((bsd_info.pbi_flags & (PROC_FLAG_TRACED | PROC_FLAG_INEXIT)) != 0)
Jim Ingham7508e732010-08-09 23:31:02 +0000731 || (bsd_info.pbi_status == SZOMB)
732 || (bsd_info.pbi_pid == our_pid))
733 continue;
734 char pid_name[MAXCOMLEN * 2 + 1];
735 int name_len;
736 name_len = proc_name(bsd_info.pbi_pid, pid_name, MAXCOMLEN * 2);
737 if (name_len == 0)
738 continue;
739
740 if (strstr(pid_name, name) != pid_name)
741 continue;
742 matches.AppendString (pid_name);
743 pids.push_back (bsd_info.pbi_pid);
744 num_matches++;
745 }
746
747 return num_matches;
748}
749
750ArchSpec
751Host::GetArchSpecForExistingProcess (lldb::pid_t pid)
752{
753 ArchSpec return_spec;
754
755 struct proc_bsdinfo bsd_info;
756 int error = proc_pidinfo (pid, PROC_PIDTBSDINFO, (uint64_t) 0, &bsd_info, PROC_PIDTBSDINFO_SIZE);
757 if (error == 0)
758 return return_spec;
759 if (bsd_info.pbi_flags & PROC_FLAG_LP64)
760 return_spec.SetArch(LLDB_ARCH_DEFAULT_64BIT);
761 else
762 return_spec.SetArch(LLDB_ARCH_DEFAULT_32BIT);
763
764 return return_spec;
765}
766
767ArchSpec
768Host::GetArchSpecForExistingProcess (const char *process_name)
769{
770 ArchSpec returnSpec;
771 StringList matches;
772 std::vector<lldb::pid_t> pids;
773 if (ListProcessesMatchingName(process_name, matches, pids))
774 {
775 if (matches.GetSize() == 1)
776 {
777 return GetArchSpecForExistingProcess(pids[0]);
778 }
779 }
780 return returnSpec;
781}