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