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