Home | History | Annotate | Download | only in macosx
      1 //===-- 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 "lldb/Host/Host.h"
     11 
     12 #include <AvailabilityMacros.h>
     13 
     14 #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
     15 #define NO_XPC_SERVICES 1 
     16 #endif
     17 
     18 #if !defined(NO_XPC_SERVICES)
     19 #define __XPC_PRIVATE_H__
     20 #include <xpc/xpc.h>
     21 #include "launcherXPCService/LauncherXPCService.h"
     22 #endif
     23 
     24 #include <asl.h>
     25 #include <crt_externs.h>
     26 #include <execinfo.h>
     27 #include <grp.h>
     28 #include <libproc.h>
     29 #include <pwd.h>
     30 #include <spawn.h>
     31 #include <stdio.h>
     32 #include <sys/proc.h>
     33 #include <sys/stat.h>
     34 #include <sys/sysctl.h>
     35 #include <sys/types.h>
     36 #include <unistd.h>
     37 
     38 #include "lldb/Core/ArchSpec.h"
     39 #include "lldb/Core/Communication.h"
     40 #include "lldb/Core/ConnectionFileDescriptor.h"
     41 #include "lldb/Core/DataExtractor.h"
     42 #include "lldb/Core/Log.h"
     43 #include "lldb/Core/Module.h"
     44 #include "lldb/Core/StreamFile.h"
     45 #include "lldb/Core/StreamString.h"
     46 #include "lldb/Host/Endian.h"
     47 #include "lldb/Host/FileSpec.h"
     48 #include "lldb/Target/Platform.h"
     49 #include "lldb/Target/Process.h"
     50 #include "lldb/Utility/CleanUp.h"
     51 
     52 #include "cfcpp/CFCBundle.h"
     53 #include "cfcpp/CFCMutableArray.h"
     54 #include "cfcpp/CFCMutableDictionary.h"
     55 #include "cfcpp/CFCReleaser.h"
     56 #include "cfcpp/CFCString.h"
     57 
     58 #include "llvm/Support/Host.h"
     59 #include "llvm/Support/MachO.h"
     60 
     61 #include <objc/objc-auto.h>
     62 
     63 #include <CoreFoundation/CoreFoundation.h>
     64 #include <Foundation/Foundation.h>
     65 
     66 #if !defined(__arm__)
     67 #include <Carbon/Carbon.h>
     68 #endif
     69 
     70 #ifndef _POSIX_SPAWN_DISABLE_ASLR
     71 #define _POSIX_SPAWN_DISABLE_ASLR       0x0100
     72 #endif
     73 
     74 extern "C" 
     75 {
     76     int __pthread_chdir(const char *path);
     77     int __pthread_fchdir (int fildes);
     78 }
     79 
     80 using namespace lldb;
     81 using namespace lldb_private;
     82 
     83 static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT;
     84 static pthread_key_t g_thread_create_key = 0;
     85 
     86 class MacOSXDarwinThread
     87 {
     88 public:
     89     MacOSXDarwinThread(const char *thread_name) :
     90         m_pool (nil)
     91     {
     92         // Register our thread with the collector if garbage collection is enabled.
     93         if (objc_collectingEnabled())
     94         {
     95 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
     96             // On Leopard and earlier there is no way objc_registerThreadWithCollector
     97             // function, so we do it manually.
     98             auto_zone_register_thread(auto_zone());
     99 #else
    100             // On SnowLeopard and later we just call the thread registration function.
    101             objc_registerThreadWithCollector();
    102 #endif
    103         }
    104         else
    105         {
    106             m_pool = [[NSAutoreleasePool alloc] init];
    107         }
    108 
    109 
    110         Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name);
    111     }
    112 
    113     ~MacOSXDarwinThread()
    114     {
    115         if (m_pool)
    116         {
    117             [m_pool drain];
    118             m_pool = nil;
    119         }
    120     }
    121 
    122     static void PThreadDestructor (void *v)
    123     {
    124         if (v)
    125             delete static_cast<MacOSXDarwinThread*>(v);
    126         ::pthread_setspecific (g_thread_create_key, NULL);
    127     }
    128 
    129 protected:
    130     NSAutoreleasePool * m_pool;
    131 private:
    132     DISALLOW_COPY_AND_ASSIGN (MacOSXDarwinThread);
    133 };
    134 
    135 static void
    136 InitThreadCreated()
    137 {
    138     ::pthread_key_create (&g_thread_create_key, MacOSXDarwinThread::PThreadDestructor);
    139 }
    140 
    141 void
    142 Host::ThreadCreated (const char *thread_name)
    143 {
    144     ::pthread_once (&g_thread_create_once, InitThreadCreated);
    145     if (g_thread_create_key)
    146     {
    147         ::pthread_setspecific (g_thread_create_key, new MacOSXDarwinThread(thread_name));
    148     }
    149 }
    150 
    151 std::string
    152 Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
    153 {
    154     std::string thread_name;
    155 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
    156     // We currently can only get the name of a thread in the current process.
    157     if (pid == Host::GetCurrentProcessID())
    158     {
    159         char pthread_name[1024];
    160         if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0)
    161         {
    162             if (pthread_name[0])
    163             {
    164                 thread_name = pthread_name;
    165             }
    166         }
    167         else
    168         {
    169             dispatch_queue_t current_queue = ::dispatch_get_current_queue ();
    170             if (current_queue != NULL)
    171             {
    172                 const char *queue_name = dispatch_queue_get_label (current_queue);
    173                 if (queue_name && queue_name[0])
    174                 {
    175                     thread_name = queue_name;
    176                 }
    177             }
    178         }
    179     }
    180 #endif
    181     return thread_name;
    182 }
    183 
    184 bool
    185 Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle_directory)
    186 {
    187 #if defined (__APPLE__)
    188     if (file.GetFileType () == FileSpec::eFileTypeDirectory)
    189     {
    190         char path[PATH_MAX];
    191         if (file.GetPath(path, sizeof(path)))
    192         {
    193             CFCBundle bundle (path);
    194             if (bundle.GetPath (path, sizeof(path)))
    195             {
    196                 bundle_directory.SetFile (path, false);
    197                 return true;
    198             }
    199         }
    200     }
    201 #endif
    202     bundle_directory.Clear();
    203     return false;
    204 }
    205 
    206 
    207 bool
    208 Host::ResolveExecutableInBundle (FileSpec &file)
    209 {
    210 #if defined (__APPLE__)
    211     if (file.GetFileType () == FileSpec::eFileTypeDirectory)
    212     {
    213         char path[PATH_MAX];
    214         if (file.GetPath(path, sizeof(path)))
    215         {
    216             CFCBundle bundle (path);
    217             CFCReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
    218             if (url.get())
    219             {
    220                 if (::CFURLGetFileSystemRepresentation (url.get(), YES, (UInt8*)path, sizeof(path)))
    221                 {
    222                     file.SetFile(path, false);
    223                     return true;
    224                 }
    225             }
    226         }
    227     }
    228 #endif
    229   return false;
    230 }
    231 
    232 lldb::pid_t
    233 Host::LaunchApplication (const FileSpec &app_file_spec)
    234 {
    235 #if defined (__arm__)
    236     return LLDB_INVALID_PROCESS_ID;
    237 #else
    238     char app_path[PATH_MAX];
    239     app_file_spec.GetPath(app_path, sizeof(app_path));
    240 
    241     LSApplicationParameters app_params;
    242     ::memset (&app_params, 0, sizeof (app_params));
    243     app_params.flags = kLSLaunchDefaults | 
    244                        kLSLaunchDontAddToRecents | 
    245                        kLSLaunchNewInstance;
    246     
    247     
    248     FSRef app_fsref;
    249     CFCString app_cfstr (app_path, kCFStringEncodingUTF8);
    250     
    251     OSStatus error = ::FSPathMakeRef ((const UInt8 *)app_path, &app_fsref, NULL);
    252     
    253     // If we found the app, then store away the name so we don't have to re-look it up.
    254     if (error != noErr)
    255         return LLDB_INVALID_PROCESS_ID;
    256     
    257     app_params.application = &app_fsref;
    258 
    259     ProcessSerialNumber psn;
    260 
    261     error = ::LSOpenApplication (&app_params, &psn);
    262 
    263     if (error != noErr)
    264         return LLDB_INVALID_PROCESS_ID;
    265 
    266     ::pid_t pid = LLDB_INVALID_PROCESS_ID;
    267     error = ::GetProcessPID(&psn, &pid);
    268     if (error != noErr)
    269         return LLDB_INVALID_PROCESS_ID;
    270     return pid;
    271 #endif
    272 }
    273 
    274 
    275 static void *
    276 AcceptPIDFromInferior (void *arg)
    277 {
    278     const char *connect_url = (const char *)arg;
    279     ConnectionFileDescriptor file_conn;
    280     Error error;
    281     if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
    282     {
    283         char pid_str[256];
    284         ::memset (pid_str, 0, sizeof(pid_str));
    285         ConnectionStatus status;
    286         const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL);
    287         if (pid_str_len > 0)
    288         {
    289             int pid = atoi (pid_str);
    290             return (void *)(intptr_t)pid;
    291         }
    292     }
    293     return NULL;
    294 }
    295 
    296 static bool
    297 WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
    298 {
    299     const int time_delta_usecs = 100000;
    300     const int num_retries = timeout_in_seconds/time_delta_usecs;
    301     for (int i=0; i<num_retries; i++)
    302     {
    303         struct proc_bsdinfo bsd_info;
    304         int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO, 
    305                                     (uint64_t) 0, 
    306                                     &bsd_info, 
    307                                     PROC_PIDTBSDINFO_SIZE);
    308         
    309         switch (error)
    310         {
    311         case EINVAL:
    312         case ENOTSUP:
    313         case ESRCH:
    314         case EPERM:
    315             return false;
    316         
    317         default:
    318             break;
    319 
    320         case 0:
    321             if (bsd_info.pbi_status == SSTOP)
    322                 return true;
    323         }
    324         ::usleep (time_delta_usecs);
    325     }
    326     return false;
    327 }
    328 #if !defined(__arm__)
    329 
    330 //static lldb::pid_t
    331 //LaunchInNewTerminalWithCommandFile 
    332 //(
    333 //    const char **argv, 
    334 //    const char **envp,
    335 //    const char *working_dir,
    336 //    const ArchSpec *arch_spec,
    337 //    bool stop_at_entry,
    338 //    bool disable_aslr
    339 //)
    340 //{
    341 //    if (!argv || !argv[0])
    342 //        return LLDB_INVALID_PROCESS_ID;
    343 //
    344 //    OSStatus error = 0;
    345 //    
    346 //    FileSpec program (argv[0], false);
    347 //    
    348 //    
    349 //    std::string unix_socket_name;
    350 //
    351 //    char temp_file_path[PATH_MAX];
    352 //    const char *tmpdir = ::getenv ("TMPDIR");
    353 //    if (tmpdir == NULL)
    354 //        tmpdir = "/tmp/";
    355 //    ::snprintf (temp_file_path, sizeof(temp_file_path), "%s%s-XXXXXX", tmpdir, program.GetFilename().AsCString());
    356 //    
    357 //    if (::mktemp (temp_file_path) == NULL)
    358 //        return LLDB_INVALID_PROCESS_ID;
    359 //
    360 //    unix_socket_name.assign (temp_file_path);
    361 //
    362 //    ::strlcat (temp_file_path, ".command", sizeof (temp_file_path));
    363 //
    364 //    StreamFile command_file;
    365 //    command_file.GetFile().Open (temp_file_path, 
    366 //                                 File::eOpenOptionWrite | File::eOpenOptionCanCreate,
    367 //                                 File::ePermissionsDefault);
    368 //    
    369 //    if (!command_file.GetFile().IsValid())
    370 //        return LLDB_INVALID_PROCESS_ID;
    371 //    
    372 //    FileSpec darwin_debug_file_spec;
    373 //    if (!Host::GetLLDBPath (ePathTypeSupportExecutableDir, darwin_debug_file_spec))
    374 //        return LLDB_INVALID_PROCESS_ID;
    375 //    darwin_debug_file_spec.GetFilename().SetCString("darwin-debug");
    376 //        
    377 //    if (!darwin_debug_file_spec.Exists())
    378 //        return LLDB_INVALID_PROCESS_ID;
    379 //    
    380 //    char launcher_path[PATH_MAX];
    381 //    darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path));
    382 //    command_file.Printf("\"%s\" ", launcher_path);
    383 //    
    384 //    command_file.Printf("--unix-socket=%s ", unix_socket_name.c_str());
    385 //    
    386 //    if (arch_spec && arch_spec->IsValid())
    387 //    {
    388 //        command_file.Printf("--arch=%s ", arch_spec->GetArchitectureName());
    389 //    }
    390 //
    391 //    if (disable_aslr)
    392 //    {
    393 //        command_file.PutCString("--disable-aslr ");
    394 //    }
    395 //        
    396 //    command_file.PutCString("-- ");
    397 //
    398 //    if (argv)
    399 //    {
    400 //        for (size_t i=0; argv[i] != NULL; ++i)
    401 //        {
    402 //            command_file.Printf("\"%s\" ", argv[i]);
    403 //        }
    404 //    }
    405 //    command_file.PutCString("\necho Process exited with status $?\n");
    406 //    command_file.GetFile().Close();
    407 //    if (::chmod (temp_file_path, S_IRWXU | S_IRWXG) != 0)
    408 //        return LLDB_INVALID_PROCESS_ID;
    409 //            
    410 //    CFCMutableDictionary cf_env_dict;
    411 //    
    412 //    const bool can_create = true;
    413 //    if (envp)
    414 //    {
    415 //        for (size_t i=0; envp[i] != NULL; ++i)
    416 //        {
    417 //            const char *env_entry = envp[i];            
    418 //            const char *equal_pos = strchr(env_entry, '=');
    419 //            if (equal_pos)
    420 //            {
    421 //                std::string env_key (env_entry, equal_pos);
    422 //                std::string env_val (equal_pos + 1);
    423 //                CFCString cf_env_key (env_key.c_str(), kCFStringEncodingUTF8);
    424 //                CFCString cf_env_val (env_val.c_str(), kCFStringEncodingUTF8);
    425 //                cf_env_dict.AddValue (cf_env_key.get(), cf_env_val.get(), can_create);
    426 //            }
    427 //        }
    428 //    }
    429 //    
    430 //    LSApplicationParameters app_params;
    431 //    ::memset (&app_params, 0, sizeof (app_params));
    432 //    app_params.flags = kLSLaunchDontAddToRecents | kLSLaunchAsync;
    433 //    app_params.argv = NULL;
    434 //    app_params.environment = (CFDictionaryRef)cf_env_dict.get();
    435 //
    436 //    CFCReleaser<CFURLRef> command_file_url (::CFURLCreateFromFileSystemRepresentation (NULL, 
    437 //                                                                                       (const UInt8 *)temp_file_path, 
    438 //                                                                                       strlen(temp_file_path),
    439 //                                                                                       false));
    440 //    
    441 //    CFCMutableArray urls;
    442 //    
    443 //    // Terminal.app will open the ".command" file we have created
    444 //    // and run our process inside it which will wait at the entry point
    445 //    // for us to attach.
    446 //    urls.AppendValue(command_file_url.get());
    447 //
    448 //
    449 //    lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
    450 //
    451 //    Error lldb_error;
    452 //    // Sleep and wait a bit for debugserver to start to listen...
    453 //    char connect_url[128];
    454 //    ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name.c_str());
    455 //
    456 //    // Spawn a new thread to accept incoming connection on the connect_url
    457 //    // so we can grab the pid from the inferior
    458 //    lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name.c_str(),
    459 //                                                       AcceptPIDFromInferior,
    460 //                                                       connect_url,
    461 //                                                       &lldb_error);
    462 //    
    463 //    ProcessSerialNumber psn;
    464 //    error = LSOpenURLsWithRole(urls.get(), kLSRolesShell, NULL, &app_params, &psn, 1);
    465 //    if (error == noErr)
    466 //    {
    467 //        thread_result_t accept_thread_result = NULL;
    468 //        if (Host::ThreadJoin (accept_thread, &accept_thread_result, &lldb_error))
    469 //        {
    470 //            if (accept_thread_result)
    471 //            {
    472 //                pid = (intptr_t)accept_thread_result;
    473 //            
    474 //                // Wait for process to be stopped the the entry point by watching
    475 //                // for the process status to be set to SSTOP which indicates it it
    476 //                // SIGSTOP'ed at the entry point
    477 //                WaitForProcessToSIGSTOP (pid, 5);
    478 //            }
    479 //        }
    480 //    }
    481 //    else
    482 //    {
    483 //        Host::ThreadCancel (accept_thread, &lldb_error);
    484 //    }
    485 //
    486 //    return pid;
    487 //}
    488 
    489 const char *applscript_in_new_tty = 
    490 "tell application \"Terminal\"\n"
    491 "	do script \"%s\"\n"
    492 "end tell\n";
    493 
    494 
    495 const char *applscript_in_existing_tty = "\
    496 set the_shell_script to \"%s\"\n\
    497 tell application \"Terminal\"\n\
    498 	repeat with the_window in (get windows)\n\
    499 		repeat with the_tab in tabs of the_window\n\
    500 			set the_tty to tty in the_tab\n\
    501 			if the_tty contains \"%s\" then\n\
    502 				if the_tab is not busy then\n\
    503 					set selected of the_tab to true\n\
    504 					set frontmost of the_window to true\n\
    505 					do script the_shell_script in the_tab\n\
    506 					return\n\
    507 				end if\n\
    508 			end if\n\
    509 		end repeat\n\
    510 	end repeat\n\
    511 	do script the_shell_script\n\
    512 end tell\n";
    513 
    514 
    515 static Error
    516 LaunchInNewTerminalWithAppleScript (const char *exe_path, ProcessLaunchInfo &launch_info)
    517 {
    518     Error error;
    519     char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";    
    520     if (::mktemp (unix_socket_name) == NULL)
    521     {
    522         error.SetErrorString ("failed to make temporary path for a unix socket");
    523         return error;
    524     }
    525     
    526     StreamString command;
    527     FileSpec darwin_debug_file_spec;
    528     if (!Host::GetLLDBPath (ePathTypeSupportExecutableDir, darwin_debug_file_spec))
    529     {
    530         error.SetErrorString ("can't locate the 'darwin-debug' executable");
    531         return error;
    532     }
    533 
    534     darwin_debug_file_spec.GetFilename().SetCString("darwin-debug");
    535         
    536     if (!darwin_debug_file_spec.Exists())
    537     {
    538         error.SetErrorStringWithFormat ("the 'darwin-debug' executable doesn't exists at '%s'", 
    539                                         darwin_debug_file_spec.GetPath().c_str());
    540         return error;
    541     }
    542     
    543     char launcher_path[PATH_MAX];
    544     darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path));
    545 
    546     const ArchSpec &arch_spec = launch_info.GetArchitecture();
    547     if (arch_spec.IsValid())
    548         command.Printf("arch -arch %s ", arch_spec.GetArchitectureName());
    549 
    550     command.Printf("'%s' --unix-socket=%s", launcher_path, unix_socket_name);
    551 
    552     if (arch_spec.IsValid())
    553         command.Printf(" --arch=%s", arch_spec.GetArchitectureName());
    554 
    555     const char *working_dir = launch_info.GetWorkingDirectory();
    556     if (working_dir)
    557         command.Printf(" --working-dir '%s'", working_dir);
    558     else
    559     {
    560         char cwd[PATH_MAX];
    561         if (getcwd(cwd, PATH_MAX))
    562             command.Printf(" --working-dir '%s'", cwd);
    563     }
    564     
    565     if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR))
    566         command.PutCString(" --disable-aslr");
    567     
    568     // We are launching on this host in a terminal. So compare the environemnt on the host
    569     // to what is supplied in the launch_info. Any items that aren't in the host environemnt
    570     // need to be sent to darwin-debug. If we send all environment entries, we might blow the
    571     // max command line length, so we only send user modified entries.
    572     const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector ();
    573     StringList host_env;
    574     const size_t host_env_count = Host::GetEnvironment (host_env);
    575     const char *env_entry;
    576     for (size_t env_idx = 0; (env_entry = envp[env_idx]) != NULL; ++env_idx)
    577     {
    578         bool add_entry = true;
    579         for (size_t i=0; i<host_env_count; ++i)
    580         {
    581             const char *host_env_entry = host_env.GetStringAtIndex(i);
    582             if (strcmp(env_entry, host_env_entry) == 0)
    583             {
    584                 add_entry = false;
    585                 break;
    586             }
    587         }
    588         if (add_entry)
    589         {
    590             command.Printf(" --env='%s'", env_entry);
    591         }
    592     }
    593 
    594     command.PutCString(" -- ");
    595 
    596     const char **argv = launch_info.GetArguments().GetConstArgumentVector ();
    597     if (argv)
    598     {
    599         for (size_t i=0; argv[i] != NULL; ++i)
    600         {
    601             if (i==0)
    602                 command.Printf(" '%s'", exe_path);
    603             else
    604                 command.Printf(" '%s'", argv[i]);
    605         }
    606     }
    607     else
    608     {
    609         command.Printf(" '%s'", exe_path);
    610     }
    611     command.PutCString (" ; echo Process exited with status $?");
    612     
    613     StreamString applescript_source;
    614 
    615     const char *tty_command = command.GetString().c_str();
    616 //    if (tty_name && tty_name[0])
    617 //    {
    618 //        applescript_source.Printf (applscript_in_existing_tty, 
    619 //                                   tty_command,
    620 //                                   tty_name);
    621 //    }
    622 //    else
    623 //    {
    624         applescript_source.Printf (applscript_in_new_tty, 
    625                                    tty_command);
    626 //    }
    627 
    628     
    629 
    630     const char *script_source = applescript_source.GetString().c_str();
    631     //puts (script_source);
    632     NSAppleScript* applescript = [[NSAppleScript alloc] initWithSource:[NSString stringWithCString:script_source encoding:NSUTF8StringEncoding]];
    633 
    634     lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
    635 
    636     Error lldb_error;
    637     // Sleep and wait a bit for debugserver to start to listen...
    638     ConnectionFileDescriptor file_conn;
    639     char connect_url[128];
    640     ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
    641 
    642     // Spawn a new thread to accept incoming connection on the connect_url
    643     // so we can grab the pid from the inferior. We have to do this because we
    644     // are sending an AppleScript that will launch a process in Terminal.app,
    645     // in a shell and the shell will fork/exec a couple of times before we get
    646     // to the process that we wanted to launch. So when our process actually
    647     // gets launched, we will handshake with it and get the process ID for it.
    648     lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
    649                                                        AcceptPIDFromInferior,
    650                                                        connect_url,
    651                                                        &lldb_error);
    652     
    653 
    654     [applescript executeAndReturnError:nil];
    655     
    656     thread_result_t accept_thread_result = NULL;
    657     if (Host::ThreadJoin (accept_thread, &accept_thread_result, &lldb_error))
    658     {
    659         if (accept_thread_result)
    660         {
    661             pid = (intptr_t)accept_thread_result;
    662         
    663             // Wait for process to be stopped the the entry point by watching
    664             // for the process status to be set to SSTOP which indicates it it
    665             // SIGSTOP'ed at the entry point
    666             WaitForProcessToSIGSTOP (pid, 5);
    667         }
    668     }
    669     ::unlink (unix_socket_name);
    670     [applescript release];
    671     if (pid != LLDB_INVALID_PROCESS_ID)
    672         launch_info.SetProcessID (pid);
    673     return error;
    674 }
    675 
    676 #endif // #if !defined(__arm__)
    677 
    678 
    679 // On MacOSX CrashReporter will display a string for each shared library if
    680 // the shared library has an exported symbol named "__crashreporter_info__".
    681 
    682 static Mutex&
    683 GetCrashReporterMutex ()
    684 {
    685     static Mutex g_mutex;
    686     return g_mutex;
    687 }
    688 
    689 extern "C" {
    690     const char *__crashreporter_info__ = NULL;
    691 }
    692 
    693 asm(".desc ___crashreporter_info__, 0x10");
    694 
    695 void
    696 Host::SetCrashDescriptionWithFormat (const char *format, ...)
    697 {
    698     static StreamString g_crash_description;
    699     Mutex::Locker locker (GetCrashReporterMutex ());
    700     
    701     if (format)
    702     {
    703         va_list args;
    704         va_start (args, format);
    705         g_crash_description.GetString().clear();
    706         g_crash_description.PrintfVarArg(format, args);
    707         va_end (args);
    708         __crashreporter_info__ = g_crash_description.GetData();
    709     }
    710     else
    711     {
    712         __crashreporter_info__ = NULL;
    713     }
    714 }
    715 
    716 void
    717 Host::SetCrashDescription (const char *cstr)
    718 {
    719     Mutex::Locker locker (GetCrashReporterMutex ());
    720     static std::string g_crash_description;
    721     if (cstr)
    722     {
    723         g_crash_description.assign (cstr);
    724         __crashreporter_info__ = g_crash_description.c_str();
    725     }
    726     else
    727     {
    728         __crashreporter_info__ = NULL;
    729     }
    730 }
    731 
    732 bool
    733 Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no)
    734 {
    735 #if defined(__arm__)
    736     return false;
    737 #else
    738     // We attach this to an 'odoc' event to specify a particular selection
    739     typedef struct {
    740         int16_t   reserved0;  // must be zero
    741         int16_t   fLineNumber;
    742         int32_t   fSelStart;
    743         int32_t   fSelEnd;
    744         uint32_t  reserved1;  // must be zero
    745         uint32_t  reserved2;  // must be zero
    746     } BabelAESelInfo;
    747     
    748     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST));
    749     char file_path[PATH_MAX];
    750     file_spec.GetPath(file_path, PATH_MAX);
    751     CFCString file_cfstr (file_path, kCFStringEncodingUTF8);
    752     CFCReleaser<CFURLRef> file_URL (::CFURLCreateWithFileSystemPath (NULL, 
    753                                                                      file_cfstr.get(), 
    754                                                                      kCFURLPOSIXPathStyle, 
    755                                                                      false));
    756                                                                      
    757     if (log)
    758         log->Printf("Sending source file: \"%s\" and line: %d to external editor.\n", file_path, line_no);
    759     
    760     long error;	
    761     BabelAESelInfo file_and_line_info = 
    762     {
    763         0,                         // reserved0
    764         (int16_t)(line_no - 1),    // fLineNumber (zero based line number)
    765         1,                         // fSelStart
    766         1024,                      // fSelEnd
    767         0,                         // reserved1
    768         0                          // reserved2
    769     };
    770 
    771     AEKeyDesc file_and_line_desc;
    772     
    773     error = ::AECreateDesc (typeUTF8Text, 
    774                             &file_and_line_info, 
    775                             sizeof (file_and_line_info), 
    776                             &(file_and_line_desc.descContent));
    777     
    778     if (error != noErr)
    779     {
    780         if (log)
    781             log->Printf("Error creating AEDesc: %ld.\n", error);
    782         return false;
    783     }
    784     
    785     file_and_line_desc.descKey = keyAEPosition;
    786     
    787     static std::string g_app_name;
    788     static FSRef g_app_fsref;
    789 
    790     LSApplicationParameters app_params;
    791     ::memset (&app_params, 0, sizeof (app_params));
    792     app_params.flags = kLSLaunchDefaults | 
    793                        kLSLaunchDontAddToRecents | 
    794                        kLSLaunchDontSwitch;
    795     
    796     char *external_editor = ::getenv ("LLDB_EXTERNAL_EDITOR");
    797     
    798     if (external_editor)
    799     {
    800         if (log)
    801             log->Printf("Looking for external editor \"%s\".\n", external_editor);
    802 
    803         if (g_app_name.empty() || strcmp (g_app_name.c_str(), external_editor) != 0)
    804         {
    805             CFCString editor_name (external_editor, kCFStringEncodingUTF8);
    806             error = ::LSFindApplicationForInfo (kLSUnknownCreator, 
    807                                                 NULL, 
    808                                                 editor_name.get(), 
    809                                                 &g_app_fsref, 
    810                                                 NULL);
    811             
    812             // If we found the app, then store away the name so we don't have to re-look it up.
    813             if (error != noErr)
    814             {
    815                 if (log)
    816                     log->Printf("Could not find External Editor application, error: %ld.\n", error);
    817                 return false;
    818             }
    819                 
    820         }
    821         app_params.application = &g_app_fsref;
    822     }
    823 
    824     ProcessSerialNumber psn;
    825     CFCReleaser<CFArrayRef> file_array(CFArrayCreate (NULL, (const void **) file_URL.ptr_address(false), 1, NULL));
    826     error = ::LSOpenURLsWithRole (file_array.get(), 
    827                                   kLSRolesAll, 
    828                                   &file_and_line_desc, 
    829                                   &app_params, 
    830                                   &psn, 
    831                                   1);
    832     
    833     AEDisposeDesc (&(file_and_line_desc.descContent));
    834 
    835     if (error != noErr)
    836     {
    837         if (log)
    838             log->Printf("LSOpenURLsWithRole failed, error: %ld.\n", error);
    839 
    840         return false;
    841     }
    842     
    843     ProcessInfoRec which_process;
    844     ::memset(&which_process, 0, sizeof(which_process));
    845     unsigned char ap_name[PATH_MAX];
    846     which_process.processName = ap_name;
    847     error = ::GetProcessInformation (&psn, &which_process);
    848     
    849     bool using_xcode;
    850     if (error != noErr)
    851     {
    852         if (log)
    853             log->Printf("GetProcessInformation failed, error: %ld.\n", error);
    854         using_xcode = false;
    855     }
    856     else
    857         using_xcode = strncmp((char *) ap_name+1, "Xcode", (int) ap_name[0]) == 0;
    858     
    859     // Xcode doesn't obey the line number in the Open Apple Event.  So I have to send
    860     // it an AppleScript to focus on the right line.
    861     
    862     if (using_xcode)
    863     {
    864         static ComponentInstance osa_component = NULL;
    865         static const char *as_template = "tell application \"Xcode\"\n"
    866                                    "set doc to the first document whose path is \"%s\"\n"
    867                                    "set the selection to paragraph %d of doc\n"
    868                                    "--- set the selected paragraph range to {%d, %d} of doc\n"
    869                                    "end tell\n";
    870         const int chars_for_int = 32;
    871         static int as_template_len = strlen (as_template);
    872 
    873       
    874         char *as_str;
    875         AEDesc as_desc;
    876       
    877         if (osa_component == NULL)
    878         {
    879             osa_component = ::OpenDefaultComponent (kOSAComponentType,
    880                                                     kAppleScriptSubtype);
    881         }
    882         
    883         if (osa_component == NULL)
    884         {
    885             if (log)
    886                 log->Printf("Could not get default AppleScript component.\n");
    887             return false;
    888         }
    889 
    890         uint32_t as_str_size = as_template_len + strlen (file_path) + 3 * chars_for_int + 1;     
    891         as_str = (char *) malloc (as_str_size);
    892         ::snprintf (as_str, 
    893                     as_str_size - 1, 
    894                     as_template, 
    895                     file_path, 
    896                     line_no, 
    897                     line_no, 
    898                     line_no);
    899 
    900         error = ::AECreateDesc (typeChar, 
    901                                 as_str, 
    902                                 strlen (as_str),
    903                                 &as_desc);
    904         
    905         ::free (as_str);
    906 
    907         if (error != noErr)
    908         {
    909             if (log)
    910                 log->Printf("Failed to create AEDesc for Xcode AppleEvent: %ld.\n", error);
    911             return false;
    912         }
    913             
    914         OSAID ret_OSAID;
    915         error = ::OSACompileExecute (osa_component, 
    916                                      &as_desc, 
    917                                      kOSANullScript, 
    918                                      kOSAModeNeverInteract, 
    919                                      &ret_OSAID);
    920         
    921         ::OSADispose (osa_component, ret_OSAID);
    922 
    923         ::AEDisposeDesc (&as_desc);
    924 
    925         if (error != noErr)
    926         {
    927             if (log)
    928                 log->Printf("Sending AppleEvent to Xcode failed, error: %ld.\n", error);
    929             return false;
    930         }
    931     }
    932     return true;
    933 #endif // #if !defined(__arm__)
    934 }
    935 
    936 
    937 void
    938 Host::Backtrace (Stream &strm, uint32_t max_frames)
    939 {
    940     if (max_frames > 0)
    941     {
    942         std::vector<void *> frame_buffer (max_frames, NULL);
    943         int num_frames = ::backtrace (&frame_buffer[0], frame_buffer.size());
    944         char** strs = ::backtrace_symbols (&frame_buffer[0], num_frames);
    945         if (strs)
    946         {
    947             // Start at 1 to skip the "Host::Backtrace" frame
    948             for (int i = 1; i < num_frames; ++i)
    949                 strm.Printf("%s\n", strs[i]);
    950             ::free (strs);
    951         }
    952     }
    953 }
    954 
    955 size_t
    956 Host::GetEnvironment (StringList &env)
    957 {
    958     char **host_env = *_NSGetEnviron();
    959     char *env_entry;
    960     size_t i;
    961     for (i=0; (env_entry = host_env[i]) != NULL; ++i)
    962         env.AppendString(env_entry);
    963     return i;
    964         
    965 }
    966 
    967 
    968 bool
    969 Host::GetOSBuildString (std::string &s)
    970 {
    971     int mib[2] = { CTL_KERN, KERN_OSVERSION };
    972     char cstr[PATH_MAX];
    973     size_t cstr_len = sizeof(cstr);
    974     if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0)
    975     {
    976         s.assign (cstr, cstr_len);
    977         return true;
    978     }
    979     
    980     s.clear();
    981     return false;
    982 }
    983 
    984 bool
    985 Host::GetOSKernelDescription (std::string &s)
    986 {
    987     int mib[2] = { CTL_KERN, KERN_VERSION };
    988     char cstr[PATH_MAX];
    989     size_t cstr_len = sizeof(cstr);
    990     if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0)
    991     {
    992         s.assign (cstr, cstr_len);
    993         return true;
    994     }
    995     s.clear();
    996     return false;
    997 }
    998     
    999 #include <libxml/parser.h>
   1000 #include <libxml/tree.h>
   1001 
   1002 bool
   1003 Host::GetOSVersion 
   1004 (
   1005     uint32_t &major, 
   1006     uint32_t &minor, 
   1007     uint32_t &update
   1008 )
   1009 {
   1010     static const char *version_plist_file = "/System/Library/CoreServices/SystemVersion.plist";
   1011     char buffer[256];
   1012     const char *product_version_str = NULL;
   1013     
   1014     CFCReleaser<CFURLRef> plist_url(CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
   1015                                                                             (UInt8 *) version_plist_file,
   1016                                                                             strlen (version_plist_file), NO));
   1017     if (plist_url.get())
   1018     {
   1019         CFCReleaser<CFPropertyListRef> property_list;
   1020         CFCReleaser<CFStringRef>       error_string;
   1021         CFCReleaser<CFDataRef>         resource_data;
   1022         SInt32                         error_code;
   1023  
   1024         // Read the XML file.
   1025         if (CFURLCreateDataAndPropertiesFromResource (kCFAllocatorDefault,
   1026                                                       plist_url.get(),
   1027                                                       resource_data.ptr_address(),
   1028                                                       NULL,
   1029                                                       NULL,
   1030                                                       &error_code))
   1031         {
   1032                // Reconstitute the dictionary using the XML data.
   1033             property_list = CFPropertyListCreateFromXMLData (kCFAllocatorDefault,
   1034                                                               resource_data.get(),
   1035                                                               kCFPropertyListImmutable,
   1036                                                               error_string.ptr_address());
   1037             if (CFGetTypeID(property_list.get()) == CFDictionaryGetTypeID())
   1038             {
   1039                 CFDictionaryRef property_dict = (CFDictionaryRef) property_list.get();
   1040                 CFStringRef product_version_key = CFSTR("ProductVersion");
   1041                 CFPropertyListRef product_version_value;
   1042                 product_version_value = CFDictionaryGetValue(property_dict, product_version_key);
   1043                 if (product_version_value && CFGetTypeID(product_version_value) == CFStringGetTypeID())
   1044                 {
   1045                     CFStringRef product_version_cfstr = (CFStringRef) product_version_value;
   1046                     product_version_str = CFStringGetCStringPtr(product_version_cfstr, kCFStringEncodingUTF8);
   1047                     if (product_version_str != NULL) {
   1048                         if (CFStringGetCString(product_version_cfstr, buffer, 256, kCFStringEncodingUTF8))
   1049                             product_version_str = buffer;
   1050                     }
   1051                 }
   1052             }
   1053         }
   1054     }
   1055     
   1056 
   1057     if (product_version_str)
   1058     {
   1059         Args::StringToVersion(product_version_str, major, minor, update);
   1060         return true;
   1061     }
   1062     else
   1063         return false;
   1064 
   1065 }
   1066 
   1067 static bool
   1068 GetMacOSXProcessName (const ProcessInstanceInfoMatch *match_info_ptr,
   1069                       ProcessInstanceInfo &process_info)
   1070 {
   1071     if (process_info.ProcessIDIsValid())
   1072     {
   1073         char process_name[MAXCOMLEN * 2 + 1];
   1074         int name_len = ::proc_name(process_info.GetProcessID(), process_name, MAXCOMLEN * 2);
   1075         if (name_len == 0)
   1076             return false;
   1077         
   1078         if (match_info_ptr == NULL || NameMatches(process_name,
   1079                                                   match_info_ptr->GetNameMatchType(),
   1080                                                   match_info_ptr->GetProcessInfo().GetName()))
   1081         {
   1082             process_info.GetExecutableFile().SetFile (process_name, false);
   1083             return true;
   1084         }
   1085     }
   1086     process_info.GetExecutableFile().Clear();
   1087     return false;
   1088 }
   1089 
   1090 
   1091 static bool
   1092 GetMacOSXProcessCPUType (ProcessInstanceInfo &process_info)
   1093 {
   1094     if (process_info.ProcessIDIsValid())
   1095     {
   1096         // Make a new mib to stay thread safe
   1097         int mib[CTL_MAXNAME]={0,};
   1098         size_t mib_len = CTL_MAXNAME;
   1099         if (::sysctlnametomib("sysctl.proc_cputype", mib, &mib_len)) 
   1100             return false;
   1101     
   1102         mib[mib_len] = process_info.GetProcessID();
   1103         mib_len++;
   1104     
   1105         cpu_type_t cpu, sub = 0;
   1106         size_t len = sizeof(cpu);
   1107         if (::sysctl (mib, mib_len, &cpu, &len, 0, 0) == 0)
   1108         {
   1109             switch (cpu)
   1110             {
   1111                 case llvm::MachO::CPUTypeI386:      sub = llvm::MachO::CPUSubType_I386_ALL;     break;
   1112                 case llvm::MachO::CPUTypeX86_64:    sub = llvm::MachO::CPUSubType_X86_64_ALL;   break;
   1113                 case llvm::MachO::CPUTypeARM:
   1114                     {
   1115                         uint32_t cpusubtype = 0;
   1116                         len = sizeof(cpusubtype);
   1117                         if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
   1118                             sub = cpusubtype;
   1119                     }
   1120                     break;
   1121 
   1122                 default:
   1123                     break;
   1124             }
   1125             process_info.GetArchitecture ().SetArchitecture (eArchTypeMachO, cpu, sub);
   1126             return true;
   1127         }
   1128     }
   1129     process_info.GetArchitecture().Clear();
   1130     return false;
   1131 }
   1132 
   1133 static bool
   1134 GetMacOSXProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr,
   1135                       ProcessInstanceInfo &process_info)
   1136 {
   1137     if (process_info.ProcessIDIsValid())
   1138     {
   1139         int proc_args_mib[3] = { CTL_KERN, KERN_PROCARGS2, (int)process_info.GetProcessID() };
   1140 
   1141         char arg_data[8192];
   1142         size_t arg_data_size = sizeof(arg_data);
   1143         if (::sysctl (proc_args_mib, 3, arg_data, &arg_data_size , NULL, 0) == 0)
   1144         {
   1145             DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *));
   1146             lldb::offset_t offset = 0;
   1147             uint32_t argc = data.GetU32 (&offset);
   1148             const char *cstr;
   1149             
   1150             cstr = data.GetCStr (&offset);
   1151             if (cstr)
   1152             {
   1153                 process_info.GetExecutableFile().SetFile(cstr, false);
   1154 
   1155                 if (match_info_ptr == NULL || 
   1156                     NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(),
   1157                                  match_info_ptr->GetNameMatchType(),
   1158                                  match_info_ptr->GetProcessInfo().GetName()))
   1159                 {
   1160                     // Skip NULLs
   1161                     while (1)
   1162                     {
   1163                         const uint8_t *p = data.PeekData(offset, 1);
   1164                         if ((p == NULL) || (*p != '\0'))
   1165                             break;
   1166                         ++offset;
   1167                     }
   1168                     // Now extract all arguments
   1169                     Args &proc_args = process_info.GetArguments();
   1170                     for (int i=0; i<argc; ++i)
   1171                     {
   1172                         cstr = data.GetCStr(&offset);
   1173                         if (cstr)
   1174                             proc_args.AppendArgument(cstr);
   1175                     }
   1176                     return true;
   1177                 }
   1178             }
   1179         }
   1180     }
   1181     return false;
   1182 }
   1183 
   1184 static bool
   1185 GetMacOSXProcessUserAndGroup (ProcessInstanceInfo &process_info)
   1186 {
   1187     if (process_info.ProcessIDIsValid())
   1188     {
   1189         int mib[4];
   1190         mib[0] = CTL_KERN;
   1191         mib[1] = KERN_PROC;
   1192         mib[2] = KERN_PROC_PID;
   1193         mib[3] = process_info.GetProcessID();
   1194         struct kinfo_proc proc_kinfo;
   1195         size_t proc_kinfo_size = sizeof(struct kinfo_proc);
   1196 
   1197         if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
   1198         {
   1199             if (proc_kinfo_size > 0)
   1200             {
   1201                 process_info.SetParentProcessID (proc_kinfo.kp_eproc.e_ppid);
   1202                 process_info.SetUserID (proc_kinfo.kp_eproc.e_pcred.p_ruid);
   1203                 process_info.SetGroupID (proc_kinfo.kp_eproc.e_pcred.p_rgid);
   1204                 process_info.SetEffectiveUserID (proc_kinfo.kp_eproc.e_ucred.cr_uid);
   1205                 if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
   1206                     process_info.SetEffectiveGroupID (proc_kinfo.kp_eproc.e_ucred.cr_groups[0]);
   1207                 else
   1208                     process_info.SetEffectiveGroupID (UINT32_MAX);            
   1209                 return true;
   1210             }
   1211         }
   1212     }
   1213     process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID);
   1214     process_info.SetUserID (UINT32_MAX);
   1215     process_info.SetGroupID (UINT32_MAX);
   1216     process_info.SetEffectiveUserID (UINT32_MAX);
   1217     process_info.SetEffectiveGroupID (UINT32_MAX);            
   1218     return false;
   1219 }
   1220 
   1221 
   1222 uint32_t
   1223 Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
   1224 {
   1225     std::vector<struct kinfo_proc> kinfos;
   1226     
   1227     int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
   1228     
   1229     size_t pid_data_size = 0;
   1230     if (::sysctl (mib, 4, NULL, &pid_data_size, NULL, 0) != 0)
   1231         return 0;
   1232     
   1233     // Add a few extra in case a few more show up
   1234     const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10;
   1235 
   1236     kinfos.resize (estimated_pid_count);
   1237     pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);
   1238     
   1239     if (::sysctl (mib, 4, &kinfos[0], &pid_data_size, NULL, 0) != 0)
   1240         return 0;
   1241 
   1242     const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));
   1243 
   1244     bool all_users = match_info.GetMatchAllUsers();
   1245     const lldb::pid_t our_pid = getpid();
   1246     const uid_t our_uid = getuid();
   1247     for (int i = 0; i < actual_pid_count; i++)
   1248     {
   1249         const struct kinfo_proc &kinfo = kinfos[i];
   1250         
   1251         bool kinfo_user_matches = false;
   1252         if (all_users)
   1253             kinfo_user_matches = true;
   1254         else
   1255             kinfo_user_matches = kinfo.kp_eproc.e_pcred.p_ruid == our_uid;
   1256 
   1257         // Special case, if lldb is being run as root we can attach to anything.
   1258         if (our_uid == 0)
   1259           kinfo_user_matches = true;
   1260 
   1261         if (kinfo_user_matches == false         || // Make sure the user is acceptable
   1262             kinfo.kp_proc.p_pid == our_pid      || // Skip this process
   1263             kinfo.kp_proc.p_pid == 0            || // Skip kernel (kernel pid is zero)
   1264             kinfo.kp_proc.p_stat == SZOMB       || // Zombies are bad, they like brains...
   1265             kinfo.kp_proc.p_flag & P_TRACED     || // Being debugged?
   1266             kinfo.kp_proc.p_flag & P_WEXIT      || // Working on exiting?
   1267             kinfo.kp_proc.p_flag & P_TRANSLATED)   // Skip translated ppc (Rosetta)
   1268             continue;
   1269 
   1270         ProcessInstanceInfo process_info;
   1271         process_info.SetProcessID (kinfo.kp_proc.p_pid);
   1272         process_info.SetParentProcessID (kinfo.kp_eproc.e_ppid);
   1273         process_info.SetUserID (kinfo.kp_eproc.e_pcred.p_ruid);
   1274         process_info.SetGroupID (kinfo.kp_eproc.e_pcred.p_rgid);
   1275         process_info.SetEffectiveUserID (kinfo.kp_eproc.e_ucred.cr_uid);
   1276         if (kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
   1277             process_info.SetEffectiveGroupID (kinfo.kp_eproc.e_ucred.cr_groups[0]);
   1278         else
   1279             process_info.SetEffectiveGroupID (UINT32_MAX);            
   1280 
   1281         // Make sure our info matches before we go fetch the name and cpu type
   1282         if (match_info.Matches (process_info))
   1283         {
   1284             if (GetMacOSXProcessArgs (&match_info, process_info))
   1285             {
   1286                 GetMacOSXProcessCPUType (process_info);
   1287                 if (match_info.Matches (process_info))
   1288                     process_infos.Append (process_info);
   1289             }
   1290         }
   1291     }    
   1292     return process_infos.GetSize();
   1293 }
   1294 
   1295 bool
   1296 Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
   1297 {
   1298     process_info.SetProcessID(pid);
   1299     bool success = false;
   1300     
   1301     if (GetMacOSXProcessArgs (NULL, process_info))
   1302         success = true;
   1303     
   1304     if (GetMacOSXProcessCPUType (process_info))
   1305         success = true;
   1306     
   1307     if (GetMacOSXProcessUserAndGroup (process_info))
   1308         success = true;
   1309     
   1310     if (success)
   1311         return true;
   1312     
   1313     process_info.Clear();
   1314     return false;
   1315 }
   1316 
   1317 static short
   1318 GetPosixspawnFlags (ProcessLaunchInfo &launch_info)
   1319 {
   1320     short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
   1321     if (launch_info.GetFlags().Test (eLaunchFlagExec))
   1322         flags |= POSIX_SPAWN_SETEXEC;           // Darwin specific posix_spawn flag
   1323     
   1324     if (launch_info.GetFlags().Test (eLaunchFlagDebug))
   1325         flags |= POSIX_SPAWN_START_SUSPENDED;   // Darwin specific posix_spawn flag
   1326     
   1327     if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR))
   1328         flags |= _POSIX_SPAWN_DISABLE_ASLR;     // Darwin specific posix_spawn flag
   1329         
   1330     if (launch_info.GetLaunchInSeparateProcessGroup())
   1331         flags |= POSIX_SPAWN_SETPGROUP;
   1332     
   1333 //#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
   1334 //    // Close all files exception those with file actions if this is supported.
   1335 //    flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;       
   1336 //#endif
   1337     
   1338     return flags;
   1339 }
   1340 
   1341 #if !NO_XPC_SERVICES
   1342 static void
   1343 PackageXPCArguments (xpc_object_t message, const char *prefix, const Args& args)
   1344 {
   1345     size_t count = args.GetArgumentCount();
   1346     char buf[50]; // long enough for 'argXXX'
   1347     memset(buf, 0, 50);
   1348     sprintf(buf, "%sCount", prefix);
   1349 	xpc_dictionary_set_int64(message, buf, count);
   1350     for (int i=0; i<count; i++) {
   1351         memset(buf, 0, 50);
   1352         sprintf(buf, "%s%i", prefix, i);
   1353         xpc_dictionary_set_string(message, buf, args.GetArgumentAtIndex(i));
   1354     }
   1355 }
   1356 
   1357 /*
   1358  A valid authorizationRef means that 
   1359     - there is the LaunchUsingXPCRightName rights in the /etc/authorization
   1360     - we have successfully copied the rights to be send over the XPC wire
   1361  Once obtained, it will be valid for as long as the process lives.
   1362  */
   1363 static AuthorizationRef authorizationRef = NULL;
   1364 static Error
   1365 getXPCAuthorization (ProcessLaunchInfo &launch_info)
   1366 {
   1367     Error error;
   1368     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
   1369     
   1370     if ((launch_info.GetUserID() == 0) && !authorizationRef)
   1371     {
   1372         OSStatus createStatus = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);
   1373         if (createStatus != errAuthorizationSuccess)
   1374         {
   1375             error.SetError(1, eErrorTypeGeneric);
   1376             error.SetErrorString("Can't create authorizationRef.");
   1377             if (log)
   1378             {
   1379                 error.PutToLog(log, "%s", error.AsCString());
   1380             }
   1381             return error;
   1382         }
   1383         
   1384         OSStatus rightsStatus = AuthorizationRightGet(LaunchUsingXPCRightName, NULL);
   1385         if (rightsStatus != errAuthorizationSuccess)
   1386         {
   1387             // No rights in the security database, Create it with the right prompt.
   1388             CFStringRef prompt = CFSTR("Xcode is trying to take control of a root process.");
   1389             CFStringRef keys[] = { CFSTR("en") };
   1390             CFTypeRef values[] = { prompt };
   1391             CFDictionaryRef promptDict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
   1392             
   1393             CFStringRef keys1[] = { CFSTR("class"), CFSTR("group"), CFSTR("comment"),               CFSTR("default-prompt"), CFSTR("shared") };
   1394             CFTypeRef values1[] = { CFSTR("user"),  CFSTR("admin"), CFSTR(LaunchUsingXPCRightName), promptDict,              kCFBooleanFalse };
   1395             CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys1, (const void **)values1, 5, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
   1396             rightsStatus = AuthorizationRightSet(authorizationRef, LaunchUsingXPCRightName, dict, NULL, NULL, NULL);
   1397             CFRelease(promptDict);
   1398             CFRelease(dict);
   1399         }
   1400             
   1401         OSStatus copyRightStatus = errAuthorizationDenied;
   1402         if (rightsStatus == errAuthorizationSuccess)
   1403         {
   1404             AuthorizationItem item1 = { LaunchUsingXPCRightName, 0, NULL, 0 };
   1405             AuthorizationItem items[] = {item1};
   1406             AuthorizationRights requestedRights = {1, items };
   1407             AuthorizationFlags authorizationFlags = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights;
   1408             copyRightStatus = AuthorizationCopyRights(authorizationRef, &requestedRights, kAuthorizationEmptyEnvironment, authorizationFlags, NULL);
   1409         }
   1410         
   1411         if (copyRightStatus != errAuthorizationSuccess)
   1412         {
   1413             // Eventually when the commandline supports running as root and the user is not
   1414             // logged in in the current audit session, we will need the trick in gdb where
   1415             // we ask the user to type in the root passwd in the terminal.
   1416             error.SetError(2, eErrorTypeGeneric);
   1417             error.SetErrorStringWithFormat("Launching as root needs root authorization.");
   1418             if (log)
   1419             {
   1420                 error.PutToLog(log, "%s", error.AsCString());
   1421             }
   1422             
   1423             if (authorizationRef)
   1424             {
   1425                 AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
   1426                 authorizationRef = NULL;
   1427             }
   1428         }
   1429     }
   1430 
   1431     return error;
   1432 }
   1433 #endif
   1434 
   1435 static Error
   1436 LaunchProcessXPC (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid)
   1437 {
   1438 #if !NO_XPC_SERVICES
   1439     Error error = getXPCAuthorization(launch_info);
   1440     if (error.Fail())
   1441         return error;
   1442     
   1443     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
   1444     
   1445     uid_t requested_uid = launch_info.GetUserID();
   1446     const char *xpc_service  = nil;
   1447     bool send_auth = false;
   1448     AuthorizationExternalForm extForm;
   1449     if ((requested_uid == UINT32_MAX) || (requested_uid == Host::GetEffectiveUserID()))
   1450     {
   1451         xpc_service = "com.apple.lldb.launcherXPCService";
   1452     }
   1453     else if (requested_uid == 0)
   1454     {
   1455         if (AuthorizationMakeExternalForm(authorizationRef, &extForm) == errAuthorizationSuccess)
   1456         {
   1457             send_auth = true;
   1458         }
   1459         else
   1460         {
   1461             error.SetError(3, eErrorTypeGeneric);
   1462             error.SetErrorStringWithFormat("Launching root via XPC needs to externalize authorization reference.");
   1463             if (log)
   1464             {
   1465                 error.PutToLog(log, "%s", error.AsCString());
   1466             }
   1467             return error;
   1468         }
   1469         xpc_service = "com.apple.lldb.launcherRootXPCService";
   1470     }
   1471     else
   1472     {
   1473         error.SetError(4, eErrorTypeGeneric);
   1474         error.SetErrorStringWithFormat("Launching via XPC is only currently available for either the login user or root.");
   1475         if (log)
   1476         {
   1477             error.PutToLog(log, "%s", error.AsCString());
   1478         }
   1479         return error;
   1480     }
   1481     
   1482     xpc_connection_t conn = xpc_connection_create(xpc_service, NULL);
   1483     
   1484 	xpc_connection_set_event_handler(conn, ^(xpc_object_t event) {
   1485         xpc_type_t	type = xpc_get_type(event);
   1486         
   1487         if (type == XPC_TYPE_ERROR) {
   1488             if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
   1489                 // The service has either canceled itself, crashed, or been terminated.
   1490                 // The XPC connection is still valid and sending a message to it will re-launch the service.
   1491                 // If the service is state-full, this is the time to initialize the new service.
   1492                 return;
   1493             } else if (event == XPC_ERROR_CONNECTION_INVALID) {
   1494                 // The service is invalid. Either the service name supplied to xpc_connection_create() is incorrect
   1495                 // or we (this process) have canceled the service; we can do any cleanup of appliation state at this point.
   1496                 // printf("Service disconnected");
   1497                 return;
   1498             } else {
   1499                 // printf("Unexpected error from service: %s", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
   1500             }
   1501             
   1502         } else {
   1503             // printf("Received unexpected event in handler");
   1504         }
   1505     });
   1506     
   1507     xpc_connection_set_finalizer_f (conn, xpc_finalizer_t(xpc_release));
   1508 	xpc_connection_resume (conn);
   1509     xpc_object_t message = xpc_dictionary_create (nil, nil, 0);
   1510     
   1511     if (send_auth)
   1512     {
   1513         xpc_dictionary_set_data(message, LauncherXPCServiceAuthKey, extForm.bytes, sizeof(AuthorizationExternalForm));
   1514     }
   1515     
   1516     PackageXPCArguments(message, LauncherXPCServiceArgPrefxKey, launch_info.GetArguments());
   1517     PackageXPCArguments(message, LauncherXPCServiceEnvPrefxKey, launch_info.GetEnvironmentEntries());
   1518     
   1519     // Posix spawn stuff.
   1520     xpc_dictionary_set_int64(message, LauncherXPCServiceCPUTypeKey, launch_info.GetArchitecture().GetMachOCPUType());
   1521     xpc_dictionary_set_int64(message, LauncherXPCServicePosixspawnFlagsKey, GetPosixspawnFlags(launch_info));
   1522     
   1523     xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, message);
   1524     xpc_type_t returnType = xpc_get_type(reply);
   1525     if (returnType == XPC_TYPE_DICTIONARY)
   1526     {
   1527         pid = xpc_dictionary_get_int64(reply, LauncherXPCServiceChildPIDKey);
   1528         if (pid == 0)
   1529         {
   1530             int errorType = xpc_dictionary_get_int64(reply, LauncherXPCServiceErrorTypeKey);
   1531             int errorCode = xpc_dictionary_get_int64(reply, LauncherXPCServiceCodeTypeKey);
   1532             
   1533             error.SetError(errorCode, eErrorTypeGeneric);
   1534             error.SetErrorStringWithFormat("Problems with launching via XPC. Error type : %i, code : %i", errorType, errorCode);
   1535             if (log)
   1536             {
   1537                 error.PutToLog(log, "%s", error.AsCString());
   1538             }
   1539             
   1540             if (authorizationRef)
   1541             {
   1542                 AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
   1543                 authorizationRef = NULL;
   1544             }
   1545         }
   1546     }
   1547     else if (returnType == XPC_TYPE_ERROR)
   1548     {
   1549         error.SetError(5, eErrorTypeGeneric);
   1550         error.SetErrorStringWithFormat("Problems with launching via XPC. XPC error : %s", xpc_dictionary_get_string(reply, XPC_ERROR_KEY_DESCRIPTION));
   1551         if (log)
   1552         {
   1553             error.PutToLog(log, "%s", error.AsCString());
   1554         }
   1555     }
   1556     
   1557     return error;
   1558 #else
   1559     Error error;
   1560     return error;
   1561 #endif
   1562 }
   1563 
   1564 static Error
   1565 LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid)
   1566 {
   1567     Error error;
   1568     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
   1569     
   1570     posix_spawnattr_t attr;
   1571     error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);
   1572     
   1573     if (error.Fail() || log)
   1574         error.PutToLog(log, "::posix_spawnattr_init ( &attr )");
   1575     if (error.Fail())
   1576         return error;
   1577 
   1578     // Make a quick class that will cleanup the posix spawn attributes in case
   1579     // we return in the middle of this function.
   1580     lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy);
   1581     
   1582     sigset_t no_signals;
   1583     sigset_t all_signals;
   1584     sigemptyset (&no_signals);
   1585     sigfillset (&all_signals);
   1586     ::posix_spawnattr_setsigmask(&attr, &no_signals);
   1587     ::posix_spawnattr_setsigdefault(&attr, &all_signals);
   1588 
   1589     short flags = GetPosixspawnFlags(launch_info);
   1590     error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX);
   1591     if (error.Fail() || log)
   1592         error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags);
   1593     if (error.Fail())
   1594         return error;
   1595     
   1596 #if !defined(__arm__)
   1597     
   1598     // We don't need to do this for ARM, and we really shouldn't now that we
   1599     // have multiple CPU subtypes and no posix_spawnattr call that allows us
   1600     // to set which CPU subtype to launch...
   1601     const ArchSpec &arch_spec = launch_info.GetArchitecture();
   1602     cpu_type_t cpu = arch_spec.GetMachOCPUType();
   1603     if (cpu != 0 && 
   1604         cpu != UINT32_MAX && 
   1605         cpu != LLDB_INVALID_CPUTYPE)
   1606     {
   1607         size_t ocount = 0;
   1608         error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX);
   1609         if (error.Fail() || log)
   1610             error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu, (uint64_t)ocount);
   1611         
   1612         if (error.Fail() || ocount != 1)
   1613             return error;
   1614     }
   1615     
   1616 #endif
   1617     
   1618     const char *tmp_argv[2];
   1619     char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector();
   1620     char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector();
   1621     if (argv == NULL)
   1622     {
   1623         // posix_spawn gets very unhappy if it doesn't have at least the program
   1624         // name in argv[0]. One of the side affects I have noticed is the environment
   1625         // variables don't make it into the child process if "argv == NULL"!!!
   1626         tmp_argv[0] = exe_path;
   1627         tmp_argv[1] = NULL;
   1628         argv = (char * const*)tmp_argv;
   1629     }
   1630 
   1631     const char *working_dir = launch_info.GetWorkingDirectory();
   1632     if (working_dir)
   1633     {
   1634         // No more thread specific current working directory
   1635         if (__pthread_chdir (working_dir) < 0) {
   1636             if (errno == ENOENT) {
   1637                 error.SetErrorStringWithFormat("No such file or directory: %s", working_dir);
   1638             } else if (errno == ENOTDIR) {
   1639                 error.SetErrorStringWithFormat("Path doesn't name a directory: %s", working_dir);
   1640             } else {
   1641                 error.SetErrorStringWithFormat("An unknown error occurred when changing directory for process execution.");
   1642             }
   1643             return error;
   1644         }
   1645     }
   1646     
   1647     const size_t num_file_actions = launch_info.GetNumFileActions ();
   1648     if (num_file_actions > 0)
   1649     {
   1650         posix_spawn_file_actions_t file_actions;
   1651         error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
   1652         if (error.Fail() || log)
   1653             error.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )");
   1654         if (error.Fail())
   1655             return error;
   1656 
   1657         // Make a quick class that will cleanup the posix spawn attributes in case
   1658         // we return in the middle of this function.
   1659         lldb_utility::CleanUp <posix_spawn_file_actions_t *, int> posix_spawn_file_actions_cleanup (&file_actions, posix_spawn_file_actions_destroy);
   1660 
   1661         for (size_t i=0; i<num_file_actions; ++i)
   1662         {
   1663             const ProcessLaunchInfo::FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i);
   1664             if (launch_file_action)
   1665             {
   1666                 if (!ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (&file_actions,
   1667                                                                              launch_file_action,
   1668                                                                              log,
   1669                                                                              error))
   1670                     return error;
   1671             }
   1672         }
   1673         
   1674         error.SetError (::posix_spawnp (&pid, 
   1675                                         exe_path, 
   1676                                         &file_actions, 
   1677                                         &attr, 
   1678                                         argv,
   1679                                         envp),
   1680                         eErrorTypePOSIX);
   1681 
   1682         if (error.Fail() || log)
   1683         {
   1684             error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )",
   1685                            pid, 
   1686                            exe_path, 
   1687                            &file_actions, 
   1688                            &attr, 
   1689                            argv, 
   1690                            envp);
   1691             if (log)
   1692             {
   1693                 for (int ii=0; argv[ii]; ++ii)
   1694                     log->Printf("argv[%i] = '%s'", ii, argv[ii]);
   1695             }
   1696         }
   1697 
   1698     }
   1699     else
   1700     {
   1701         error.SetError (::posix_spawnp (&pid, 
   1702                                         exe_path, 
   1703                                         NULL, 
   1704                                         &attr, 
   1705                                         argv,
   1706                                         envp),
   1707                         eErrorTypePOSIX);
   1708 
   1709         if (error.Fail() || log)
   1710         {
   1711             error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )",
   1712                            pid, 
   1713                            exe_path, 
   1714                            &attr, 
   1715                            argv, 
   1716                            envp);
   1717             if (log)
   1718             {
   1719                 for (int ii=0; argv[ii]; ++ii)
   1720                     log->Printf("argv[%i] = '%s'", ii, argv[ii]);
   1721             }
   1722         }
   1723     }
   1724     
   1725     if (working_dir)
   1726     {
   1727         // No more thread specific current working directory
   1728         __pthread_fchdir (-1);
   1729     }
   1730     
   1731     return error;
   1732 }
   1733 
   1734 static bool
   1735 ShouldLaunchUsingXPC(const char *exe_path, ProcessLaunchInfo &launch_info)
   1736 {
   1737     bool result = false;
   1738 
   1739 #if !NO_XPC_SERVICES    
   1740     const char *debugserver = "/debugserver";
   1741     int len = strlen(debugserver);
   1742     int exe_len = strlen(exe_path);
   1743     if (exe_len >= len)
   1744     {
   1745         const char *part = exe_path + (exe_len - len);
   1746         if (strcmp(part, debugserver) == 0)
   1747         {
   1748             // We are dealing with debugserver.
   1749             uid_t requested_uid = launch_info.GetUserID();
   1750             if (requested_uid == 0)
   1751             {
   1752                 // Launching XPC works for root. It also works for the non-attaching case for current login
   1753                 // but unfortunately, we can't detect it here.
   1754                 result = true;
   1755             }
   1756         }
   1757     }
   1758 #endif
   1759     
   1760     return result;
   1761 }
   1762 
   1763 Error
   1764 Host::LaunchProcess (ProcessLaunchInfo &launch_info)
   1765 {
   1766     Error error;
   1767     char exe_path[PATH_MAX];
   1768     PlatformSP host_platform_sp (Platform::GetDefaultPlatform ());
   1769     
   1770     const ArchSpec &arch_spec = launch_info.GetArchitecture();
   1771     
   1772     FileSpec exe_spec(launch_info.GetExecutableFile());
   1773     
   1774     FileSpec::FileType file_type = exe_spec.GetFileType();
   1775     if (file_type != FileSpec::eFileTypeRegular)
   1776     {
   1777         lldb::ModuleSP exe_module_sp;
   1778         error = host_platform_sp->ResolveExecutable (exe_spec,
   1779                                                      arch_spec,
   1780                                                      exe_module_sp,
   1781                                                      NULL);
   1782         
   1783         if (error.Fail())
   1784             return error;
   1785         
   1786         if (exe_module_sp)
   1787             exe_spec = exe_module_sp->GetFileSpec();
   1788     }
   1789     
   1790     if (exe_spec.Exists())
   1791     {
   1792         exe_spec.GetPath (exe_path, sizeof(exe_path));
   1793     }
   1794     else
   1795     {
   1796         launch_info.GetExecutableFile().GetPath (exe_path, sizeof(exe_path));
   1797         error.SetErrorStringWithFormat ("executable doesn't exist: '%s'", exe_path);
   1798         return error;
   1799     }
   1800     
   1801     if (launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))
   1802     {
   1803 #if !defined(__arm__)
   1804         return LaunchInNewTerminalWithAppleScript (exe_path, launch_info);
   1805 #else
   1806         error.SetErrorString ("launching a processs in a new terminal is not supported on iOS devices");
   1807         return error;
   1808 #endif
   1809     }
   1810     
   1811     ::pid_t pid = LLDB_INVALID_PROCESS_ID;
   1812     
   1813     if (ShouldLaunchUsingXPC(exe_path, launch_info))
   1814     {
   1815         error = LaunchProcessXPC(exe_path, launch_info, pid);
   1816     }
   1817     else
   1818     {
   1819         error = LaunchProcessPosixSpawn(exe_path, launch_info, pid);
   1820     }
   1821     
   1822     if (pid != LLDB_INVALID_PROCESS_ID)
   1823     {
   1824         // If all went well, then set the process ID into the launch info
   1825         launch_info.SetProcessID(pid);
   1826         
   1827         // Make sure we reap any processes we spawn or we will have zombies.
   1828         if (!launch_info.MonitorProcess())
   1829         {
   1830             const bool monitor_signals = false;
   1831             StartMonitoringChildProcess (Process::SetProcessExitStatus, 
   1832                                          NULL, 
   1833                                          pid, 
   1834                                          monitor_signals);
   1835         }
   1836     }
   1837     else
   1838     {
   1839         // Invalid process ID, something didn't go well
   1840         if (error.Success())
   1841             error.SetErrorString ("process launch failed for unknown reasons");
   1842     }
   1843     return error;
   1844 }
   1845 
   1846 lldb::thread_t
   1847 Host::StartMonitoringChildProcess (Host::MonitorChildProcessCallback callback,
   1848                                    void *callback_baton,
   1849                                    lldb::pid_t pid,
   1850                                    bool monitor_signals)
   1851 {
   1852     lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
   1853     unsigned long mask = DISPATCH_PROC_EXIT;
   1854     if (monitor_signals)
   1855         mask |= DISPATCH_PROC_SIGNAL;
   1856 
   1857     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
   1858 
   1859 
   1860     dispatch_source_t source = ::dispatch_source_create (DISPATCH_SOURCE_TYPE_PROC, 
   1861                                                          pid, 
   1862                                                          mask, 
   1863                                                          ::dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT,0));
   1864 
   1865     if (log)
   1866         log->Printf ("Host::StartMonitoringChildProcess (callback=%p, baton=%p, pid=%i, monitor_signals=%i) source = %p\n", 
   1867                      callback, 
   1868                      callback_baton, 
   1869                      (int)pid, 
   1870                      monitor_signals, 
   1871                      source);
   1872 
   1873     if (source)
   1874     {
   1875         ::dispatch_source_set_cancel_handler (source, ^{
   1876             ::dispatch_release (source);
   1877         });
   1878         ::dispatch_source_set_event_handler (source, ^{
   1879             
   1880             int status= 0;
   1881             int wait_pid = 0;
   1882             bool cancel = false;
   1883             bool exited = false;
   1884             do
   1885             {
   1886                 wait_pid = ::waitpid (pid, &status, 0);
   1887             } while (wait_pid < 0 && errno == EINTR);
   1888 
   1889             if (wait_pid >= 0)
   1890             {
   1891                 int signal = 0;
   1892                 int exit_status = 0;
   1893                 const char *status_cstr = NULL;
   1894                 if (WIFSTOPPED(status))
   1895                 {
   1896                     signal = WSTOPSIG(status);
   1897                     status_cstr = "STOPPED";
   1898                 }
   1899                 else if (WIFEXITED(status))
   1900                 {
   1901                     exit_status = WEXITSTATUS(status);
   1902                     status_cstr = "EXITED";
   1903                     exited = true;
   1904                 }
   1905                 else if (WIFSIGNALED(status))
   1906                 {
   1907                     signal = WTERMSIG(status);
   1908                     status_cstr = "SIGNALED";
   1909                     exited = true;
   1910                     exit_status = -1;
   1911                 }
   1912                 else
   1913                 {
   1914                     status_cstr = "???";
   1915                 }
   1916 
   1917                 if (log)
   1918                     log->Printf ("::waitpid (pid = %llu, &status, 0) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_status = %i",
   1919                                  pid,
   1920                                  wait_pid,
   1921                                  status,
   1922                                  status_cstr,
   1923                                  signal,
   1924                                  exit_status);
   1925                 
   1926                 if (callback)
   1927                     cancel = callback (callback_baton, pid, exited, signal, exit_status);
   1928                 
   1929                 if (exited || cancel)
   1930                 {
   1931                     ::dispatch_source_cancel(source);
   1932                 }
   1933             }
   1934         });
   1935 
   1936         ::dispatch_resume (source);
   1937     }
   1938     return thread;
   1939 }
   1940 
   1941 //----------------------------------------------------------------------
   1942 // Log to both stderr and to ASL Logging when running on MacOSX.
   1943 //----------------------------------------------------------------------
   1944 void
   1945 Host::SystemLog (SystemLogType type, const char *format, va_list args)
   1946 {
   1947     if (format && format[0])
   1948     {
   1949         static aslmsg g_aslmsg = NULL;
   1950         if (g_aslmsg == NULL)
   1951         {
   1952             g_aslmsg = ::asl_new (ASL_TYPE_MSG);
   1953             char asl_key_sender[PATH_MAX];
   1954             snprintf(asl_key_sender, sizeof(asl_key_sender), "com.apple.LLDB.framework");
   1955             ::asl_set (g_aslmsg, ASL_KEY_SENDER, asl_key_sender);
   1956         }
   1957         
   1958         // Copy the va_list so we can log this message twice
   1959         va_list copy_args;
   1960         va_copy (copy_args, args);
   1961         // Log to stderr
   1962         ::vfprintf (stderr, format, copy_args);
   1963         va_end (copy_args);
   1964 
   1965         int asl_level;
   1966         switch (type)
   1967         {
   1968             case eSystemLogError:
   1969                 asl_level = ASL_LEVEL_ERR;
   1970                 break;
   1971                 
   1972             case eSystemLogWarning:
   1973                 asl_level = ASL_LEVEL_WARNING;
   1974                 break;
   1975         }
   1976         
   1977         // Log to ASL
   1978         ::asl_vlog (NULL, g_aslmsg, asl_level, format, args);
   1979     }
   1980 }
   1981 
   1982 lldb::DataBufferSP
   1983 Host::GetAuxvData(lldb_private::Process *process)
   1984 {
   1985     return lldb::DataBufferSP();
   1986 }
   1987