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