]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/debugserver/source/DNB.cpp
Vendor import of lldb trunk r256945:
[FreeBSD/FreeBSD.git] / tools / debugserver / source / DNB.cpp
1 //===-- DNB.cpp -------------------------------------------------*- 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 //  Created by Greg Clayton on 3/23/07.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "DNB.h"
15 #include <inttypes.h>
16 #include <signal.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <sys/resource.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <sys/wait.h>
23 #include <unistd.h>
24 #include <sys/sysctl.h>
25 #include <map>
26 #include <vector>
27 #include <libproc.h>
28
29 #if defined (__APPLE__)
30 #include <pthread.h>
31 #include <sched.h>
32 #endif
33
34 #define TRY_KQUEUE 1
35
36 #ifdef TRY_KQUEUE
37     #include <sys/event.h>
38     #include <sys/time.h>
39     #ifdef NOTE_EXIT_DETAIL
40         #define USE_KQUEUE
41     #endif
42 #endif
43
44 #include "MacOSX/MachProcess.h"
45 #include "MacOSX/MachTask.h"
46 #include "MacOSX/Genealogy.h"
47 #include "MacOSX/ThreadInfo.h"
48 #include "CFString.h"
49 #include "DNBLog.h"
50 #include "DNBDataRef.h"
51 #include "DNBThreadResumeActions.h"
52 #include "DNBTimer.h"
53 #include "CFBundle.h"
54
55
56 typedef std::shared_ptr<MachProcess> MachProcessSP;
57 typedef std::map<nub_process_t, MachProcessSP> ProcessMap;
58 typedef ProcessMap::iterator ProcessMapIter;
59 typedef ProcessMap::const_iterator ProcessMapConstIter;
60
61 size_t GetAllInfos (std::vector<struct kinfo_proc>& proc_infos);
62 static size_t GetAllInfosMatchingName (const char *process_name, std::vector<struct kinfo_proc>& matching_proc_infos);
63
64 //----------------------------------------------------------------------
65 // A Thread safe singleton to get a process map pointer.
66 //
67 // Returns a pointer to the existing process map, or a pointer to a
68 // newly created process map if CAN_CREATE is non-zero.
69 //----------------------------------------------------------------------
70 static ProcessMap*
71 GetProcessMap(bool can_create)
72 {
73     static ProcessMap* g_process_map_ptr = NULL;
74
75     if (can_create && g_process_map_ptr == NULL)
76     {
77         static pthread_mutex_t g_process_map_mutex = PTHREAD_MUTEX_INITIALIZER;
78         PTHREAD_MUTEX_LOCKER (locker, &g_process_map_mutex);
79         if (g_process_map_ptr == NULL)
80             g_process_map_ptr = new ProcessMap;
81     }
82     return g_process_map_ptr;
83 }
84
85 //----------------------------------------------------------------------
86 // Add PID to the shared process pointer map.
87 //
88 // Return non-zero value if we succeed in adding the process to the map.
89 // The only time this should fail is if we run out of memory and can't
90 // allocate a ProcessMap.
91 //----------------------------------------------------------------------
92 static nub_bool_t
93 AddProcessToMap (nub_process_t pid, MachProcessSP& procSP)
94 {
95     ProcessMap* process_map = GetProcessMap(true);
96     if (process_map)
97     {
98         process_map->insert(std::make_pair(pid, procSP));
99         return true;
100     }
101     return false;
102 }
103
104 //----------------------------------------------------------------------
105 // Remove the shared pointer for PID from the process map.
106 //
107 // Returns the number of items removed from the process map.
108 //----------------------------------------------------------------------
109 //static size_t
110 //RemoveProcessFromMap (nub_process_t pid)
111 //{
112 //    ProcessMap* process_map = GetProcessMap(false);
113 //    if (process_map)
114 //    {
115 //        return process_map->erase(pid);
116 //    }
117 //    return 0;
118 //}
119
120 //----------------------------------------------------------------------
121 // Get the shared pointer for PID from the existing process map.
122 //
123 // Returns true if we successfully find a shared pointer to a
124 // MachProcess object.
125 //----------------------------------------------------------------------
126 static nub_bool_t
127 GetProcessSP (nub_process_t pid, MachProcessSP& procSP)
128 {
129     ProcessMap* process_map = GetProcessMap(false);
130     if (process_map != NULL)
131     {
132         ProcessMapIter pos = process_map->find(pid);
133         if (pos != process_map->end())
134         {
135             procSP = pos->second;
136             return true;
137         }
138     }
139     procSP.reset();
140     return false;
141 }
142
143 #ifdef USE_KQUEUE
144 void *
145 kqueue_thread (void *arg)
146 {
147     int kq_id = (int) (intptr_t) arg;
148     
149 #if defined (__APPLE__)
150     pthread_setname_np ("kqueue thread");
151 #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
152     struct sched_param thread_param;
153     int thread_sched_policy;
154     if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0) 
155     {
156         thread_param.sched_priority = 47;
157         pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
158     }
159 #endif
160 #endif
161
162     struct kevent death_event;
163     while (1)
164     {        
165         int n_events = kevent (kq_id, NULL, 0, &death_event, 1, NULL);
166         if (n_events == -1)
167         {
168             if (errno == EINTR)
169                 continue;
170             else
171             {
172                 DNBLogError ("kqueue failed with error: (%d): %s", errno, strerror(errno));
173                 return NULL;
174             }
175         }
176         else if (death_event.flags & EV_ERROR)
177         {
178             int error_no = static_cast<int>(death_event.data);
179             const char *error_str = strerror(error_no);
180             if (error_str == NULL)
181                 error_str = "Unknown error";
182             DNBLogError ("Failed to initialize kqueue event: (%d): %s", error_no, error_str );
183             return NULL;
184         }
185         else
186         {
187             int status;
188             const pid_t pid = (pid_t)death_event.ident;
189             const pid_t child_pid = waitpid (pid, &status, 0);
190             
191             
192             bool exited = false;
193             int signal = 0;
194             int exit_status = 0;
195             if (WIFSTOPPED(status))
196             {
197                 signal = WSTOPSIG(status);
198                 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> STOPPED (signal = %i)", child_pid, signal);
199             }
200             else if (WIFEXITED(status))
201             {
202                 exit_status = WEXITSTATUS(status);
203                 exited = true;
204                 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> EXITED (status = %i)", child_pid, exit_status);
205             }
206             else if (WIFSIGNALED(status))
207             {
208                 signal = WTERMSIG(status);
209                 if (child_pid == abs(pid))
210                 {
211                     DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED and EXITED (signal = %i)", child_pid, signal);
212                     char exit_info[64];
213                     ::snprintf (exit_info, sizeof(exit_info), "Terminated due to signal %i", signal);
214                     DNBProcessSetExitInfo (child_pid, exit_info);
215                     exited = true;
216                     exit_status = INT8_MAX;
217                 }
218                 else
219                 {
220                     DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED (signal = %i)", child_pid, signal);
221                 }
222             }
223
224             if (exited)
225             {
226                 if (death_event.data & NOTE_EXIT_MEMORY)
227                     DNBProcessSetExitInfo (child_pid, "Terminated due to memory issue");
228                 else if (death_event.data & NOTE_EXIT_DECRYPTFAIL)
229                     DNBProcessSetExitInfo (child_pid, "Terminated due to decrypt failure");
230                 else if (death_event.data & NOTE_EXIT_CSERROR)
231                     DNBProcessSetExitInfo (child_pid, "Terminated due to code signing error");
232                 
233                 DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): setting exit status for pid = %i to %i", child_pid, exit_status);
234                 DNBProcessSetExitStatus (child_pid, status);
235                 return NULL;
236             }
237         }
238     }
239 }
240
241 static bool
242 spawn_kqueue_thread (pid_t pid)
243 {
244     pthread_t thread;
245     int kq_id;
246     
247     kq_id = kqueue();
248     if (kq_id == -1)
249     {
250         DNBLogError ("Could not get kqueue for pid = %i.", pid);
251         return false;
252     }
253
254     struct kevent reg_event;
255     
256     EV_SET(&reg_event, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT|NOTE_EXITSTATUS|NOTE_EXIT_DETAIL, 0, NULL);
257     // Register the event:
258     int result = kevent (kq_id, &reg_event, 1, NULL, 0, NULL);
259     if (result != 0)
260     {
261         DNBLogError ("Failed to register kqueue NOTE_EXIT event for pid %i, error: %d.", pid, result);
262         return false;
263     }
264     
265     int ret = ::pthread_create (&thread, NULL, kqueue_thread, (void *)(intptr_t)kq_id);
266     
267     // pthread_create returns 0 if successful
268     if (ret == 0)
269     {
270         ::pthread_detach (thread);
271         return true;
272     }
273     return false;
274 }
275 #endif // #if USE_KQUEUE
276
277 static void *
278 waitpid_thread (void *arg)
279 {
280     const pid_t pid = (pid_t)(intptr_t)arg;
281     int status;
282
283 #if defined (__APPLE__)
284     pthread_setname_np ("waitpid thread");
285 #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
286     struct sched_param thread_param;
287     int thread_sched_policy;
288     if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0) 
289     {
290         thread_param.sched_priority = 47;
291         pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
292     }
293 #endif
294 #endif
295
296     while (1)
297     {
298         pid_t child_pid = waitpid(pid, &status, 0);
299         DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): waitpid (pid = %i, &status, 0) => %i, status = %i, errno = %i", pid, child_pid, status, errno);
300
301         if (child_pid < 0)
302         {
303             if (errno == EINTR)
304                 continue;
305             break;
306         }
307         else
308         {
309             if (WIFSTOPPED(status))
310             {
311                 continue;
312             }
313             else// if (WIFEXITED(status) || WIFSIGNALED(status))
314             {
315                 DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): setting exit status for pid = %i to %i", child_pid, status);
316                 DNBProcessSetExitStatus (child_pid, status);
317                 return NULL;
318             }
319         }
320     }
321
322     // We should never exit as long as our child process is alive, so if we
323     // do something else went wrong and we should exit...
324     DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): main loop exited, setting exit status to an invalid value (-1) for pid %i", pid);
325     DNBProcessSetExitStatus (pid, -1);
326     return NULL;
327 }
328 static bool
329 spawn_waitpid_thread (pid_t pid)
330 {
331 #ifdef USE_KQUEUE
332     bool success = spawn_kqueue_thread (pid);
333     if (success)
334         return true;
335 #endif
336
337     pthread_t thread;
338     int ret = ::pthread_create (&thread, NULL, waitpid_thread, (void *)(intptr_t)pid);
339     // pthread_create returns 0 if successful
340     if (ret == 0)
341     {
342         ::pthread_detach (thread);
343         return true;
344     }
345     return false;
346 }
347
348 nub_process_t
349 DNBProcessLaunch (const char *path,
350                   char const *argv[],
351                   const char *envp[],
352                   const char *working_directory, // NULL => don't change, non-NULL => set working directory for inferior to this
353                   const char *stdin_path,
354                   const char *stdout_path,
355                   const char *stderr_path,
356                   bool no_stdio,
357                   nub_launch_flavor_t launch_flavor,
358                   int disable_aslr,
359                   const char *event_data,
360                   char *err_str,
361                   size_t err_len)
362 {
363     DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, working_dir=%s, stdin=%s, stdout=%s, stderr=%s, no-stdio=%i, launch_flavor = %u, disable_aslr = %d, err = %p, err_len = %llu) called...",
364                      __FUNCTION__, 
365                      path, 
366                      argv, 
367                      envp, 
368                      working_directory,
369                      stdin_path,
370                      stdout_path,
371                      stderr_path,
372                      no_stdio,
373                      launch_flavor, 
374                      disable_aslr, 
375                      err_str, 
376                      (uint64_t)err_len);
377     
378     if (err_str && err_len > 0)
379         err_str[0] = '\0';
380     struct stat path_stat;
381     if (::stat(path, &path_stat) == -1)
382     {
383         char stat_error[256];
384         ::strerror_r (errno, stat_error, sizeof(stat_error));
385         snprintf(err_str, err_len, "%s (%s)", stat_error, path);
386         return INVALID_NUB_PROCESS;
387     }
388
389     MachProcessSP processSP (new MachProcess);
390     if (processSP.get())
391     {
392         DNBError launch_err;
393         pid_t pid = processSP->LaunchForDebug (path, 
394                                                argv, 
395                                                envp, 
396                                                working_directory, 
397                                                stdin_path, 
398                                                stdout_path, 
399                                                stderr_path, 
400                                                no_stdio, 
401                                                launch_flavor, 
402                                                disable_aslr,
403                                                event_data,
404                                                launch_err);
405         if (err_str)
406         {
407             *err_str = '\0';
408             if (launch_err.Fail())
409             {
410                 const char *launch_err_str = launch_err.AsString();
411                 if (launch_err_str)
412                 {
413                     strncpy(err_str, launch_err_str, err_len-1);
414                     err_str[err_len-1] = '\0';  // Make sure the error string is terminated
415                 }
416             }
417         }
418
419         DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid);
420
421         if (pid != INVALID_NUB_PROCESS)
422         {
423             // Spawn a thread to reap our child inferior process...
424             spawn_waitpid_thread (pid);
425
426             if (processSP->Task().TaskPortForProcessID (launch_err) == TASK_NULL)
427             {
428                 // We failed to get the task for our process ID which is bad.
429                 // Kill our process otherwise it will be stopped at the entry
430                 // point and get reparented to someone else and never go away.
431                 DNBLog ("Could not get task port for process, sending SIGKILL and exiting.");
432                 kill (SIGKILL, pid);
433
434                 if (err_str && err_len > 0)
435                 {
436                     if (launch_err.AsString())
437                     {
438                         ::snprintf (err_str, err_len, "failed to get the task for process %i (%s)", pid, launch_err.AsString());
439                     }
440                     else
441                     {
442                         ::snprintf (err_str, err_len, "failed to get the task for process %i", pid);
443                     }
444                 }
445             }
446             else
447             {
448                 bool res = AddProcessToMap(pid, processSP);
449                 UNUSED_IF_ASSERT_DISABLED(res);
450                 assert(res && "Couldn't add process to map!");
451                 return pid;
452             }
453         }
454     }
455     return INVALID_NUB_PROCESS;
456 }
457
458 // If there is one process with a given name, return the pid for that process.
459 nub_process_t
460 DNBProcessGetPIDByName (const char *name)
461 {
462     std::vector<struct kinfo_proc> matching_proc_infos;
463     size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
464     if (num_matching_proc_infos == 1)
465     {
466         return matching_proc_infos[0].kp_proc.p_pid;
467     }
468     return INVALID_NUB_PROCESS;
469 }
470
471 nub_process_t
472 DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len)
473 {
474     if (err_str && err_len > 0)
475         err_str[0] = '\0';
476     std::vector<struct kinfo_proc> matching_proc_infos;
477     size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
478     if (num_matching_proc_infos == 0)
479     {
480         DNBLogError ("error: no processes match '%s'\n", name);
481         return INVALID_NUB_PROCESS;
482     }
483     else if (num_matching_proc_infos > 1)
484     {
485         DNBLogError ("error: %llu processes match '%s':\n", (uint64_t)num_matching_proc_infos, name);
486         size_t i;
487         for (i=0; i<num_matching_proc_infos; ++i)
488             DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm);
489         return INVALID_NUB_PROCESS;
490     }
491     
492     return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len);
493 }
494
495 nub_process_t
496 DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_str, size_t err_len)
497 {
498     if (err_str && err_len > 0)
499         err_str[0] = '\0';
500
501     pid_t pid = INVALID_NUB_PROCESS;
502     MachProcessSP processSP(new MachProcess);
503     if (processSP.get())
504     {
505         DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", attach_pid);
506         pid = processSP->AttachForDebug (attach_pid, err_str,  err_len);
507
508         if (pid != INVALID_NUB_PROCESS)
509         {
510             bool res = AddProcessToMap(pid, processSP);
511             UNUSED_IF_ASSERT_DISABLED(res);
512             assert(res && "Couldn't add process to map!");
513             spawn_waitpid_thread(pid);
514         }
515     }
516
517     while (pid != INVALID_NUB_PROCESS)
518     {
519         // Wait for process to start up and hit entry point
520         DNBLogThreadedIf (LOG_PROCESS, 
521                           "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...",
522                           __FUNCTION__, 
523                           pid);
524         nub_event_t set_events = DNBProcessWaitForEvents (pid,
525                                                           eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged,
526                                                           true, 
527                                                           timeout);
528
529         DNBLogThreadedIf (LOG_PROCESS, 
530                           "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x",
531                           __FUNCTION__, 
532                           pid, 
533                           set_events);
534
535         if (set_events == 0)
536         {
537             if (err_str && err_len > 0)
538                 snprintf(err_str, err_len, "operation timed out");
539             pid = INVALID_NUB_PROCESS;
540         }
541         else
542         {
543             if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged))
544             {
545                 nub_state_t pid_state = DNBProcessGetState (pid);
546                 DNBLogThreadedIf (LOG_PROCESS, "%s process %4.4x state changed (eEventProcessStateChanged): %s",
547                         __FUNCTION__, pid, DNBStateAsString(pid_state));
548
549                 switch (pid_state)
550                 {
551                     default:
552                     case eStateInvalid:
553                     case eStateUnloaded:
554                     case eStateAttaching:
555                     case eStateLaunching:
556                     case eStateSuspended:
557                         break;  // Ignore
558                         
559                     case eStateRunning:
560                     case eStateStepping:
561                         // Still waiting to stop at entry point...
562                         break;
563                         
564                     case eStateStopped:
565                     case eStateCrashed:
566                         return pid;
567
568                     case eStateDetached:
569                     case eStateExited:
570                         if (err_str && err_len > 0)
571                             snprintf(err_str, err_len, "process exited");
572                         return INVALID_NUB_PROCESS;
573                 }
574             }
575
576             DNBProcessResetEvents(pid, set_events);
577         }
578     }
579
580     return INVALID_NUB_PROCESS;
581 }
582
583 size_t
584 GetAllInfos (std::vector<struct kinfo_proc>& proc_infos)
585 {
586     size_t size = 0;
587     int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
588     u_int namelen = sizeof(name)/sizeof(int);
589     int err;
590
591     // Try to find out how many processes are around so we can
592     // size the buffer appropriately.  sysctl's man page specifically suggests
593     // this approach, and says it returns a bit larger size than needed to
594     // handle any new processes created between then and now.
595
596     err = ::sysctl (name, namelen, NULL, &size, NULL, 0);
597
598     if ((err < 0) && (err != ENOMEM))
599     {
600         proc_infos.clear();
601         perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)");
602         return 0;
603     }
604
605
606     // Increase the size of the buffer by a few processes in case more have
607     // been spawned
608     proc_infos.resize (size / sizeof(struct kinfo_proc));
609     size = proc_infos.size() * sizeof(struct kinfo_proc);   // Make sure we don't exceed our resize...
610     err = ::sysctl (name, namelen, &proc_infos[0], &size, NULL, 0);
611     if (err < 0)
612     {
613         proc_infos.clear();
614         return 0;
615     }
616
617     // Trim down our array to fit what we actually got back
618     proc_infos.resize(size / sizeof(struct kinfo_proc));
619     return proc_infos.size();
620 }
621
622 static size_t
623 GetAllInfosMatchingName(const char *full_process_name, std::vector<struct kinfo_proc>& matching_proc_infos)
624 {
625
626     matching_proc_infos.clear();
627     if (full_process_name && full_process_name[0])
628     {
629         // We only get the process name, not the full path, from the proc_info.  So just take the
630         // base name of the process name...
631         const char *process_name;
632         process_name = strrchr (full_process_name, '/');
633         if (process_name == NULL)
634             process_name = full_process_name;
635         else
636             process_name++;
637
638         const size_t process_name_len = strlen(process_name);
639         std::vector<struct kinfo_proc> proc_infos;
640         const size_t num_proc_infos = GetAllInfos(proc_infos);
641         if (num_proc_infos > 0)
642         {
643             uint32_t i;
644             for (i=0; i<num_proc_infos; i++)
645             {
646                 // Skip zombie processes and processes with unset status
647                 if (proc_infos[i].kp_proc.p_stat == 0 || proc_infos[i].kp_proc.p_stat == SZOMB)
648                     continue;
649
650                 // Check for process by name. We only check the first MAXCOMLEN
651                 // chars as that is all that kp_proc.p_comm holds.
652                 
653                 if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm, MAXCOMLEN) == 0)
654                 {
655                     if (process_name_len > MAXCOMLEN)
656                     {
657                         // We found a matching process name whose first MAXCOMLEN
658                         // characters match, but there is more to the name than
659                         // this. We need to get the full process name.  Use proc_pidpath, which will get
660                         // us the full path to the executed process.
661
662                         char proc_path_buf[PATH_MAX];
663                         
664                         int return_val = proc_pidpath (proc_infos[i].kp_proc.p_pid, proc_path_buf, PATH_MAX);
665                         if (return_val > 0)
666                         {
667                             // Okay, now search backwards from that to see if there is a
668                             // slash in the name.  Note, even though we got all the args we don't care
669                             // because the list data is just a bunch of concatenated null terminated strings
670                             // so strrchr will start from the end of argv0.
671                             
672                             const char *argv_basename = strrchr(proc_path_buf, '/');
673                             if (argv_basename)
674                             {
675                                 // Skip the '/'
676                                 ++argv_basename;
677                             }
678                             else
679                             {
680                                 // We didn't find a directory delimiter in the process argv[0], just use what was in there
681                                 argv_basename = proc_path_buf;
682                             }
683
684                             if (argv_basename)
685                             {
686                                 if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0)
687                                 {
688                                     matching_proc_infos.push_back(proc_infos[i]);
689                                 }
690                             }
691                         }
692                     }
693                     else
694                     {
695                         // We found a matching process, add it to our list
696                         matching_proc_infos.push_back(proc_infos[i]);
697                     }
698                 }
699             }
700         }
701     }
702     // return the newly added matches.
703     return matching_proc_infos.size();
704 }
705
706 nub_process_t
707 DNBProcessAttachWait (const char *waitfor_process_name, 
708                       nub_launch_flavor_t launch_flavor,
709                       bool ignore_existing,
710                       struct timespec *timeout_abstime, 
711                       useconds_t waitfor_interval,
712                       char *err_str, 
713                       size_t err_len,
714                       DNBShouldCancelCallback should_cancel_callback,
715                       void *callback_data)
716 {
717     DNBError prepare_error;
718     std::vector<struct kinfo_proc> exclude_proc_infos;
719     size_t num_exclude_proc_infos;
720
721     // If the PrepareForAttach returns a valid token, use  MachProcess to check
722     // for the process, otherwise scan the process table.
723
724     const void *attach_token = MachProcess::PrepareForAttach (waitfor_process_name, launch_flavor, true, prepare_error);
725
726     if (prepare_error.Fail())
727     {
728         DNBLogError ("Error in PrepareForAttach: %s", prepare_error.AsString());
729         return INVALID_NUB_PROCESS;
730     }
731
732     if (attach_token == NULL)
733     {
734         if (ignore_existing)
735             num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos);
736         else
737             num_exclude_proc_infos = 0;
738     }
739
740     DNBLogThreadedIf (LOG_PROCESS, "Waiting for '%s' to appear...\n", waitfor_process_name);
741
742     // Loop and try to find the process by name
743     nub_process_t waitfor_pid = INVALID_NUB_PROCESS;
744
745     while (waitfor_pid == INVALID_NUB_PROCESS)
746     {
747         if (attach_token != NULL)
748         {
749             nub_process_t pid;
750             pid = MachProcess::CheckForProcess(attach_token, launch_flavor);
751             if (pid != INVALID_NUB_PROCESS)
752             {
753                 waitfor_pid = pid;
754                 break;
755             }
756         }
757         else
758         {
759
760             // Get the current process list, and check for matches that
761             // aren't in our original list. If anyone wants to attach
762             // to an existing process by name, they should do it with
763             // --attach=PROCNAME. Else we will wait for the first matching
764             // process that wasn't in our exclusion list.
765             std::vector<struct kinfo_proc> proc_infos;
766             const size_t num_proc_infos = GetAllInfosMatchingName (waitfor_process_name, proc_infos);
767             for (size_t i=0; i<num_proc_infos; i++)
768             {
769                 nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid;
770                 for (size_t j=0; j<num_exclude_proc_infos; j++)
771                 {
772                     if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid)
773                     {
774                         // This process was in our exclusion list, don't use it.
775                         curr_pid = INVALID_NUB_PROCESS;
776                         break;
777                     }
778                 }
779
780                 // If we didn't find CURR_PID in our exclusion list, then use it.
781                 if (curr_pid != INVALID_NUB_PROCESS)
782                 {
783                     // We found our process!
784                     waitfor_pid = curr_pid;
785                     break;
786                 }
787             }
788         }
789
790         // If we haven't found our process yet, check for a timeout
791         // and then sleep for a bit until we poll again.
792         if (waitfor_pid == INVALID_NUB_PROCESS)
793         {
794             if (timeout_abstime != NULL)
795             {
796                 // Check to see if we have a waitfor-duration option that
797                 // has timed out?
798                 if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime))
799                 {
800                     if (err_str && err_len > 0)
801                         snprintf(err_str, err_len, "operation timed out");
802                     DNBLogError ("error: waiting for process '%s' timed out.\n", waitfor_process_name);
803                     return INVALID_NUB_PROCESS;
804                 }
805             }
806
807             // Call the should cancel callback as well...
808
809             if (should_cancel_callback != NULL
810                 && should_cancel_callback (callback_data))
811             {
812                 DNBLogThreadedIf (LOG_PROCESS, "DNBProcessAttachWait cancelled by should_cancel callback.");
813                 waitfor_pid = INVALID_NUB_PROCESS;
814                 break;
815             }
816
817             ::usleep (waitfor_interval);    // Sleep for WAITFOR_INTERVAL, then poll again
818         }
819     }
820
821     if (waitfor_pid != INVALID_NUB_PROCESS)
822     {
823         DNBLogThreadedIf (LOG_PROCESS, "Attaching to %s with pid %i...\n", waitfor_process_name, waitfor_pid);
824         waitfor_pid = DNBProcessAttach (waitfor_pid, timeout_abstime, err_str, err_len);
825     }
826
827     bool success = waitfor_pid != INVALID_NUB_PROCESS;
828     MachProcess::CleanupAfterAttach (attach_token, launch_flavor, success, prepare_error);
829
830     return waitfor_pid;
831 }
832
833 nub_bool_t
834 DNBProcessDetach (nub_process_t pid)
835 {
836     MachProcessSP procSP;
837     if (GetProcessSP (pid, procSP))
838     {
839         const bool remove = true;
840         DNBLogThreaded("Disabling breakpoints and watchpoints, and detaching from %d.", pid);
841         procSP->DisableAllBreakpoints(remove);
842         procSP->DisableAllWatchpoints (remove);
843         return procSP->Detach();
844     }
845     return false;
846 }
847
848 nub_bool_t
849 DNBProcessKill (nub_process_t pid)
850 {
851     MachProcessSP procSP;
852     if (GetProcessSP (pid, procSP))
853     {
854         return procSP->Kill ();
855     }
856     return false;
857 }
858
859 nub_bool_t
860 DNBProcessSignal (nub_process_t pid, int signal)
861 {
862     MachProcessSP procSP;
863     if (GetProcessSP (pid, procSP))
864     {
865         return procSP->Signal (signal);
866     }
867     return false;
868 }
869
870
871 nub_bool_t
872 DNBProcessInterrupt(nub_process_t pid)
873 {
874     MachProcessSP procSP;
875     if (GetProcessSP (pid, procSP))
876         return procSP->Interrupt();
877     return false;
878 }
879
880 nub_bool_t
881 DNBProcessSendEvent (nub_process_t pid, const char *event)
882 {
883     MachProcessSP procSP;
884     if (GetProcessSP (pid, procSP))
885     {
886         // FIXME: Do something with the error...
887         DNBError send_error;
888         return procSP->SendEvent (event, send_error);
889     }
890     return false;
891 }
892
893
894 nub_bool_t
895 DNBProcessIsAlive (nub_process_t pid)
896 {
897     MachProcessSP procSP;
898     if (GetProcessSP (pid, procSP))
899     {
900         return MachTask::IsValid (procSP->Task().TaskPort());
901     }
902     return eStateInvalid;
903 }
904
905 //----------------------------------------------------------------------
906 // Process and Thread state information
907 //----------------------------------------------------------------------
908 nub_state_t
909 DNBProcessGetState (nub_process_t pid)
910 {
911     MachProcessSP procSP;
912     if (GetProcessSP (pid, procSP))
913     {
914         return procSP->GetState();
915     }
916     return eStateInvalid;
917 }
918
919 //----------------------------------------------------------------------
920 // Process and Thread state information
921 //----------------------------------------------------------------------
922 nub_bool_t
923 DNBProcessGetExitStatus (nub_process_t pid, int* status)
924 {
925     MachProcessSP procSP;
926     if (GetProcessSP (pid, procSP))
927     {
928         return procSP->GetExitStatus(status);
929     }
930     return false;
931 }
932
933 nub_bool_t
934 DNBProcessSetExitStatus (nub_process_t pid, int status)
935 {
936     MachProcessSP procSP;
937     if (GetProcessSP (pid, procSP))
938     {
939         procSP->SetExitStatus(status);
940         return true;
941     }
942     return false;
943 }
944
945 const char *
946 DNBProcessGetExitInfo (nub_process_t pid)
947 {
948     MachProcessSP procSP;
949     if (GetProcessSP (pid, procSP))
950     {
951         return procSP->GetExitInfo();
952     }
953     return NULL;
954 }
955
956 nub_bool_t
957 DNBProcessSetExitInfo (nub_process_t pid, const char *info)
958 {
959     MachProcessSP procSP;
960     if (GetProcessSP (pid, procSP))
961     {
962         procSP->SetExitInfo(info);
963         return true;
964     }
965     return false;
966 }
967
968 const char *
969 DNBThreadGetName (nub_process_t pid, nub_thread_t tid)
970 {
971     MachProcessSP procSP;
972     if (GetProcessSP (pid, procSP))
973         return procSP->ThreadGetName(tid);
974     return NULL;
975 }
976
977
978 nub_bool_t
979 DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info)
980 {
981     MachProcessSP procSP;
982     if (GetProcessSP (pid, procSP))
983         return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info);
984     return false;
985 }
986
987 nub_state_t
988 DNBThreadGetState (nub_process_t pid, nub_thread_t tid)
989 {
990     MachProcessSP procSP;
991     if (GetProcessSP (pid, procSP))
992     {
993         return procSP->ThreadGetState(tid);
994     }
995     return eStateInvalid;
996 }
997
998 const char *
999 DNBStateAsString(nub_state_t state)
1000 {
1001     switch (state)
1002     {
1003     case eStateInvalid:     return "Invalid";
1004     case eStateUnloaded:    return "Unloaded";
1005     case eStateAttaching:   return "Attaching";
1006     case eStateLaunching:   return "Launching";
1007     case eStateStopped:     return "Stopped";
1008     case eStateRunning:     return "Running";
1009     case eStateStepping:    return "Stepping";
1010     case eStateCrashed:     return "Crashed";
1011     case eStateDetached:    return "Detached";
1012     case eStateExited:      return "Exited";
1013     case eStateSuspended:   return "Suspended";
1014     }
1015     return "nub_state_t ???";
1016 }
1017
1018 Genealogy::ThreadActivitySP
1019 DNBGetGenealogyInfoForThread (nub_process_t pid, nub_thread_t tid, bool &timed_out)
1020 {
1021     Genealogy::ThreadActivitySP thread_activity_sp;
1022     MachProcessSP procSP;
1023     if (GetProcessSP (pid, procSP))
1024         thread_activity_sp = procSP->GetGenealogyInfoForThread (tid, timed_out);
1025     return thread_activity_sp;
1026 }
1027
1028 Genealogy::ProcessExecutableInfoSP
1029 DNBGetGenealogyImageInfo (nub_process_t pid, size_t idx)
1030 {
1031     Genealogy::ProcessExecutableInfoSP image_info_sp;
1032     MachProcessSP procSP;
1033     if (GetProcessSP (pid, procSP))
1034     {
1035         image_info_sp = procSP->GetGenealogyImageInfo (idx);
1036     }
1037     return image_info_sp;
1038 }
1039
1040 ThreadInfo::QoS
1041 DNBGetRequestedQoSForThread (nub_process_t pid, nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index)
1042 {
1043     MachProcessSP procSP;
1044     if (GetProcessSP (pid, procSP))
1045     {
1046         return procSP->GetRequestedQoS (tid, tsd, dti_qos_class_index);
1047     }
1048     return ThreadInfo::QoS();
1049 }
1050
1051 nub_addr_t
1052 DNBGetPThreadT (nub_process_t pid, nub_thread_t tid)
1053 {
1054     MachProcessSP procSP;
1055     if (GetProcessSP (pid, procSP))
1056     {
1057         return procSP->GetPThreadT (tid);
1058     }
1059     return INVALID_NUB_ADDRESS;
1060 }
1061
1062 nub_addr_t
1063 DNBGetDispatchQueueT (nub_process_t pid, nub_thread_t tid)
1064 {
1065     MachProcessSP procSP;
1066     if (GetProcessSP (pid, procSP))
1067     {
1068         return procSP->GetDispatchQueueT (tid);
1069     }
1070     return INVALID_NUB_ADDRESS;
1071 }
1072
1073 nub_addr_t
1074 DNBGetTSDAddressForThread (nub_process_t pid, nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size)
1075 {
1076     MachProcessSP procSP;
1077     if (GetProcessSP (pid, procSP))
1078     {
1079         return procSP->GetTSDAddressForThread (tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
1080     }
1081     return INVALID_NUB_ADDRESS;
1082 }
1083
1084 JSONGenerator::ObjectSP 
1085 DNBGetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count)
1086 {
1087     MachProcessSP procSP;
1088     if (GetProcessSP (pid, procSP))
1089     {
1090         return procSP->GetLoadedDynamicLibrariesInfos (pid, image_list_address, image_count);
1091     }
1092     return JSONGenerator::ObjectSP();
1093 }
1094
1095
1096
1097 const char *
1098 DNBProcessGetExecutablePath (nub_process_t pid)
1099 {
1100     MachProcessSP procSP;
1101     if (GetProcessSP (pid, procSP))
1102     {
1103         return procSP->Path();
1104     }
1105     return NULL;
1106 }
1107
1108 nub_size_t
1109 DNBProcessGetArgumentCount (nub_process_t pid)
1110 {
1111     MachProcessSP procSP;
1112     if (GetProcessSP (pid, procSP))
1113     {
1114         return procSP->ArgumentCount();
1115     }
1116     return 0;
1117 }
1118
1119 const char *
1120 DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx)
1121 {
1122     MachProcessSP procSP;
1123     if (GetProcessSP (pid, procSP))
1124     {
1125         return procSP->ArgumentAtIndex (idx);
1126     }
1127     return NULL;
1128 }
1129
1130
1131 //----------------------------------------------------------------------
1132 // Execution control
1133 //----------------------------------------------------------------------
1134 nub_bool_t
1135 DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions)
1136 {
1137     DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1138     MachProcessSP procSP;
1139     if (GetProcessSP (pid, procSP))
1140     {
1141         DNBThreadResumeActions thread_actions (actions, num_actions);
1142
1143         // Below we add a default thread plan just in case one wasn't
1144         // provided so all threads always know what they were supposed to do
1145         if (thread_actions.IsEmpty())
1146         {
1147             // No thread plans were given, so the default it to run all threads
1148             thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0);
1149         }
1150         else
1151         {
1152             // Some thread plans were given which means anything that wasn't
1153             // specified should remain stopped.
1154             thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
1155         }
1156         return procSP->Resume (thread_actions);
1157     }
1158     return false;
1159 }
1160
1161 nub_bool_t
1162 DNBProcessHalt (nub_process_t pid)
1163 {
1164     DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1165     MachProcessSP procSP;
1166     if (GetProcessSP (pid, procSP))
1167         return procSP->Signal (SIGSTOP);
1168     return false;
1169 }
1170 //
1171 //nub_bool_t
1172 //DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step)
1173 //{
1174 //    DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", __FUNCTION__, pid, tid, (uint32_t)step);
1175 //    MachProcessSP procSP;
1176 //    if (GetProcessSP (pid, procSP))
1177 //    {
1178 //        return procSP->Resume(tid, step, 0);
1179 //    }
1180 //    return false;
1181 //}
1182 //
1183 //nub_bool_t
1184 //DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t step, int signal)
1185 //{
1186 //    DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal);
1187 //    MachProcessSP procSP;
1188 //    if (GetProcessSP (pid, procSP))
1189 //    {
1190 //        return procSP->Resume(tid, step, signal);
1191 //    }
1192 //    return false;
1193 //}
1194
1195 nub_event_t
1196 DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout)
1197 {
1198     nub_event_t result = 0;
1199     MachProcessSP procSP;
1200     if (GetProcessSP (pid, procSP))
1201     {
1202         if (wait_for_set)
1203             result = procSP->Events().WaitForSetEvents(event_mask, timeout);
1204         else
1205             result = procSP->Events().WaitForEventsToReset(event_mask, timeout);
1206     }
1207     return result;
1208 }
1209
1210 void
1211 DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask)
1212 {
1213     MachProcessSP procSP;
1214     if (GetProcessSP (pid, procSP))
1215         procSP->Events().ResetEvents(event_mask);
1216 }
1217
1218 // Breakpoints
1219 nub_bool_t
1220 DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware)
1221 {
1222     MachProcessSP procSP;
1223     if (GetProcessSP (pid, procSP))
1224         return procSP->CreateBreakpoint(addr, size, hardware) != NULL;
1225     return false;
1226 }
1227
1228 nub_bool_t
1229 DNBBreakpointClear (nub_process_t pid, nub_addr_t addr)
1230 {
1231     MachProcessSP procSP;
1232     if (GetProcessSP (pid, procSP))
1233         return procSP->DisableBreakpoint(addr, true);
1234     return false; // Failed
1235 }
1236
1237
1238 //----------------------------------------------------------------------
1239 // Watchpoints
1240 //----------------------------------------------------------------------
1241 nub_bool_t
1242 DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware)
1243 {
1244     MachProcessSP procSP;
1245     if (GetProcessSP (pid, procSP))
1246         return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL;
1247     return false;
1248 }
1249
1250 nub_bool_t
1251 DNBWatchpointClear (nub_process_t pid, nub_addr_t addr)
1252 {
1253     MachProcessSP procSP;
1254     if (GetProcessSP (pid, procSP))
1255         return procSP->DisableWatchpoint(addr, true);
1256     return false; // Failed
1257 }
1258
1259 //----------------------------------------------------------------------
1260 // Return the number of supported hardware watchpoints.
1261 //----------------------------------------------------------------------
1262 uint32_t
1263 DNBWatchpointGetNumSupportedHWP (nub_process_t pid)
1264 {
1265     MachProcessSP procSP;
1266     if (GetProcessSP (pid, procSP))
1267         return procSP->GetNumSupportedHardwareWatchpoints();
1268     return 0;
1269 }
1270
1271 //----------------------------------------------------------------------
1272 // Read memory in the address space of process PID. This call will take
1273 // care of setting and restoring permissions and breaking up the memory
1274 // read into multiple chunks as required.
1275 //
1276 // RETURNS: number of bytes actually read
1277 //----------------------------------------------------------------------
1278 nub_size_t
1279 DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf)
1280 {
1281     MachProcessSP procSP;
1282     if (GetProcessSP (pid, procSP))
1283         return procSP->ReadMemory(addr, size, buf);
1284     return 0;
1285 }
1286
1287 uint64_t
1288 DNBProcessMemoryReadInteger (nub_process_t pid, nub_addr_t addr, nub_size_t integer_size, uint64_t fail_value)
1289 {
1290     union Integers
1291     {
1292         uint8_t     u8;
1293         uint16_t    u16;
1294         uint32_t    u32;
1295         uint64_t    u64;
1296     };
1297
1298     if (integer_size <= sizeof(uint64_t))
1299     {
1300         Integers ints;
1301         if (DNBProcessMemoryRead(pid, addr, integer_size, &ints) == integer_size)
1302         {
1303             switch (integer_size)
1304             {
1305                 case 1: return ints.u8;
1306                 case 2: return ints.u16;
1307                 case 3: return ints.u32 & 0xffffffu;
1308                 case 4: return ints.u32;
1309                 case 5: return ints.u32 & 0x000000ffffffffffull;
1310                 case 6: return ints.u32 & 0x0000ffffffffffffull;
1311                 case 7: return ints.u32 & 0x00ffffffffffffffull;
1312                 case 8: return ints.u64;
1313             }
1314         }
1315     }
1316     return fail_value;
1317
1318 }
1319
1320 nub_addr_t
1321 DNBProcessMemoryReadPointer (nub_process_t pid, nub_addr_t addr)
1322 {
1323     cpu_type_t cputype = DNBProcessGetCPUType (pid);
1324     if (cputype)
1325     {
1326         const nub_size_t pointer_size = (cputype & CPU_ARCH_ABI64) ? 8 : 4;
1327         return DNBProcessMemoryReadInteger(pid, addr, pointer_size, 0);
1328     }
1329     return 0;
1330
1331 }
1332
1333 std::string
1334 DNBProcessMemoryReadCString (nub_process_t pid, nub_addr_t addr)
1335 {
1336     std::string cstr;
1337     char buffer[256];
1338     const nub_size_t max_buffer_cstr_length = sizeof(buffer)-1;
1339     buffer[max_buffer_cstr_length] = '\0';
1340     nub_size_t length = 0;
1341     nub_addr_t curr_addr = addr;
1342     do
1343     {
1344         nub_size_t bytes_read = DNBProcessMemoryRead(pid, curr_addr, max_buffer_cstr_length, buffer);
1345         if (bytes_read == 0)
1346             break;
1347         length = strlen(buffer);
1348         cstr.append(buffer, length);
1349         curr_addr += length;
1350     } while (length == max_buffer_cstr_length);
1351     return cstr;
1352 }
1353
1354 std::string
1355 DNBProcessMemoryReadCStringFixed (nub_process_t pid, nub_addr_t addr, nub_size_t fixed_length)
1356 {
1357     std::string cstr;
1358     char buffer[fixed_length+1];
1359     buffer[fixed_length] = '\0';
1360     nub_size_t bytes_read = DNBProcessMemoryRead(pid, addr, fixed_length, buffer);
1361     if (bytes_read > 0)
1362         cstr.assign(buffer);
1363     return cstr;
1364 }
1365
1366
1367 //----------------------------------------------------------------------
1368 // Write memory to the address space of process PID. This call will take
1369 // care of setting and restoring permissions and breaking up the memory
1370 // write into multiple chunks as required.
1371 //
1372 // RETURNS: number of bytes actually written
1373 //----------------------------------------------------------------------
1374 nub_size_t
1375 DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf)
1376 {
1377     MachProcessSP procSP;
1378     if (GetProcessSP (pid, procSP))
1379         return procSP->WriteMemory(addr, size, buf);
1380     return 0;
1381 }
1382
1383 nub_addr_t
1384 DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions)
1385 {
1386     MachProcessSP procSP;
1387     if (GetProcessSP (pid, procSP))
1388         return procSP->Task().AllocateMemory (size, permissions);
1389     return 0;
1390 }
1391
1392 nub_bool_t
1393 DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr)
1394 {
1395     MachProcessSP procSP;
1396     if (GetProcessSP (pid, procSP))
1397         return procSP->Task().DeallocateMemory (addr);
1398     return 0;
1399 }
1400
1401 //----------------------------------------------------------------------
1402 // Find attributes of the memory region that contains ADDR for process PID,
1403 // if possible, and return a string describing those attributes.
1404 //
1405 // Returns 1 if we could find attributes for this region and OUTBUF can
1406 // be sent to the remote debugger.
1407 //
1408 // Returns 0 if we couldn't find the attributes for a region of memory at
1409 // that address and OUTBUF should not be sent.
1410 //
1411 // Returns -1 if this platform cannot look up information about memory regions
1412 // or if we do not yet have a valid launched process.
1413 //
1414 //----------------------------------------------------------------------
1415 int
1416 DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info)
1417 {
1418     MachProcessSP procSP;
1419     if (GetProcessSP (pid, procSP))
1420         return procSP->Task().GetMemoryRegionInfo (addr, region_info);
1421
1422     return -1;
1423 }
1424
1425 std::string
1426 DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType)
1427 {
1428     MachProcessSP procSP;
1429     if (GetProcessSP (pid, procSP))
1430         return procSP->Task().GetProfileData(scanType);
1431     
1432     return std::string("");
1433 }
1434
1435 nub_bool_t
1436 DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type)
1437 {
1438     MachProcessSP procSP;
1439     if (GetProcessSP (pid, procSP))
1440     {
1441         procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type);
1442         return true;
1443     }
1444     
1445     return false;    
1446 }
1447
1448 //----------------------------------------------------------------------
1449 // Get the number of threads for the specified process.
1450 //----------------------------------------------------------------------
1451 nub_size_t
1452 DNBProcessGetNumThreads (nub_process_t pid)
1453 {
1454     MachProcessSP procSP;
1455     if (GetProcessSP (pid, procSP))
1456         return procSP->GetNumThreads();
1457     return 0;
1458 }
1459
1460 //----------------------------------------------------------------------
1461 // Get the thread ID of the current thread.
1462 //----------------------------------------------------------------------
1463 nub_thread_t
1464 DNBProcessGetCurrentThread (nub_process_t pid)
1465 {
1466     MachProcessSP procSP;
1467     if (GetProcessSP (pid, procSP))
1468         return procSP->GetCurrentThread();
1469     return 0;
1470 }
1471
1472 //----------------------------------------------------------------------
1473 // Get the mach port number of the current thread.
1474 //----------------------------------------------------------------------
1475 nub_thread_t
1476 DNBProcessGetCurrentThreadMachPort (nub_process_t pid)
1477 {
1478     MachProcessSP procSP;
1479     if (GetProcessSP (pid, procSP))
1480         return procSP->GetCurrentThreadMachPort();
1481     return 0;
1482 }
1483
1484 //----------------------------------------------------------------------
1485 // Change the current thread.
1486 //----------------------------------------------------------------------
1487 nub_thread_t
1488 DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid)
1489 {
1490     MachProcessSP procSP;
1491     if (GetProcessSP (pid, procSP))
1492         return procSP->SetCurrentThread (tid);
1493     return INVALID_NUB_THREAD;
1494 }
1495
1496
1497 //----------------------------------------------------------------------
1498 // Dump a string describing a thread's stop reason to the specified file
1499 // handle
1500 //----------------------------------------------------------------------
1501 nub_bool_t
1502 DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, struct DNBThreadStopInfo *stop_info)
1503 {
1504     MachProcessSP procSP;
1505     if (GetProcessSP (pid, procSP))
1506         return procSP->GetThreadStoppedReason (tid, stop_info);
1507     return false;
1508 }
1509
1510 //----------------------------------------------------------------------
1511 // Return string description for the specified thread.
1512 //
1513 // RETURNS: NULL if the thread isn't valid, else a NULL terminated C
1514 // string from a static buffer that must be copied prior to subsequent
1515 // calls.
1516 //----------------------------------------------------------------------
1517 const char *
1518 DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid)
1519 {
1520     MachProcessSP procSP;
1521     if (GetProcessSP (pid, procSP))
1522         return procSP->GetThreadInfo (tid);
1523     return NULL;
1524 }
1525
1526 //----------------------------------------------------------------------
1527 // Get the thread ID given a thread index.
1528 //----------------------------------------------------------------------
1529 nub_thread_t
1530 DNBProcessGetThreadAtIndex (nub_process_t pid, size_t thread_idx)
1531 {
1532     MachProcessSP procSP;
1533     if (GetProcessSP (pid, procSP))
1534         return procSP->GetThreadAtIndex (thread_idx);
1535     return INVALID_NUB_THREAD;
1536 }
1537
1538 //----------------------------------------------------------------------
1539 // Do whatever is needed to sync the thread's register state with it's kernel values.
1540 //----------------------------------------------------------------------
1541 nub_bool_t
1542 DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid)
1543 {
1544     MachProcessSP procSP;
1545     if (GetProcessSP (pid, procSP))
1546         return procSP->SyncThreadState (tid);
1547     return false;
1548
1549 }
1550
1551 nub_addr_t
1552 DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid)
1553 {
1554     MachProcessSP procSP;
1555     DNBError err;
1556     if (GetProcessSP (pid, procSP))
1557         return procSP->Task().GetDYLDAllImageInfosAddress (err);
1558     return INVALID_NUB_ADDRESS;
1559 }
1560
1561
1562 nub_bool_t
1563 DNBProcessSharedLibrariesUpdated(nub_process_t pid)
1564 {
1565     MachProcessSP procSP;
1566     if (GetProcessSP (pid, procSP))
1567     {
1568         procSP->SharedLibrariesUpdated ();
1569         return true;
1570     }
1571     return false;
1572 }
1573
1574 //----------------------------------------------------------------------
1575 // Get the current shared library information for a process. Only return
1576 // the shared libraries that have changed since the last shared library
1577 // state changed event if only_changed is non-zero.
1578 //----------------------------------------------------------------------
1579 nub_size_t
1580 DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, struct DNBExecutableImageInfo **image_infos)
1581 {
1582     MachProcessSP procSP;
1583     if (GetProcessSP (pid, procSP))
1584         return procSP->CopyImageInfos (image_infos, only_changed);
1585
1586     // If we have no process, then return NULL for the shared library info
1587     // and zero for shared library count
1588     *image_infos = NULL;
1589     return 0;
1590 }
1591
1592 uint32_t
1593 DNBGetRegisterCPUType()
1594 {
1595     return DNBArchProtocol::GetRegisterCPUType ();
1596
1597 }
1598 //----------------------------------------------------------------------
1599 // Get the register set information for a specific thread.
1600 //----------------------------------------------------------------------
1601 const DNBRegisterSetInfo *
1602 DNBGetRegisterSetInfo (nub_size_t *num_reg_sets)
1603 {
1604     return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets);
1605 }
1606
1607
1608 //----------------------------------------------------------------------
1609 // Read a register value by register set and register index.
1610 //----------------------------------------------------------------------
1611 nub_bool_t
1612 DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value)
1613 {
1614     MachProcessSP procSP;
1615     ::bzero (value, sizeof(DNBRegisterValue));
1616     if (GetProcessSP (pid, procSP))
1617     {
1618         if (tid != INVALID_NUB_THREAD)
1619             return procSP->GetRegisterValue (tid, set, reg, value);
1620     }
1621     return false;
1622 }
1623
1624 nub_bool_t
1625 DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value)
1626 {
1627     if (tid != INVALID_NUB_THREAD)
1628     {
1629         MachProcessSP procSP;
1630         if (GetProcessSP (pid, procSP))
1631             return procSP->SetRegisterValue (tid, set, reg, value);
1632     }
1633     return false;
1634 }
1635
1636 nub_size_t
1637 DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len)
1638 {
1639     MachProcessSP procSP;
1640     if (GetProcessSP (pid, procSP))
1641     {
1642         if (tid != INVALID_NUB_THREAD)
1643             return procSP->GetThreadList().GetRegisterContext (tid, buf, buf_len);
1644     }
1645     ::bzero (buf, buf_len);
1646     return 0;
1647
1648 }
1649
1650 nub_size_t
1651 DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len)
1652 {
1653     MachProcessSP procSP;
1654     if (GetProcessSP (pid, procSP))
1655     {
1656         if (tid != INVALID_NUB_THREAD)
1657             return procSP->GetThreadList().SetRegisterContext (tid, buf, buf_len);
1658     }
1659     return 0;
1660 }
1661
1662 uint32_t
1663 DNBThreadSaveRegisterState (nub_process_t pid, nub_thread_t tid)
1664 {
1665     if (tid != INVALID_NUB_THREAD)
1666     {
1667         MachProcessSP procSP;
1668         if (GetProcessSP (pid, procSP))
1669             return procSP->GetThreadList().SaveRegisterState (tid);
1670     }
1671     return 0;    
1672 }
1673 nub_bool_t
1674 DNBThreadRestoreRegisterState (nub_process_t pid, nub_thread_t tid, uint32_t save_id)
1675 {
1676     if (tid != INVALID_NUB_THREAD)
1677     {
1678         MachProcessSP procSP;
1679         if (GetProcessSP (pid, procSP))
1680             return procSP->GetThreadList().RestoreRegisterState (tid, save_id);
1681     }
1682     return false;
1683 }
1684
1685
1686
1687 //----------------------------------------------------------------------
1688 // Read a register value by name.
1689 //----------------------------------------------------------------------
1690 nub_bool_t
1691 DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t reg_set, const char *reg_name, DNBRegisterValue *value)
1692 {
1693     MachProcessSP procSP;
1694     ::bzero (value, sizeof(DNBRegisterValue));
1695     if (GetProcessSP (pid, procSP))
1696     {
1697         const struct DNBRegisterSetInfo *set_info;
1698         nub_size_t num_reg_sets = 0;
1699         set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1700         if (set_info)
1701         {
1702             uint32_t set = reg_set;
1703             uint32_t reg;
1704             if (set == REGISTER_SET_ALL)
1705             {
1706                 for (set = 1; set < num_reg_sets; ++set)
1707                 {
1708                     for (reg = 0; reg < set_info[set].num_registers; ++reg)
1709                     {
1710                         if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1711                             return procSP->GetRegisterValue (tid, set, reg, value);
1712                     }
1713                 }
1714             }
1715             else
1716             {
1717                 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1718                 {
1719                     if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1720                         return procSP->GetRegisterValue (tid, set, reg, value);
1721                 }
1722             }
1723         }
1724     }
1725     return false;
1726 }
1727
1728
1729 //----------------------------------------------------------------------
1730 // Read a register set and register number from the register name.
1731 //----------------------------------------------------------------------
1732 nub_bool_t
1733 DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info)
1734 {
1735     const struct DNBRegisterSetInfo *set_info;
1736     nub_size_t num_reg_sets = 0;
1737     set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1738     if (set_info)
1739     {
1740         uint32_t set, reg;
1741         for (set = 1; set < num_reg_sets; ++set)
1742         {
1743             for (reg = 0; reg < set_info[set].num_registers; ++reg)
1744             {
1745                 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1746                 {
1747                     *info = set_info[set].registers[reg];
1748                     return true;
1749                 }
1750             }
1751         }
1752
1753         for (set = 1; set < num_reg_sets; ++set)
1754         {
1755             uint32_t reg;
1756             for (reg = 0; reg < set_info[set].num_registers; ++reg)
1757             {
1758                 if (set_info[set].registers[reg].alt == NULL)
1759                     continue;
1760
1761                 if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0)
1762                 {
1763                     *info = set_info[set].registers[reg];
1764                     return true;
1765                 }
1766             }
1767         }
1768     }
1769
1770     ::bzero (info, sizeof(DNBRegisterInfo));
1771     return false;
1772 }
1773
1774
1775 //----------------------------------------------------------------------
1776 // Set the name to address callback function that this nub can use
1777 // for any name to address lookups that are needed.
1778 //----------------------------------------------------------------------
1779 nub_bool_t
1780 DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton)
1781 {
1782     MachProcessSP procSP;
1783     if (GetProcessSP (pid, procSP))
1784     {
1785         procSP->SetNameToAddressCallback (callback, baton);
1786         return true;
1787     }
1788     return false;
1789 }
1790
1791
1792 //----------------------------------------------------------------------
1793 // Set the name to address callback function that this nub can use
1794 // for any name to address lookups that are needed.
1795 //----------------------------------------------------------------------
1796 nub_bool_t
1797 DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void  *baton)
1798 {
1799     MachProcessSP procSP;
1800     if (GetProcessSP (pid, procSP))
1801     {
1802         procSP->SetSharedLibraryInfoCallback (callback, baton);
1803         return true;
1804     }
1805     return false;
1806 }
1807
1808 nub_addr_t
1809 DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib)
1810 {
1811     MachProcessSP procSP;
1812     if (GetProcessSP (pid, procSP))
1813     {
1814         return procSP->LookupSymbol (name, shlib);
1815     }
1816     return INVALID_NUB_ADDRESS;
1817 }
1818
1819
1820 nub_size_t
1821 DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size)
1822 {
1823     MachProcessSP procSP;
1824     if (GetProcessSP (pid, procSP))
1825         return procSP->GetAvailableSTDOUT (buf, buf_size);
1826     return 0;
1827 }
1828
1829 nub_size_t
1830 DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size)
1831 {
1832     MachProcessSP procSP;
1833     if (GetProcessSP (pid, procSP))
1834         return procSP->GetAvailableSTDERR (buf, buf_size);
1835     return 0;
1836 }
1837
1838 nub_size_t
1839 DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size)
1840 {
1841     MachProcessSP procSP;
1842     if (GetProcessSP (pid, procSP))
1843         return procSP->GetAsyncProfileData (buf, buf_size);
1844     return 0;
1845 }
1846
1847 nub_size_t
1848 DNBProcessGetStopCount (nub_process_t pid)
1849 {
1850     MachProcessSP procSP;
1851     if (GetProcessSP (pid, procSP))
1852         return procSP->StopCount();
1853     return 0;
1854 }
1855
1856 uint32_t
1857 DNBProcessGetCPUType (nub_process_t pid)
1858 {
1859     MachProcessSP procSP;
1860     if (GetProcessSP (pid, procSP))
1861         return procSP->GetCPUType ();
1862     return 0;
1863     
1864 }
1865
1866 nub_bool_t
1867 DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size)
1868 {
1869     if (path == NULL || path[0] == '\0')
1870         return false;
1871
1872     char max_path[PATH_MAX];
1873     std::string result;
1874     CFString::GlobPath(path, result);
1875
1876     if (result.empty())
1877         result = path;
1878     
1879     struct stat path_stat;
1880     if (::stat(path, &path_stat) == 0)
1881     {
1882         if ((path_stat.st_mode & S_IFMT) == S_IFDIR)
1883         {
1884             CFBundle bundle (path);
1885             CFReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
1886             if (url.get())
1887             {
1888                 if (::CFURLGetFileSystemRepresentation (url.get(), true, (UInt8*)resolved_path, resolved_path_size))
1889                     return true;
1890             }
1891         }
1892     }
1893
1894     if (realpath(path, max_path))
1895     {
1896         // Found the path relatively...
1897         ::strncpy(resolved_path, max_path, resolved_path_size);
1898         return strlen(resolved_path) + 1 < resolved_path_size;
1899     }
1900     else
1901     {
1902         // Not a relative path, check the PATH environment variable if the
1903         const char *PATH = getenv("PATH");
1904         if (PATH)
1905         {
1906             const char *curr_path_start = PATH;
1907             const char *curr_path_end;
1908             while (curr_path_start && *curr_path_start)
1909             {
1910                 curr_path_end = strchr(curr_path_start, ':');
1911                 if (curr_path_end == NULL)
1912                 {
1913                     result.assign(curr_path_start);
1914                     curr_path_start = NULL;
1915                 }
1916                 else if (curr_path_end > curr_path_start)
1917                 {
1918                     size_t len = curr_path_end - curr_path_start;
1919                     result.assign(curr_path_start, len);
1920                     curr_path_start += len + 1;
1921                 }
1922                 else
1923                     break;
1924
1925                 result += '/';
1926                 result += path;
1927                 struct stat s;
1928                 if (stat(result.c_str(), &s) == 0)
1929                 {
1930                     ::strncpy(resolved_path, result.c_str(), resolved_path_size);
1931                     return result.size() + 1 < resolved_path_size;
1932                 }
1933             }
1934         }
1935     }
1936     return false;
1937 }
1938
1939 bool
1940 DNBGetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch)
1941 {
1942     return MachProcess::GetOSVersionNumbers (major, minor, patch);
1943 }
1944
1945
1946 void
1947 DNBInitialize()
1948 {
1949     DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()");
1950 #if defined (__i386__) || defined (__x86_64__)
1951     DNBArchImplI386::Initialize();
1952     DNBArchImplX86_64::Initialize();
1953 #elif defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
1954     DNBArchMachARM::Initialize();
1955     DNBArchMachARM64::Initialize();
1956 #endif
1957 }
1958
1959 void
1960 DNBTerminate()
1961 {
1962 }
1963
1964 nub_bool_t
1965 DNBSetArchitecture (const char *arch)
1966 {
1967     if (arch && arch[0])
1968     {
1969         if (strcasecmp (arch, "i386") == 0)
1970             return DNBArchProtocol::SetArchitecture (CPU_TYPE_I386);
1971         else if ((strcasecmp (arch, "x86_64") == 0) || (strcasecmp (arch, "x86_64h") == 0))
1972             return DNBArchProtocol::SetArchitecture (CPU_TYPE_X86_64);
1973         else if (strstr (arch, "arm64") == arch || strstr (arch, "armv8") == arch || strstr (arch, "aarch64") == arch)
1974             return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM64);
1975         else if (strstr (arch, "arm") == arch)
1976             return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM);
1977     }
1978     return false;
1979 }