blob: f6fd4c11dd299c3a0baac89fb0df40228ce2af6b [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
Greg Clayton8f3b21d2010-09-07 20:11:56 +000010#include "lldb/Host/Host.h"
Greg Clayton24b48ff2010-10-17 22:03:32 +000011
Greg Clayton638351a2010-12-04 00:10:17 +000012#include <crt_externs.h>
Greg Claytonb749a262010-12-03 06:02:24 +000013#include <execinfo.h>
Greg Claytona733c042011-03-21 21:25:07 +000014#include <grp.h>
Greg Clayton6bd1a9e2010-10-19 18:15:50 +000015#include <libproc.h>
Greg Claytona733c042011-03-21 21:25:07 +000016#include <pwd.h>
Greg Claytonb749a262010-12-03 06:02:24 +000017#include <stdio.h>
Greg Clayton6bd1a9e2010-10-19 18:15:50 +000018#include <sys/proc.h>
Greg Clayton24b48ff2010-10-17 22:03:32 +000019#include <sys/stat.h>
Greg Claytona733c042011-03-21 21:25:07 +000020#include <sys/sysctl.h>
Greg Clayton6bd1a9e2010-10-19 18:15:50 +000021#include <sys/types.h>
Greg Claytonb749a262010-12-03 06:02:24 +000022#include <unistd.h>
Greg Clayton24b48ff2010-10-17 22:03:32 +000023
24#include "lldb/Core/ArchSpec.h"
Greg Clayton36f63a92010-10-19 03:25:40 +000025#include "lldb/Core/Communication.h"
26#include "lldb/Core/ConnectionFileDescriptor.h"
Greg Clayton5f54ac32011-02-08 05:05:52 +000027#include "lldb/Host/FileSpec.h"
Greg Clayton8f3b21d2010-09-07 20:11:56 +000028#include "lldb/Core/Log.h"
Greg Clayton24b48ff2010-10-17 22:03:32 +000029#include "lldb/Core/StreamFile.h"
30#include "lldb/Core/StreamString.h"
Greg Claytona733c042011-03-21 21:25:07 +000031#include "lldb/Target/Process.h"
Chris Lattner24943d22010-06-08 16:52:24 +000032
Greg Clayton54e7afa2010-07-09 20:39:50 +000033#include "cfcpp/CFCBundle.h"
Greg Clayton24b48ff2010-10-17 22:03:32 +000034#include "cfcpp/CFCMutableArray.h"
Greg Clayton4b407112010-09-30 21:49:03 +000035#include "cfcpp/CFCMutableDictionary.h"
Greg Clayton54e7afa2010-07-09 20:39:50 +000036#include "cfcpp/CFCReleaser.h"
37#include "cfcpp/CFCString.h"
Chris Lattner24943d22010-06-08 16:52:24 +000038
Greg Claytona733c042011-03-21 21:25:07 +000039#include "llvm/Support/Host.h"
40#include "llvm/Support/MachO.h"
41
Greg Clayton8f3b21d2010-09-07 20:11:56 +000042#include <objc/objc-auto.h>
43
Greg Clayton4b407112010-09-30 21:49:03 +000044#include <ApplicationServices/ApplicationServices.h>
Greg Clayton8f3b21d2010-09-07 20:11:56 +000045#include <Carbon/Carbon.h>
46#include <Foundation/Foundation.h>
Chris Lattner24943d22010-06-08 16:52:24 +000047
48using namespace lldb;
49using namespace lldb_private;
50
Chris Lattner24943d22010-06-08 16:52:24 +000051class MacOSXDarwinThread
52{
53public:
54 MacOSXDarwinThread(const char *thread_name) :
55 m_pool (nil)
56 {
57 // Register our thread with the collector if garbage collection is enabled.
58 if (objc_collectingEnabled())
59 {
60#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
61 // On Leopard and earlier there is no way objc_registerThreadWithCollector
62 // function, so we do it manually.
63 auto_zone_register_thread(auto_zone());
64#else
Greg Clayton5d187e52011-01-08 20:28:42 +000065 // On SnowLeopard and later we just call the thread registration function.
Chris Lattner24943d22010-06-08 16:52:24 +000066 objc_registerThreadWithCollector();
67#endif
68 }
69 else
70 {
71 m_pool = [[NSAutoreleasePool alloc] init];
72 }
73
74
75 Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name);
76 }
77
78 ~MacOSXDarwinThread()
79 {
80 if (m_pool)
81 [m_pool release];
82 }
83
84 static void PThreadDestructor (void *v)
85 {
86 delete (MacOSXDarwinThread*)v;
87 }
88
89protected:
90 NSAutoreleasePool * m_pool;
91private:
92 DISALLOW_COPY_AND_ASSIGN (MacOSXDarwinThread);
93};
94
95static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT;
96static pthread_key_t g_thread_create_key = 0;
97
98static void
99InitThreadCreated()
100{
101 ::pthread_key_create (&g_thread_create_key, MacOSXDarwinThread::PThreadDestructor);
102}
103
Chris Lattner24943d22010-06-08 16:52:24 +0000104void
105Host::ThreadCreated (const char *thread_name)
106{
107 ::pthread_once (&g_thread_create_once, InitThreadCreated);
108 if (g_thread_create_key)
109 {
110 ::pthread_setspecific (g_thread_create_key, new MacOSXDarwinThread(thread_name));
111 }
112}
113
Chris Lattner24943d22010-06-08 16:52:24 +0000114
115bool
Greg Clayton24b48ff2010-10-17 22:03:32 +0000116Host::ResolveExecutableInBundle (FileSpec &file)
Chris Lattner24943d22010-06-08 16:52:24 +0000117{
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000118#if defined (__APPLE__)
Greg Clayton24b48ff2010-10-17 22:03:32 +0000119 if (file.GetFileType () == FileSpec::eFileTypeDirectory)
Chris Lattner24943d22010-06-08 16:52:24 +0000120 {
Greg Clayton24b48ff2010-10-17 22:03:32 +0000121 char path[PATH_MAX];
122 if (file.GetPath(path, sizeof(path)))
Chris Lattner24943d22010-06-08 16:52:24 +0000123 {
Greg Clayton24b48ff2010-10-17 22:03:32 +0000124 CFCBundle bundle (path);
125 CFCReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
126 if (url.get())
127 {
128 if (::CFURLGetFileSystemRepresentation (url.get(), YES, (UInt8*)path, sizeof(path)))
129 {
Greg Clayton537a7a82010-10-20 20:54:39 +0000130 file.SetFile(path, false);
Greg Clayton24b48ff2010-10-17 22:03:32 +0000131 return true;
132 }
133 }
Chris Lattner24943d22010-06-08 16:52:24 +0000134 }
135 }
Greg Clayton8f3b21d2010-09-07 20:11:56 +0000136#endif
137 return false;
Jim Ingham7508e732010-08-09 23:31:02 +0000138}
Jim Ingham74989e82010-08-30 19:44:40 +0000139
Greg Clayton4b407112010-09-30 21:49:03 +0000140lldb::pid_t
141Host::LaunchApplication (const FileSpec &app_file_spec)
142{
143 char app_path[PATH_MAX];
144 app_file_spec.GetPath(app_path, sizeof(app_path));
145
146 LSApplicationParameters app_params;
Greg Claytonddff7cc2011-02-04 21:13:05 +0000147 ::memset (&app_params, 0, sizeof (app_params));
Greg Clayton4b407112010-09-30 21:49:03 +0000148 app_params.flags = kLSLaunchDefaults |
149 kLSLaunchDontAddToRecents |
Greg Clayton24b48ff2010-10-17 22:03:32 +0000150 kLSLaunchNewInstance;
151
Greg Clayton4b407112010-09-30 21:49:03 +0000152
153 FSRef app_fsref;
154 CFCString app_cfstr (app_path, kCFStringEncodingUTF8);
155
Benjamin Kramerfddc25a2010-11-10 20:16:47 +0000156 OSStatus error = ::FSPathMakeRef ((const UInt8 *)app_path, &app_fsref, NULL);
Greg Clayton4b407112010-09-30 21:49:03 +0000157
158 // If we found the app, then store away the name so we don't have to re-look it up.
159 if (error != noErr)
160 return LLDB_INVALID_PROCESS_ID;
161
162 app_params.application = &app_fsref;
163
164 ProcessSerialNumber psn;
165
166 error = ::LSOpenApplication (&app_params, &psn);
167
168 if (error != noErr)
169 return LLDB_INVALID_PROCESS_ID;
170
171 ::pid_t pid = LLDB_INVALID_PROCESS_ID;
172 error = ::GetProcessPID(&psn, &pid);
173 return pid;
174}
175
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000176
177static void *
178AcceptPIDFromInferior (void *arg)
Greg Clayton24b48ff2010-10-17 22:03:32 +0000179{
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000180 const char *connect_url = (const char *)arg;
Greg Claytonea3259d2010-10-19 17:03:58 +0000181 ConnectionFileDescriptor file_conn;
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000182 Error error;
183 if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
Greg Claytonea3259d2010-10-19 17:03:58 +0000184 {
185 char pid_str[256];
Greg Claytonddff7cc2011-02-04 21:13:05 +0000186 ::memset (pid_str, 0, sizeof(pid_str));
Greg Claytonea3259d2010-10-19 17:03:58 +0000187 ConnectionStatus status;
188 const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), status, NULL);
189 if (pid_str_len > 0)
190 {
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000191 int pid = atoi (pid_str);
192 return (void *)(intptr_t)pid;
Greg Claytonea3259d2010-10-19 17:03:58 +0000193 }
194 }
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000195 return NULL;
Greg Claytonea3259d2010-10-19 17:03:58 +0000196}
197
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000198static bool
199WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
200{
201 const int time_delta_usecs = 100000;
202 const int num_retries = timeout_in_seconds/time_delta_usecs;
203 for (int i=0; i<num_retries; i++)
204 {
205 struct proc_bsdinfo bsd_info;
206 int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
207 (uint64_t) 0,
208 &bsd_info,
209 PROC_PIDTBSDINFO_SIZE);
210
211 switch (error)
212 {
213 case EINVAL:
214 case ENOTSUP:
215 case ESRCH:
216 case EPERM:
217 return false;
218
219 default:
220 break;
221
222 case 0:
223 if (bsd_info.pbi_status == SSTOP)
224 return true;
225 }
226 ::usleep (time_delta_usecs);
227 }
228 return false;
229}
230
231static lldb::pid_t
232LaunchInNewTerminalWithCommandFile
Greg Claytonea3259d2010-10-19 17:03:58 +0000233(
234 const char **argv,
235 const char **envp,
Greg Claytonde915be2011-01-23 05:56:20 +0000236 const char *working_dir,
Greg Claytonea3259d2010-10-19 17:03:58 +0000237 const ArchSpec *arch_spec,
238 bool stop_at_entry,
239 bool disable_aslr
240)
241{
242 if (!argv || !argv[0])
243 return LLDB_INVALID_PROCESS_ID;
Greg Clayton24b48ff2010-10-17 22:03:32 +0000244
245 OSStatus error = 0;
246
Greg Clayton537a7a82010-10-20 20:54:39 +0000247 FileSpec program (argv[0], false);
Greg Clayton24b48ff2010-10-17 22:03:32 +0000248
249
Greg Clayton36f63a92010-10-19 03:25:40 +0000250 std::string unix_socket_name;
251
Greg Clayton24b48ff2010-10-17 22:03:32 +0000252 char temp_file_path[PATH_MAX];
253 const char *tmpdir = ::getenv ("TMPDIR");
254 if (tmpdir == NULL)
255 tmpdir = "/tmp/";
256 ::snprintf (temp_file_path, sizeof(temp_file_path), "%s%s-XXXXXX", tmpdir, program.GetFilename().AsCString());
257
258 if (::mktemp (temp_file_path) == NULL)
259 return LLDB_INVALID_PROCESS_ID;
260
Greg Clayton36f63a92010-10-19 03:25:40 +0000261 unix_socket_name.assign (temp_file_path);
262
Greg Clayton24b48ff2010-10-17 22:03:32 +0000263 ::strncat (temp_file_path, ".command", sizeof (temp_file_path));
264
Greg Clayton58928562011-02-09 01:08:52 +0000265 StreamFile command_file;
266 command_file.GetFile().Open (temp_file_path,
267 File::eOpenOptionWrite | File::eOpenOptionCanCreate,
268 File::ePermissionsDefault);
269
270 if (!command_file.GetFile().IsValid())
271 return LLDB_INVALID_PROCESS_ID;
Greg Clayton24b48ff2010-10-17 22:03:32 +0000272
273 FileSpec darwin_debug_file_spec;
274 if (!Host::GetLLDBPath (ePathTypeSupportExecutableDir, darwin_debug_file_spec))
275 return LLDB_INVALID_PROCESS_ID;
276 darwin_debug_file_spec.GetFilename().SetCString("darwin-debug");
277
278 if (!darwin_debug_file_spec.Exists())
279 return LLDB_INVALID_PROCESS_ID;
280
281 char launcher_path[PATH_MAX];
282 darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path));
283 command_file.Printf("\"%s\" ", launcher_path);
284
Greg Clayton36f63a92010-10-19 03:25:40 +0000285 command_file.Printf("--unix-socket=%s ", unix_socket_name.c_str());
286
Greg Clayton24b48ff2010-10-17 22:03:32 +0000287 if (arch_spec && arch_spec->IsValid())
288 {
Greg Clayton940b1032011-02-23 00:35:02 +0000289 command_file.Printf("--arch=%s ", arch_spec->GetArchitectureName());
Greg Clayton24b48ff2010-10-17 22:03:32 +0000290 }
291
292 if (disable_aslr)
293 {
294 command_file.PutCString("--disable-aslr ");
295 }
296
297 command_file.PutCString("-- ");
298
299 if (argv)
300 {
301 for (size_t i=0; argv[i] != NULL; ++i)
302 {
303 command_file.Printf("\"%s\" ", argv[i]);
304 }
305 }
Greg Claytonc1d37752010-10-18 01:45:30 +0000306 command_file.PutCString("\necho Process exited with status $?\n");
Greg Clayton58928562011-02-09 01:08:52 +0000307 command_file.GetFile().Close();
Greg Clayton24b48ff2010-10-17 22:03:32 +0000308 if (::chmod (temp_file_path, S_IRWXU | S_IRWXG) != 0)
309 return LLDB_INVALID_PROCESS_ID;
310
311 CFCMutableDictionary cf_env_dict;
312
313 const bool can_create = true;
314 if (envp)
315 {
316 for (size_t i=0; envp[i] != NULL; ++i)
317 {
318 const char *env_entry = envp[i];
319 const char *equal_pos = strchr(env_entry, '=');
320 if (equal_pos)
321 {
322 std::string env_key (env_entry, equal_pos);
323 std::string env_val (equal_pos + 1);
324 CFCString cf_env_key (env_key.c_str(), kCFStringEncodingUTF8);
325 CFCString cf_env_val (env_val.c_str(), kCFStringEncodingUTF8);
326 cf_env_dict.AddValue (cf_env_key.get(), cf_env_val.get(), can_create);
327 }
328 }
329 }
330
331 LSApplicationParameters app_params;
Greg Claytonddff7cc2011-02-04 21:13:05 +0000332 ::memset (&app_params, 0, sizeof (app_params));
Greg Clayton24b48ff2010-10-17 22:03:32 +0000333 app_params.flags = kLSLaunchDontAddToRecents | kLSLaunchAsync;
334 app_params.argv = NULL;
335 app_params.environment = (CFDictionaryRef)cf_env_dict.get();
336
337 CFCReleaser<CFURLRef> command_file_url (::CFURLCreateFromFileSystemRepresentation (NULL,
338 (const UInt8 *)temp_file_path,
Greg Clayton36f63a92010-10-19 03:25:40 +0000339 strlen(temp_file_path),
Greg Clayton24b48ff2010-10-17 22:03:32 +0000340 false));
341
342 CFCMutableArray urls;
343
344 // Terminal.app will open the ".command" file we have created
345 // and run our process inside it which will wait at the entry point
346 // for us to attach.
347 urls.AppendValue(command_file_url.get());
348
Greg Clayton36f63a92010-10-19 03:25:40 +0000349
350 lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
351
352 Error lldb_error;
353 // Sleep and wait a bit for debugserver to start to listen...
Greg Clayton36f63a92010-10-19 03:25:40 +0000354 char connect_url[128];
355 ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name.c_str());
356
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000357 // Spawn a new thread to accept incoming connection on the connect_url
358 // so we can grab the pid from the inferior
359 lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name.c_str(),
360 AcceptPIDFromInferior,
361 connect_url,
362 &lldb_error);
363
Greg Clayton24b48ff2010-10-17 22:03:32 +0000364 ProcessSerialNumber psn;
365 error = LSOpenURLsWithRole(urls.get(), kLSRolesShell, NULL, &app_params, &psn, 1);
Greg Clayton36f63a92010-10-19 03:25:40 +0000366 if (error == noErr)
367 {
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000368 thread_result_t accept_thread_result = NULL;
369 if (Host::ThreadJoin (accept_thread, &accept_thread_result, &lldb_error))
Greg Clayton36f63a92010-10-19 03:25:40 +0000370 {
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000371 if (accept_thread_result)
Greg Clayton36f63a92010-10-19 03:25:40 +0000372 {
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000373 pid = (intptr_t)accept_thread_result;
374
375 // Wait for process to be stopped the the entry point by watching
376 // for the process status to be set to SSTOP which indicates it it
377 // SIGSTOP'ed at the entry point
378 WaitForProcessToSIGSTOP (pid, 5);
Greg Clayton36f63a92010-10-19 03:25:40 +0000379 }
380 }
381 }
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000382 else
383 {
384 Host::ThreadCancel (accept_thread, &lldb_error);
385 }
386
Greg Clayton24b48ff2010-10-17 22:03:32 +0000387 return pid;
388}
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000389
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000390const char *applscript_in_new_tty =
391"tell application \"Terminal\"\n"
392" do script \"%s\"\n"
393"end tell\n";
394
395
396const char *applscript_in_existing_tty = "\
397set the_shell_script to \"%s\"\n\
398tell application \"Terminal\"\n\
399 repeat with the_window in (get windows)\n\
400 repeat with the_tab in tabs of the_window\n\
401 set the_tty to tty in the_tab\n\
402 if the_tty contains \"%s\" then\n\
403 if the_tab is not busy then\n\
404 set selected of the_tab to true\n\
405 set frontmost of the_window to true\n\
406 do script the_shell_script in the_tab\n\
407 return\n\
408 end if\n\
409 end if\n\
410 end repeat\n\
411 end repeat\n\
412 do script the_shell_script\n\
413end tell\n";
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000414
415lldb::pid_t
416LaunchInNewTerminalWithAppleScript
417(
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000418 const char *tty_name,
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000419 const char **argv,
420 const char **envp,
Greg Claytonde915be2011-01-23 05:56:20 +0000421 const char *working_dir,
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000422 const ArchSpec *arch_spec,
423 bool stop_at_entry,
424 bool disable_aslr
425)
426{
427 if (!argv || !argv[0])
428 return LLDB_INVALID_PROCESS_ID;
429
430 std::string unix_socket_name;
431
432 char temp_file_path[PATH_MAX] = "/tmp/XXXXXX";
433 if (::mktemp (temp_file_path) == NULL)
434 return LLDB_INVALID_PROCESS_ID;
435
436 unix_socket_name.assign (temp_file_path);
437
438 StreamString command;
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000439 FileSpec darwin_debug_file_spec;
440 if (!Host::GetLLDBPath (ePathTypeSupportExecutableDir, darwin_debug_file_spec))
441 return LLDB_INVALID_PROCESS_ID;
442 darwin_debug_file_spec.GetFilename().SetCString("darwin-debug");
443
444 if (!darwin_debug_file_spec.Exists())
445 return LLDB_INVALID_PROCESS_ID;
446
447 char launcher_path[PATH_MAX];
448 darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path));
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000449
Greg Claytonb29b8c62010-11-08 03:06:10 +0000450 if (arch_spec)
Greg Clayton940b1032011-02-23 00:35:02 +0000451 command.Printf("arch -arch %s ", arch_spec->GetArchitectureName());
Greg Claytonb29b8c62010-11-08 03:06:10 +0000452
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000453 command.Printf("'%s' --unix-socket=%s", launcher_path, unix_socket_name.c_str());
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000454
455 if (arch_spec && arch_spec->IsValid())
Greg Clayton940b1032011-02-23 00:35:02 +0000456 command.Printf(" --arch=%s", arch_spec->GetArchitectureName());
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000457
Greg Claytonde915be2011-01-23 05:56:20 +0000458 if (working_dir)
459 command.Printf(" --working-dir '%s'", working_dir);
460
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000461 if (disable_aslr)
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000462 command.PutCString(" --disable-aslr");
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000463
464 command.PutCString(" --");
465
466 if (argv)
467 {
468 for (size_t i=0; argv[i] != NULL; ++i)
469 {
470 command.Printf(" '%s'", argv[i]);
471 }
472 }
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000473 command.PutCString (" ; echo Process exited with status $?");
474
475 StreamString applescript_source;
476
Greg Claytonb29b8c62010-11-08 03:06:10 +0000477 const char *tty_command = command.GetString().c_str();
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000478 if (tty_name && tty_name[0])
479 {
480 applescript_source.Printf (applscript_in_existing_tty,
Greg Claytonb29b8c62010-11-08 03:06:10 +0000481 tty_command,
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000482 tty_name);
483 }
484 else
485 {
486 applescript_source.Printf (applscript_in_new_tty,
Greg Claytonb29b8c62010-11-08 03:06:10 +0000487 tty_command);
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000488 }
489
490
491
492 const char *script_source = applescript_source.GetString().c_str();
493 //puts (script_source);
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000494 NSAppleScript* applescript = [[NSAppleScript alloc] initWithSource:[NSString stringWithCString:script_source encoding:NSUTF8StringEncoding]];
495
496 lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
497
498 Error lldb_error;
499 // Sleep and wait a bit for debugserver to start to listen...
500 ConnectionFileDescriptor file_conn;
501 char connect_url[128];
502 ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name.c_str());
503
504 // Spawn a new thread to accept incoming connection on the connect_url
505 // so we can grab the pid from the inferior
506 lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name.c_str(),
507 AcceptPIDFromInferior,
508 connect_url,
509 &lldb_error);
510
511
512 [applescript executeAndReturnError:nil];
513
514 thread_result_t accept_thread_result = NULL;
515 if (Host::ThreadJoin (accept_thread, &accept_thread_result, &lldb_error))
516 {
517 if (accept_thread_result)
518 {
519 pid = (intptr_t)accept_thread_result;
520
521 // Wait for process to be stopped the the entry point by watching
522 // for the process status to be set to SSTOP which indicates it it
523 // SIGSTOP'ed at the entry point
524 WaitForProcessToSIGSTOP (pid, 5);
525 }
526 }
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000527 ::unlink (unix_socket_name.c_str());
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000528 [applescript release];
529 return pid;
530}
531
532
533#define LLDB_HOST_USE_APPLESCRIPT
534
535lldb::pid_t
536Host::LaunchInNewTerminal
537(
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000538 const char *tty_name,
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000539 const char **argv,
540 const char **envp,
Greg Claytonde915be2011-01-23 05:56:20 +0000541 const char *working_dir,
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000542 const ArchSpec *arch_spec,
543 bool stop_at_entry,
544 bool disable_aslr
545)
546{
547#if defined (LLDB_HOST_USE_APPLESCRIPT)
Greg Claytonde915be2011-01-23 05:56:20 +0000548 return LaunchInNewTerminalWithAppleScript (tty_name, argv, envp, working_dir, arch_spec, stop_at_entry, disable_aslr);
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000549#else
Greg Claytonde915be2011-01-23 05:56:20 +0000550 return LaunchInNewTerminalWithCommandFile (argv, envp, working_dir, arch_spec, stop_at_entry, disable_aslr);
Greg Claytonea3259d2010-10-19 17:03:58 +0000551#endif
Greg Clayton6bd1a9e2010-10-19 18:15:50 +0000552}
553
Greg Claytone98ac252010-11-10 04:57:04 +0000554// On MacOSX CrashReporter will display a string for each shared library if
555// the shared library has an exported symbol named "__crashreporter_info__".
556
557static Mutex&
558GetCrashReporterMutex ()
559{
560 static Mutex g_mutex;
561 return g_mutex;
562}
563
564extern "C" {
565 const char *__crashreporter_info__ = NULL;
566};
567
568asm(".desc ___crashreporter_info__, 0x10");
569
570void
571Host::SetCrashDescriptionWithFormat (const char *format, ...)
572{
573 static StreamString g_crash_description;
574 Mutex::Locker locker (GetCrashReporterMutex ());
575
576 if (format)
577 {
578 va_list args;
579 va_start (args, format);
Greg Clayton74e55ed2010-11-10 19:43:40 +0000580 g_crash_description.GetString().clear();
Greg Claytone98ac252010-11-10 04:57:04 +0000581 g_crash_description.PrintfVarArg(format, args);
582 va_end (args);
583 __crashreporter_info__ = g_crash_description.GetData();
584 }
585 else
586 {
587 __crashreporter_info__ = NULL;
588 }
589}
590
591void
592Host::SetCrashDescription (const char *cstr)
593{
594 Mutex::Locker locker (GetCrashReporterMutex ());
595 __crashreporter_info__ = cstr;
596}
Greg Clayton24b48ff2010-10-17 22:03:32 +0000597
Jim Ingham74989e82010-08-30 19:44:40 +0000598bool
Greg Clayton4b407112010-09-30 21:49:03 +0000599Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no)
Jim Ingham74989e82010-08-30 19:44:40 +0000600{
601 // We attach this to an 'odoc' event to specify a particular selection
602 typedef struct {
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000603 int16_t reserved0; // must be zero
604 int16_t fLineNumber;
605 int32_t fSelStart;
606 int32_t fSelEnd;
607 uint32_t reserved1; // must be zero
608 uint32_t reserved2; // must be zero
Jim Ingham74989e82010-08-30 19:44:40 +0000609 } BabelAESelInfo;
610
Greg Claytone005f2c2010-11-06 01:53:30 +0000611 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST));
Jim Ingham74989e82010-08-30 19:44:40 +0000612 char file_path[PATH_MAX];
613 file_spec.GetPath(file_path, PATH_MAX);
614 CFCString file_cfstr (file_path, kCFStringEncodingUTF8);
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000615 CFCReleaser<CFURLRef> file_URL (::CFURLCreateWithFileSystemPath (NULL,
616 file_cfstr.get(),
617 kCFURLPOSIXPathStyle,
618 false));
Jim Inghamb0fff352010-08-31 18:05:13 +0000619
620 if (log)
621 log->Printf("Sending source file: \"%s\" and line: %d to external editor.\n", file_path, line_no);
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000622
Jim Ingham74989e82010-08-30 19:44:40 +0000623 OSStatus error;
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000624 BabelAESelInfo file_and_line_info =
625 {
626 0, // reserved0
627 line_no - 1, // fLineNumber (zero based line number)
628 1, // fSelStart
629 1024, // fSelEnd
630 0, // reserved1
631 0 // reserved2
632 };
Jim Ingham74989e82010-08-30 19:44:40 +0000633
634 AEKeyDesc file_and_line_desc;
635
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000636 error = ::AECreateDesc (typeUTF8Text,
637 &file_and_line_info,
638 sizeof (file_and_line_info),
639 &(file_and_line_desc.descContent));
Jim Ingham74989e82010-08-30 19:44:40 +0000640
Jim Ingham74989e82010-08-30 19:44:40 +0000641 if (error != noErr)
642 {
Jim Inghamb0fff352010-08-31 18:05:13 +0000643 if (log)
644 log->Printf("Error creating AEDesc: %d.\n", error);
Jim Ingham74989e82010-08-30 19:44:40 +0000645 return false;
646 }
647
648 file_and_line_desc.descKey = keyAEPosition;
649
Greg Claytoncb0989a2010-08-31 18:56:24 +0000650 static std::string g_app_name;
Greg Clayton452bf612010-08-31 18:35:14 +0000651 static FSRef g_app_fsref;
652
Jim Ingham74989e82010-08-30 19:44:40 +0000653 LSApplicationParameters app_params;
Greg Claytonddff7cc2011-02-04 21:13:05 +0000654 ::memset (&app_params, 0, sizeof (app_params));
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000655 app_params.flags = kLSLaunchDefaults |
656 kLSLaunchDontAddToRecents |
657 kLSLaunchDontSwitch;
Greg Clayton452bf612010-08-31 18:35:14 +0000658
Jim Ingham363180d2010-08-30 23:48:25 +0000659 char *external_editor = ::getenv ("LLDB_EXTERNAL_EDITOR");
660
Greg Clayton452bf612010-08-31 18:35:14 +0000661 if (external_editor)
Jim Ingham363180d2010-08-30 23:48:25 +0000662 {
Jim Inghamb0fff352010-08-31 18:05:13 +0000663 if (log)
664 log->Printf("Looking for external editor \"%s\".\n", external_editor);
665
Greg Claytoncb0989a2010-08-31 18:56:24 +0000666 if (g_app_name.empty() || strcmp (g_app_name.c_str(), external_editor) != 0)
Jim Ingham363180d2010-08-30 23:48:25 +0000667 {
Jim Ingham363180d2010-08-30 23:48:25 +0000668 CFCString editor_name (external_editor, kCFStringEncodingUTF8);
Greg Clayton452bf612010-08-31 18:35:14 +0000669 error = ::LSFindApplicationForInfo (kLSUnknownCreator,
670 NULL,
671 editor_name.get(),
672 &g_app_fsref,
673 NULL);
Jim Ingham363180d2010-08-30 23:48:25 +0000674
675 // If we found the app, then store away the name so we don't have to re-look it up.
Greg Clayton452bf612010-08-31 18:35:14 +0000676 if (error != noErr)
Jim Inghamb0fff352010-08-31 18:05:13 +0000677 {
678 if (log)
679 log->Printf("Could not find External Editor application, error: %d.\n", error);
Jim Ingham363180d2010-08-30 23:48:25 +0000680 return false;
Jim Inghamb0fff352010-08-31 18:05:13 +0000681 }
Jim Ingham363180d2010-08-30 23:48:25 +0000682
683 }
Greg Clayton452bf612010-08-31 18:35:14 +0000684 app_params.application = &g_app_fsref;
Jim Ingham363180d2010-08-30 23:48:25 +0000685 }
686
Jim Ingham74989e82010-08-30 19:44:40 +0000687 ProcessSerialNumber psn;
688 CFCReleaser<CFArrayRef> file_array(CFArrayCreate (NULL, (const void **) file_URL.ptr_address(false), 1, NULL));
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000689 error = ::LSOpenURLsWithRole (file_array.get(),
Jim Ingham363180d2010-08-30 23:48:25 +0000690 kLSRolesAll,
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000691 &file_and_line_desc,
692 &app_params,
693 &psn,
694 1);
695
Jim Ingham74989e82010-08-30 19:44:40 +0000696 AEDisposeDesc (&(file_and_line_desc.descContent));
697
698 if (error != noErr)
699 {
Jim Inghamb0fff352010-08-31 18:05:13 +0000700 if (log)
701 log->Printf("LSOpenURLsWithRole failed, error: %d.\n", error);
702
Jim Ingham74989e82010-08-30 19:44:40 +0000703 return false;
704 }
705
706 ProcessInfoRec which_process;
Greg Claytonddff7cc2011-02-04 21:13:05 +0000707 ::memset(&which_process, 0, sizeof(which_process));
Jim Ingham74989e82010-08-30 19:44:40 +0000708 unsigned char ap_name[PATH_MAX];
709 which_process.processName = ap_name;
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000710 error = ::GetProcessInformation (&psn, &which_process);
Jim Ingham74989e82010-08-30 19:44:40 +0000711
Jim Inghamb0fff352010-08-31 18:05:13 +0000712 bool using_xcode;
713 if (error != noErr)
714 {
715 if (log)
716 log->Printf("GetProcessInformation failed, error: %d.\n", error);
717 using_xcode = false;
718 }
719 else
720 using_xcode = strncmp((char *) ap_name+1, "Xcode", (int) ap_name[0]) == 0;
Jim Ingham74989e82010-08-30 19:44:40 +0000721
722 // Xcode doesn't obey the line number in the Open Apple Event. So I have to send
723 // it an AppleScript to focus on the right line.
724
725 if (using_xcode)
726 {
727 static ComponentInstance osa_component = NULL;
728 static const char *as_template = "tell application \"Xcode\"\n"
729 "set doc to the first document whose path is \"%s\"\n"
730 "set the selection to paragraph %d of doc\n"
731 "--- set the selected paragraph range to {%d, %d} of doc\n"
732 "end tell\n";
733 const int chars_for_int = 32;
734 static int as_template_len = strlen (as_template);
735
736
737 char *as_str;
738 AEDesc as_desc;
739
740 if (osa_component == NULL)
741 {
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000742 osa_component = ::OpenDefaultComponent (kOSAComponentType,
743 kAppleScriptSubtype);
Jim Ingham74989e82010-08-30 19:44:40 +0000744 }
745
746 if (osa_component == NULL)
747 {
Jim Inghamb0fff352010-08-31 18:05:13 +0000748 if (log)
749 log->Printf("Could not get default AppleScript component.\n");
Jim Ingham74989e82010-08-30 19:44:40 +0000750 return false;
751 }
752
753 uint32_t as_str_size = as_template_len + strlen (file_path) + 3 * chars_for_int + 1;
754 as_str = (char *) malloc (as_str_size);
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000755 ::snprintf (as_str,
756 as_str_size - 1,
757 as_template,
758 file_path,
759 line_no,
760 line_no,
761 line_no);
Jim Ingham74989e82010-08-30 19:44:40 +0000762
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000763 error = ::AECreateDesc (typeChar,
764 as_str,
765 strlen (as_str),
766 &as_desc);
767
768 ::free (as_str);
Jim Ingham74989e82010-08-30 19:44:40 +0000769
770 if (error != noErr)
Jim Inghamb0fff352010-08-31 18:05:13 +0000771 {
772 if (log)
773 log->Printf("Failed to create AEDesc for Xcode AppleEvent: %d.\n", error);
Jim Ingham74989e82010-08-30 19:44:40 +0000774 return false;
Jim Inghamb0fff352010-08-31 18:05:13 +0000775 }
Jim Ingham74989e82010-08-30 19:44:40 +0000776
777 OSAID ret_OSAID;
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000778 error = ::OSACompileExecute (osa_component,
779 &as_desc,
780 kOSANullScript,
781 kOSAModeNeverInteract,
782 &ret_OSAID);
783
784 ::OSADispose (osa_component, ret_OSAID);
Jim Ingham74989e82010-08-30 19:44:40 +0000785
Greg Claytonf4fa8a92010-08-30 22:00:34 +0000786 ::AEDisposeDesc (&as_desc);
Jim Ingham74989e82010-08-30 19:44:40 +0000787
788 if (error != noErr)
Jim Inghamb0fff352010-08-31 18:05:13 +0000789 {
790 if (log)
791 log->Printf("Sending AppleEvent to Xcode failed, error: %d.\n", error);
Jim Ingham74989e82010-08-30 19:44:40 +0000792 return false;
Jim Inghamb0fff352010-08-31 18:05:13 +0000793 }
Jim Ingham74989e82010-08-30 19:44:40 +0000794 }
795
796 return true;
797}
Greg Claytonb749a262010-12-03 06:02:24 +0000798
799
800void
801Host::Backtrace (Stream &strm, uint32_t max_frames)
802{
803 char backtrace_path[] = "/tmp/lldb-backtrace-tmp-XXXXXX";
804 int backtrace_fd = ::mkstemp (backtrace_path);
805 if (backtrace_fd != -1)
806 {
807 std::vector<void *> frame_buffer (max_frames, NULL);
808 int count = ::backtrace (&frame_buffer[0], frame_buffer.size());
809 ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd);
810
811 const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR);
812
813 if (::lseek(backtrace_fd, 0, SEEK_SET) == 0)
814 {
815 char *buffer = (char *)::malloc (buffer_size);
816 if (buffer)
817 {
818 ssize_t bytes_read = ::read (backtrace_fd, buffer, buffer_size);
819 if (bytes_read > 0)
820 strm.Write(buffer, bytes_read);
821 ::free (buffer);
822 }
823 }
824 ::close (backtrace_fd);
825 ::unlink (backtrace_path);
826 }
827}
Greg Clayton638351a2010-12-04 00:10:17 +0000828
829size_t
830Host::GetEnvironment (StringList &env)
831{
832 char **host_env = *_NSGetEnviron();
833 char *env_entry;
834 size_t i;
835 for (i=0; (env_entry = host_env[i]) != NULL; ++i)
836 env.AppendString(env_entry);
837 return i;
838
839}
Greg Claytonb1888f22011-03-19 01:12:21 +0000840
841
842bool
Greg Clayton58e26e02011-03-24 04:28:38 +0000843Host::GetOSBuildString (std::string &s)
844{
845 int mib[2] = { CTL_KERN, KERN_OSVERSION };
846 char cstr[PATH_MAX];
847 size_t cstr_len = sizeof(cstr);
848 if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0)
849 {
850 s.assign (cstr, cstr_len);
851 return true;
852 }
853
854 s.clear();
855 return false;
856}
857
858bool
859Host::GetOSKernelDescription (std::string &s)
860{
861 int mib[2] = { CTL_KERN, KERN_VERSION };
862 char cstr[PATH_MAX];
863 size_t cstr_len = sizeof(cstr);
864 if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0)
865 {
866 s.assign (cstr, cstr_len);
867 return true;
868 }
869 s.clear();
870 return false;
871}
872
873bool
Greg Claytonb1888f22011-03-19 01:12:21 +0000874Host::GetOSVersion
875(
876 uint32_t &major,
877 uint32_t &minor,
878 uint32_t &update
879)
880{
881
882 SInt32 version;
883
884 OSErr err = ::Gestalt (gestaltSystemVersion, &version);
885 if (err != noErr)
886 return false;
887
888 if (version < 0x1040)
889 {
890 major = ((version & 0xF000) >> 12) * 10 + ((version & 0x0F00) >> 8);
891 minor = (version & 0x00F0) >> 4;
892 update = (version & 0x000F);
893 }
894 else
895 {
896 if (::Gestalt (gestaltSystemVersionMajor, &version) != noErr)
897 return false;
898 major = version;
899
900 if (::Gestalt (gestaltSystemVersionMinor, &version) == noErr)
901 minor = version;
902 else
903 minor = 0;
904
905 if (::Gestalt (gestaltSystemVersionBugFix, &version) == noErr)
906 update = version;
907 else
908 update = 0;
909 }
910
911 return true;
Greg Claytonb1888f22011-03-19 01:12:21 +0000912}
913
Greg Claytona733c042011-03-21 21:25:07 +0000914static bool
915GetMacOSXProcessName (NameMatchType name_match_type,
916 const char *name_match,
917 ProcessInfo &process_info)
918{
919 if (process_info.ProcessIDIsValid())
920 {
921 char process_name[MAXCOMLEN * 2 + 1];
922 int name_len = ::proc_name(process_info.GetProcessID(), process_name, MAXCOMLEN * 2);
923 if (name_len == 0)
924 return false;
925
926 if (NameMatches(process_name, name_match_type, name_match))
927 {
928 process_info.SetName (process_name);
929 return true;
930 }
931 }
932 process_info.SetName (NULL);
933 return false;
934}
935
936
937static bool
938GetMacOSXProcessCPUType (ProcessInfo &process_info)
939{
940 if (process_info.ProcessIDIsValid())
941 {
942 // Make a new mib to stay thread safe
943 int mib[CTL_MAXNAME]={0,};
944 size_t mib_len = CTL_MAXNAME;
945 if (::sysctlnametomib("sysctl.proc_cputype", mib, &mib_len))
946 return false;
947
948 mib[mib_len] = process_info.GetProcessID();
949 mib_len++;
950
951 cpu_type_t cpu, sub;
952 size_t cpu_len = sizeof(cpu);
953 if (::sysctl (mib, mib_len, &cpu, &cpu_len, 0, 0) == 0)
954 {
955 switch (cpu)
956 {
957 case llvm::MachO::CPUTypeI386: sub = llvm::MachO::CPUSubType_I386_ALL; break;
958 case llvm::MachO::CPUTypeX86_64: sub = llvm::MachO::CPUSubType_X86_64_ALL; break;
959 default: break;
960 }
Greg Claytonb3448432011-03-24 21:19:54 +0000961 process_info.GetArchitecture ().SetArchitecture (eArchTypeMachO, cpu, sub);
Greg Claytona733c042011-03-21 21:25:07 +0000962 return true;
963 }
964 }
965 process_info.GetArchitecture().Clear();
966 return false;
967}
968
969// TODO: move this into the platform
970static bool
971GetGroupName (uint32_t gid, std::string &group_name)
972{
973 char group_buffer[PATH_MAX];
974 size_t group_buffer_size = sizeof(group_buffer);
975 struct group group_info;
976 struct group *group_info_ptr = &group_info;
977 // User the real user ID here, not the effective user ID
978 if (::getgrgid_r (gid,
979 &group_info,
980 group_buffer,
981 group_buffer_size,
982 &group_info_ptr) == 0)
983 {
984 if (group_info_ptr)
985 {
986 group_name.assign (group_info_ptr->gr_name);
987 return true;
988 }
989 }
990 group_name.clear();
991 return false;
992}
993
994// TODO: move this into the platform
995static bool
996GetUserName (uint32_t uid, std::string &user_name)
997{
998 struct passwd user_info;
999 struct passwd *user_info_ptr = &user_info;
1000 char user_buffer[PATH_MAX];
1001 size_t user_buffer_size = sizeof(user_buffer);
1002 if (::getpwuid_r (uid,
1003 &user_info,
1004 user_buffer,
1005 user_buffer_size,
1006 &user_info_ptr) == 0)
1007 {
1008 if (user_info_ptr)
1009 {
1010 user_name.assign (user_info_ptr->pw_name);
1011 return true;
1012 }
1013 }
1014 user_name.clear();
1015 return false;
1016}
1017
1018
1019static bool
1020GetMacOSXProcessUserAndGroup (ProcessInfo &process_info)
1021{
1022 if (process_info.ProcessIDIsValid())
1023 {
1024 int mib[4];
1025 mib[0] = CTL_KERN;
1026 mib[1] = KERN_PROC;
1027 mib[2] = KERN_PROC_PID;
1028 mib[3] = process_info.GetProcessID();
1029 struct kinfo_proc proc_kinfo;
1030 size_t proc_kinfo_size = sizeof(struct kinfo_proc);
1031
1032 if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
1033 {
1034 if (proc_kinfo_size > 0)
1035 {
1036 process_info.SetParentProcessID (proc_kinfo.kp_eproc.e_ppid);
1037 process_info.SetRealUserID (proc_kinfo.kp_eproc.e_pcred.p_ruid);
1038 process_info.SetRealGroupID (proc_kinfo.kp_eproc.e_pcred.p_rgid);
1039 process_info.SetEffectiveUserID (proc_kinfo.kp_eproc.e_ucred.cr_uid);
1040 if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
1041 process_info.SetEffectiveGroupID (proc_kinfo.kp_eproc.e_ucred.cr_groups[0]);
1042 else
1043 process_info.SetEffectiveGroupID (UINT32_MAX);
1044 return true;
1045 }
1046 }
1047 }
1048 process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID);
1049 process_info.SetRealUserID (UINT32_MAX);
1050 process_info.SetRealGroupID (UINT32_MAX);
1051 process_info.SetEffectiveUserID (UINT32_MAX);
1052 process_info.SetEffectiveGroupID (UINT32_MAX);
1053 return false;
1054}
1055
1056
1057uint32_t
1058Host::FindProcessesByName (const char *name, NameMatchType name_match_type, ProcessInfoList &process_infos)
1059{
1060 int num_pids;
1061 int size_of_pids;
1062 std::vector<int> pid_list;
1063
1064 size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
1065 if (size_of_pids == -1)
1066 return 0;
1067
1068 num_pids = size_of_pids/sizeof(int);
1069
1070 pid_list.resize (size_of_pids);
1071 size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, &pid_list[0], size_of_pids);
1072 if (size_of_pids == -1)
1073 return 0;
1074
1075 lldb::pid_t our_pid = getpid();
1076
1077 for (int i = 0; i < num_pids; i++)
1078 {
1079 struct proc_bsdinfo bsd_info;
1080 int error = proc_pidinfo (pid_list[i], PROC_PIDTBSDINFO, (uint64_t) 0, &bsd_info, PROC_PIDTBSDINFO_SIZE);
1081 if (error == 0)
1082 continue;
1083
1084 // Don't offer to attach to zombie processes, already traced or exiting
1085 // processes, and of course, ourselves... It looks like passing the second arg of
1086 // 0 to proc_listpids will exclude zombies anyway, but that's not documented so...
1087 if (((bsd_info.pbi_flags & (PROC_FLAG_TRACED | PROC_FLAG_INEXIT)) != 0)
1088 || (bsd_info.pbi_status == SZOMB)
1089 || (bsd_info.pbi_pid == our_pid))
1090 continue;
1091
1092 ProcessInfo process_info;
1093 process_info.SetProcessID (bsd_info.pbi_pid);
1094 if (GetMacOSXProcessName (name_match_type, name, process_info))
1095 {
1096 GetMacOSXProcessCPUType (process_info);
1097 GetMacOSXProcessUserAndGroup (process_info);
1098 process_infos.Append (process_info);
1099 }
1100 }
1101 return process_infos.GetSize();
1102}
1103
1104bool
1105Host::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
1106{
1107 process_info.SetProcessID(pid);
1108 if (GetMacOSXProcessName (eNameMatchIgnore, NULL, process_info))
1109 {
1110 GetMacOSXProcessCPUType (process_info);
1111 GetMacOSXProcessUserAndGroup (process_info);
1112 return true;
1113 }
1114 process_info.Clear();
1115 return false;
1116}
1117
Greg Claytonb1888f22011-03-19 01:12:21 +00001118