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