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