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