blob: 2191d8b6137d560781acd6f6bc414e4a2cbad714 [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>
Jim Ingham74989e82010-08-30 19:44:40 +000027#include <CoreServices/CoreServices.h>
28#include <Carbon/Carbon.h>
Chris Lattner24943d22010-06-08 16:52:24 +000029
Greg Clayton54e7afa2010-07-09 20:39:50 +000030#include "cfcpp/CFCBundle.h"
31#include "cfcpp/CFCReleaser.h"
32#include "cfcpp/CFCString.h"
Chris Lattner24943d22010-06-08 16:52:24 +000033
34#include "lldb/Host/Host.h"
35#include "lldb/Core/ArchSpec.h"
36#include "lldb/Core/ConstString.h"
37#include "lldb/Core/Error.h"
38#include "lldb/Core/FileSpec.h"
39#include "lldb/Core/Log.h"
40#include "lldb/Core/StreamString.h"
41#include "lldb/Host/Mutex.h"
42#include "lldb/Target/Process.h"
43#include "lldb/Target/Target.h"
44#include "lldb/Target/TargetList.h"
45#include "lldb/lldb-private-log.h"
46
47using namespace lldb;
48using namespace lldb_private;
49
50//------------------------------------------------------------------
51// Return the size in bytes of a page on the host system
52//------------------------------------------------------------------
53size_t
54Host::GetPageSize()
55{
56 return ::getpagesize();
57}
58
59
60//------------------------------------------------------------------
61// Returns true if the host system is Big Endian.
62//------------------------------------------------------------------
63ByteOrder
64Host::GetByteOrder()
65{
66 union EndianTest
67 {
68 uint32_t num;
69 uint8_t bytes[sizeof(uint32_t)];
70 } endian = { (uint16_t)0x11223344 };
71 switch (endian.bytes[0])
72 {
73 case 0x11: return eByteOrderLittle;
74 case 0x44: return eByteOrderBig;
75 case 0x33: return eByteOrderPDP;
76 }
77 return eByteOrderInvalid;
78}
79
80lldb::pid_t
81Host::GetCurrentProcessID()
82{
83 return ::getpid();
84}
85
86lldb::pid_t
87Host::GetCurrentThreadID()
88{
89 return ::mach_thread_self();
90}
91
92
93const ArchSpec &
94Host::GetArchitecture ()
95{
96 static ArchSpec g_host_arch;
97 if (!g_host_arch.IsValid())
98 {
99 uint32_t cputype, cpusubtype;
100 uint32_t is_64_bit_capable;
101 size_t len = sizeof(cputype);
102 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
103 {
104 len = sizeof(cpusubtype);
105 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
106 g_host_arch.SetArch(cputype, cpusubtype);
107
108 len = sizeof (is_64_bit_capable);
109 if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
110 {
111 if (is_64_bit_capable)
112 {
113 if (cputype == CPU_TYPE_I386 && cpusubtype == CPU_SUBTYPE_486)
114 cpusubtype = CPU_SUBTYPE_I386_ALL;
115
116 cputype |= CPU_ARCH_ABI64;
117 }
118 }
119 }
120 }
121 return g_host_arch;
122}
123
124const ConstString &
125Host::GetVendorString()
126{
127 static ConstString g_vendor;
128 if (!g_vendor)
129 {
130 char ostype[64];
131 size_t len = sizeof(ostype);
132 if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
133 g_vendor.SetCString (ostype);
134 }
135 return g_vendor;
136}
137
138const ConstString &
139Host::GetOSString()
140{
141 static ConstString g_os_string("apple");
142 return g_os_string;
143}
144
145const ConstString &
146Host::GetTargetTriple()
147{
148 static ConstString g_host_triple;
149 if (!(g_host_triple))
150 {
151 StreamString triple;
152 triple.Printf("%s-%s-%s",
153 GetArchitecture ().AsCString(),
154 GetVendorString().AsCString("apple"),
155 GetOSString().AsCString("darwin"));
156
157 std::transform (triple.GetString().begin(),
158 triple.GetString().end(),
159 triple.GetString().begin(),
160 ::tolower);
161
162 g_host_triple.SetCString(triple.GetString().c_str());
163 }
164 return g_host_triple;
165}
166
167class MacOSXDarwinThread
168{
169public:
170 MacOSXDarwinThread(const char *thread_name) :
171 m_pool (nil)
172 {
173 // Register our thread with the collector if garbage collection is enabled.
174 if (objc_collectingEnabled())
175 {
176#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
177 // On Leopard and earlier there is no way objc_registerThreadWithCollector
178 // function, so we do it manually.
179 auto_zone_register_thread(auto_zone());
180#else
181 // On SnowLoepard and later we just call the thread registration function.
182 objc_registerThreadWithCollector();
183#endif
184 }
185 else
186 {
187 m_pool = [[NSAutoreleasePool alloc] init];
188 }
189
190
191 Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name);
192 }
193
194 ~MacOSXDarwinThread()
195 {
196 if (m_pool)
197 [m_pool release];
198 }
199
200 static void PThreadDestructor (void *v)
201 {
202 delete (MacOSXDarwinThread*)v;
203 }
204
205protected:
206 NSAutoreleasePool * m_pool;
207private:
208 DISALLOW_COPY_AND_ASSIGN (MacOSXDarwinThread);
209};
210
211static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT;
212static pthread_key_t g_thread_create_key = 0;
213
214static void
215InitThreadCreated()
216{
217 ::pthread_key_create (&g_thread_create_key, MacOSXDarwinThread::PThreadDestructor);
218}
219
Greg Claytonc0418152010-07-07 17:07:17 +0000220struct HostThreadCreateInfo
Chris Lattner24943d22010-06-08 16:52:24 +0000221{
222 std::string thread_name;
223 thread_func_t thread_fptr;
224 thread_arg_t thread_arg;
225
226 HostThreadCreateInfo (const char *name, thread_func_t fptr, thread_arg_t arg) :
227 thread_name (name ? name : ""),
228 thread_fptr (fptr),
229 thread_arg (arg)
230 {
231 }
232};
233
234static thread_result_t
235ThreadCreateTrampoline (thread_arg_t arg)
236{
237 HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg;
238 Host::ThreadCreated (info->thread_name.c_str());
239 thread_func_t thread_fptr = info->thread_fptr;
240 thread_arg_t thread_arg = info->thread_arg;
241
242 Log * log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);
243 if (log)
244 log->Printf("thread created");
245
246 delete info;
247 return thread_fptr (thread_arg);
248}
249
250lldb::thread_t
251Host::ThreadCreate
252(
253 const char *thread_name,
254 thread_func_t thread_fptr,
255 thread_arg_t thread_arg,
256 Error *error
257)
258{
259 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
260
261 // Host::ThreadCreateTrampoline will delete this pointer for us.
262 HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg);
263
264 int err = ::pthread_create (&thread, NULL, ThreadCreateTrampoline, info_ptr);
265 if (err == 0)
266 {
267 if (error)
268 error->Clear();
269 return thread;
270 }
271
272 if (error)
273 error->SetError (err, eErrorTypePOSIX);
274
275 return LLDB_INVALID_HOST_THREAD;
276}
277
278bool
279Host::ThreadCancel (lldb::thread_t thread, Error *error)
280{
281
282 int err = ::pthread_cancel (thread);
283 if (error)
284 error->SetError(err, eErrorTypePOSIX);
285 return err == 0;
286}
287
288bool
289Host::ThreadDetach (lldb::thread_t thread, Error *error)
290{
291 int err = ::pthread_detach (thread);
292 if (error)
293 error->SetError(err, eErrorTypePOSIX);
294 return err == 0;
295}
296
297bool
298Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error)
299{
300 int err = ::pthread_join (thread, thread_result_ptr);
301 if (error)
302 error->SetError(err, eErrorTypePOSIX);
303 return err == 0;
304}
305
306void
307Host::ThreadCreated (const char *thread_name)
308{
309 ::pthread_once (&g_thread_create_once, InitThreadCreated);
310 if (g_thread_create_key)
311 {
312 ::pthread_setspecific (g_thread_create_key, new MacOSXDarwinThread(thread_name));
313 }
314}
315
316//------------------------------------------------------------------
317// Control access to a static file thread name map using a single
318// static function to avoid a static constructor.
319//------------------------------------------------------------------
320static const char *
321ThreadNameAccessor (bool get, lldb::pid_t pid, lldb::tid_t tid, const char *name)
322{
323
324 uint64_t pid_tid = ((uint64_t)pid << 32) | (uint64_t)tid;
325
326 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
327 Mutex::Locker locker(&g_mutex);
328
329 typedef std::map<uint64_t, std::string> thread_name_map;
Johnny Chen99343352010-08-23 17:13:12 +0000330 // rdar://problem/8153284
331 // Fixed a crasher where during shutdown, loggings attempted to access the
332 // thread name but the static map instance had already been destructed.
333 // Another approach is to introduce a static guard object which monitors its
334 // own destruction and raises a flag, but this incurs more overhead.
335 static thread_name_map *g_thread_names_ptr = new thread_name_map();
336 thread_name_map &g_thread_names = *g_thread_names_ptr;
Chris Lattner24943d22010-06-08 16:52:24 +0000337
338 if (get)
339 {
340 // See if the thread name exists in our thread name pool
341 thread_name_map::iterator pos = g_thread_names.find(pid_tid);
342 if (pos != g_thread_names.end())
343 return pos->second.c_str();
344 }
345 else
346 {
347 // Set the thread name
348 g_thread_names[pid_tid] = name;
349 }
350 return NULL;
351}
352
353
354
355const char *
356Host::GetSignalAsCString (int signo)
357{
358 switch (signo)
359 {
360 case SIGHUP: return "SIGHUP"; // 1 hangup
361 case SIGINT: return "SIGINT"; // 2 interrupt
362 case SIGQUIT: return "SIGQUIT"; // 3 quit
363 case SIGILL: return "SIGILL"; // 4 illegal instruction (not reset when caught)
364 case SIGTRAP: return "SIGTRAP"; // 5 trace trap (not reset when caught)
365 case SIGABRT: return "SIGABRT"; // 6 abort()
366#if defined(_POSIX_C_SOURCE)
367 case SIGPOLL: return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported)
368#else // !_POSIX_C_SOURCE
369 case SIGEMT: return "SIGEMT"; // 7 EMT instruction
370#endif // !_POSIX_C_SOURCE
371 case SIGFPE: return "SIGFPE"; // 8 floating point exception
372 case SIGKILL: return "SIGKILL"; // 9 kill (cannot be caught or ignored)
373 case SIGBUS: return "SIGBUS"; // 10 bus error
374 case SIGSEGV: return "SIGSEGV"; // 11 segmentation violation
375 case SIGSYS: return "SIGSYS"; // 12 bad argument to system call
376 case SIGPIPE: return "SIGPIPE"; // 13 write on a pipe with no one to read it
377 case SIGALRM: return "SIGALRM"; // 14 alarm clock
378 case SIGTERM: return "SIGTERM"; // 15 software termination signal from kill
379 case SIGURG: return "SIGURG"; // 16 urgent condition on IO channel
380 case SIGSTOP: return "SIGSTOP"; // 17 sendable stop signal not from tty
381 case SIGTSTP: return "SIGTSTP"; // 18 stop signal from tty
382 case SIGCONT: return "SIGCONT"; // 19 continue a stopped process
383 case SIGCHLD: return "SIGCHLD"; // 20 to parent on child stop or exit
384 case SIGTTIN: return "SIGTTIN"; // 21 to readers pgrp upon background tty read
385 case SIGTTOU: return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local&LTOSTOP)
386#if !defined(_POSIX_C_SOURCE)
387 case SIGIO: return "SIGIO"; // 23 input/output possible signal
388#endif
389 case SIGXCPU: return "SIGXCPU"; // 24 exceeded CPU time limit
390 case SIGXFSZ: return "SIGXFSZ"; // 25 exceeded file size limit
391 case SIGVTALRM: return "SIGVTALRM"; // 26 virtual time alarm
392 case SIGPROF: return "SIGPROF"; // 27 profiling time alarm
393#if !defined(_POSIX_C_SOURCE)
394 case SIGWINCH: return "SIGWINCH"; // 28 window size changes
395 case SIGINFO: return "SIGINFO"; // 29 information request
396#endif
397 case SIGUSR1: return "SIGUSR1"; // 30 user defined signal 1
398 case SIGUSR2: return "SIGUSR2"; // 31 user defined signal 2
399 default:
400 break;
401 }
402 return NULL;
403}
404
405const char *
406Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
407{
408 const char *name = ThreadNameAccessor (true, pid, tid, NULL);
409 if (name == NULL)
410 {
411 // We currently can only get the name of a thread in the current process.
412#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
413 if (pid == Host::GetCurrentProcessID())
414 {
415 char pthread_name[1024];
416 if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0)
417 {
418 if (pthread_name[0])
419 {
420 // Set the thread in our string pool
421 ThreadNameAccessor (false, pid, tid, pthread_name);
422 // Get our copy of the thread name string
423 name = ThreadNameAccessor (true, pid, tid, NULL);
424 }
425 }
426 }
427#endif
428 }
429 return name;
430}
431
432void
433Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name)
434{
435 lldb::pid_t curr_pid = Host::GetCurrentProcessID();
436 lldb::tid_t curr_tid = Host::GetCurrentThreadID();
437 if (pid == LLDB_INVALID_PROCESS_ID)
438 pid = curr_pid;
439
440 if (tid == LLDB_INVALID_THREAD_ID)
441 tid = curr_tid;
442
443#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
444 // Set the pthread name if possible
445 if (pid == curr_pid && tid == curr_tid)
446 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000447 ::pthread_setname_np (name);
Chris Lattner24943d22010-06-08 16:52:24 +0000448 }
449#endif
450 ThreadNameAccessor (false, pid, tid, name);
451}
452
453FileSpec
454Host::GetProgramFileSpec ()
455{
456 static FileSpec g_program_filepsec;
457 if (!g_program_filepsec)
458 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000459 char program_fullpath[PATH_MAX];
Chris Lattner24943d22010-06-08 16:52:24 +0000460 // If DST is NULL, then return the number of bytes needed.
Greg Clayton54e7afa2010-07-09 20:39:50 +0000461 uint32_t len = sizeof(program_fullpath);
462 int err = _NSGetExecutablePath (program_fullpath, &len);
Chris Lattner24943d22010-06-08 16:52:24 +0000463 if (err == 0)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000464 g_program_filepsec.SetFile (program_fullpath);
465 else if (err == -1)
466 {
467 char *large_program_fullpath = (char *)::malloc (len + 1);
468
469 err = _NSGetExecutablePath (large_program_fullpath, &len);
470 if (err == 0)
471 g_program_filepsec.SetFile (large_program_fullpath);
472
473 ::free (large_program_fullpath);
474 }
Chris Lattner24943d22010-06-08 16:52:24 +0000475 }
476 return g_program_filepsec;
477}
478
479
480FileSpec
481Host::GetModuleFileSpecForHostAddress (const void *host_addr)
482{
483 FileSpec module_filespec;
484 Dl_info info;
485 if (::dladdr (host_addr, &info))
486 {
487 if (info.dli_fname)
488 module_filespec.SetFile(info.dli_fname);
489 }
490 return module_filespec;
491}
492
493
494bool
495Host::ResolveExecutableInBundle (FileSpec *file)
496{
497 if (file->GetFileType () == FileSpec::eFileTypeDirectory)
498 {
499 char path[PATH_MAX];
500 if (file->GetPath(path, sizeof(path)))
501 {
502 CFCBundle bundle (path);
503 CFCReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
504 if (url.get())
505 {
506 if (::CFURLGetFileSystemRepresentation (url.get(), YES, (UInt8*)path, sizeof(path)))
507 {
508 file->SetFile(path);
509 return true;
510 }
511 }
512 }
513 }
514 return false;
515}
516
Greg Claytonc0418152010-07-07 17:07:17 +0000517struct MonitorInfo
Chris Lattner24943d22010-06-08 16:52:24 +0000518{
Greg Clayton75ccf502010-08-21 02:22:51 +0000519 lldb::pid_t pid; // The process ID to monitor
520 Host::MonitorChildProcessCallback callback; // The callback function to call when "pid" exits or signals
521 void *callback_baton; // The callback baton for the callback function
522 bool monitor_signals; // If true, call the callback when "pid" gets signaled.
Chris Lattner24943d22010-06-08 16:52:24 +0000523};
524
Chris Lattner24943d22010-06-08 16:52:24 +0000525static void *
526MonitorChildProcessThreadFunction (void *arg);
527
Greg Clayton75ccf502010-08-21 02:22:51 +0000528lldb::thread_t
Chris Lattner24943d22010-06-08 16:52:24 +0000529Host::StartMonitoringChildProcess
530(
Greg Clayton75ccf502010-08-21 02:22:51 +0000531 Host::MonitorChildProcessCallback callback,
Chris Lattner24943d22010-06-08 16:52:24 +0000532 void *callback_baton,
533 lldb::pid_t pid,
534 bool monitor_signals
535)
536{
Greg Clayton75ccf502010-08-21 02:22:51 +0000537
538 lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
Chris Lattner24943d22010-06-08 16:52:24 +0000539 if (callback)
540 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000541 std::auto_ptr<MonitorInfo> info_ap(new MonitorInfo);
542
543 info_ap->pid = pid;
544 info_ap->callback = callback;
545 info_ap->callback_baton = callback_baton;
546 info_ap->monitor_signals = monitor_signals;
547
548 char thread_name[256];
549 ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%i)>", pid);
550 thread = ThreadCreate (thread_name,
551 MonitorChildProcessThreadFunction,
552 info_ap.get(),
553 NULL);
554
555 if (thread != LLDB_INVALID_HOST_THREAD)
556 info_ap.release();
Chris Lattner24943d22010-06-08 16:52:24 +0000557 }
Greg Clayton75ccf502010-08-21 02:22:51 +0000558 return thread;
Chris Lattner24943d22010-06-08 16:52:24 +0000559}
560
Chris Lattner24943d22010-06-08 16:52:24 +0000561//------------------------------------------------------------------
562// Scoped class that will disable thread canceling when it is
563// constructed, and exception safely restore the previous value it
564// when it goes out of scope.
565//------------------------------------------------------------------
566class ScopedPThreadCancelDisabler
567{
568public:
569
570 ScopedPThreadCancelDisabler()
571 {
572 // Disable the ability for this thread to be cancelled
573 int err = ::pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &m_old_state);
574 if (err != 0)
575 m_old_state = -1;
576
577 }
578
579 ~ScopedPThreadCancelDisabler()
580 {
581 // Restore the ability for this thread to be cancelled to what it
582 // previously was.
583 if (m_old_state != -1)
584 ::pthread_setcancelstate (m_old_state, 0);
585 }
586private:
587 int m_old_state; // Save the old cancelability state.
588};
589
590
591
592static void *
593MonitorChildProcessThreadFunction (void *arg)
594{
595 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
596 const char *function = __FUNCTION__;
597 if (log)
598 log->Printf ("%s (arg = %p) thread starting...", function, arg);
599
Greg Clayton75ccf502010-08-21 02:22:51 +0000600 MonitorInfo *info = (MonitorInfo *)arg;
601
602 const Host::MonitorChildProcessCallback callback = info->callback;
603 void * const callback_baton = info->callback_baton;
604 const lldb::pid_t pid = info->pid;
605 const bool monitor_signals = info->monitor_signals;
606
607 delete info;
608
Chris Lattner24943d22010-06-08 16:52:24 +0000609 int status = -1;
610 const int options = 0;
611 struct rusage *rusage = NULL;
612 while (1)
613 {
614 if (log)
Greg Clayton75ccf502010-08-21 02:22:51 +0000615 log->Printf("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p)...", function, pid, options, rusage);
Chris Lattner24943d22010-06-08 16:52:24 +0000616
617 // Wait for all child processes
618 ::pthread_testcancel ();
Greg Clayton75ccf502010-08-21 02:22:51 +0000619 const lldb::pid_t wait_pid = ::wait4 (pid, &status, options, rusage);
Chris Lattner24943d22010-06-08 16:52:24 +0000620 ::pthread_testcancel ();
621
Greg Clayton75ccf502010-08-21 02:22:51 +0000622 if (wait_pid == -1)
Chris Lattner24943d22010-06-08 16:52:24 +0000623 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000624 if (errno == EINTR)
625 continue;
626 else
627 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000628 }
Greg Clayton75ccf502010-08-21 02:22:51 +0000629 else if (wait_pid == pid)
Chris Lattner24943d22010-06-08 16:52:24 +0000630 {
Chris Lattner24943d22010-06-08 16:52:24 +0000631 bool exited = false;
632 int signal = 0;
633 int exit_status = 0;
634 const char *status_cstr = NULL;
635 if (WIFSTOPPED(status))
636 {
637 signal = WSTOPSIG(status);
638 status_cstr = "STOPPED";
639 }
640 else if (WIFEXITED(status))
641 {
642 exit_status = WEXITSTATUS(status);
643 status_cstr = "EXITED";
644 exited = true;
645 }
646 else if (WIFSIGNALED(status))
647 {
648 signal = WTERMSIG(status);
649 status_cstr = "SIGNALED";
650 exited = true;
651 exit_status = -1;
652 }
653 else
654 {
655 status_cstr = "(???)";
656 }
657
Greg Clayton75ccf502010-08-21 02:22:51 +0000658 // Scope for pthread_cancel_disabler
Chris Lattner24943d22010-06-08 16:52:24 +0000659 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000660 ScopedPThreadCancelDisabler pthread_cancel_disabler;
661
662 if (log)
663 log->Printf ("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_state = %i",
664 function,
665 wait_pid,
666 options,
667 rusage,
668 pid,
669 status,
670 status_cstr,
671 signal,
672 exit_status);
673
674 if (exited || (signal != 0 && monitor_signals))
Chris Lattner24943d22010-06-08 16:52:24 +0000675 {
Greg Clayton75ccf502010-08-21 02:22:51 +0000676 bool callback_return = callback (callback_baton, pid, signal, exit_status);
677
678 // If our process exited, then this thread should exit
679 if (exited)
680 break;
681 // If the callback returns true, it means this process should
682 // exit
683 if (callback_return)
684 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000685 }
686 }
687 }
688 }
689
690 if (log)
Greg Clayton75ccf502010-08-21 02:22:51 +0000691 log->Printf ("%s (arg = %p) thread exiting...", __FUNCTION__, arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000692
Chris Lattner24943d22010-06-08 16:52:24 +0000693 return NULL;
694}
695
696void
697Host::WillTerminate ()
698{
Chris Lattner24943d22010-06-08 16:52:24 +0000699}
700
Jim Ingham7508e732010-08-09 23:31:02 +0000701uint32_t
702Host::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
703{
704
705 int num_pids;
706 int size_of_pids;
707 int *pid_list;
708 uint32_t num_matches = 0;
709
710 size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
711 if (size_of_pids == -1)
712 return 0;
713
714 num_pids = size_of_pids/sizeof(int);
715 pid_list = (int *) malloc(size_of_pids);
716 size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, pid_list, size_of_pids);
717 if (size_of_pids == -1)
718 return 0;
719
Benjamin Kramer410f7212010-08-10 13:22:03 +0000720 lldb::pid_t our_pid = getpid();
Jim Ingham7508e732010-08-09 23:31:02 +0000721
722 for (int i = 0; i < num_pids; i++)
723 {
724 struct proc_bsdinfo bsd_info;
725 int error = proc_pidinfo (pid_list[i], PROC_PIDTBSDINFO, (uint64_t) 0, &bsd_info, PROC_PIDTBSDINFO_SIZE);
726 if (error == 0)
727 continue;
728
729 // Don't offer to attach to zombie processes, already traced or exiting
730 // processes, and of course, ourselves... It looks like passing the second arg of
731 // 0 to proc_listpids will exclude zombies anyway, but that's not documented so...
Benjamin Kramer410f7212010-08-10 13:22:03 +0000732 if (((bsd_info.pbi_flags & (PROC_FLAG_TRACED | PROC_FLAG_INEXIT)) != 0)
Jim Ingham7508e732010-08-09 23:31:02 +0000733 || (bsd_info.pbi_status == SZOMB)
734 || (bsd_info.pbi_pid == our_pid))
735 continue;
736 char pid_name[MAXCOMLEN * 2 + 1];
737 int name_len;
738 name_len = proc_name(bsd_info.pbi_pid, pid_name, MAXCOMLEN * 2);
739 if (name_len == 0)
740 continue;
741
742 if (strstr(pid_name, name) != pid_name)
743 continue;
744 matches.AppendString (pid_name);
745 pids.push_back (bsd_info.pbi_pid);
746 num_matches++;
747 }
748
749 return num_matches;
750}
751
752ArchSpec
753Host::GetArchSpecForExistingProcess (lldb::pid_t pid)
754{
755 ArchSpec return_spec;
756
757 struct proc_bsdinfo bsd_info;
758 int error = proc_pidinfo (pid, PROC_PIDTBSDINFO, (uint64_t) 0, &bsd_info, PROC_PIDTBSDINFO_SIZE);
759 if (error == 0)
760 return return_spec;
761 if (bsd_info.pbi_flags & PROC_FLAG_LP64)
762 return_spec.SetArch(LLDB_ARCH_DEFAULT_64BIT);
763 else
764 return_spec.SetArch(LLDB_ARCH_DEFAULT_32BIT);
765
766 return return_spec;
767}
768
769ArchSpec
770Host::GetArchSpecForExistingProcess (const char *process_name)
771{
772 ArchSpec returnSpec;
773 StringList matches;
774 std::vector<lldb::pid_t> pids;
775 if (ListProcessesMatchingName(process_name, matches, pids))
776 {
777 if (matches.GetSize() == 1)
778 {
779 return GetArchSpecForExistingProcess(pids[0]);
780 }
781 }
782 return returnSpec;
783}
Jim Ingham74989e82010-08-30 19:44:40 +0000784
785bool
786Host::OpenFileInExternalEditor (FileSpec &file_spec, uint32_t line_no)
787{
788 // We attach this to an 'odoc' event to specify a particular selection
789 typedef struct {
790 int16_t reserved0; // must be zero
791 int16_t fLineNumber;
792 int32_t fSelStart;
793 int32_t fSelEnd;
794 uint32_t reserved1; // must be zero
795 uint32_t reserved2; // must be zero
796 } BabelAESelInfo;
797
798 char file_path[PATH_MAX];
799 file_spec.GetPath(file_path, PATH_MAX);
800 CFCString file_cfstr (file_path, kCFStringEncodingUTF8);
801 CFCReleaser<CFURLRef> file_URL(::CFURLCreateWithFileSystemPath(NULL, file_cfstr.get(), kCFURLPOSIXPathStyle, false));
802
803 OSStatus error;
804 BabelAESelInfo file_and_line_info;
805
806 AEKeyDesc file_and_line_desc;
807
808 bzero(&file_and_line_info, sizeof (file_and_line_info));
809 file_and_line_info.fSelStart = 1;
810 file_and_line_info.fSelEnd = 1;
811 file_and_line_info.fLineNumber = line_no - 1;
812
813 error = AECreateDesc(typeChar, &file_and_line_info, sizeof (file_and_line_info), &(file_and_line_desc.descContent));
814 if (error != noErr)
815 {
816 return false;
817 }
818
819 file_and_line_desc.descKey = keyAEPosition;
820
821 LSApplicationParameters app_params;
822 bzero (&app_params, sizeof (app_params));
823 app_params.flags = kLSLaunchDefaults | kLSLaunchDontSwitch;
824
825 ProcessSerialNumber psn;
826 CFCReleaser<CFArrayRef> file_array(CFArrayCreate (NULL, (const void **) file_URL.ptr_address(false), 1, NULL));
827 error = LSOpenURLsWithRole(file_array.get(), kLSRolesAll, &file_and_line_desc, &app_params, &psn, 1);
828
829 AEDisposeDesc (&(file_and_line_desc.descContent));
830
831 if (error != noErr)
832 {
833 return false;
834 }
835
836 ProcessInfoRec which_process;
837 bzero(&which_process, sizeof(which_process));
838 unsigned char ap_name[PATH_MAX];
839 which_process.processName = ap_name;
840 error = GetProcessInformation (&psn, &which_process);
841
842 bool using_xcode = strncmp((char *) ap_name+1, "Xcode", 5) == 0;
843
844 // Xcode doesn't obey the line number in the Open Apple Event. So I have to send
845 // it an AppleScript to focus on the right line.
846
847 if (using_xcode)
848 {
849 static ComponentInstance osa_component = NULL;
850 static const char *as_template = "tell application \"Xcode\"\n"
851 "set doc to the first document whose path is \"%s\"\n"
852 "set the selection to paragraph %d of doc\n"
853 "--- set the selected paragraph range to {%d, %d} of doc\n"
854 "end tell\n";
855 const int chars_for_int = 32;
856 static int as_template_len = strlen (as_template);
857
858
859 char *as_str;
860 AEDesc as_desc;
861
862 if (osa_component == NULL)
863 {
864 osa_component = OpenDefaultComponent (kOSAComponentType,
865 kAppleScriptSubtype);
866 }
867
868 if (osa_component == NULL)
869 {
870 return false;
871 }
872
873 uint32_t as_str_size = as_template_len + strlen (file_path) + 3 * chars_for_int + 1;
874 as_str = (char *) malloc (as_str_size);
875 snprintf (as_str, as_str_size - 1, as_template, file_path, line_no, line_no, line_no);
876 error = AECreateDesc (typeChar, as_str, strlen (as_str), &as_desc);
877
878 free (as_str);
879
880 if (error != noErr)
881 return false;
882
883 OSAID ret_OSAID;
884 error = OSACompileExecute (osa_component, &as_desc, kOSANullScript,
885 kOSAModeNeverInteract, &ret_OSAID);
886
887 OSADispose (osa_component, ret_OSAID);
888
889 AEDisposeDesc (&as_desc);
890
891 if (error != noErr)
892 return false;
893 }
894
895 return true;
896}