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 = death_event.data;
179             const char *error_str = strerror(death_event.data);
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             const char *status_cstr = NULL;
196             if (WIFSTOPPED(status))
197             {
198                 signal = WSTOPSIG(status);
199                 status_cstr = "STOPPED";
200                 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> STOPPED (signal = %i)", child_pid, signal);
201             }
202             else if (WIFEXITED(status))
203             {
204                 exit_status = WEXITSTATUS(status);
205                 status_cstr = "EXITED";
206                 exited = true;
207                 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> EXITED (status = %i)", child_pid, exit_status);
208             }
209             else if (WIFSIGNALED(status))
210             {
211                 signal = WTERMSIG(status);
212                 status_cstr = "SIGNALED";
213                 if (child_pid == abs(pid))
214                 {
215                     DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED and EXITED (signal = %i)", child_pid, signal);
216                     char exit_info[64];
217                     ::snprintf (exit_info, sizeof(exit_info), "Terminated due to signal %i", signal);
218                     DNBProcessSetExitInfo (child_pid, exit_info);
219                     exited = true;
220                     exit_status = INT8_MAX;
221                 }
222                 else
223                 {
224                     DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED (signal = %i)", child_pid, signal);
225                 }
226             }
227 
228             if (exited)
229             {
230                 if (death_event.data & NOTE_EXIT_MEMORY)
231                     DNBProcessSetExitInfo (child_pid, "Terminated due to memory issue");
232                 else if (death_event.data & NOTE_EXIT_DECRYPTFAIL)
233                     DNBProcessSetExitInfo (child_pid, "Terminated due to decrypt failure");
234                 else if (death_event.data & NOTE_EXIT_CSERROR)
235                     DNBProcessSetExitInfo (child_pid, "Terminated due to code signing error");
236 
237                 DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): setting exit status for pid = %i to %i", child_pid, exit_status);
238                 DNBProcessSetExitStatus (child_pid, status);
239                 return NULL;
240             }
241         }
242     }
243 }
244 
245 static bool
246 spawn_kqueue_thread (pid_t pid)
247 {
248     pthread_t thread;
249     int kq_id;
250 
251     kq_id = kqueue();
252     if (kq_id == -1)
253     {
254         DNBLogError ("Could not get kqueue for pid = %i.", pid);
255         return false;
256     }
257 
258     struct kevent reg_event;
259 
260     EV_SET(&reg_event, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT|NOTE_EXITSTATUS|NOTE_EXIT_DETAIL, 0, NULL);
261     // Register the event:
262     int result = kevent (kq_id, &reg_event, 1, NULL, 0, NULL);
263     if (result != 0)
264     {
265         DNBLogError ("Failed to register kqueue NOTE_EXIT event for pid %i, error: %d.", pid, result);
266         return false;
267     }
268 
269     int ret = ::pthread_create (&thread, NULL, kqueue_thread, (void *)(intptr_t)kq_id);
270 
271     // pthread_create returns 0 if successful
272     if (ret == 0)
273     {
274         ::pthread_detach (thread);
275         return true;
276     }
277     return false;
278 }
279 #endif // #if USE_KQUEUE
280 
281 static void *
282 waitpid_thread (void *arg)
283 {
284     const pid_t pid = (pid_t)(intptr_t)arg;
285     int status;
286 
287 #if defined (__APPLE__)
288     pthread_setname_np ("waitpid thread");
289 #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
290     struct sched_param thread_param;
291     int thread_sched_policy;
292     if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0)
293     {
294         thread_param.sched_priority = 47;
295         pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
296     }
297 #endif
298 #endif
299 
300     while (1)
301     {
302         pid_t child_pid = waitpid(pid, &status, 0);
303         DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): waitpid (pid = %i, &status, 0) => %i, status = %i, errno = %i", pid, child_pid, status, errno);
304 
305         if (child_pid < 0)
306         {
307             if (errno == EINTR)
308                 continue;
309             break;
310         }
311         else
312         {
313             if (WIFSTOPPED(status))
314             {
315                 continue;
316             }
317             else// if (WIFEXITED(status) || WIFSIGNALED(status))
318             {
319                 DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): setting exit status for pid = %i to %i", child_pid, status);
320                 DNBProcessSetExitStatus (child_pid, status);
321                 return NULL;
322             }
323         }
324     }
325 
326     // We should never exit as long as our child process is alive, so if we
327     // do something else went wrong and we should exit...
328     DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): main loop exited, setting exit status to an invalid value (-1) for pid %i", pid);
329     DNBProcessSetExitStatus (pid, -1);
330     return NULL;
331 }
332 static bool
333 spawn_waitpid_thread (pid_t pid)
334 {
335 #ifdef USE_KQUEUE
336     bool success = spawn_kqueue_thread (pid);
337     if (success)
338         return true;
339 #endif
340 
341     pthread_t thread;
342     int ret = ::pthread_create (&thread, NULL, waitpid_thread, (void *)(intptr_t)pid);
343     // pthread_create returns 0 if successful
344     if (ret == 0)
345     {
346         ::pthread_detach (thread);
347         return true;
348     }
349     return false;
350 }
351 
352 nub_process_t
353 DNBProcessLaunch (const char *path,
354                   char const *argv[],
355                   const char *envp[],
356                   const char *working_directory, // NULL => don't change, non-NULL => set working directory for inferior to this
357                   const char *stdin_path,
358                   const char *stdout_path,
359                   const char *stderr_path,
360                   bool no_stdio,
361                   nub_launch_flavor_t launch_flavor,
362                   int disable_aslr,
363                   const char *event_data,
364                   char *err_str,
365                   size_t err_len)
366 {
367     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...",
368                      __FUNCTION__,
369                      path,
370                      argv,
371                      envp,
372                      working_directory,
373                      stdin_path,
374                      stdout_path,
375                      stderr_path,
376                      no_stdio,
377                      launch_flavor,
378                      disable_aslr,
379                      err_str,
380                      (uint64_t)err_len);
381 
382     if (err_str && err_len > 0)
383         err_str[0] = '\0';
384     struct stat path_stat;
385     if (::stat(path, &path_stat) == -1)
386     {
387         char stat_error[256];
388         ::strerror_r (errno, stat_error, sizeof(stat_error));
389         snprintf(err_str, err_len, "%s (%s)", stat_error, path);
390         return INVALID_NUB_PROCESS;
391     }
392 
393     MachProcessSP processSP (new MachProcess);
394     if (processSP.get())
395     {
396         DNBError launch_err;
397         pid_t pid = processSP->LaunchForDebug (path,
398                                                argv,
399                                                envp,
400                                                working_directory,
401                                                stdin_path,
402                                                stdout_path,
403                                                stderr_path,
404                                                no_stdio,
405                                                launch_flavor,
406                                                disable_aslr,
407                                                event_data,
408                                                launch_err);
409         if (err_str)
410         {
411             *err_str = '\0';
412             if (launch_err.Fail())
413             {
414                 const char *launch_err_str = launch_err.AsString();
415                 if (launch_err_str)
416                 {
417                     strncpy(err_str, launch_err_str, err_len-1);
418                     err_str[err_len-1] = '\0';  // Make sure the error string is terminated
419                 }
420             }
421         }
422 
423         DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid);
424 
425         if (pid != INVALID_NUB_PROCESS)
426         {
427             // Spawn a thread to reap our child inferior process...
428             spawn_waitpid_thread (pid);
429 
430             if (processSP->Task().TaskPortForProcessID (launch_err) == TASK_NULL)
431             {
432                 // We failed to get the task for our process ID which is bad.
433                 // Kill our process otherwise it will be stopped at the entry
434                 // point and get reparented to someone else and never go away.
435                 DNBLog ("Could not get task port for process, sending SIGKILL and exiting.");
436                 kill (SIGKILL, pid);
437 
438                 if (err_str && err_len > 0)
439                 {
440                     if (launch_err.AsString())
441                     {
442                         ::snprintf (err_str, err_len, "failed to get the task for process %i (%s)", pid, launch_err.AsString());
443                     }
444                     else
445                     {
446                         ::snprintf (err_str, err_len, "failed to get the task for process %i", pid);
447                     }
448                 }
449             }
450             else
451             {
452                 bool res = AddProcessToMap(pid, processSP);
453                 assert(res && "Couldn't add process to map!");
454                 return pid;
455             }
456         }
457     }
458     return INVALID_NUB_PROCESS;
459 }
460 
461 nub_process_t
462 DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len)
463 {
464     if (err_str && err_len > 0)
465         err_str[0] = '\0';
466     std::vector<struct kinfo_proc> matching_proc_infos;
467     size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
468     if (num_matching_proc_infos == 0)
469     {
470         DNBLogError ("error: no processes match '%s'\n", name);
471         return INVALID_NUB_PROCESS;
472     }
473     else if (num_matching_proc_infos > 1)
474     {
475         DNBLogError ("error: %llu processes match '%s':\n", (uint64_t)num_matching_proc_infos, name);
476         size_t i;
477         for (i=0; i<num_matching_proc_infos; ++i)
478             DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm);
479         return INVALID_NUB_PROCESS;
480     }
481 
482     return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len);
483 }
484 
485 nub_process_t
486 DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_str, size_t err_len)
487 {
488     if (err_str && err_len > 0)
489         err_str[0] = '\0';
490 
491     pid_t pid = INVALID_NUB_PROCESS;
492     MachProcessSP processSP(new MachProcess);
493     if (processSP.get())
494     {
495         DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", attach_pid);
496         pid = processSP->AttachForDebug (attach_pid, err_str,  err_len);
497 
498         if (pid != INVALID_NUB_PROCESS)
499         {
500             bool res = AddProcessToMap(pid, processSP);
501             assert(res && "Couldn't add process to map!");
502             spawn_waitpid_thread(pid);
503         }
504     }
505 
506     while (pid != INVALID_NUB_PROCESS)
507     {
508         // Wait for process to start up and hit entry point
509         DNBLogThreadedIf (LOG_PROCESS,
510                           "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...",
511                           __FUNCTION__,
512                           pid);
513         nub_event_t set_events = DNBProcessWaitForEvents (pid,
514                                                           eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged,
515                                                           true,
516                                                           timeout);
517 
518         DNBLogThreadedIf (LOG_PROCESS,
519                           "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x",
520                           __FUNCTION__,
521                           pid,
522                           set_events);
523 
524         if (set_events == 0)
525         {
526             if (err_str && err_len > 0)
527                 snprintf(err_str, err_len, "operation timed out");
528             pid = INVALID_NUB_PROCESS;
529         }
530         else
531         {
532             if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged))
533             {
534                 nub_state_t pid_state = DNBProcessGetState (pid);
535                 DNBLogThreadedIf (LOG_PROCESS, "%s process %4.4x state changed (eEventProcessStateChanged): %s",
536                         __FUNCTION__, pid, DNBStateAsString(pid_state));
537 
538                 switch (pid_state)
539                 {
540                     default:
541                     case eStateInvalid:
542                     case eStateUnloaded:
543                     case eStateAttaching:
544                     case eStateLaunching:
545                     case eStateSuspended:
546                         break;  // Ignore
547 
548                     case eStateRunning:
549                     case eStateStepping:
550                         // Still waiting to stop at entry point...
551                         break;
552 
553                     case eStateStopped:
554                     case eStateCrashed:
555                         return pid;
556 
557                     case eStateDetached:
558                     case eStateExited:
559                         if (err_str && err_len > 0)
560                             snprintf(err_str, err_len, "process exited");
561                         return INVALID_NUB_PROCESS;
562                 }
563             }
564 
565             DNBProcessResetEvents(pid, set_events);
566         }
567     }
568 
569     return INVALID_NUB_PROCESS;
570 }
571 
572 size_t
573 GetAllInfos (std::vector<struct kinfo_proc>& proc_infos)
574 {
575     size_t size = 0;
576     int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
577     u_int namelen = sizeof(name)/sizeof(int);
578     int err;
579 
580     // Try to find out how many processes are around so we can
581     // size the buffer appropriately.  sysctl's man page specifically suggests
582     // this approach, and says it returns a bit larger size than needed to
583     // handle any new processes created between then and now.
584 
585     err = ::sysctl (name, namelen, NULL, &size, NULL, 0);
586 
587     if ((err < 0) && (err != ENOMEM))
588     {
589         proc_infos.clear();
590         perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)");
591         return 0;
592     }
593 
594 
595     // Increase the size of the buffer by a few processes in case more have
596     // been spawned
597     proc_infos.resize (size / sizeof(struct kinfo_proc));
598     size = proc_infos.size() * sizeof(struct kinfo_proc);   // Make sure we don't exceed our resize...
599     err = ::sysctl (name, namelen, &proc_infos[0], &size, NULL, 0);
600     if (err < 0)
601     {
602         proc_infos.clear();
603         return 0;
604     }
605 
606     // Trim down our array to fit what we actually got back
607     proc_infos.resize(size / sizeof(struct kinfo_proc));
608     return proc_infos.size();
609 }
610 
611 static size_t
612 GetAllInfosMatchingName(const char *full_process_name, std::vector<struct kinfo_proc>& matching_proc_infos)
613 {
614 
615     matching_proc_infos.clear();
616     if (full_process_name && full_process_name[0])
617     {
618         // We only get the process name, not the full path, from the proc_info.  So just take the
619         // base name of the process name...
620         const char *process_name;
621         process_name = strrchr (full_process_name, '/');
622         if (process_name == NULL)
623             process_name = full_process_name;
624         else
625             process_name++;
626 
627         const int process_name_len = strlen(process_name);
628         std::vector<struct kinfo_proc> proc_infos;
629         const size_t num_proc_infos = GetAllInfos(proc_infos);
630         if (num_proc_infos > 0)
631         {
632             uint32_t i;
633             for (i=0; i<num_proc_infos; i++)
634             {
635                 // Skip zombie processes and processes with unset status
636                 if (proc_infos[i].kp_proc.p_stat == 0 || proc_infos[i].kp_proc.p_stat == SZOMB)
637                     continue;
638 
639                 // Check for process by name. We only check the first MAXCOMLEN
640                 // chars as that is all that kp_proc.p_comm holds.
641 
642                 if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm, MAXCOMLEN) == 0)
643                 {
644                     if (process_name_len > MAXCOMLEN)
645                     {
646                         // We found a matching process name whose first MAXCOMLEN
647                         // characters match, but there is more to the name than
648                         // this. We need to get the full process name.  Use proc_pidpath, which will get
649                         // us the full path to the executed process.
650 
651                         char proc_path_buf[PATH_MAX];
652 
653                         int return_val = proc_pidpath (proc_infos[i].kp_proc.p_pid, proc_path_buf, PATH_MAX);
654                         if (return_val > 0)
655                         {
656                             // Okay, now search backwards from that to see if there is a
657                             // slash in the name.  Note, even though we got all the args we don't care
658                             // because the list data is just a bunch of concatenated null terminated strings
659                             // so strrchr will start from the end of argv0.
660 
661                             const char *argv_basename = strrchr(proc_path_buf, '/');
662                             if (argv_basename)
663                             {
664                                 // Skip the '/'
665                                 ++argv_basename;
666                             }
667                             else
668                             {
669                                 // We didn't find a directory delimiter in the process argv[0], just use what was in there
670                                 argv_basename = proc_path_buf;
671                             }
672 
673                             if (argv_basename)
674                             {
675                                 if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0)
676                                 {
677                                     matching_proc_infos.push_back(proc_infos[i]);
678                                 }
679                             }
680                         }
681                     }
682                     else
683                     {
684                         // We found a matching process, add it to our list
685                         matching_proc_infos.push_back(proc_infos[i]);
686                     }
687                 }
688             }
689         }
690     }
691     // return the newly added matches.
692     return matching_proc_infos.size();
693 }
694 
695 nub_process_t
696 DNBProcessAttachWait (const char *waitfor_process_name,
697                       nub_launch_flavor_t launch_flavor,
698                       bool ignore_existing,
699                       struct timespec *timeout_abstime,
700                       useconds_t waitfor_interval,
701                       char *err_str,
702                       size_t err_len,
703                       DNBShouldCancelCallback should_cancel_callback,
704                       void *callback_data)
705 {
706     DNBError prepare_error;
707     std::vector<struct kinfo_proc> exclude_proc_infos;
708     size_t num_exclude_proc_infos;
709 
710     // If the PrepareForAttach returns a valid token, use  MachProcess to check
711     // for the process, otherwise scan the process table.
712 
713     const void *attach_token = MachProcess::PrepareForAttach (waitfor_process_name, launch_flavor, true, prepare_error);
714 
715     if (prepare_error.Fail())
716     {
717         DNBLogError ("Error in PrepareForAttach: %s", prepare_error.AsString());
718         return INVALID_NUB_PROCESS;
719     }
720 
721     if (attach_token == NULL)
722     {
723         if (ignore_existing)
724             num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos);
725         else
726             num_exclude_proc_infos = 0;
727     }
728 
729     DNBLogThreadedIf (LOG_PROCESS, "Waiting for '%s' to appear...\n", waitfor_process_name);
730 
731     // Loop and try to find the process by name
732     nub_process_t waitfor_pid = INVALID_NUB_PROCESS;
733 
734     while (waitfor_pid == INVALID_NUB_PROCESS)
735     {
736         if (attach_token != NULL)
737         {
738             nub_process_t pid;
739             pid = MachProcess::CheckForProcess(attach_token);
740             if (pid != INVALID_NUB_PROCESS)
741             {
742                 waitfor_pid = pid;
743                 break;
744             }
745         }
746         else
747         {
748 
749             // Get the current process list, and check for matches that
750             // aren't in our original list. If anyone wants to attach
751             // to an existing process by name, they should do it with
752             // --attach=PROCNAME. Else we will wait for the first matching
753             // process that wasn't in our exclusion list.
754             std::vector<struct kinfo_proc> proc_infos;
755             const size_t num_proc_infos = GetAllInfosMatchingName (waitfor_process_name, proc_infos);
756             for (size_t i=0; i<num_proc_infos; i++)
757             {
758                 nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid;
759                 for (size_t j=0; j<num_exclude_proc_infos; j++)
760                 {
761                     if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid)
762                     {
763                         // This process was in our exclusion list, don't use it.
764                         curr_pid = INVALID_NUB_PROCESS;
765                         break;
766                     }
767                 }
768 
769                 // If we didn't find CURR_PID in our exclusion list, then use it.
770                 if (curr_pid != INVALID_NUB_PROCESS)
771                 {
772                     // We found our process!
773                     waitfor_pid = curr_pid;
774                     break;
775                 }
776             }
777         }
778 
779         // If we haven't found our process yet, check for a timeout
780         // and then sleep for a bit until we poll again.
781         if (waitfor_pid == INVALID_NUB_PROCESS)
782         {
783             if (timeout_abstime != NULL)
784             {
785                 // Check to see if we have a waitfor-duration option that
786                 // has timed out?
787                 if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime))
788                 {
789                     if (err_str && err_len > 0)
790                         snprintf(err_str, err_len, "operation timed out");
791                     DNBLogError ("error: waiting for process '%s' timed out.\n", waitfor_process_name);
792                     return INVALID_NUB_PROCESS;
793                 }
794             }
795 
796             // Call the should cancel callback as well...
797 
798             if (should_cancel_callback != NULL
799                 && should_cancel_callback (callback_data))
800             {
801                 DNBLogThreadedIf (LOG_PROCESS, "DNBProcessAttachWait cancelled by should_cancel callback.");
802                 waitfor_pid = INVALID_NUB_PROCESS;
803                 break;
804             }
805 
806             ::usleep (waitfor_interval);    // Sleep for WAITFOR_INTERVAL, then poll again
807         }
808     }
809 
810     if (waitfor_pid != INVALID_NUB_PROCESS)
811     {
812         DNBLogThreadedIf (LOG_PROCESS, "Attaching to %s with pid %i...\n", waitfor_process_name, waitfor_pid);
813         waitfor_pid = DNBProcessAttach (waitfor_pid, timeout_abstime, err_str, err_len);
814     }
815 
816     bool success = waitfor_pid != INVALID_NUB_PROCESS;
817     MachProcess::CleanupAfterAttach (attach_token, success, prepare_error);
818 
819     return waitfor_pid;
820 }
821 
822 nub_bool_t
823 DNBProcessDetach (nub_process_t pid)
824 {
825     MachProcessSP procSP;
826     if (GetProcessSP (pid, procSP))
827     {
828         const bool remove = true;
829         DNBLogThreaded("Disabling breakpoints and watchpoints, and detaching from %d.", pid);
830         procSP->DisableAllBreakpoints(remove);
831         procSP->DisableAllWatchpoints (remove);
832         return procSP->Detach();
833     }
834     return false;
835 }
836 
837 nub_bool_t
838 DNBProcessKill (nub_process_t pid)
839 {
840     MachProcessSP procSP;
841     if (GetProcessSP (pid, procSP))
842     {
843         return procSP->Kill ();
844     }
845     return false;
846 }
847 
848 nub_bool_t
849 DNBProcessSignal (nub_process_t pid, int signal)
850 {
851     MachProcessSP procSP;
852     if (GetProcessSP (pid, procSP))
853     {
854         return procSP->Signal (signal);
855     }
856     return false;
857 }
858 
859 
860 nub_bool_t
861 DNBProcessInterrupt(nub_process_t pid)
862 {
863     MachProcessSP procSP;
864     if (GetProcessSP (pid, procSP))
865         return procSP->Interrupt();
866     return false;
867 }
868 
869 nub_bool_t
870 DNBProcessSendEvent (nub_process_t pid, const char *event)
871 {
872     MachProcessSP procSP;
873     if (GetProcessSP (pid, procSP))
874     {
875         // FIXME: Do something with the error...
876         DNBError send_error;
877         return procSP->SendEvent (event, send_error);
878     }
879     return false;
880 }
881 
882 
883 nub_bool_t
884 DNBProcessIsAlive (nub_process_t pid)
885 {
886     MachProcessSP procSP;
887     if (GetProcessSP (pid, procSP))
888     {
889         return MachTask::IsValid (procSP->Task().TaskPort());
890     }
891     return eStateInvalid;
892 }
893 
894 //----------------------------------------------------------------------
895 // Process and Thread state information
896 //----------------------------------------------------------------------
897 nub_state_t
898 DNBProcessGetState (nub_process_t pid)
899 {
900     MachProcessSP procSP;
901     if (GetProcessSP (pid, procSP))
902     {
903         return procSP->GetState();
904     }
905     return eStateInvalid;
906 }
907 
908 //----------------------------------------------------------------------
909 // Process and Thread state information
910 //----------------------------------------------------------------------
911 nub_bool_t
912 DNBProcessGetExitStatus (nub_process_t pid, int* status)
913 {
914     MachProcessSP procSP;
915     if (GetProcessSP (pid, procSP))
916     {
917         return procSP->GetExitStatus(status);
918     }
919     return false;
920 }
921 
922 nub_bool_t
923 DNBProcessSetExitStatus (nub_process_t pid, int status)
924 {
925     MachProcessSP procSP;
926     if (GetProcessSP (pid, procSP))
927     {
928         procSP->SetExitStatus(status);
929         return true;
930     }
931     return false;
932 }
933 
934 const char *
935 DNBProcessGetExitInfo (nub_process_t pid)
936 {
937     MachProcessSP procSP;
938     if (GetProcessSP (pid, procSP))
939     {
940         return procSP->GetExitInfo();
941     }
942     return NULL;
943 }
944 
945 nub_bool_t
946 DNBProcessSetExitInfo (nub_process_t pid, const char *info)
947 {
948     MachProcessSP procSP;
949     if (GetProcessSP (pid, procSP))
950     {
951         procSP->SetExitInfo(info);
952         return true;
953     }
954     return false;
955 }
956 
957 const char *
958 DNBThreadGetName (nub_process_t pid, nub_thread_t tid)
959 {
960     MachProcessSP procSP;
961     if (GetProcessSP (pid, procSP))
962         return procSP->ThreadGetName(tid);
963     return NULL;
964 }
965 
966 
967 nub_bool_t
968 DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info)
969 {
970     MachProcessSP procSP;
971     if (GetProcessSP (pid, procSP))
972         return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info);
973     return false;
974 }
975 
976 nub_state_t
977 DNBThreadGetState (nub_process_t pid, nub_thread_t tid)
978 {
979     MachProcessSP procSP;
980     if (GetProcessSP (pid, procSP))
981     {
982         return procSP->ThreadGetState(tid);
983     }
984     return eStateInvalid;
985 }
986 
987 const char *
988 DNBStateAsString(nub_state_t state)
989 {
990     switch (state)
991     {
992     case eStateInvalid:     return "Invalid";
993     case eStateUnloaded:    return "Unloaded";
994     case eStateAttaching:   return "Attaching";
995     case eStateLaunching:   return "Launching";
996     case eStateStopped:     return "Stopped";
997     case eStateRunning:     return "Running";
998     case eStateStepping:    return "Stepping";
999     case eStateCrashed:     return "Crashed";
1000     case eStateDetached:    return "Detached";
1001     case eStateExited:      return "Exited";
1002     case eStateSuspended:   return "Suspended";
1003     }
1004     return "nub_state_t ???";
1005 }
1006 
1007 Genealogy::ThreadActivitySP
1008 DNBGetGenealogyInfoForThread (nub_process_t pid, nub_thread_t tid, bool &timed_out)
1009 {
1010     Genealogy::ThreadActivitySP thread_activity_sp;
1011     MachProcessSP procSP;
1012     if (GetProcessSP (pid, procSP))
1013         thread_activity_sp = procSP->GetGenealogyInfoForThread (tid, timed_out);
1014     return thread_activity_sp;
1015 }
1016 
1017 Genealogy::ProcessExecutableInfoSP
1018 DNBGetGenealogyImageInfo (nub_process_t pid, size_t idx)
1019 {
1020     Genealogy::ProcessExecutableInfoSP image_info_sp;
1021     MachProcessSP procSP;
1022     if (GetProcessSP (pid, procSP))
1023     {
1024         image_info_sp = procSP->GetGenealogyImageInfo (idx);
1025     }
1026     return image_info_sp;
1027 }
1028 
1029 ThreadInfo::QoS
1030 DNBGetRequestedQoSForThread (nub_process_t pid, nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index)
1031 {
1032     MachProcessSP procSP;
1033     if (GetProcessSP (pid, procSP))
1034     {
1035         return procSP->GetRequestedQoS (tid, tsd, dti_qos_class_index);
1036     }
1037     return ThreadInfo::QoS();
1038 }
1039 
1040 nub_addr_t
1041 DNBGetPThreadT (nub_process_t pid, nub_thread_t tid)
1042 {
1043     MachProcessSP procSP;
1044     if (GetProcessSP (pid, procSP))
1045     {
1046         return procSP->GetPThreadT (tid);
1047     }
1048     return INVALID_NUB_ADDRESS;
1049 }
1050 
1051 nub_addr_t
1052 DNBGetDispatchQueueT (nub_process_t pid, nub_thread_t tid)
1053 {
1054     MachProcessSP procSP;
1055     if (GetProcessSP (pid, procSP))
1056     {
1057         return procSP->GetDispatchQueueT (tid);
1058     }
1059     return INVALID_NUB_ADDRESS;
1060 }
1061 
1062 nub_addr_t
1063 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)
1064 {
1065     MachProcessSP procSP;
1066     if (GetProcessSP (pid, procSP))
1067     {
1068         return procSP->GetTSDAddressForThread (tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
1069     }
1070     return INVALID_NUB_ADDRESS;
1071 }
1072 
1073 
1074 const char *
1075 DNBProcessGetExecutablePath (nub_process_t pid)
1076 {
1077     MachProcessSP procSP;
1078     if (GetProcessSP (pid, procSP))
1079     {
1080         return procSP->Path();
1081     }
1082     return NULL;
1083 }
1084 
1085 nub_size_t
1086 DNBProcessGetArgumentCount (nub_process_t pid)
1087 {
1088     MachProcessSP procSP;
1089     if (GetProcessSP (pid, procSP))
1090     {
1091         return procSP->ArgumentCount();
1092     }
1093     return 0;
1094 }
1095 
1096 const char *
1097 DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx)
1098 {
1099     MachProcessSP procSP;
1100     if (GetProcessSP (pid, procSP))
1101     {
1102         return procSP->ArgumentAtIndex (idx);
1103     }
1104     return NULL;
1105 }
1106 
1107 
1108 //----------------------------------------------------------------------
1109 // Execution control
1110 //----------------------------------------------------------------------
1111 nub_bool_t
1112 DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions)
1113 {
1114     DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1115     MachProcessSP procSP;
1116     if (GetProcessSP (pid, procSP))
1117     {
1118         DNBThreadResumeActions thread_actions (actions, num_actions);
1119 
1120         // Below we add a default thread plan just in case one wasn't
1121         // provided so all threads always know what they were supposed to do
1122         if (thread_actions.IsEmpty())
1123         {
1124             // No thread plans were given, so the default it to run all threads
1125             thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0);
1126         }
1127         else
1128         {
1129             // Some thread plans were given which means anything that wasn't
1130             // specified should remain stopped.
1131             thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
1132         }
1133         return procSP->Resume (thread_actions);
1134     }
1135     return false;
1136 }
1137 
1138 nub_bool_t
1139 DNBProcessHalt (nub_process_t pid)
1140 {
1141     DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1142     MachProcessSP procSP;
1143     if (GetProcessSP (pid, procSP))
1144         return procSP->Signal (SIGSTOP);
1145     return false;
1146 }
1147 //
1148 //nub_bool_t
1149 //DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step)
1150 //{
1151 //    DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", __FUNCTION__, pid, tid, (uint32_t)step);
1152 //    MachProcessSP procSP;
1153 //    if (GetProcessSP (pid, procSP))
1154 //    {
1155 //        return procSP->Resume(tid, step, 0);
1156 //    }
1157 //    return false;
1158 //}
1159 //
1160 //nub_bool_t
1161 //DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t step, int signal)
1162 //{
1163 //    DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal);
1164 //    MachProcessSP procSP;
1165 //    if (GetProcessSP (pid, procSP))
1166 //    {
1167 //        return procSP->Resume(tid, step, signal);
1168 //    }
1169 //    return false;
1170 //}
1171 
1172 nub_event_t
1173 DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout)
1174 {
1175     nub_event_t result = 0;
1176     MachProcessSP procSP;
1177     if (GetProcessSP (pid, procSP))
1178     {
1179         if (wait_for_set)
1180             result = procSP->Events().WaitForSetEvents(event_mask, timeout);
1181         else
1182             result = procSP->Events().WaitForEventsToReset(event_mask, timeout);
1183     }
1184     return result;
1185 }
1186 
1187 void
1188 DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask)
1189 {
1190     MachProcessSP procSP;
1191     if (GetProcessSP (pid, procSP))
1192         procSP->Events().ResetEvents(event_mask);
1193 }
1194 
1195 // Breakpoints
1196 nub_bool_t
1197 DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware)
1198 {
1199     MachProcessSP procSP;
1200     if (GetProcessSP (pid, procSP))
1201         return procSP->CreateBreakpoint(addr, size, hardware) != NULL;
1202     return false;
1203 }
1204 
1205 nub_bool_t
1206 DNBBreakpointClear (nub_process_t pid, nub_addr_t addr)
1207 {
1208     MachProcessSP procSP;
1209     if (GetProcessSP (pid, procSP))
1210         return procSP->DisableBreakpoint(addr, true);
1211     return false; // Failed
1212 }
1213 
1214 
1215 //----------------------------------------------------------------------
1216 // Watchpoints
1217 //----------------------------------------------------------------------
1218 nub_bool_t
1219 DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware)
1220 {
1221     MachProcessSP procSP;
1222     if (GetProcessSP (pid, procSP))
1223         return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL;
1224     return false;
1225 }
1226 
1227 nub_bool_t
1228 DNBWatchpointClear (nub_process_t pid, nub_addr_t addr)
1229 {
1230     MachProcessSP procSP;
1231     if (GetProcessSP (pid, procSP))
1232         return procSP->DisableWatchpoint(addr, true);
1233     return false; // Failed
1234 }
1235 
1236 //----------------------------------------------------------------------
1237 // Return the number of supported hardware watchpoints.
1238 //----------------------------------------------------------------------
1239 uint32_t
1240 DNBWatchpointGetNumSupportedHWP (nub_process_t pid)
1241 {
1242     MachProcessSP procSP;
1243     if (GetProcessSP (pid, procSP))
1244         return procSP->GetNumSupportedHardwareWatchpoints();
1245     return 0;
1246 }
1247 
1248 //----------------------------------------------------------------------
1249 // Read memory in the address space of process PID. This call will take
1250 // care of setting and restoring permissions and breaking up the memory
1251 // read into multiple chunks as required.
1252 //
1253 // RETURNS: number of bytes actually read
1254 //----------------------------------------------------------------------
1255 nub_size_t
1256 DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf)
1257 {
1258     MachProcessSP procSP;
1259     if (GetProcessSP (pid, procSP))
1260         return procSP->ReadMemory(addr, size, buf);
1261     return 0;
1262 }
1263 
1264 //----------------------------------------------------------------------
1265 // Write memory to the address space of process PID. This call will take
1266 // care of setting and restoring permissions and breaking up the memory
1267 // write into multiple chunks as required.
1268 //
1269 // RETURNS: number of bytes actually written
1270 //----------------------------------------------------------------------
1271 nub_size_t
1272 DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf)
1273 {
1274     MachProcessSP procSP;
1275     if (GetProcessSP (pid, procSP))
1276         return procSP->WriteMemory(addr, size, buf);
1277     return 0;
1278 }
1279 
1280 nub_addr_t
1281 DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions)
1282 {
1283     MachProcessSP procSP;
1284     if (GetProcessSP (pid, procSP))
1285         return procSP->Task().AllocateMemory (size, permissions);
1286     return 0;
1287 }
1288 
1289 nub_bool_t
1290 DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr)
1291 {
1292     MachProcessSP procSP;
1293     if (GetProcessSP (pid, procSP))
1294         return procSP->Task().DeallocateMemory (addr);
1295     return 0;
1296 }
1297 
1298 //----------------------------------------------------------------------
1299 // Find attributes of the memory region that contains ADDR for process PID,
1300 // if possible, and return a string describing those attributes.
1301 //
1302 // Returns 1 if we could find attributes for this region and OUTBUF can
1303 // be sent to the remote debugger.
1304 //
1305 // Returns 0 if we couldn't find the attributes for a region of memory at
1306 // that address and OUTBUF should not be sent.
1307 //
1308 // Returns -1 if this platform cannot look up information about memory regions
1309 // or if we do not yet have a valid launched process.
1310 //
1311 //----------------------------------------------------------------------
1312 int
1313 DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info)
1314 {
1315     MachProcessSP procSP;
1316     if (GetProcessSP (pid, procSP))
1317         return procSP->Task().GetMemoryRegionInfo (addr, region_info);
1318 
1319     return -1;
1320 }
1321 
1322 std::string
1323 DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType)
1324 {
1325     MachProcessSP procSP;
1326     if (GetProcessSP (pid, procSP))
1327         return procSP->Task().GetProfileData(scanType);
1328 
1329     return std::string("");
1330 }
1331 
1332 nub_bool_t
1333 DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type)
1334 {
1335     MachProcessSP procSP;
1336     if (GetProcessSP (pid, procSP))
1337     {
1338         procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type);
1339         return true;
1340     }
1341 
1342     return false;
1343 }
1344 
1345 //----------------------------------------------------------------------
1346 // Formatted output that uses memory and registers from process and
1347 // thread in place of arguments.
1348 //----------------------------------------------------------------------
1349 nub_size_t
1350 DNBPrintf (nub_process_t pid, nub_thread_t tid, nub_addr_t base_addr, FILE *file, const char *format)
1351 {
1352     if (file == NULL)
1353         return 0;
1354     enum printf_flags
1355     {
1356         alternate_form          = (1 << 0),
1357         zero_padding            = (1 << 1),
1358         negative_field_width    = (1 << 2),
1359         blank_space             = (1 << 3),
1360         show_sign               = (1 << 4),
1361         show_thousands_separator= (1 << 5),
1362     };
1363 
1364     enum printf_length_modifiers
1365     {
1366         length_mod_h            = (1 << 0),
1367         length_mod_hh           = (1 << 1),
1368         length_mod_l            = (1 << 2),
1369         length_mod_ll           = (1 << 3),
1370         length_mod_L            = (1 << 4),
1371         length_mod_j            = (1 << 5),
1372         length_mod_t            = (1 << 6),
1373         length_mod_z            = (1 << 7),
1374         length_mod_q            = (1 << 8),
1375     };
1376 
1377     nub_addr_t addr = base_addr;
1378     char *end_format = (char*)format + strlen(format);
1379     char *end = NULL;    // For strtoXXXX calls;
1380     std::basic_string<uint8_t> buf;
1381     nub_size_t total_bytes_read = 0;
1382     DNBDataRef data;
1383     const char *f;
1384     for (f = format; *f != '\0' && f < end_format; f++)
1385     {
1386         char ch = *f;
1387         switch (ch)
1388         {
1389         case '%':
1390             {
1391                 f++;    // Skip the '%' character
1392 //                int min_field_width = 0;
1393 //                int precision = 0;
1394                 //uint32_t flags = 0;
1395                 uint32_t length_modifiers = 0;
1396                 uint32_t byte_size = 0;
1397                 uint32_t actual_byte_size = 0;
1398                 bool is_string = false;
1399                 bool is_register = false;
1400                 DNBRegisterValue register_value;
1401                 int64_t    register_offset = 0;
1402                 nub_addr_t register_addr = INVALID_NUB_ADDRESS;
1403 
1404                 // Create the format string to use for this conversion specification
1405                 // so we can remove and mprintf specific flags and formatters.
1406                 std::string fprintf_format("%");
1407 
1408                 // Decode any flags
1409                 switch (*f)
1410                 {
1411                 case '#': fprintf_format += *f++; break; //flags |= alternate_form;          break;
1412                 case '0': fprintf_format += *f++; break; //flags |= zero_padding;            break;
1413                 case '-': fprintf_format += *f++; break; //flags |= negative_field_width;    break;
1414                 case ' ': fprintf_format += *f++; break; //flags |= blank_space;             break;
1415                 case '+': fprintf_format += *f++; break; //flags |= show_sign;               break;
1416                 case ',': fprintf_format += *f++; break; //flags |= show_thousands_separator;break;
1417                 case '{':
1418                 case '[':
1419                     {
1420                         // We have a register name specification that can take two forms:
1421                         // ${regname} or ${regname+offset}
1422                         //        The action is to read the register value and add the signed offset
1423                         //        (if any) and use that as the value to format.
1424                         // $[regname] or $[regname+offset]
1425                         //        The action is to read the register value and add the signed offset
1426                         //        (if any) and use the result as an address to dereference. The size
1427                         //        of what is dereferenced is specified by the actual byte size that
1428                         //        follows the minimum field width and precision (see comments below).
1429                         switch (*f)
1430                         {
1431                         case '{':
1432                         case '[':
1433                             {
1434                                 char open_scope_ch = *f;
1435                                 f++;
1436                                 const char *reg_name = f;
1437                                 size_t reg_name_length = strcspn(f, "+-}]");
1438                                 if (reg_name_length > 0)
1439                                 {
1440                                     std::string register_name(reg_name, reg_name_length);
1441                                     f += reg_name_length;
1442                                     register_offset = strtoll(f, &end, 0);
1443                                     if (f < end)
1444                                         f = end;
1445                                     if ((open_scope_ch == '{' && *f != '}') || (open_scope_ch == '[' && *f != ']'))
1446                                     {
1447                                         fprintf(file, "error: Invalid register format string. Valid formats are %%{regname} or %%{regname+offset}, %%[regname] or %%[regname+offset]\n");
1448                                         return total_bytes_read;
1449                                     }
1450                                     else
1451                                     {
1452                                         f++;
1453                                         if (DNBThreadGetRegisterValueByName(pid, tid, REGISTER_SET_ALL, register_name.c_str(), &register_value))
1454                                         {
1455                                             // Set the address to dereference using the register value plus the offset
1456                                             switch (register_value.info.size)
1457                                             {
1458                                             default:
1459                                             case 0:
1460                                                 fprintf (file, "error: unsupported register size of %u.\n", register_value.info.size);
1461                                                 return total_bytes_read;
1462 
1463                                             case 1:        register_addr = register_value.value.uint8  + register_offset; break;
1464                                             case 2:        register_addr = register_value.value.uint16 + register_offset; break;
1465                                             case 4:        register_addr = register_value.value.uint32 + register_offset; break;
1466                                             case 8:        register_addr = register_value.value.uint64 + register_offset; break;
1467                                             case 16:
1468                                                 if (open_scope_ch == '[')
1469                                                 {
1470                                                     fprintf (file, "error: register size (%u) too large for address.\n", register_value.info.size);
1471                                                     return total_bytes_read;
1472                                                 }
1473                                                 break;
1474                                             }
1475 
1476                                             if (open_scope_ch == '{')
1477                                             {
1478                                                 byte_size = register_value.info.size;
1479                                                 is_register = true;    // value is in a register
1480 
1481                                             }
1482                                             else
1483                                             {
1484                                                 addr = register_addr;    // Use register value and offset as the address
1485                                             }
1486                                         }
1487                                         else
1488                                         {
1489                                             fprintf(file, "error: unable to read register '%s' for process %#.4x and thread %#.8" PRIx64 "\n", register_name.c_str(), pid, tid);
1490                                             return total_bytes_read;
1491                                         }
1492                                     }
1493                                 }
1494                             }
1495                             break;
1496 
1497                         default:
1498                             fprintf(file, "error: %%$ must be followed by (regname + n) or [regname + n]\n");
1499                             return total_bytes_read;
1500                         }
1501                     }
1502                     break;
1503                 }
1504 
1505                 // Check for a minimum field width
1506                 if (isdigit(*f))
1507                 {
1508                     //min_field_width = strtoul(f, &end, 10);
1509                     strtoul(f, &end, 10);
1510                     if (end > f)
1511                     {
1512                         fprintf_format.append(f, end - f);
1513                         f = end;
1514                     }
1515                 }
1516 
1517 
1518                 // Check for a precision
1519                 if (*f == '.')
1520                 {
1521                     f++;
1522                     if (isdigit(*f))
1523                     {
1524                         fprintf_format += '.';
1525                         //precision = strtoul(f, &end, 10);
1526                         strtoul(f, &end, 10);
1527                         if (end > f)
1528                         {
1529                             fprintf_format.append(f, end - f);
1530                             f = end;
1531                         }
1532                     }
1533                 }
1534 
1535 
1536                 // mprintf specific: read the optional actual byte size (abs)
1537                 // after the standard minimum field width (mfw) and precision (prec).
1538                 // Standard printf calls you can have "mfw.prec" or ".prec", but
1539                 // mprintf can have "mfw.prec.abs", ".prec.abs" or "..abs". This is nice
1540                 // for strings that may be in a fixed size buffer, but may not use all bytes
1541                 // in that buffer for printable characters.
1542                 if (*f == '.')
1543                 {
1544                     f++;
1545                     actual_byte_size = strtoul(f, &end, 10);
1546                     if (end > f)
1547                     {
1548                         byte_size = actual_byte_size;
1549                         f = end;
1550                     }
1551                 }
1552 
1553                 // Decode the length modifiers
1554                 switch (*f)
1555                 {
1556                 case 'h':    // h and hh length modifiers
1557                     fprintf_format += *f++;
1558                     length_modifiers |= length_mod_h;
1559                     if (*f == 'h')
1560                     {
1561                         fprintf_format += *f++;
1562                         length_modifiers |= length_mod_hh;
1563                     }
1564                     break;
1565 
1566                 case 'l': // l and ll length modifiers
1567                     fprintf_format += *f++;
1568                     length_modifiers |= length_mod_l;
1569                     if (*f == 'h')
1570                     {
1571                         fprintf_format += *f++;
1572                         length_modifiers |= length_mod_ll;
1573                     }
1574                     break;
1575 
1576                 case 'L':    fprintf_format += *f++;    length_modifiers |= length_mod_L;    break;
1577                 case 'j':    fprintf_format += *f++;    length_modifiers |= length_mod_j;    break;
1578                 case 't':    fprintf_format += *f++;    length_modifiers |= length_mod_t;    break;
1579                 case 'z':    fprintf_format += *f++;    length_modifiers |= length_mod_z;    break;
1580                 case 'q':    fprintf_format += *f++;    length_modifiers |= length_mod_q;    break;
1581                 }
1582 
1583                 // Decode the conversion specifier
1584                 switch (*f)
1585                 {
1586                 case '_':
1587                     // mprintf specific format items
1588                     {
1589                         ++f;    // Skip the '_' character
1590                         switch (*f)
1591                         {
1592                         case 'a':    // Print the current address
1593                             ++f;
1594                             fprintf_format += "ll";
1595                             fprintf_format += *f;    // actual format to show address with follows the 'a' ("%_ax")
1596                             fprintf (file, fprintf_format.c_str(), addr);
1597                             break;
1598                         case 'o':    // offset from base address
1599                             ++f;
1600                             fprintf_format += "ll";
1601                             fprintf_format += *f;    // actual format to show address with follows the 'a' ("%_ox")
1602                             fprintf(file, fprintf_format.c_str(), addr - base_addr);
1603                             break;
1604                         default:
1605                             fprintf (file, "error: unsupported mprintf specific format character '%c'.\n", *f);
1606                             break;
1607                         }
1608                         continue;
1609                     }
1610                     break;
1611 
1612                 case 'D':
1613                 case 'O':
1614                 case 'U':
1615                     fprintf_format += *f;
1616                     if (byte_size == 0)
1617                         byte_size = sizeof(long int);
1618                     break;
1619 
1620                 case 'd':
1621                 case 'i':
1622                 case 'o':
1623                 case 'u':
1624                 case 'x':
1625                 case 'X':
1626                     fprintf_format += *f;
1627                     if (byte_size == 0)
1628                     {
1629                         if (length_modifiers & length_mod_hh)
1630                             byte_size = sizeof(char);
1631                         else if (length_modifiers & length_mod_h)
1632                             byte_size = sizeof(short);
1633                         else if (length_modifiers & length_mod_ll)
1634                             byte_size = sizeof(long long);
1635                         else if (length_modifiers & length_mod_l)
1636                             byte_size = sizeof(long);
1637                         else
1638                             byte_size = sizeof(int);
1639                     }
1640                     break;
1641 
1642                 case 'a':
1643                 case 'A':
1644                 case 'f':
1645                 case 'F':
1646                 case 'e':
1647                 case 'E':
1648                 case 'g':
1649                 case 'G':
1650                     fprintf_format += *f;
1651                     if (byte_size == 0)
1652                     {
1653                         if (length_modifiers & length_mod_L)
1654                             byte_size = sizeof(long double);
1655                         else
1656                             byte_size = sizeof(double);
1657                     }
1658                     break;
1659 
1660                 case 'c':
1661                     if ((length_modifiers & length_mod_l) == 0)
1662                     {
1663                         fprintf_format += *f;
1664                         if (byte_size == 0)
1665                             byte_size = sizeof(char);
1666                         break;
1667                     }
1668                     // Fall through to 'C' modifier below...
1669 
1670                 case 'C':
1671                     fprintf_format += *f;
1672                     if (byte_size == 0)
1673                         byte_size = sizeof(wchar_t);
1674                     break;
1675 
1676                 case 's':
1677                     fprintf_format += *f;
1678                     if (is_register || byte_size == 0)
1679                         is_string = 1;
1680                     break;
1681 
1682                 case 'p':
1683                     fprintf_format += *f;
1684                     if (byte_size == 0)
1685                         byte_size = sizeof(void*);
1686                     break;
1687                 }
1688 
1689                 if (is_string)
1690                 {
1691                     std::string mem_string;
1692                     const size_t string_buf_len = 4;
1693                     char string_buf[string_buf_len+1];
1694                     char *string_buf_end = string_buf + string_buf_len;
1695                     string_buf[string_buf_len] = '\0';
1696                     nub_size_t bytes_read;
1697                     nub_addr_t str_addr = is_register ? register_addr : addr;
1698                     while ((bytes_read = DNBProcessMemoryRead(pid, str_addr, string_buf_len, &string_buf[0])) > 0)
1699                     {
1700                         // Did we get a NULL termination character yet?
1701                         if (strchr(string_buf, '\0') == string_buf_end)
1702                         {
1703                             // no NULL terminator yet, append as a std::string
1704                             mem_string.append(string_buf, string_buf_len);
1705                             str_addr += string_buf_len;
1706                         }
1707                         else
1708                         {
1709                             // yep
1710                             break;
1711                         }
1712                     }
1713                     // Append as a C-string so we don't get the extra NULL
1714                     // characters in the temp buffer (since it was resized)
1715                     mem_string += string_buf;
1716                     size_t mem_string_len = mem_string.size() + 1;
1717                     fprintf(file, fprintf_format.c_str(), mem_string.c_str());
1718                     if (mem_string_len > 0)
1719                     {
1720                         if (!is_register)
1721                         {
1722                             addr += mem_string_len;
1723                             total_bytes_read += mem_string_len;
1724                         }
1725                     }
1726                     else
1727                         return total_bytes_read;
1728                 }
1729                 else
1730                 if (byte_size > 0)
1731                 {
1732                     buf.resize(byte_size);
1733                     nub_size_t bytes_read = 0;
1734                     if (is_register)
1735                         bytes_read = register_value.info.size;
1736                     else
1737                         bytes_read = DNBProcessMemoryRead(pid, addr, buf.size(), &buf[0]);
1738                     if (bytes_read > 0)
1739                     {
1740                         if (!is_register)
1741                             total_bytes_read += bytes_read;
1742 
1743                         if (bytes_read == byte_size)
1744                         {
1745                             switch (*f)
1746                             {
1747                             case 'd':
1748                             case 'i':
1749                             case 'o':
1750                             case 'u':
1751                             case 'X':
1752                             case 'x':
1753                             case 'a':
1754                             case 'A':
1755                             case 'f':
1756                             case 'F':
1757                             case 'e':
1758                             case 'E':
1759                             case 'g':
1760                             case 'G':
1761                             case 'p':
1762                             case 'c':
1763                             case 'C':
1764                                 {
1765                                     if (is_register)
1766                                         data.SetData(&register_value.value.v_uint8[0], register_value.info.size);
1767                                     else
1768                                         data.SetData(&buf[0], bytes_read);
1769                                     DNBDataRef::offset_t data_offset = 0;
1770                                     if (byte_size <= 4)
1771                                     {
1772                                         uint32_t u32 = data.GetMax32(&data_offset, byte_size);
1773                                         // Show the actual byte width when displaying hex
1774                                         fprintf(file, fprintf_format.c_str(), u32);
1775                                     }
1776                                     else if (byte_size <= 8)
1777                                     {
1778                                         uint64_t u64 = data.GetMax64(&data_offset, byte_size);
1779                                         // Show the actual byte width when displaying hex
1780                                         fprintf(file, fprintf_format.c_str(), u64);
1781                                     }
1782                                     else
1783                                     {
1784                                         fprintf(file, "error: integer size not supported, must be 8 bytes or less (%u bytes).\n", byte_size);
1785                                     }
1786                                     if (!is_register)
1787                                         addr += byte_size;
1788                                 }
1789                                 break;
1790 
1791                             case 's':
1792                                 fprintf(file, fprintf_format.c_str(), buf.c_str());
1793                                 addr += byte_size;
1794                                 break;
1795 
1796                             default:
1797                                 fprintf(file, "error: unsupported conversion specifier '%c'.\n", *f);
1798                                 break;
1799                             }
1800                         }
1801                     }
1802                 }
1803                 else
1804                     return total_bytes_read;
1805             }
1806             break;
1807 
1808         case '\\':
1809             {
1810                 f++;
1811                 switch (*f)
1812                 {
1813                 case 'e': ch = '\e'; break;
1814                 case 'a': ch = '\a'; break;
1815                 case 'b': ch = '\b'; break;
1816                 case 'f': ch = '\f'; break;
1817                 case 'n': ch = '\n'; break;
1818                 case 'r': ch = '\r'; break;
1819                 case 't': ch = '\t'; break;
1820                 case 'v': ch = '\v'; break;
1821                 case '\'': ch = '\''; break;
1822                 case '\\': ch = '\\'; break;
1823                 case '0':
1824                 case '1':
1825                 case '2':
1826                 case '3':
1827                 case '4':
1828                 case '5':
1829                 case '6':
1830                 case '7':
1831                     ch = strtoul(f, &end, 8);
1832                     f = end;
1833                     break;
1834                 default:
1835                     ch = *f;
1836                     break;
1837                 }
1838                 fputc(ch, file);
1839             }
1840             break;
1841 
1842         default:
1843             fputc(ch, file);
1844             break;
1845         }
1846     }
1847     return total_bytes_read;
1848 }
1849 
1850 
1851 //----------------------------------------------------------------------
1852 // Get the number of threads for the specified process.
1853 //----------------------------------------------------------------------
1854 nub_size_t
1855 DNBProcessGetNumThreads (nub_process_t pid)
1856 {
1857     MachProcessSP procSP;
1858     if (GetProcessSP (pid, procSP))
1859         return procSP->GetNumThreads();
1860     return 0;
1861 }
1862 
1863 //----------------------------------------------------------------------
1864 // Get the thread ID of the current thread.
1865 //----------------------------------------------------------------------
1866 nub_thread_t
1867 DNBProcessGetCurrentThread (nub_process_t pid)
1868 {
1869     MachProcessSP procSP;
1870     if (GetProcessSP (pid, procSP))
1871         return procSP->GetCurrentThread();
1872     return 0;
1873 }
1874 
1875 //----------------------------------------------------------------------
1876 // Get the mach port number of the current thread.
1877 //----------------------------------------------------------------------
1878 nub_thread_t
1879 DNBProcessGetCurrentThreadMachPort (nub_process_t pid)
1880 {
1881     MachProcessSP procSP;
1882     if (GetProcessSP (pid, procSP))
1883         return procSP->GetCurrentThreadMachPort();
1884     return 0;
1885 }
1886 
1887 //----------------------------------------------------------------------
1888 // Change the current thread.
1889 //----------------------------------------------------------------------
1890 nub_thread_t
1891 DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid)
1892 {
1893     MachProcessSP procSP;
1894     if (GetProcessSP (pid, procSP))
1895         return procSP->SetCurrentThread (tid);
1896     return INVALID_NUB_THREAD;
1897 }
1898 
1899 
1900 //----------------------------------------------------------------------
1901 // Dump a string describing a thread's stop reason to the specified file
1902 // handle
1903 //----------------------------------------------------------------------
1904 nub_bool_t
1905 DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, struct DNBThreadStopInfo *stop_info)
1906 {
1907     MachProcessSP procSP;
1908     if (GetProcessSP (pid, procSP))
1909         return procSP->GetThreadStoppedReason (tid, stop_info);
1910     return false;
1911 }
1912 
1913 //----------------------------------------------------------------------
1914 // Return string description for the specified thread.
1915 //
1916 // RETURNS: NULL if the thread isn't valid, else a NULL terminated C
1917 // string from a static buffer that must be copied prior to subsequent
1918 // calls.
1919 //----------------------------------------------------------------------
1920 const char *
1921 DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid)
1922 {
1923     MachProcessSP procSP;
1924     if (GetProcessSP (pid, procSP))
1925         return procSP->GetThreadInfo (tid);
1926     return NULL;
1927 }
1928 
1929 //----------------------------------------------------------------------
1930 // Get the thread ID given a thread index.
1931 //----------------------------------------------------------------------
1932 nub_thread_t
1933 DNBProcessGetThreadAtIndex (nub_process_t pid, size_t thread_idx)
1934 {
1935     MachProcessSP procSP;
1936     if (GetProcessSP (pid, procSP))
1937         return procSP->GetThreadAtIndex (thread_idx);
1938     return INVALID_NUB_THREAD;
1939 }
1940 
1941 //----------------------------------------------------------------------
1942 // Do whatever is needed to sync the thread's register state with it's kernel values.
1943 //----------------------------------------------------------------------
1944 nub_bool_t
1945 DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid)
1946 {
1947     MachProcessSP procSP;
1948     if (GetProcessSP (pid, procSP))
1949         return procSP->SyncThreadState (tid);
1950     return false;
1951 
1952 }
1953 
1954 nub_addr_t
1955 DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid)
1956 {
1957     MachProcessSP procSP;
1958     DNBError err;
1959     if (GetProcessSP (pid, procSP))
1960         return procSP->Task().GetDYLDAllImageInfosAddress (err);
1961     return INVALID_NUB_ADDRESS;
1962 }
1963 
1964 
1965 nub_bool_t
1966 DNBProcessSharedLibrariesUpdated(nub_process_t pid)
1967 {
1968     MachProcessSP procSP;
1969     if (GetProcessSP (pid, procSP))
1970     {
1971         procSP->SharedLibrariesUpdated ();
1972         return true;
1973     }
1974     return false;
1975 }
1976 
1977 //----------------------------------------------------------------------
1978 // Get the current shared library information for a process. Only return
1979 // the shared libraries that have changed since the last shared library
1980 // state changed event if only_changed is non-zero.
1981 //----------------------------------------------------------------------
1982 nub_size_t
1983 DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, struct DNBExecutableImageInfo **image_infos)
1984 {
1985     MachProcessSP procSP;
1986     if (GetProcessSP (pid, procSP))
1987         return procSP->CopyImageInfos (image_infos, only_changed);
1988 
1989     // If we have no process, then return NULL for the shared library info
1990     // and zero for shared library count
1991     *image_infos = NULL;
1992     return 0;
1993 }
1994 
1995 //----------------------------------------------------------------------
1996 // Get the register set information for a specific thread.
1997 //----------------------------------------------------------------------
1998 const DNBRegisterSetInfo *
1999 DNBGetRegisterSetInfo (nub_size_t *num_reg_sets)
2000 {
2001     return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets);
2002 }
2003 
2004 
2005 //----------------------------------------------------------------------
2006 // Read a register value by register set and register index.
2007 //----------------------------------------------------------------------
2008 nub_bool_t
2009 DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value)
2010 {
2011     MachProcessSP procSP;
2012     ::bzero (value, sizeof(DNBRegisterValue));
2013     if (GetProcessSP (pid, procSP))
2014     {
2015         if (tid != INVALID_NUB_THREAD)
2016             return procSP->GetRegisterValue (tid, set, reg, value);
2017     }
2018     return false;
2019 }
2020 
2021 nub_bool_t
2022 DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value)
2023 {
2024     if (tid != INVALID_NUB_THREAD)
2025     {
2026         MachProcessSP procSP;
2027         if (GetProcessSP (pid, procSP))
2028             return procSP->SetRegisterValue (tid, set, reg, value);
2029     }
2030     return false;
2031 }
2032 
2033 nub_size_t
2034 DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len)
2035 {
2036     MachProcessSP procSP;
2037     if (GetProcessSP (pid, procSP))
2038     {
2039         if (tid != INVALID_NUB_THREAD)
2040             return procSP->GetThreadList().GetRegisterContext (tid, buf, buf_len);
2041     }
2042     ::bzero (buf, buf_len);
2043     return 0;
2044 
2045 }
2046 
2047 nub_size_t
2048 DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len)
2049 {
2050     MachProcessSP procSP;
2051     if (GetProcessSP (pid, procSP))
2052     {
2053         if (tid != INVALID_NUB_THREAD)
2054             return procSP->GetThreadList().SetRegisterContext (tid, buf, buf_len);
2055     }
2056     return 0;
2057 }
2058 
2059 uint32_t
2060 DNBThreadSaveRegisterState (nub_process_t pid, nub_thread_t tid)
2061 {
2062     if (tid != INVALID_NUB_THREAD)
2063     {
2064         MachProcessSP procSP;
2065         if (GetProcessSP (pid, procSP))
2066             return procSP->GetThreadList().SaveRegisterState (tid);
2067     }
2068     return 0;
2069 }
2070 nub_bool_t
2071 DNBThreadRestoreRegisterState (nub_process_t pid, nub_thread_t tid, uint32_t save_id)
2072 {
2073     if (tid != INVALID_NUB_THREAD)
2074     {
2075         MachProcessSP procSP;
2076         if (GetProcessSP (pid, procSP))
2077             return procSP->GetThreadList().RestoreRegisterState (tid, save_id);
2078     }
2079     return false;
2080 }
2081 
2082 
2083 
2084 //----------------------------------------------------------------------
2085 // Read a register value by name.
2086 //----------------------------------------------------------------------
2087 nub_bool_t
2088 DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t reg_set, const char *reg_name, DNBRegisterValue *value)
2089 {
2090     MachProcessSP procSP;
2091     ::bzero (value, sizeof(DNBRegisterValue));
2092     if (GetProcessSP (pid, procSP))
2093     {
2094         const struct DNBRegisterSetInfo *set_info;
2095         nub_size_t num_reg_sets = 0;
2096         set_info = DNBGetRegisterSetInfo (&num_reg_sets);
2097         if (set_info)
2098         {
2099             uint32_t set = reg_set;
2100             uint32_t reg;
2101             if (set == REGISTER_SET_ALL)
2102             {
2103                 for (set = 1; set < num_reg_sets; ++set)
2104                 {
2105                     for (reg = 0; reg < set_info[set].num_registers; ++reg)
2106                     {
2107                         if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
2108                             return procSP->GetRegisterValue (tid, set, reg, value);
2109                     }
2110                 }
2111             }
2112             else
2113             {
2114                 for (reg = 0; reg < set_info[set].num_registers; ++reg)
2115                 {
2116                     if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
2117                         return procSP->GetRegisterValue (tid, set, reg, value);
2118                 }
2119             }
2120         }
2121     }
2122     return false;
2123 }
2124 
2125 
2126 //----------------------------------------------------------------------
2127 // Read a register set and register number from the register name.
2128 //----------------------------------------------------------------------
2129 nub_bool_t
2130 DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info)
2131 {
2132     const struct DNBRegisterSetInfo *set_info;
2133     nub_size_t num_reg_sets = 0;
2134     set_info = DNBGetRegisterSetInfo (&num_reg_sets);
2135     if (set_info)
2136     {
2137         uint32_t set, reg;
2138         for (set = 1; set < num_reg_sets; ++set)
2139         {
2140             for (reg = 0; reg < set_info[set].num_registers; ++reg)
2141             {
2142                 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
2143                 {
2144                     *info = set_info[set].registers[reg];
2145                     return true;
2146                 }
2147             }
2148         }
2149 
2150         for (set = 1; set < num_reg_sets; ++set)
2151         {
2152             uint32_t reg;
2153             for (reg = 0; reg < set_info[set].num_registers; ++reg)
2154             {
2155                 if (set_info[set].registers[reg].alt == NULL)
2156                     continue;
2157 
2158                 if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0)
2159                 {
2160                     *info = set_info[set].registers[reg];
2161                     return true;
2162                 }
2163             }
2164         }
2165     }
2166 
2167     ::bzero (info, sizeof(DNBRegisterInfo));
2168     return false;
2169 }
2170 
2171 
2172 //----------------------------------------------------------------------
2173 // Set the name to address callback function that this nub can use
2174 // for any name to address lookups that are needed.
2175 //----------------------------------------------------------------------
2176 nub_bool_t
2177 DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton)
2178 {
2179     MachProcessSP procSP;
2180     if (GetProcessSP (pid, procSP))
2181     {
2182         procSP->SetNameToAddressCallback (callback, baton);
2183         return true;
2184     }
2185     return false;
2186 }
2187 
2188 
2189 //----------------------------------------------------------------------
2190 // Set the name to address callback function that this nub can use
2191 // for any name to address lookups that are needed.
2192 //----------------------------------------------------------------------
2193 nub_bool_t
2194 DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void  *baton)
2195 {
2196     MachProcessSP procSP;
2197     if (GetProcessSP (pid, procSP))
2198     {
2199         procSP->SetSharedLibraryInfoCallback (callback, baton);
2200         return true;
2201     }
2202     return false;
2203 }
2204 
2205 nub_addr_t
2206 DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib)
2207 {
2208     MachProcessSP procSP;
2209     if (GetProcessSP (pid, procSP))
2210     {
2211         return procSP->LookupSymbol (name, shlib);
2212     }
2213     return INVALID_NUB_ADDRESS;
2214 }
2215 
2216 
2217 nub_size_t
2218 DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size)
2219 {
2220     MachProcessSP procSP;
2221     if (GetProcessSP (pid, procSP))
2222         return procSP->GetAvailableSTDOUT (buf, buf_size);
2223     return 0;
2224 }
2225 
2226 nub_size_t
2227 DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size)
2228 {
2229     MachProcessSP procSP;
2230     if (GetProcessSP (pid, procSP))
2231         return procSP->GetAvailableSTDERR (buf, buf_size);
2232     return 0;
2233 }
2234 
2235 nub_size_t
2236 DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size)
2237 {
2238     MachProcessSP procSP;
2239     if (GetProcessSP (pid, procSP))
2240         return procSP->GetAsyncProfileData (buf, buf_size);
2241     return 0;
2242 }
2243 
2244 nub_size_t
2245 DNBProcessGetStopCount (nub_process_t pid)
2246 {
2247     MachProcessSP procSP;
2248     if (GetProcessSP (pid, procSP))
2249         return procSP->StopCount();
2250     return 0;
2251 }
2252 
2253 uint32_t
2254 DNBProcessGetCPUType (nub_process_t pid)
2255 {
2256     MachProcessSP procSP;
2257     if (GetProcessSP (pid, procSP))
2258         return procSP->GetCPUType ();
2259     return 0;
2260 
2261 }
2262 
2263 nub_bool_t
2264 DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size)
2265 {
2266     if (path == NULL || path[0] == '\0')
2267         return false;
2268 
2269     char max_path[PATH_MAX];
2270     std::string result;
2271     CFString::GlobPath(path, result);
2272 
2273     if (result.empty())
2274         result = path;
2275 
2276     struct stat path_stat;
2277     if (::stat(path, &path_stat) == 0)
2278     {
2279         if ((path_stat.st_mode & S_IFMT) == S_IFDIR)
2280         {
2281             CFBundle bundle (path);
2282             CFReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
2283             if (url.get())
2284             {
2285                 if (::CFURLGetFileSystemRepresentation (url.get(), true, (UInt8*)resolved_path, resolved_path_size))
2286                     return true;
2287             }
2288         }
2289     }
2290 
2291     if (realpath(path, max_path))
2292     {
2293         // Found the path relatively...
2294         ::strncpy(resolved_path, max_path, resolved_path_size);
2295         return strlen(resolved_path) + 1 < resolved_path_size;
2296     }
2297     else
2298     {
2299         // Not a relative path, check the PATH environment variable if the
2300         const char *PATH = getenv("PATH");
2301         if (PATH)
2302         {
2303             const char *curr_path_start = PATH;
2304             const char *curr_path_end;
2305             while (curr_path_start && *curr_path_start)
2306             {
2307                 curr_path_end = strchr(curr_path_start, ':');
2308                 if (curr_path_end == NULL)
2309                 {
2310                     result.assign(curr_path_start);
2311                     curr_path_start = NULL;
2312                 }
2313                 else if (curr_path_end > curr_path_start)
2314                 {
2315                     size_t len = curr_path_end - curr_path_start;
2316                     result.assign(curr_path_start, len);
2317                     curr_path_start += len + 1;
2318                 }
2319                 else
2320                     break;
2321 
2322                 result += '/';
2323                 result += path;
2324                 struct stat s;
2325                 if (stat(result.c_str(), &s) == 0)
2326                 {
2327                     ::strncpy(resolved_path, result.c_str(), resolved_path_size);
2328                     return result.size() + 1 < resolved_path_size;
2329                 }
2330             }
2331         }
2332     }
2333     return false;
2334 }
2335 
2336 
2337 void
2338 DNBInitialize()
2339 {
2340     DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()");
2341 #if defined (__i386__) || defined (__x86_64__)
2342     DNBArchImplI386::Initialize();
2343     DNBArchImplX86_64::Initialize();
2344 #elif defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
2345     DNBArchMachARM::Initialize();
2346     DNBArchMachARM64::Initialize();
2347 #endif
2348 }
2349 
2350 void
2351 DNBTerminate()
2352 {
2353 }
2354 
2355 nub_bool_t
2356 DNBSetArchitecture (const char *arch)
2357 {
2358     if (arch && arch[0])
2359     {
2360         if (strcasecmp (arch, "i386") == 0)
2361             return DNBArchProtocol::SetArchitecture (CPU_TYPE_I386);
2362         else if ((strcasecmp (arch, "x86_64") == 0) || (strcasecmp (arch, "x86_64h") == 0))
2363             return DNBArchProtocol::SetArchitecture (CPU_TYPE_X86_64);
2364         else if (strstr (arch, "arm64") == arch || strstr (arch, "armv8") == arch || strstr (arch, "aarch64") == arch)
2365             return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM64);
2366         else if (strstr (arch, "arm") == arch)
2367             return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM);
2368     }
2369     return false;
2370 }
2371