1 //===-- DNB.cpp -------------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Created by Greg Clayton on 3/23/07.
12 //===----------------------------------------------------------------------===//
19 #include <sys/resource.h>
21 #include <sys/types.h>
24 #include <sys/sysctl.h>
29 #if defined (__APPLE__)
37 #include <sys/event.h>
39 #ifdef NOTE_EXIT_DETAIL
44 #include "MacOSX/MachProcess.h"
45 #include "MacOSX/MachTask.h"
46 #include "MacOSX/Genealogy.h"
47 #include "MacOSX/ThreadInfo.h"
50 #include "DNBDataRef.h"
51 #include "DNBThreadResumeActions.h"
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;
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);
64 //----------------------------------------------------------------------
65 // A Thread safe singleton to get a process map pointer.
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 //----------------------------------------------------------------------
71 GetProcessMap(bool can_create)
73 static ProcessMap* g_process_map_ptr = NULL;
75 if (can_create && g_process_map_ptr == NULL)
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;
82 return g_process_map_ptr;
85 //----------------------------------------------------------------------
86 // Add PID to the shared process pointer map.
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 //----------------------------------------------------------------------
93 AddProcessToMap (nub_process_t pid, MachProcessSP& procSP)
95 ProcessMap* process_map = GetProcessMap(true);
98 process_map->insert(std::make_pair(pid, procSP));
104 //----------------------------------------------------------------------
105 // Remove the shared pointer for PID from the process map.
107 // Returns the number of items removed from the process map.
108 //----------------------------------------------------------------------
110 //RemoveProcessFromMap (nub_process_t pid)
112 // ProcessMap* process_map = GetProcessMap(false);
115 // return process_map->erase(pid);
120 //----------------------------------------------------------------------
121 // Get the shared pointer for PID from the existing process map.
123 // Returns true if we successfully find a shared pointer to a
124 // MachProcess object.
125 //----------------------------------------------------------------------
127 GetProcessSP (nub_process_t pid, MachProcessSP& procSP)
129 ProcessMap* process_map = GetProcessMap(false);
130 if (process_map != NULL)
132 ProcessMapIter pos = process_map->find(pid);
133 if (pos != process_map->end())
135 procSP = pos->second;
145 kqueue_thread (void *arg)
147 int kq_id = (int) (intptr_t) arg;
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)
156 thread_param.sched_priority = 47;
157 pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
162 struct kevent death_event;
165 int n_events = kevent (kq_id, NULL, 0, &death_event, 1, NULL);
172 DNBLogError ("kqueue failed with error: (%d): %s", errno, strerror(errno));
176 else if (death_event.flags & EV_ERROR)
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 );
188 const pid_t pid = (pid_t)death_event.ident;
189 const pid_t child_pid = waitpid (pid, &status, 0);
195 if (WIFSTOPPED(status))
197 signal = WSTOPSIG(status);
198 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> STOPPED (signal = %i)", child_pid, signal);
200 else if (WIFEXITED(status))
202 exit_status = WEXITSTATUS(status);
204 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> EXITED (status = %i)", child_pid, exit_status);
206 else if (WIFSIGNALED(status))
208 signal = WTERMSIG(status);
209 if (child_pid == abs(pid))
211 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED and EXITED (signal = %i)", child_pid, signal);
213 ::snprintf (exit_info, sizeof(exit_info), "Terminated due to signal %i", signal);
214 DNBProcessSetExitInfo (child_pid, exit_info);
216 exit_status = INT8_MAX;
220 DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED (signal = %i)", child_pid, signal);
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");
233 DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): setting exit status for pid = %i to %i", child_pid, exit_status);
234 DNBProcessSetExitStatus (child_pid, status);
242 spawn_kqueue_thread (pid_t pid)
250 DNBLogError ("Could not get kqueue for pid = %i.", pid);
254 struct kevent reg_event;
256 EV_SET(®_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, ®_event, 1, NULL, 0, NULL);
261 DNBLogError ("Failed to register kqueue NOTE_EXIT event for pid %i, error: %d.", pid, result);
265 int ret = ::pthread_create (&thread, NULL, kqueue_thread, (void *)(intptr_t)kq_id);
267 // pthread_create returns 0 if successful
270 ::pthread_detach (thread);
275 #endif // #if USE_KQUEUE
278 waitpid_thread (void *arg)
280 const pid_t pid = (pid_t)(intptr_t)arg;
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)
290 thread_param.sched_priority = 47;
291 pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
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);
309 if (WIFSTOPPED(status))
313 else// if (WIFEXITED(status) || WIFSIGNALED(status))
315 DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): setting exit status for pid = %i to %i", child_pid, status);
316 DNBProcessSetExitStatus (child_pid, status);
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);
329 spawn_waitpid_thread (pid_t pid)
332 bool success = spawn_kqueue_thread (pid);
338 int ret = ::pthread_create (&thread, NULL, waitpid_thread, (void *)(intptr_t)pid);
339 // pthread_create returns 0 if successful
342 ::pthread_detach (thread);
349 DNBProcessLaunch (const char *path,
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,
357 nub_launch_flavor_t launch_flavor,
359 const char *event_data,
363 DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, working_dir=%s, stdin=%s, stdout=%s, stderr=%s, no-stdio=%i, launch_flavor = %u, disable_aslr = %d, err = %p, err_len = %llu) called...",
378 if (err_str && err_len > 0)
380 struct stat path_stat;
381 if (::stat(path, &path_stat) == -1)
383 char stat_error[256];
384 ::strerror_r (errno, stat_error, sizeof(stat_error));
385 snprintf(err_str, err_len, "%s (%s)", stat_error, path);
386 return INVALID_NUB_PROCESS;
389 MachProcessSP processSP (new MachProcess);
393 pid_t pid = processSP->LaunchForDebug (path,
408 if (launch_err.Fail())
410 const char *launch_err_str = launch_err.AsString();
413 strncpy(err_str, launch_err_str, err_len-1);
414 err_str[err_len-1] = '\0'; // Make sure the error string is terminated
419 DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid);
421 if (pid != INVALID_NUB_PROCESS)
423 // Spawn a thread to reap our child inferior process...
424 spawn_waitpid_thread (pid);
426 if (processSP->Task().TaskPortForProcessID (launch_err) == TASK_NULL)
428 // We failed to get the task for our process ID which is bad.
429 // Kill our process otherwise it will be stopped at the entry
430 // point and get reparented to someone else and never go away.
431 DNBLog ("Could not get task port for process, sending SIGKILL and exiting.");
434 if (err_str && err_len > 0)
436 if (launch_err.AsString())
438 ::snprintf (err_str, err_len, "failed to get the task for process %i (%s)", pid, launch_err.AsString());
442 ::snprintf (err_str, err_len, "failed to get the task for process %i", pid);
448 bool res = AddProcessToMap(pid, processSP);
449 UNUSED_IF_ASSERT_DISABLED(res);
450 assert(res && "Couldn't add process to map!");
455 return INVALID_NUB_PROCESS;
458 // If there is one process with a given name, return the pid for that process.
460 DNBProcessGetPIDByName (const char *name)
462 std::vector<struct kinfo_proc> matching_proc_infos;
463 size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
464 if (num_matching_proc_infos == 1)
466 return matching_proc_infos[0].kp_proc.p_pid;
468 return INVALID_NUB_PROCESS;
472 DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len)
474 if (err_str && err_len > 0)
476 std::vector<struct kinfo_proc> matching_proc_infos;
477 size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos);
478 if (num_matching_proc_infos == 0)
480 DNBLogError ("error: no processes match '%s'\n", name);
481 return INVALID_NUB_PROCESS;
483 else if (num_matching_proc_infos > 1)
485 DNBLogError ("error: %llu processes match '%s':\n", (uint64_t)num_matching_proc_infos, name);
487 for (i=0; i<num_matching_proc_infos; ++i)
488 DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm);
489 return INVALID_NUB_PROCESS;
492 return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len);
496 DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_str, size_t err_len)
498 if (err_str && err_len > 0)
501 pid_t pid = INVALID_NUB_PROCESS;
502 MachProcessSP processSP(new MachProcess);
505 DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", attach_pid);
506 pid = processSP->AttachForDebug (attach_pid, err_str, err_len);
508 if (pid != INVALID_NUB_PROCESS)
510 bool res = AddProcessToMap(pid, processSP);
511 UNUSED_IF_ASSERT_DISABLED(res);
512 assert(res && "Couldn't add process to map!");
513 spawn_waitpid_thread(pid);
517 while (pid != INVALID_NUB_PROCESS)
519 // Wait for process to start up and hit entry point
520 DNBLogThreadedIf (LOG_PROCESS,
521 "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...",
524 nub_event_t set_events = DNBProcessWaitForEvents (pid,
525 eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged,
529 DNBLogThreadedIf (LOG_PROCESS,
530 "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x",
537 if (err_str && err_len > 0)
538 snprintf(err_str, err_len, "operation timed out");
539 pid = INVALID_NUB_PROCESS;
543 if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged))
545 nub_state_t pid_state = DNBProcessGetState (pid);
546 DNBLogThreadedIf (LOG_PROCESS, "%s process %4.4x state changed (eEventProcessStateChanged): %s",
547 __FUNCTION__, pid, DNBStateAsString(pid_state));
554 case eStateAttaching:
555 case eStateLaunching:
556 case eStateSuspended:
561 // Still waiting to stop at entry point...
570 if (err_str && err_len > 0)
571 snprintf(err_str, err_len, "process exited");
572 return INVALID_NUB_PROCESS;
576 DNBProcessResetEvents(pid, set_events);
580 return INVALID_NUB_PROCESS;
584 GetAllInfos (std::vector<struct kinfo_proc>& proc_infos)
587 int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
588 u_int namelen = sizeof(name)/sizeof(int);
591 // Try to find out how many processes are around so we can
592 // size the buffer appropriately. sysctl's man page specifically suggests
593 // this approach, and says it returns a bit larger size than needed to
594 // handle any new processes created between then and now.
596 err = ::sysctl (name, namelen, NULL, &size, NULL, 0);
598 if ((err < 0) && (err != ENOMEM))
601 perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)");
606 // Increase the size of the buffer by a few processes in case more have
608 proc_infos.resize (size / sizeof(struct kinfo_proc));
609 size = proc_infos.size() * sizeof(struct kinfo_proc); // Make sure we don't exceed our resize...
610 err = ::sysctl (name, namelen, &proc_infos[0], &size, NULL, 0);
617 // Trim down our array to fit what we actually got back
618 proc_infos.resize(size / sizeof(struct kinfo_proc));
619 return proc_infos.size();
623 GetAllInfosMatchingName(const char *full_process_name, std::vector<struct kinfo_proc>& matching_proc_infos)
626 matching_proc_infos.clear();
627 if (full_process_name && full_process_name[0])
629 // We only get the process name, not the full path, from the proc_info. So just take the
630 // base name of the process name...
631 const char *process_name;
632 process_name = strrchr (full_process_name, '/');
633 if (process_name == NULL)
634 process_name = full_process_name;
638 const size_t process_name_len = strlen(process_name);
639 std::vector<struct kinfo_proc> proc_infos;
640 const size_t num_proc_infos = GetAllInfos(proc_infos);
641 if (num_proc_infos > 0)
644 for (i=0; i<num_proc_infos; i++)
646 // Skip zombie processes and processes with unset status
647 if (proc_infos[i].kp_proc.p_stat == 0 || proc_infos[i].kp_proc.p_stat == SZOMB)
650 // Check for process by name. We only check the first MAXCOMLEN
651 // chars as that is all that kp_proc.p_comm holds.
653 if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm, MAXCOMLEN) == 0)
655 if (process_name_len > MAXCOMLEN)
657 // We found a matching process name whose first MAXCOMLEN
658 // characters match, but there is more to the name than
659 // this. We need to get the full process name. Use proc_pidpath, which will get
660 // us the full path to the executed process.
662 char proc_path_buf[PATH_MAX];
664 int return_val = proc_pidpath (proc_infos[i].kp_proc.p_pid, proc_path_buf, PATH_MAX);
667 // Okay, now search backwards from that to see if there is a
668 // slash in the name. Note, even though we got all the args we don't care
669 // because the list data is just a bunch of concatenated null terminated strings
670 // so strrchr will start from the end of argv0.
672 const char *argv_basename = strrchr(proc_path_buf, '/');
680 // We didn't find a directory delimiter in the process argv[0], just use what was in there
681 argv_basename = proc_path_buf;
686 if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0)
688 matching_proc_infos.push_back(proc_infos[i]);
695 // We found a matching process, add it to our list
696 matching_proc_infos.push_back(proc_infos[i]);
702 // return the newly added matches.
703 return matching_proc_infos.size();
707 DNBProcessAttachWait (const char *waitfor_process_name,
708 nub_launch_flavor_t launch_flavor,
709 bool ignore_existing,
710 struct timespec *timeout_abstime,
711 useconds_t waitfor_interval,
714 DNBShouldCancelCallback should_cancel_callback,
717 DNBError prepare_error;
718 std::vector<struct kinfo_proc> exclude_proc_infos;
719 size_t num_exclude_proc_infos;
721 // If the PrepareForAttach returns a valid token, use MachProcess to check
722 // for the process, otherwise scan the process table.
724 const void *attach_token = MachProcess::PrepareForAttach (waitfor_process_name, launch_flavor, true, prepare_error);
726 if (prepare_error.Fail())
728 DNBLogError ("Error in PrepareForAttach: %s", prepare_error.AsString());
729 return INVALID_NUB_PROCESS;
732 if (attach_token == NULL)
735 num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos);
737 num_exclude_proc_infos = 0;
740 DNBLogThreadedIf (LOG_PROCESS, "Waiting for '%s' to appear...\n", waitfor_process_name);
742 // Loop and try to find the process by name
743 nub_process_t waitfor_pid = INVALID_NUB_PROCESS;
745 while (waitfor_pid == INVALID_NUB_PROCESS)
747 if (attach_token != NULL)
750 pid = MachProcess::CheckForProcess(attach_token, launch_flavor);
751 if (pid != INVALID_NUB_PROCESS)
760 // Get the current process list, and check for matches that
761 // aren't in our original list. If anyone wants to attach
762 // to an existing process by name, they should do it with
763 // --attach=PROCNAME. Else we will wait for the first matching
764 // process that wasn't in our exclusion list.
765 std::vector<struct kinfo_proc> proc_infos;
766 const size_t num_proc_infos = GetAllInfosMatchingName (waitfor_process_name, proc_infos);
767 for (size_t i=0; i<num_proc_infos; i++)
769 nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid;
770 for (size_t j=0; j<num_exclude_proc_infos; j++)
772 if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid)
774 // This process was in our exclusion list, don't use it.
775 curr_pid = INVALID_NUB_PROCESS;
780 // If we didn't find CURR_PID in our exclusion list, then use it.
781 if (curr_pid != INVALID_NUB_PROCESS)
783 // We found our process!
784 waitfor_pid = curr_pid;
790 // If we haven't found our process yet, check for a timeout
791 // and then sleep for a bit until we poll again.
792 if (waitfor_pid == INVALID_NUB_PROCESS)
794 if (timeout_abstime != NULL)
796 // Check to see if we have a waitfor-duration option that
798 if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime))
800 if (err_str && err_len > 0)
801 snprintf(err_str, err_len, "operation timed out");
802 DNBLogError ("error: waiting for process '%s' timed out.\n", waitfor_process_name);
803 return INVALID_NUB_PROCESS;
807 // Call the should cancel callback as well...
809 if (should_cancel_callback != NULL
810 && should_cancel_callback (callback_data))
812 DNBLogThreadedIf (LOG_PROCESS, "DNBProcessAttachWait cancelled by should_cancel callback.");
813 waitfor_pid = INVALID_NUB_PROCESS;
817 ::usleep (waitfor_interval); // Sleep for WAITFOR_INTERVAL, then poll again
821 if (waitfor_pid != INVALID_NUB_PROCESS)
823 DNBLogThreadedIf (LOG_PROCESS, "Attaching to %s with pid %i...\n", waitfor_process_name, waitfor_pid);
824 waitfor_pid = DNBProcessAttach (waitfor_pid, timeout_abstime, err_str, err_len);
827 bool success = waitfor_pid != INVALID_NUB_PROCESS;
828 MachProcess::CleanupAfterAttach (attach_token, launch_flavor, success, prepare_error);
834 DNBProcessDetach (nub_process_t pid)
836 MachProcessSP procSP;
837 if (GetProcessSP (pid, procSP))
839 const bool remove = true;
840 DNBLogThreaded("Disabling breakpoints and watchpoints, and detaching from %d.", pid);
841 procSP->DisableAllBreakpoints(remove);
842 procSP->DisableAllWatchpoints (remove);
843 return procSP->Detach();
849 DNBProcessKill (nub_process_t pid)
851 MachProcessSP procSP;
852 if (GetProcessSP (pid, procSP))
854 return procSP->Kill ();
860 DNBProcessSignal (nub_process_t pid, int signal)
862 MachProcessSP procSP;
863 if (GetProcessSP (pid, procSP))
865 return procSP->Signal (signal);
872 DNBProcessInterrupt(nub_process_t pid)
874 MachProcessSP procSP;
875 if (GetProcessSP (pid, procSP))
876 return procSP->Interrupt();
881 DNBProcessSendEvent (nub_process_t pid, const char *event)
883 MachProcessSP procSP;
884 if (GetProcessSP (pid, procSP))
886 // FIXME: Do something with the error...
888 return procSP->SendEvent (event, send_error);
895 DNBProcessIsAlive (nub_process_t pid)
897 MachProcessSP procSP;
898 if (GetProcessSP (pid, procSP))
900 return MachTask::IsValid (procSP->Task().TaskPort());
902 return eStateInvalid;
905 //----------------------------------------------------------------------
906 // Process and Thread state information
907 //----------------------------------------------------------------------
909 DNBProcessGetState (nub_process_t pid)
911 MachProcessSP procSP;
912 if (GetProcessSP (pid, procSP))
914 return procSP->GetState();
916 return eStateInvalid;
919 //----------------------------------------------------------------------
920 // Process and Thread state information
921 //----------------------------------------------------------------------
923 DNBProcessGetExitStatus (nub_process_t pid, int* status)
925 MachProcessSP procSP;
926 if (GetProcessSP (pid, procSP))
928 return procSP->GetExitStatus(status);
934 DNBProcessSetExitStatus (nub_process_t pid, int status)
936 MachProcessSP procSP;
937 if (GetProcessSP (pid, procSP))
939 procSP->SetExitStatus(status);
946 DNBProcessGetExitInfo (nub_process_t pid)
948 MachProcessSP procSP;
949 if (GetProcessSP (pid, procSP))
951 return procSP->GetExitInfo();
957 DNBProcessSetExitInfo (nub_process_t pid, const char *info)
959 MachProcessSP procSP;
960 if (GetProcessSP (pid, procSP))
962 procSP->SetExitInfo(info);
969 DNBThreadGetName (nub_process_t pid, nub_thread_t tid)
971 MachProcessSP procSP;
972 if (GetProcessSP (pid, procSP))
973 return procSP->ThreadGetName(tid);
979 DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info)
981 MachProcessSP procSP;
982 if (GetProcessSP (pid, procSP))
983 return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info);
988 DNBThreadGetState (nub_process_t pid, nub_thread_t tid)
990 MachProcessSP procSP;
991 if (GetProcessSP (pid, procSP))
993 return procSP->ThreadGetState(tid);
995 return eStateInvalid;
999 DNBStateAsString(nub_state_t state)
1003 case eStateInvalid: return "Invalid";
1004 case eStateUnloaded: return "Unloaded";
1005 case eStateAttaching: return "Attaching";
1006 case eStateLaunching: return "Launching";
1007 case eStateStopped: return "Stopped";
1008 case eStateRunning: return "Running";
1009 case eStateStepping: return "Stepping";
1010 case eStateCrashed: return "Crashed";
1011 case eStateDetached: return "Detached";
1012 case eStateExited: return "Exited";
1013 case eStateSuspended: return "Suspended";
1015 return "nub_state_t ???";
1018 Genealogy::ThreadActivitySP
1019 DNBGetGenealogyInfoForThread (nub_process_t pid, nub_thread_t tid, bool &timed_out)
1021 Genealogy::ThreadActivitySP thread_activity_sp;
1022 MachProcessSP procSP;
1023 if (GetProcessSP (pid, procSP))
1024 thread_activity_sp = procSP->GetGenealogyInfoForThread (tid, timed_out);
1025 return thread_activity_sp;
1028 Genealogy::ProcessExecutableInfoSP
1029 DNBGetGenealogyImageInfo (nub_process_t pid, size_t idx)
1031 Genealogy::ProcessExecutableInfoSP image_info_sp;
1032 MachProcessSP procSP;
1033 if (GetProcessSP (pid, procSP))
1035 image_info_sp = procSP->GetGenealogyImageInfo (idx);
1037 return image_info_sp;
1041 DNBGetRequestedQoSForThread (nub_process_t pid, nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index)
1043 MachProcessSP procSP;
1044 if (GetProcessSP (pid, procSP))
1046 return procSP->GetRequestedQoS (tid, tsd, dti_qos_class_index);
1048 return ThreadInfo::QoS();
1052 DNBGetPThreadT (nub_process_t pid, nub_thread_t tid)
1054 MachProcessSP procSP;
1055 if (GetProcessSP (pid, procSP))
1057 return procSP->GetPThreadT (tid);
1059 return INVALID_NUB_ADDRESS;
1063 DNBGetDispatchQueueT (nub_process_t pid, nub_thread_t tid)
1065 MachProcessSP procSP;
1066 if (GetProcessSP (pid, procSP))
1068 return procSP->GetDispatchQueueT (tid);
1070 return INVALID_NUB_ADDRESS;
1074 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)
1076 MachProcessSP procSP;
1077 if (GetProcessSP (pid, procSP))
1079 return procSP->GetTSDAddressForThread (tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
1081 return INVALID_NUB_ADDRESS;
1084 JSONGenerator::ObjectSP
1085 DNBGetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count)
1087 MachProcessSP procSP;
1088 if (GetProcessSP (pid, procSP))
1090 return procSP->GetLoadedDynamicLibrariesInfos (pid, image_list_address, image_count);
1092 return JSONGenerator::ObjectSP();
1098 DNBProcessGetExecutablePath (nub_process_t pid)
1100 MachProcessSP procSP;
1101 if (GetProcessSP (pid, procSP))
1103 return procSP->Path();
1109 DNBProcessGetArgumentCount (nub_process_t pid)
1111 MachProcessSP procSP;
1112 if (GetProcessSP (pid, procSP))
1114 return procSP->ArgumentCount();
1120 DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx)
1122 MachProcessSP procSP;
1123 if (GetProcessSP (pid, procSP))
1125 return procSP->ArgumentAtIndex (idx);
1131 //----------------------------------------------------------------------
1132 // Execution control
1133 //----------------------------------------------------------------------
1135 DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions)
1137 DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1138 MachProcessSP procSP;
1139 if (GetProcessSP (pid, procSP))
1141 DNBThreadResumeActions thread_actions (actions, num_actions);
1143 // Below we add a default thread plan just in case one wasn't
1144 // provided so all threads always know what they were supposed to do
1145 if (thread_actions.IsEmpty())
1147 // No thread plans were given, so the default it to run all threads
1148 thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0);
1152 // Some thread plans were given which means anything that wasn't
1153 // specified should remain stopped.
1154 thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
1156 return procSP->Resume (thread_actions);
1162 DNBProcessHalt (nub_process_t pid)
1164 DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid);
1165 MachProcessSP procSP;
1166 if (GetProcessSP (pid, procSP))
1167 return procSP->Signal (SIGSTOP);
1172 //DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step)
1174 // DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", __FUNCTION__, pid, tid, (uint32_t)step);
1175 // MachProcessSP procSP;
1176 // if (GetProcessSP (pid, procSP))
1178 // return procSP->Resume(tid, step, 0);
1184 //DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t step, int signal)
1186 // DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal);
1187 // MachProcessSP procSP;
1188 // if (GetProcessSP (pid, procSP))
1190 // return procSP->Resume(tid, step, signal);
1196 DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout)
1198 nub_event_t result = 0;
1199 MachProcessSP procSP;
1200 if (GetProcessSP (pid, procSP))
1203 result = procSP->Events().WaitForSetEvents(event_mask, timeout);
1205 result = procSP->Events().WaitForEventsToReset(event_mask, timeout);
1211 DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask)
1213 MachProcessSP procSP;
1214 if (GetProcessSP (pid, procSP))
1215 procSP->Events().ResetEvents(event_mask);
1220 DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware)
1222 MachProcessSP procSP;
1223 if (GetProcessSP (pid, procSP))
1224 return procSP->CreateBreakpoint(addr, size, hardware) != NULL;
1229 DNBBreakpointClear (nub_process_t pid, nub_addr_t addr)
1231 MachProcessSP procSP;
1232 if (GetProcessSP (pid, procSP))
1233 return procSP->DisableBreakpoint(addr, true);
1234 return false; // Failed
1238 //----------------------------------------------------------------------
1240 //----------------------------------------------------------------------
1242 DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware)
1244 MachProcessSP procSP;
1245 if (GetProcessSP (pid, procSP))
1246 return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL;
1251 DNBWatchpointClear (nub_process_t pid, nub_addr_t addr)
1253 MachProcessSP procSP;
1254 if (GetProcessSP (pid, procSP))
1255 return procSP->DisableWatchpoint(addr, true);
1256 return false; // Failed
1259 //----------------------------------------------------------------------
1260 // Return the number of supported hardware watchpoints.
1261 //----------------------------------------------------------------------
1263 DNBWatchpointGetNumSupportedHWP (nub_process_t pid)
1265 MachProcessSP procSP;
1266 if (GetProcessSP (pid, procSP))
1267 return procSP->GetNumSupportedHardwareWatchpoints();
1271 //----------------------------------------------------------------------
1272 // Read memory in the address space of process PID. This call will take
1273 // care of setting and restoring permissions and breaking up the memory
1274 // read into multiple chunks as required.
1276 // RETURNS: number of bytes actually read
1277 //----------------------------------------------------------------------
1279 DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf)
1281 MachProcessSP procSP;
1282 if (GetProcessSP (pid, procSP))
1283 return procSP->ReadMemory(addr, size, buf);
1288 DNBProcessMemoryReadInteger (nub_process_t pid, nub_addr_t addr, nub_size_t integer_size, uint64_t fail_value)
1298 if (integer_size <= sizeof(uint64_t))
1301 if (DNBProcessMemoryRead(pid, addr, integer_size, &ints) == integer_size)
1303 switch (integer_size)
1305 case 1: return ints.u8;
1306 case 2: return ints.u16;
1307 case 3: return ints.u32 & 0xffffffu;
1308 case 4: return ints.u32;
1309 case 5: return ints.u32 & 0x000000ffffffffffull;
1310 case 6: return ints.u32 & 0x0000ffffffffffffull;
1311 case 7: return ints.u32 & 0x00ffffffffffffffull;
1312 case 8: return ints.u64;
1321 DNBProcessMemoryReadPointer (nub_process_t pid, nub_addr_t addr)
1323 cpu_type_t cputype = DNBProcessGetCPUType (pid);
1326 const nub_size_t pointer_size = (cputype & CPU_ARCH_ABI64) ? 8 : 4;
1327 return DNBProcessMemoryReadInteger(pid, addr, pointer_size, 0);
1334 DNBProcessMemoryReadCString (nub_process_t pid, nub_addr_t addr)
1338 const nub_size_t max_buffer_cstr_length = sizeof(buffer)-1;
1339 buffer[max_buffer_cstr_length] = '\0';
1340 nub_size_t length = 0;
1341 nub_addr_t curr_addr = addr;
1344 nub_size_t bytes_read = DNBProcessMemoryRead(pid, curr_addr, max_buffer_cstr_length, buffer);
1345 if (bytes_read == 0)
1347 length = strlen(buffer);
1348 cstr.append(buffer, length);
1349 curr_addr += length;
1350 } while (length == max_buffer_cstr_length);
1355 DNBProcessMemoryReadCStringFixed (nub_process_t pid, nub_addr_t addr, nub_size_t fixed_length)
1358 char buffer[fixed_length+1];
1359 buffer[fixed_length] = '\0';
1360 nub_size_t bytes_read = DNBProcessMemoryRead(pid, addr, fixed_length, buffer);
1362 cstr.assign(buffer);
1367 //----------------------------------------------------------------------
1368 // Write memory to the address space of process PID. This call will take
1369 // care of setting and restoring permissions and breaking up the memory
1370 // write into multiple chunks as required.
1372 // RETURNS: number of bytes actually written
1373 //----------------------------------------------------------------------
1375 DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf)
1377 MachProcessSP procSP;
1378 if (GetProcessSP (pid, procSP))
1379 return procSP->WriteMemory(addr, size, buf);
1384 DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions)
1386 MachProcessSP procSP;
1387 if (GetProcessSP (pid, procSP))
1388 return procSP->Task().AllocateMemory (size, permissions);
1393 DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr)
1395 MachProcessSP procSP;
1396 if (GetProcessSP (pid, procSP))
1397 return procSP->Task().DeallocateMemory (addr);
1401 //----------------------------------------------------------------------
1402 // Find attributes of the memory region that contains ADDR for process PID,
1403 // if possible, and return a string describing those attributes.
1405 // Returns 1 if we could find attributes for this region and OUTBUF can
1406 // be sent to the remote debugger.
1408 // Returns 0 if we couldn't find the attributes for a region of memory at
1409 // that address and OUTBUF should not be sent.
1411 // Returns -1 if this platform cannot look up information about memory regions
1412 // or if we do not yet have a valid launched process.
1414 //----------------------------------------------------------------------
1416 DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info)
1418 MachProcessSP procSP;
1419 if (GetProcessSP (pid, procSP))
1420 return procSP->Task().GetMemoryRegionInfo (addr, region_info);
1426 DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType)
1428 MachProcessSP procSP;
1429 if (GetProcessSP (pid, procSP))
1430 return procSP->Task().GetProfileData(scanType);
1432 return std::string("");
1436 DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type)
1438 MachProcessSP procSP;
1439 if (GetProcessSP (pid, procSP))
1441 procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type);
1448 //----------------------------------------------------------------------
1449 // Get the number of threads for the specified process.
1450 //----------------------------------------------------------------------
1452 DNBProcessGetNumThreads (nub_process_t pid)
1454 MachProcessSP procSP;
1455 if (GetProcessSP (pid, procSP))
1456 return procSP->GetNumThreads();
1460 //----------------------------------------------------------------------
1461 // Get the thread ID of the current thread.
1462 //----------------------------------------------------------------------
1464 DNBProcessGetCurrentThread (nub_process_t pid)
1466 MachProcessSP procSP;
1467 if (GetProcessSP (pid, procSP))
1468 return procSP->GetCurrentThread();
1472 //----------------------------------------------------------------------
1473 // Get the mach port number of the current thread.
1474 //----------------------------------------------------------------------
1476 DNBProcessGetCurrentThreadMachPort (nub_process_t pid)
1478 MachProcessSP procSP;
1479 if (GetProcessSP (pid, procSP))
1480 return procSP->GetCurrentThreadMachPort();
1484 //----------------------------------------------------------------------
1485 // Change the current thread.
1486 //----------------------------------------------------------------------
1488 DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid)
1490 MachProcessSP procSP;
1491 if (GetProcessSP (pid, procSP))
1492 return procSP->SetCurrentThread (tid);
1493 return INVALID_NUB_THREAD;
1497 //----------------------------------------------------------------------
1498 // Dump a string describing a thread's stop reason to the specified file
1500 //----------------------------------------------------------------------
1502 DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, struct DNBThreadStopInfo *stop_info)
1504 MachProcessSP procSP;
1505 if (GetProcessSP (pid, procSP))
1506 return procSP->GetThreadStoppedReason (tid, stop_info);
1510 //----------------------------------------------------------------------
1511 // Return string description for the specified thread.
1513 // RETURNS: NULL if the thread isn't valid, else a NULL terminated C
1514 // string from a static buffer that must be copied prior to subsequent
1516 //----------------------------------------------------------------------
1518 DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid)
1520 MachProcessSP procSP;
1521 if (GetProcessSP (pid, procSP))
1522 return procSP->GetThreadInfo (tid);
1526 //----------------------------------------------------------------------
1527 // Get the thread ID given a thread index.
1528 //----------------------------------------------------------------------
1530 DNBProcessGetThreadAtIndex (nub_process_t pid, size_t thread_idx)
1532 MachProcessSP procSP;
1533 if (GetProcessSP (pid, procSP))
1534 return procSP->GetThreadAtIndex (thread_idx);
1535 return INVALID_NUB_THREAD;
1538 //----------------------------------------------------------------------
1539 // Do whatever is needed to sync the thread's register state with it's kernel values.
1540 //----------------------------------------------------------------------
1542 DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid)
1544 MachProcessSP procSP;
1545 if (GetProcessSP (pid, procSP))
1546 return procSP->SyncThreadState (tid);
1552 DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid)
1554 MachProcessSP procSP;
1556 if (GetProcessSP (pid, procSP))
1557 return procSP->Task().GetDYLDAllImageInfosAddress (err);
1558 return INVALID_NUB_ADDRESS;
1563 DNBProcessSharedLibrariesUpdated(nub_process_t pid)
1565 MachProcessSP procSP;
1566 if (GetProcessSP (pid, procSP))
1568 procSP->SharedLibrariesUpdated ();
1574 //----------------------------------------------------------------------
1575 // Get the current shared library information for a process. Only return
1576 // the shared libraries that have changed since the last shared library
1577 // state changed event if only_changed is non-zero.
1578 //----------------------------------------------------------------------
1580 DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, struct DNBExecutableImageInfo **image_infos)
1582 MachProcessSP procSP;
1583 if (GetProcessSP (pid, procSP))
1584 return procSP->CopyImageInfos (image_infos, only_changed);
1586 // If we have no process, then return NULL for the shared library info
1587 // and zero for shared library count
1588 *image_infos = NULL;
1593 DNBGetRegisterCPUType()
1595 return DNBArchProtocol::GetRegisterCPUType ();
1598 //----------------------------------------------------------------------
1599 // Get the register set information for a specific thread.
1600 //----------------------------------------------------------------------
1601 const DNBRegisterSetInfo *
1602 DNBGetRegisterSetInfo (nub_size_t *num_reg_sets)
1604 return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets);
1608 //----------------------------------------------------------------------
1609 // Read a register value by register set and register index.
1610 //----------------------------------------------------------------------
1612 DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value)
1614 MachProcessSP procSP;
1615 ::bzero (value, sizeof(DNBRegisterValue));
1616 if (GetProcessSP (pid, procSP))
1618 if (tid != INVALID_NUB_THREAD)
1619 return procSP->GetRegisterValue (tid, set, reg, value);
1625 DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value)
1627 if (tid != INVALID_NUB_THREAD)
1629 MachProcessSP procSP;
1630 if (GetProcessSP (pid, procSP))
1631 return procSP->SetRegisterValue (tid, set, reg, value);
1637 DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len)
1639 MachProcessSP procSP;
1640 if (GetProcessSP (pid, procSP))
1642 if (tid != INVALID_NUB_THREAD)
1643 return procSP->GetThreadList().GetRegisterContext (tid, buf, buf_len);
1645 ::bzero (buf, buf_len);
1651 DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len)
1653 MachProcessSP procSP;
1654 if (GetProcessSP (pid, procSP))
1656 if (tid != INVALID_NUB_THREAD)
1657 return procSP->GetThreadList().SetRegisterContext (tid, buf, buf_len);
1663 DNBThreadSaveRegisterState (nub_process_t pid, nub_thread_t tid)
1665 if (tid != INVALID_NUB_THREAD)
1667 MachProcessSP procSP;
1668 if (GetProcessSP (pid, procSP))
1669 return procSP->GetThreadList().SaveRegisterState (tid);
1674 DNBThreadRestoreRegisterState (nub_process_t pid, nub_thread_t tid, uint32_t save_id)
1676 if (tid != INVALID_NUB_THREAD)
1678 MachProcessSP procSP;
1679 if (GetProcessSP (pid, procSP))
1680 return procSP->GetThreadList().RestoreRegisterState (tid, save_id);
1687 //----------------------------------------------------------------------
1688 // Read a register value by name.
1689 //----------------------------------------------------------------------
1691 DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t reg_set, const char *reg_name, DNBRegisterValue *value)
1693 MachProcessSP procSP;
1694 ::bzero (value, sizeof(DNBRegisterValue));
1695 if (GetProcessSP (pid, procSP))
1697 const struct DNBRegisterSetInfo *set_info;
1698 nub_size_t num_reg_sets = 0;
1699 set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1702 uint32_t set = reg_set;
1704 if (set == REGISTER_SET_ALL)
1706 for (set = 1; set < num_reg_sets; ++set)
1708 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1710 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1711 return procSP->GetRegisterValue (tid, set, reg, value);
1717 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1719 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1720 return procSP->GetRegisterValue (tid, set, reg, value);
1729 //----------------------------------------------------------------------
1730 // Read a register set and register number from the register name.
1731 //----------------------------------------------------------------------
1733 DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info)
1735 const struct DNBRegisterSetInfo *set_info;
1736 nub_size_t num_reg_sets = 0;
1737 set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1741 for (set = 1; set < num_reg_sets; ++set)
1743 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1745 if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0)
1747 *info = set_info[set].registers[reg];
1753 for (set = 1; set < num_reg_sets; ++set)
1756 for (reg = 0; reg < set_info[set].num_registers; ++reg)
1758 if (set_info[set].registers[reg].alt == NULL)
1761 if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0)
1763 *info = set_info[set].registers[reg];
1770 ::bzero (info, sizeof(DNBRegisterInfo));
1775 //----------------------------------------------------------------------
1776 // Set the name to address callback function that this nub can use
1777 // for any name to address lookups that are needed.
1778 //----------------------------------------------------------------------
1780 DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton)
1782 MachProcessSP procSP;
1783 if (GetProcessSP (pid, procSP))
1785 procSP->SetNameToAddressCallback (callback, baton);
1792 //----------------------------------------------------------------------
1793 // Set the name to address callback function that this nub can use
1794 // for any name to address lookups that are needed.
1795 //----------------------------------------------------------------------
1797 DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void *baton)
1799 MachProcessSP procSP;
1800 if (GetProcessSP (pid, procSP))
1802 procSP->SetSharedLibraryInfoCallback (callback, baton);
1809 DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib)
1811 MachProcessSP procSP;
1812 if (GetProcessSP (pid, procSP))
1814 return procSP->LookupSymbol (name, shlib);
1816 return INVALID_NUB_ADDRESS;
1821 DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size)
1823 MachProcessSP procSP;
1824 if (GetProcessSP (pid, procSP))
1825 return procSP->GetAvailableSTDOUT (buf, buf_size);
1830 DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size)
1832 MachProcessSP procSP;
1833 if (GetProcessSP (pid, procSP))
1834 return procSP->GetAvailableSTDERR (buf, buf_size);
1839 DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size)
1841 MachProcessSP procSP;
1842 if (GetProcessSP (pid, procSP))
1843 return procSP->GetAsyncProfileData (buf, buf_size);
1848 DNBProcessGetStopCount (nub_process_t pid)
1850 MachProcessSP procSP;
1851 if (GetProcessSP (pid, procSP))
1852 return procSP->StopCount();
1857 DNBProcessGetCPUType (nub_process_t pid)
1859 MachProcessSP procSP;
1860 if (GetProcessSP (pid, procSP))
1861 return procSP->GetCPUType ();
1867 DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size)
1869 if (path == NULL || path[0] == '\0')
1872 char max_path[PATH_MAX];
1874 CFString::GlobPath(path, result);
1879 struct stat path_stat;
1880 if (::stat(path, &path_stat) == 0)
1882 if ((path_stat.st_mode & S_IFMT) == S_IFDIR)
1884 CFBundle bundle (path);
1885 CFReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
1888 if (::CFURLGetFileSystemRepresentation (url.get(), true, (UInt8*)resolved_path, resolved_path_size))
1894 if (realpath(path, max_path))
1896 // Found the path relatively...
1897 ::strncpy(resolved_path, max_path, resolved_path_size);
1898 return strlen(resolved_path) + 1 < resolved_path_size;
1902 // Not a relative path, check the PATH environment variable if the
1903 const char *PATH = getenv("PATH");
1906 const char *curr_path_start = PATH;
1907 const char *curr_path_end;
1908 while (curr_path_start && *curr_path_start)
1910 curr_path_end = strchr(curr_path_start, ':');
1911 if (curr_path_end == NULL)
1913 result.assign(curr_path_start);
1914 curr_path_start = NULL;
1916 else if (curr_path_end > curr_path_start)
1918 size_t len = curr_path_end - curr_path_start;
1919 result.assign(curr_path_start, len);
1920 curr_path_start += len + 1;
1928 if (stat(result.c_str(), &s) == 0)
1930 ::strncpy(resolved_path, result.c_str(), resolved_path_size);
1931 return result.size() + 1 < resolved_path_size;
1940 DNBGetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch)
1942 return MachProcess::GetOSVersionNumbers (major, minor, patch);
1949 DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()");
1950 #if defined (__i386__) || defined (__x86_64__)
1951 DNBArchImplI386::Initialize();
1952 DNBArchImplX86_64::Initialize();
1953 #elif defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
1954 DNBArchMachARM::Initialize();
1955 DNBArchMachARM64::Initialize();
1965 DNBSetArchitecture (const char *arch)
1967 if (arch && arch[0])
1969 if (strcasecmp (arch, "i386") == 0)
1970 return DNBArchProtocol::SetArchitecture (CPU_TYPE_I386);
1971 else if ((strcasecmp (arch, "x86_64") == 0) || (strcasecmp (arch, "x86_64h") == 0))
1972 return DNBArchProtocol::SetArchitecture (CPU_TYPE_X86_64);
1973 else if (strstr (arch, "arm64") == arch || strstr (arch, "armv8") == arch || strstr (arch, "aarch64") == arch)
1974 return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM64);
1975 else if (strstr (arch, "arm") == arch)
1976 return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM);