130fdc8d8SChris Lattner //===-- DNB.cpp -------------------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner // 1030fdc8d8SChris Lattner // Created by Greg Clayton on 3/23/07. 1130fdc8d8SChris Lattner // 1230fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 1330fdc8d8SChris Lattner 1430fdc8d8SChris Lattner #include "DNB.h" 151c73911dSJason Molenda #include <inttypes.h> 1630fdc8d8SChris Lattner #include <signal.h> 1730fdc8d8SChris Lattner #include <stdio.h> 1830fdc8d8SChris Lattner #include <stdlib.h> 1930fdc8d8SChris Lattner #include <sys/resource.h> 2030fdc8d8SChris Lattner #include <sys/stat.h> 2130fdc8d8SChris Lattner #include <sys/types.h> 2230fdc8d8SChris Lattner #include <sys/wait.h> 2330fdc8d8SChris Lattner #include <unistd.h> 2430fdc8d8SChris Lattner #include <sys/sysctl.h> 2530fdc8d8SChris Lattner #include <map> 2630fdc8d8SChris Lattner #include <vector> 27490bccd6SJim Ingham #include <libproc.h> 2830fdc8d8SChris Lattner 2936a216eeSJason Molenda #if defined (__APPLE__) 3036a216eeSJason Molenda #include <pthread.h> 3136a216eeSJason Molenda #include <sched.h> 3236a216eeSJason Molenda #endif 3336a216eeSJason Molenda 34a332978bSJason Molenda #define TRY_KQUEUE 1 35a332978bSJason Molenda 36a332978bSJason Molenda #ifdef TRY_KQUEUE 37a332978bSJason Molenda #include <sys/event.h> 38a332978bSJason Molenda #include <sys/time.h> 39a332978bSJason Molenda #ifdef NOTE_EXIT_DETAIL 40a332978bSJason Molenda #define USE_KQUEUE 41a332978bSJason Molenda #endif 42a332978bSJason Molenda #endif 43a332978bSJason Molenda 4430fdc8d8SChris Lattner #include "MacOSX/MachProcess.h" 4530fdc8d8SChris Lattner #include "MacOSX/MachTask.h" 46705b1809SJason Molenda #include "MacOSX/Genealogy.h" 47705b1809SJason Molenda #include "MacOSX/ThreadInfo.h" 4830fdc8d8SChris Lattner #include "CFString.h" 4930fdc8d8SChris Lattner #include "DNBLog.h" 5030fdc8d8SChris Lattner #include "DNBDataRef.h" 5130fdc8d8SChris Lattner #include "DNBThreadResumeActions.h" 5230fdc8d8SChris Lattner #include "DNBTimer.h" 5348baf7a7SGreg Clayton #include "CFBundle.h" 5448baf7a7SGreg Clayton 5530fdc8d8SChris Lattner 567b0992d9SGreg Clayton typedef std::shared_ptr<MachProcess> MachProcessSP; 5730fdc8d8SChris Lattner typedef std::map<nub_process_t, MachProcessSP> ProcessMap; 5830fdc8d8SChris Lattner typedef ProcessMap::iterator ProcessMapIter; 5930fdc8d8SChris Lattner typedef ProcessMap::const_iterator ProcessMapConstIter; 6030fdc8d8SChris Lattner 619eb4e038SGreg Clayton size_t GetAllInfos (std::vector<struct kinfo_proc>& proc_infos); 6230fdc8d8SChris Lattner static size_t GetAllInfosMatchingName (const char *process_name, std::vector<struct kinfo_proc>& matching_proc_infos); 6330fdc8d8SChris Lattner 6430fdc8d8SChris Lattner //---------------------------------------------------------------------- 6530fdc8d8SChris Lattner // A Thread safe singleton to get a process map pointer. 6630fdc8d8SChris Lattner // 6730fdc8d8SChris Lattner // Returns a pointer to the existing process map, or a pointer to a 6830fdc8d8SChris Lattner // newly created process map if CAN_CREATE is non-zero. 6930fdc8d8SChris Lattner //---------------------------------------------------------------------- 7030fdc8d8SChris Lattner static ProcessMap* 7130fdc8d8SChris Lattner GetProcessMap(bool can_create) 7230fdc8d8SChris Lattner { 7330fdc8d8SChris Lattner static ProcessMap* g_process_map_ptr = NULL; 7430fdc8d8SChris Lattner 7530fdc8d8SChris Lattner if (can_create && g_process_map_ptr == NULL) 7630fdc8d8SChris Lattner { 7730fdc8d8SChris Lattner static pthread_mutex_t g_process_map_mutex = PTHREAD_MUTEX_INITIALIZER; 7830fdc8d8SChris Lattner PTHREAD_MUTEX_LOCKER (locker, &g_process_map_mutex); 7930fdc8d8SChris Lattner if (g_process_map_ptr == NULL) 8030fdc8d8SChris Lattner g_process_map_ptr = new ProcessMap; 8130fdc8d8SChris Lattner } 8230fdc8d8SChris Lattner return g_process_map_ptr; 8330fdc8d8SChris Lattner } 8430fdc8d8SChris Lattner 8530fdc8d8SChris Lattner //---------------------------------------------------------------------- 8630fdc8d8SChris Lattner // Add PID to the shared process pointer map. 8730fdc8d8SChris Lattner // 8830fdc8d8SChris Lattner // Return non-zero value if we succeed in adding the process to the map. 8930fdc8d8SChris Lattner // The only time this should fail is if we run out of memory and can't 9030fdc8d8SChris Lattner // allocate a ProcessMap. 9130fdc8d8SChris Lattner //---------------------------------------------------------------------- 9230fdc8d8SChris Lattner static nub_bool_t 9330fdc8d8SChris Lattner AddProcessToMap (nub_process_t pid, MachProcessSP& procSP) 9430fdc8d8SChris Lattner { 9530fdc8d8SChris Lattner ProcessMap* process_map = GetProcessMap(true); 9630fdc8d8SChris Lattner if (process_map) 9730fdc8d8SChris Lattner { 9830fdc8d8SChris Lattner process_map->insert(std::make_pair(pid, procSP)); 9930fdc8d8SChris Lattner return true; 10030fdc8d8SChris Lattner } 10130fdc8d8SChris Lattner return false; 10230fdc8d8SChris Lattner } 10330fdc8d8SChris Lattner 10430fdc8d8SChris Lattner //---------------------------------------------------------------------- 10530fdc8d8SChris Lattner // Remove the shared pointer for PID from the process map. 10630fdc8d8SChris Lattner // 10730fdc8d8SChris Lattner // Returns the number of items removed from the process map. 10830fdc8d8SChris Lattner //---------------------------------------------------------------------- 109ee2ed525SGreg Clayton //static size_t 110ee2ed525SGreg Clayton //RemoveProcessFromMap (nub_process_t pid) 111ee2ed525SGreg Clayton //{ 112ee2ed525SGreg Clayton // ProcessMap* process_map = GetProcessMap(false); 113ee2ed525SGreg Clayton // if (process_map) 114ee2ed525SGreg Clayton // { 115ee2ed525SGreg Clayton // return process_map->erase(pid); 116ee2ed525SGreg Clayton // } 117ee2ed525SGreg Clayton // return 0; 118ee2ed525SGreg Clayton //} 11930fdc8d8SChris Lattner 12030fdc8d8SChris Lattner //---------------------------------------------------------------------- 12130fdc8d8SChris Lattner // Get the shared pointer for PID from the existing process map. 12230fdc8d8SChris Lattner // 12330fdc8d8SChris Lattner // Returns true if we successfully find a shared pointer to a 12430fdc8d8SChris Lattner // MachProcess object. 12530fdc8d8SChris Lattner //---------------------------------------------------------------------- 12630fdc8d8SChris Lattner static nub_bool_t 12730fdc8d8SChris Lattner GetProcessSP (nub_process_t pid, MachProcessSP& procSP) 12830fdc8d8SChris Lattner { 12930fdc8d8SChris Lattner ProcessMap* process_map = GetProcessMap(false); 13030fdc8d8SChris Lattner if (process_map != NULL) 13130fdc8d8SChris Lattner { 13230fdc8d8SChris Lattner ProcessMapIter pos = process_map->find(pid); 13330fdc8d8SChris Lattner if (pos != process_map->end()) 13430fdc8d8SChris Lattner { 13530fdc8d8SChris Lattner procSP = pos->second; 13630fdc8d8SChris Lattner return true; 13730fdc8d8SChris Lattner } 13830fdc8d8SChris Lattner } 13930fdc8d8SChris Lattner procSP.reset(); 14030fdc8d8SChris Lattner return false; 14130fdc8d8SChris Lattner } 14230fdc8d8SChris Lattner 143a332978bSJason Molenda #ifdef USE_KQUEUE 144a332978bSJason Molenda void * 145a332978bSJason Molenda kqueue_thread (void *arg) 146a332978bSJason Molenda { 147a332978bSJason Molenda int kq_id = (int) (intptr_t) arg; 148a332978bSJason Molenda 14936a216eeSJason Molenda #if defined (__APPLE__) 15036a216eeSJason Molenda pthread_setname_np ("kqueue thread"); 15136a216eeSJason Molenda #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) 15236a216eeSJason Molenda struct sched_param thread_param; 15336a216eeSJason Molenda int thread_sched_policy; 15436a216eeSJason Molenda if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0) 15536a216eeSJason Molenda { 15636a216eeSJason Molenda thread_param.sched_priority = 47; 15736a216eeSJason Molenda pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); 15836a216eeSJason Molenda } 15936a216eeSJason Molenda #endif 16036a216eeSJason Molenda #endif 16136a216eeSJason Molenda 162a332978bSJason Molenda struct kevent death_event; 163a332978bSJason Molenda while (1) 164a332978bSJason Molenda { 165a332978bSJason Molenda int n_events = kevent (kq_id, NULL, 0, &death_event, 1, NULL); 166a332978bSJason Molenda if (n_events == -1) 167a332978bSJason Molenda { 168a332978bSJason Molenda if (errno == EINTR) 169a332978bSJason Molenda continue; 170a332978bSJason Molenda else 171a332978bSJason Molenda { 172a332978bSJason Molenda DNBLogError ("kqueue failed with error: (%d): %s", errno, strerror(errno)); 173a332978bSJason Molenda return NULL; 174a332978bSJason Molenda } 175a332978bSJason Molenda } 176a332978bSJason Molenda else if (death_event.flags & EV_ERROR) 177a332978bSJason Molenda { 178ee2ed525SGreg Clayton int error_no = static_cast<int>(death_event.data); 179ee2ed525SGreg Clayton const char *error_str = strerror(error_no); 180a332978bSJason Molenda if (error_str == NULL) 181a332978bSJason Molenda error_str = "Unknown error"; 182a332978bSJason Molenda DNBLogError ("Failed to initialize kqueue event: (%d): %s", error_no, error_str ); 183a332978bSJason Molenda return NULL; 184a332978bSJason Molenda } 185a332978bSJason Molenda else 186a332978bSJason Molenda { 187a332978bSJason Molenda int status; 188040c560fSGreg Clayton const pid_t pid = (pid_t)death_event.ident; 189040c560fSGreg Clayton const pid_t child_pid = waitpid (pid, &status, 0); 190040c560fSGreg Clayton 191040c560fSGreg Clayton 192040c560fSGreg Clayton bool exited = false; 193040c560fSGreg Clayton int signal = 0; 194040c560fSGreg Clayton int exit_status = 0; 195040c560fSGreg Clayton if (WIFSTOPPED(status)) 196040c560fSGreg Clayton { 197040c560fSGreg Clayton signal = WSTOPSIG(status); 198040c560fSGreg Clayton DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> STOPPED (signal = %i)", child_pid, signal); 199040c560fSGreg Clayton } 200040c560fSGreg Clayton else if (WIFEXITED(status)) 201040c560fSGreg Clayton { 202040c560fSGreg Clayton exit_status = WEXITSTATUS(status); 203040c560fSGreg Clayton exited = true; 204040c560fSGreg Clayton DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> EXITED (status = %i)", child_pid, exit_status); 205040c560fSGreg Clayton } 206040c560fSGreg Clayton else if (WIFSIGNALED(status)) 207040c560fSGreg Clayton { 208040c560fSGreg Clayton signal = WTERMSIG(status); 209040c560fSGreg Clayton if (child_pid == abs(pid)) 210040c560fSGreg Clayton { 211040c560fSGreg Clayton DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED and EXITED (signal = %i)", child_pid, signal); 212040c560fSGreg Clayton char exit_info[64]; 213040c560fSGreg Clayton ::snprintf (exit_info, sizeof(exit_info), "Terminated due to signal %i", signal); 214040c560fSGreg Clayton DNBProcessSetExitInfo (child_pid, exit_info); 215040c560fSGreg Clayton exited = true; 216040c560fSGreg Clayton exit_status = INT8_MAX; 217040c560fSGreg Clayton } 218040c560fSGreg Clayton else 219040c560fSGreg Clayton { 220040c560fSGreg Clayton DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED (signal = %i)", child_pid, signal); 221040c560fSGreg Clayton } 222040c560fSGreg Clayton } 223040c560fSGreg Clayton 224040c560fSGreg Clayton if (exited) 225040c560fSGreg Clayton { 226a332978bSJason Molenda if (death_event.data & NOTE_EXIT_MEMORY) 2270c7ebe96SJim Ingham DNBProcessSetExitInfo (child_pid, "Terminated due to memory issue"); 228a332978bSJason Molenda else if (death_event.data & NOTE_EXIT_DECRYPTFAIL) 229a332978bSJason Molenda DNBProcessSetExitInfo (child_pid, "Terminated due to decrypt failure"); 230a332978bSJason Molenda else if (death_event.data & NOTE_EXIT_CSERROR) 231a332978bSJason Molenda DNBProcessSetExitInfo (child_pid, "Terminated due to code signing error"); 232a332978bSJason Molenda 233040c560fSGreg Clayton DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): setting exit status for pid = %i to %i", child_pid, exit_status); 234a332978bSJason Molenda DNBProcessSetExitStatus (child_pid, status); 235a332978bSJason Molenda return NULL; 236a332978bSJason Molenda } 237a332978bSJason Molenda } 238a332978bSJason Molenda } 239040c560fSGreg Clayton } 240a332978bSJason Molenda 241a332978bSJason Molenda static bool 242a332978bSJason Molenda spawn_kqueue_thread (pid_t pid) 243a332978bSJason Molenda { 244a332978bSJason Molenda pthread_t thread; 245a332978bSJason Molenda int kq_id; 246a332978bSJason Molenda 247a332978bSJason Molenda kq_id = kqueue(); 248a332978bSJason Molenda if (kq_id == -1) 249a332978bSJason Molenda { 250a332978bSJason Molenda DNBLogError ("Could not get kqueue for pid = %i.", pid); 251a332978bSJason Molenda return false; 252a332978bSJason Molenda } 253a332978bSJason Molenda 254a332978bSJason Molenda struct kevent reg_event; 255a332978bSJason Molenda 25660089245SJim Ingham EV_SET(®_event, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT|NOTE_EXITSTATUS|NOTE_EXIT_DETAIL, 0, NULL); 257a332978bSJason Molenda // Register the event: 258a332978bSJason Molenda int result = kevent (kq_id, ®_event, 1, NULL, 0, NULL); 259a332978bSJason Molenda if (result != 0) 260a332978bSJason Molenda { 261a332978bSJason Molenda DNBLogError ("Failed to register kqueue NOTE_EXIT event for pid %i, error: %d.", pid, result); 262a332978bSJason Molenda return false; 263a332978bSJason Molenda } 264a332978bSJason Molenda 265a332978bSJason Molenda int ret = ::pthread_create (&thread, NULL, kqueue_thread, (void *)(intptr_t)kq_id); 266a332978bSJason Molenda 267a332978bSJason Molenda // pthread_create returns 0 if successful 268a332978bSJason Molenda if (ret == 0) 269a332978bSJason Molenda { 270a332978bSJason Molenda ::pthread_detach (thread); 271a332978bSJason Molenda return true; 272a332978bSJason Molenda } 273a332978bSJason Molenda return false; 274a332978bSJason Molenda } 275a332978bSJason Molenda #endif // #if USE_KQUEUE 27630fdc8d8SChris Lattner 27730fdc8d8SChris Lattner static void * 27830fdc8d8SChris Lattner waitpid_thread (void *arg) 27930fdc8d8SChris Lattner { 28030fdc8d8SChris Lattner const pid_t pid = (pid_t)(intptr_t)arg; 28130fdc8d8SChris Lattner int status; 28236a216eeSJason Molenda 28336a216eeSJason Molenda #if defined (__APPLE__) 28436a216eeSJason Molenda pthread_setname_np ("waitpid thread"); 28536a216eeSJason Molenda #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) 28636a216eeSJason Molenda struct sched_param thread_param; 28736a216eeSJason Molenda int thread_sched_policy; 28836a216eeSJason Molenda if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0) 28936a216eeSJason Molenda { 29036a216eeSJason Molenda thread_param.sched_priority = 47; 29136a216eeSJason Molenda pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); 29236a216eeSJason Molenda } 29336a216eeSJason Molenda #endif 29436a216eeSJason Molenda #endif 29536a216eeSJason Molenda 29630fdc8d8SChris Lattner while (1) 29730fdc8d8SChris Lattner { 29830fdc8d8SChris Lattner pid_t child_pid = waitpid(pid, &status, 0); 2996467ff9aSGreg Clayton DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): waitpid (pid = %i, &status, 0) => %i, status = %i, errno = %i", pid, child_pid, status, errno); 30030fdc8d8SChris Lattner 30130fdc8d8SChris Lattner if (child_pid < 0) 30230fdc8d8SChris Lattner { 30330fdc8d8SChris Lattner if (errno == EINTR) 30430fdc8d8SChris Lattner continue; 30530fdc8d8SChris Lattner break; 30630fdc8d8SChris Lattner } 30730fdc8d8SChris Lattner else 30830fdc8d8SChris Lattner { 30930fdc8d8SChris Lattner if (WIFSTOPPED(status)) 31030fdc8d8SChris Lattner { 31130fdc8d8SChris Lattner continue; 31230fdc8d8SChris Lattner } 31330fdc8d8SChris Lattner else// if (WIFEXITED(status) || WIFSIGNALED(status)) 31430fdc8d8SChris Lattner { 3156467ff9aSGreg Clayton DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): setting exit status for pid = %i to %i", child_pid, status); 31630fdc8d8SChris Lattner DNBProcessSetExitStatus (child_pid, status); 31730fdc8d8SChris Lattner return NULL; 31830fdc8d8SChris Lattner } 31930fdc8d8SChris Lattner } 32030fdc8d8SChris Lattner } 32130fdc8d8SChris Lattner 32230fdc8d8SChris Lattner // We should never exit as long as our child process is alive, so if we 32330fdc8d8SChris Lattner // do something else went wrong and we should exit... 3246467ff9aSGreg Clayton DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): main loop exited, setting exit status to an invalid value (-1) for pid %i", pid); 32530fdc8d8SChris Lattner DNBProcessSetExitStatus (pid, -1); 32630fdc8d8SChris Lattner return NULL; 32730fdc8d8SChris Lattner } 32830fdc8d8SChris Lattner static bool 32930fdc8d8SChris Lattner spawn_waitpid_thread (pid_t pid) 33030fdc8d8SChris Lattner { 331a332978bSJason Molenda #ifdef USE_KQUEUE 332a332978bSJason Molenda bool success = spawn_kqueue_thread (pid); 333a332978bSJason Molenda if (success) 334a332978bSJason Molenda return true; 335a332978bSJason Molenda #endif 336a332978bSJason Molenda 33727148b3dSJason Molenda pthread_t thread; 33827148b3dSJason Molenda int ret = ::pthread_create (&thread, NULL, waitpid_thread, (void *)(intptr_t)pid); 33927148b3dSJason Molenda // pthread_create returns 0 if successful 34027148b3dSJason Molenda if (ret == 0) 34130fdc8d8SChris Lattner { 34230fdc8d8SChris Lattner ::pthread_detach (thread); 34330fdc8d8SChris Lattner return true; 34430fdc8d8SChris Lattner } 34530fdc8d8SChris Lattner return false; 34630fdc8d8SChris Lattner } 34730fdc8d8SChris Lattner 34830fdc8d8SChris Lattner nub_process_t 34930fdc8d8SChris Lattner DNBProcessLaunch (const char *path, 35030fdc8d8SChris Lattner char const *argv[], 35130fdc8d8SChris Lattner const char *envp[], 352aaa0ba31SBruce Mitchener const char *working_directory, // NULL => don't change, non-NULL => set working directory for inferior to this 3536779606aSGreg Clayton const char *stdin_path, 3546779606aSGreg Clayton const char *stdout_path, 3556779606aSGreg Clayton const char *stderr_path, 356f8da8631SCaroline Tice bool no_stdio, 35730fdc8d8SChris Lattner nub_launch_flavor_t launch_flavor, 358f681b94fSGreg Clayton int disable_aslr, 359a332978bSJason Molenda const char *event_data, 36030fdc8d8SChris Lattner char *err_str, 36130fdc8d8SChris Lattner size_t err_len) 36230fdc8d8SChris Lattner { 36343e0af06SGreg Clayton 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...", 364bd82a5d2SGreg Clayton __FUNCTION__, 365bd82a5d2SGreg Clayton path, 366bd82a5d2SGreg Clayton argv, 367bd82a5d2SGreg Clayton envp, 368bd82a5d2SGreg Clayton working_directory, 369bd82a5d2SGreg Clayton stdin_path, 370bd82a5d2SGreg Clayton stdout_path, 371bd82a5d2SGreg Clayton stderr_path, 372bd82a5d2SGreg Clayton no_stdio, 373bd82a5d2SGreg Clayton launch_flavor, 374bd82a5d2SGreg Clayton disable_aslr, 375bd82a5d2SGreg Clayton err_str, 37643e0af06SGreg Clayton (uint64_t)err_len); 37730fdc8d8SChris Lattner 37830fdc8d8SChris Lattner if (err_str && err_len > 0) 37930fdc8d8SChris Lattner err_str[0] = '\0'; 38030fdc8d8SChris Lattner struct stat path_stat; 38130fdc8d8SChris Lattner if (::stat(path, &path_stat) == -1) 38230fdc8d8SChris Lattner { 38330fdc8d8SChris Lattner char stat_error[256]; 38430fdc8d8SChris Lattner ::strerror_r (errno, stat_error, sizeof(stat_error)); 38530fdc8d8SChris Lattner snprintf(err_str, err_len, "%s (%s)", stat_error, path); 38630fdc8d8SChris Lattner return INVALID_NUB_PROCESS; 38730fdc8d8SChris Lattner } 38830fdc8d8SChris Lattner 38930fdc8d8SChris Lattner MachProcessSP processSP (new MachProcess); 39030fdc8d8SChris Lattner if (processSP.get()) 39130fdc8d8SChris Lattner { 39230fdc8d8SChris Lattner DNBError launch_err; 3936779606aSGreg Clayton pid_t pid = processSP->LaunchForDebug (path, 3946779606aSGreg Clayton argv, 3956779606aSGreg Clayton envp, 3966779606aSGreg Clayton working_directory, 3976779606aSGreg Clayton stdin_path, 3986779606aSGreg Clayton stdout_path, 3996779606aSGreg Clayton stderr_path, 4006779606aSGreg Clayton no_stdio, 4016779606aSGreg Clayton launch_flavor, 4026779606aSGreg Clayton disable_aslr, 403a332978bSJason Molenda event_data, 4046779606aSGreg Clayton launch_err); 40530fdc8d8SChris Lattner if (err_str) 40630fdc8d8SChris Lattner { 40730fdc8d8SChris Lattner *err_str = '\0'; 40830fdc8d8SChris Lattner if (launch_err.Fail()) 40930fdc8d8SChris Lattner { 41030fdc8d8SChris Lattner const char *launch_err_str = launch_err.AsString(); 41130fdc8d8SChris Lattner if (launch_err_str) 41230fdc8d8SChris Lattner { 41330fdc8d8SChris Lattner strncpy(err_str, launch_err_str, err_len-1); 41430fdc8d8SChris Lattner err_str[err_len-1] = '\0'; // Make sure the error string is terminated 41530fdc8d8SChris Lattner } 41630fdc8d8SChris Lattner } 41730fdc8d8SChris Lattner } 41830fdc8d8SChris Lattner 41930fdc8d8SChris Lattner DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid); 42030fdc8d8SChris Lattner 42130fdc8d8SChris Lattner if (pid != INVALID_NUB_PROCESS) 42230fdc8d8SChris Lattner { 42330fdc8d8SChris Lattner // Spawn a thread to reap our child inferior process... 42430fdc8d8SChris Lattner spawn_waitpid_thread (pid); 42530fdc8d8SChris Lattner 42630fdc8d8SChris Lattner if (processSP->Task().TaskPortForProcessID (launch_err) == TASK_NULL) 42730fdc8d8SChris Lattner { 42830fdc8d8SChris Lattner // We failed to get the task for our process ID which is bad. 429fb640c2dSGreg Clayton // Kill our process otherwise it will be stopped at the entry 430fb640c2dSGreg Clayton // point and get reparented to someone else and never go away. 431153c8e0cSJason Molenda DNBLog ("Could not get task port for process, sending SIGKILL and exiting."); 432fb640c2dSGreg Clayton kill (SIGKILL, pid); 433fb640c2dSGreg Clayton 43430fdc8d8SChris Lattner if (err_str && err_len > 0) 43530fdc8d8SChris Lattner { 43630fdc8d8SChris Lattner if (launch_err.AsString()) 43730fdc8d8SChris Lattner { 43830fdc8d8SChris Lattner ::snprintf (err_str, err_len, "failed to get the task for process %i (%s)", pid, launch_err.AsString()); 43930fdc8d8SChris Lattner } 44030fdc8d8SChris Lattner else 44130fdc8d8SChris Lattner { 44230fdc8d8SChris Lattner ::snprintf (err_str, err_len, "failed to get the task for process %i", pid); 44330fdc8d8SChris Lattner } 44430fdc8d8SChris Lattner } 44530fdc8d8SChris Lattner } 44630fdc8d8SChris Lattner else 44730fdc8d8SChris Lattner { 448b786e7d0SCharles Davis bool res = AddProcessToMap(pid, processSP); 449*8a67bf72SBruce Mitchener UNUSED_IF_ASSERT_DISABLED(res); 450b786e7d0SCharles Davis assert(res && "Couldn't add process to map!"); 45130fdc8d8SChris Lattner return pid; 45230fdc8d8SChris Lattner } 45330fdc8d8SChris Lattner } 45430fdc8d8SChris Lattner } 45530fdc8d8SChris Lattner return INVALID_NUB_PROCESS; 45630fdc8d8SChris Lattner } 45730fdc8d8SChris Lattner 45830fdc8d8SChris Lattner nub_process_t 45930fdc8d8SChris Lattner DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len) 46030fdc8d8SChris Lattner { 46130fdc8d8SChris Lattner if (err_str && err_len > 0) 46230fdc8d8SChris Lattner err_str[0] = '\0'; 46330fdc8d8SChris Lattner std::vector<struct kinfo_proc> matching_proc_infos; 46430fdc8d8SChris Lattner size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos); 46530fdc8d8SChris Lattner if (num_matching_proc_infos == 0) 46630fdc8d8SChris Lattner { 46730fdc8d8SChris Lattner DNBLogError ("error: no processes match '%s'\n", name); 46830fdc8d8SChris Lattner return INVALID_NUB_PROCESS; 46930fdc8d8SChris Lattner } 47030fdc8d8SChris Lattner else if (num_matching_proc_infos > 1) 47130fdc8d8SChris Lattner { 47243e0af06SGreg Clayton DNBLogError ("error: %llu processes match '%s':\n", (uint64_t)num_matching_proc_infos, name); 47330fdc8d8SChris Lattner size_t i; 47430fdc8d8SChris Lattner for (i=0; i<num_matching_proc_infos; ++i) 47530fdc8d8SChris Lattner DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm); 47630fdc8d8SChris Lattner return INVALID_NUB_PROCESS; 47730fdc8d8SChris Lattner } 4783af9ea56SGreg Clayton 47930fdc8d8SChris Lattner return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len); 48030fdc8d8SChris Lattner } 48130fdc8d8SChris Lattner 48230fdc8d8SChris Lattner nub_process_t 48330fdc8d8SChris Lattner DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_str, size_t err_len) 48430fdc8d8SChris Lattner { 48530fdc8d8SChris Lattner if (err_str && err_len > 0) 48630fdc8d8SChris Lattner err_str[0] = '\0'; 48730fdc8d8SChris Lattner 48864503c81SJohnny Chen pid_t pid = INVALID_NUB_PROCESS; 48930fdc8d8SChris Lattner MachProcessSP processSP(new MachProcess); 49030fdc8d8SChris Lattner if (processSP.get()) 49130fdc8d8SChris Lattner { 49230fdc8d8SChris Lattner DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", attach_pid); 49330fdc8d8SChris Lattner pid = processSP->AttachForDebug (attach_pid, err_str, err_len); 49430fdc8d8SChris Lattner 49530fdc8d8SChris Lattner if (pid != INVALID_NUB_PROCESS) 49630fdc8d8SChris Lattner { 497b786e7d0SCharles Davis bool res = AddProcessToMap(pid, processSP); 498*8a67bf72SBruce Mitchener UNUSED_IF_ASSERT_DISABLED(res); 499b786e7d0SCharles Davis assert(res && "Couldn't add process to map!"); 50030fdc8d8SChris Lattner spawn_waitpid_thread(pid); 50130fdc8d8SChris Lattner } 50230fdc8d8SChris Lattner } 50330fdc8d8SChris Lattner 50430fdc8d8SChris Lattner while (pid != INVALID_NUB_PROCESS) 50530fdc8d8SChris Lattner { 50630fdc8d8SChris Lattner // Wait for process to start up and hit entry point 5073af9ea56SGreg Clayton DNBLogThreadedIf (LOG_PROCESS, 5083af9ea56SGreg Clayton "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...", 5093af9ea56SGreg Clayton __FUNCTION__, 5103af9ea56SGreg Clayton pid); 51130fdc8d8SChris Lattner nub_event_t set_events = DNBProcessWaitForEvents (pid, 51230fdc8d8SChris Lattner eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, 5133af9ea56SGreg Clayton true, 5143af9ea56SGreg Clayton timeout); 5153af9ea56SGreg Clayton 5163af9ea56SGreg Clayton DNBLogThreadedIf (LOG_PROCESS, 5173af9ea56SGreg Clayton "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x", 5183af9ea56SGreg Clayton __FUNCTION__, 5193af9ea56SGreg Clayton pid, 5203af9ea56SGreg Clayton set_events); 52130fdc8d8SChris Lattner 52230fdc8d8SChris Lattner if (set_events == 0) 52330fdc8d8SChris Lattner { 52430fdc8d8SChris Lattner if (err_str && err_len > 0) 52530fdc8d8SChris Lattner snprintf(err_str, err_len, "operation timed out"); 52630fdc8d8SChris Lattner pid = INVALID_NUB_PROCESS; 52730fdc8d8SChris Lattner } 52830fdc8d8SChris Lattner else 52930fdc8d8SChris Lattner { 53030fdc8d8SChris Lattner if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged)) 53130fdc8d8SChris Lattner { 53230fdc8d8SChris Lattner nub_state_t pid_state = DNBProcessGetState (pid); 53330fdc8d8SChris Lattner DNBLogThreadedIf (LOG_PROCESS, "%s process %4.4x state changed (eEventProcessStateChanged): %s", 53430fdc8d8SChris Lattner __FUNCTION__, pid, DNBStateAsString(pid_state)); 53530fdc8d8SChris Lattner 53630fdc8d8SChris Lattner switch (pid_state) 53730fdc8d8SChris Lattner { 53830fdc8d8SChris Lattner default: 53930fdc8d8SChris Lattner case eStateInvalid: 54030fdc8d8SChris Lattner case eStateUnloaded: 54130fdc8d8SChris Lattner case eStateAttaching: 54230fdc8d8SChris Lattner case eStateLaunching: 54330fdc8d8SChris Lattner case eStateSuspended: 54430fdc8d8SChris Lattner break; // Ignore 54530fdc8d8SChris Lattner 54630fdc8d8SChris Lattner case eStateRunning: 54730fdc8d8SChris Lattner case eStateStepping: 54830fdc8d8SChris Lattner // Still waiting to stop at entry point... 54930fdc8d8SChris Lattner break; 55030fdc8d8SChris Lattner 55130fdc8d8SChris Lattner case eStateStopped: 55230fdc8d8SChris Lattner case eStateCrashed: 55330fdc8d8SChris Lattner return pid; 5543af9ea56SGreg Clayton 55530fdc8d8SChris Lattner case eStateDetached: 55630fdc8d8SChris Lattner case eStateExited: 55730fdc8d8SChris Lattner if (err_str && err_len > 0) 55830fdc8d8SChris Lattner snprintf(err_str, err_len, "process exited"); 55930fdc8d8SChris Lattner return INVALID_NUB_PROCESS; 56030fdc8d8SChris Lattner } 56130fdc8d8SChris Lattner } 56230fdc8d8SChris Lattner 56330fdc8d8SChris Lattner DNBProcessResetEvents(pid, set_events); 56430fdc8d8SChris Lattner } 56530fdc8d8SChris Lattner } 56630fdc8d8SChris Lattner 56730fdc8d8SChris Lattner return INVALID_NUB_PROCESS; 56830fdc8d8SChris Lattner } 56930fdc8d8SChris Lattner 5709eb4e038SGreg Clayton size_t 57130fdc8d8SChris Lattner GetAllInfos (std::vector<struct kinfo_proc>& proc_infos) 57230fdc8d8SChris Lattner { 5739eb4e038SGreg Clayton size_t size = 0; 57430fdc8d8SChris Lattner int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; 575c1fdb889SJim Ingham u_int namelen = sizeof(name)/sizeof(int); 57630fdc8d8SChris Lattner int err; 57730fdc8d8SChris Lattner 57830fdc8d8SChris Lattner // Try to find out how many processes are around so we can 57930fdc8d8SChris Lattner // size the buffer appropriately. sysctl's man page specifically suggests 58030fdc8d8SChris Lattner // this approach, and says it returns a bit larger size than needed to 58130fdc8d8SChris Lattner // handle any new processes created between then and now. 58230fdc8d8SChris Lattner 58330fdc8d8SChris Lattner err = ::sysctl (name, namelen, NULL, &size, NULL, 0); 58430fdc8d8SChris Lattner 58530fdc8d8SChris Lattner if ((err < 0) && (err != ENOMEM)) 58630fdc8d8SChris Lattner { 58730fdc8d8SChris Lattner proc_infos.clear(); 58830fdc8d8SChris Lattner perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)"); 58930fdc8d8SChris Lattner return 0; 59030fdc8d8SChris Lattner } 59130fdc8d8SChris Lattner 59230fdc8d8SChris Lattner 59330fdc8d8SChris Lattner // Increase the size of the buffer by a few processes in case more have 59430fdc8d8SChris Lattner // been spawned 59530fdc8d8SChris Lattner proc_infos.resize (size / sizeof(struct kinfo_proc)); 59630fdc8d8SChris Lattner size = proc_infos.size() * sizeof(struct kinfo_proc); // Make sure we don't exceed our resize... 59730fdc8d8SChris Lattner err = ::sysctl (name, namelen, &proc_infos[0], &size, NULL, 0); 59830fdc8d8SChris Lattner if (err < 0) 59930fdc8d8SChris Lattner { 60030fdc8d8SChris Lattner proc_infos.clear(); 60130fdc8d8SChris Lattner return 0; 60230fdc8d8SChris Lattner } 60330fdc8d8SChris Lattner 60430fdc8d8SChris Lattner // Trim down our array to fit what we actually got back 60530fdc8d8SChris Lattner proc_infos.resize(size / sizeof(struct kinfo_proc)); 60630fdc8d8SChris Lattner return proc_infos.size(); 60730fdc8d8SChris Lattner } 60830fdc8d8SChris Lattner 60930fdc8d8SChris Lattner static size_t 61030fdc8d8SChris Lattner GetAllInfosMatchingName(const char *full_process_name, std::vector<struct kinfo_proc>& matching_proc_infos) 61130fdc8d8SChris Lattner { 61230fdc8d8SChris Lattner 61330fdc8d8SChris Lattner matching_proc_infos.clear(); 61430fdc8d8SChris Lattner if (full_process_name && full_process_name[0]) 61530fdc8d8SChris Lattner { 61630fdc8d8SChris Lattner // We only get the process name, not the full path, from the proc_info. So just take the 61730fdc8d8SChris Lattner // base name of the process name... 61830fdc8d8SChris Lattner const char *process_name; 61930fdc8d8SChris Lattner process_name = strrchr (full_process_name, '/'); 62030fdc8d8SChris Lattner if (process_name == NULL) 62130fdc8d8SChris Lattner process_name = full_process_name; 62230fdc8d8SChris Lattner else 62330fdc8d8SChris Lattner process_name++; 62430fdc8d8SChris Lattner 625ee2ed525SGreg Clayton const size_t process_name_len = strlen(process_name); 62630fdc8d8SChris Lattner std::vector<struct kinfo_proc> proc_infos; 62730fdc8d8SChris Lattner const size_t num_proc_infos = GetAllInfos(proc_infos); 62830fdc8d8SChris Lattner if (num_proc_infos > 0) 62930fdc8d8SChris Lattner { 63030fdc8d8SChris Lattner uint32_t i; 63130fdc8d8SChris Lattner for (i=0; i<num_proc_infos; i++) 63230fdc8d8SChris Lattner { 63330fdc8d8SChris Lattner // Skip zombie processes and processes with unset status 63430fdc8d8SChris Lattner if (proc_infos[i].kp_proc.p_stat == 0 || proc_infos[i].kp_proc.p_stat == SZOMB) 63530fdc8d8SChris Lattner continue; 63630fdc8d8SChris Lattner 63730fdc8d8SChris Lattner // Check for process by name. We only check the first MAXCOMLEN 63830fdc8d8SChris Lattner // chars as that is all that kp_proc.p_comm holds. 639490bccd6SJim Ingham 6407dab2be2SGreg Clayton if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm, MAXCOMLEN) == 0) 6417dab2be2SGreg Clayton { 6427dab2be2SGreg Clayton if (process_name_len > MAXCOMLEN) 6437dab2be2SGreg Clayton { 6447dab2be2SGreg Clayton // We found a matching process name whose first MAXCOMLEN 6457dab2be2SGreg Clayton // characters match, but there is more to the name than 646490bccd6SJim Ingham // this. We need to get the full process name. Use proc_pidpath, which will get 647490bccd6SJim Ingham // us the full path to the executed process. 6487dab2be2SGreg Clayton 649490bccd6SJim Ingham char proc_path_buf[PATH_MAX]; 6507dab2be2SGreg Clayton 651490bccd6SJim Ingham int return_val = proc_pidpath (proc_infos[i].kp_proc.p_pid, proc_path_buf, PATH_MAX); 652490bccd6SJim Ingham if (return_val > 0) 6537dab2be2SGreg Clayton { 654490bccd6SJim Ingham // Okay, now search backwards from that to see if there is a 655490bccd6SJim Ingham // slash in the name. Note, even though we got all the args we don't care 656490bccd6SJim Ingham // because the list data is just a bunch of concatenated null terminated strings 657490bccd6SJim Ingham // so strrchr will start from the end of argv0. 658490bccd6SJim Ingham 659490bccd6SJim Ingham const char *argv_basename = strrchr(proc_path_buf, '/'); 6607dab2be2SGreg Clayton if (argv_basename) 6617dab2be2SGreg Clayton { 6627dab2be2SGreg Clayton // Skip the '/' 6637dab2be2SGreg Clayton ++argv_basename; 6647dab2be2SGreg Clayton } 6657dab2be2SGreg Clayton else 6667dab2be2SGreg Clayton { 6677dab2be2SGreg Clayton // We didn't find a directory delimiter in the process argv[0], just use what was in there 668490bccd6SJim Ingham argv_basename = proc_path_buf; 6697dab2be2SGreg Clayton } 6707dab2be2SGreg Clayton 6717dab2be2SGreg Clayton if (argv_basename) 6727dab2be2SGreg Clayton { 6737dab2be2SGreg Clayton if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0) 6747dab2be2SGreg Clayton { 6757dab2be2SGreg Clayton matching_proc_infos.push_back(proc_infos[i]); 6767dab2be2SGreg Clayton } 6777dab2be2SGreg Clayton } 6787dab2be2SGreg Clayton } 6797dab2be2SGreg Clayton } 6807dab2be2SGreg Clayton else 68130fdc8d8SChris Lattner { 68230fdc8d8SChris Lattner // We found a matching process, add it to our list 68330fdc8d8SChris Lattner matching_proc_infos.push_back(proc_infos[i]); 68430fdc8d8SChris Lattner } 68530fdc8d8SChris Lattner } 68630fdc8d8SChris Lattner } 68730fdc8d8SChris Lattner } 6887dab2be2SGreg Clayton } 68930fdc8d8SChris Lattner // return the newly added matches. 69030fdc8d8SChris Lattner return matching_proc_infos.size(); 69130fdc8d8SChris Lattner } 69230fdc8d8SChris Lattner 69330fdc8d8SChris Lattner nub_process_t 69419388cfcSGreg Clayton DNBProcessAttachWait (const char *waitfor_process_name, 69519388cfcSGreg Clayton nub_launch_flavor_t launch_flavor, 696cd16df91SJim Ingham bool ignore_existing, 69719388cfcSGreg Clayton struct timespec *timeout_abstime, 69819388cfcSGreg Clayton useconds_t waitfor_interval, 69919388cfcSGreg Clayton char *err_str, 70019388cfcSGreg Clayton size_t err_len, 70130fdc8d8SChris Lattner DNBShouldCancelCallback should_cancel_callback, 70230fdc8d8SChris Lattner void *callback_data) 70330fdc8d8SChris Lattner { 70430fdc8d8SChris Lattner DNBError prepare_error; 70530fdc8d8SChris Lattner std::vector<struct kinfo_proc> exclude_proc_infos; 70630fdc8d8SChris Lattner size_t num_exclude_proc_infos; 70730fdc8d8SChris Lattner 70830fdc8d8SChris Lattner // If the PrepareForAttach returns a valid token, use MachProcess to check 70930fdc8d8SChris Lattner // for the process, otherwise scan the process table. 71030fdc8d8SChris Lattner 71130fdc8d8SChris Lattner const void *attach_token = MachProcess::PrepareForAttach (waitfor_process_name, launch_flavor, true, prepare_error); 71230fdc8d8SChris Lattner 71330fdc8d8SChris Lattner if (prepare_error.Fail()) 71430fdc8d8SChris Lattner { 71530fdc8d8SChris Lattner DNBLogError ("Error in PrepareForAttach: %s", prepare_error.AsString()); 71630fdc8d8SChris Lattner return INVALID_NUB_PROCESS; 71730fdc8d8SChris Lattner } 71830fdc8d8SChris Lattner 71930fdc8d8SChris Lattner if (attach_token == NULL) 720cd16df91SJim Ingham { 721cd16df91SJim Ingham if (ignore_existing) 72230fdc8d8SChris Lattner num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos); 723cd16df91SJim Ingham else 724cd16df91SJim Ingham num_exclude_proc_infos = 0; 725cd16df91SJim Ingham } 72630fdc8d8SChris Lattner 72730fdc8d8SChris Lattner DNBLogThreadedIf (LOG_PROCESS, "Waiting for '%s' to appear...\n", waitfor_process_name); 72830fdc8d8SChris Lattner 72930fdc8d8SChris Lattner // Loop and try to find the process by name 73030fdc8d8SChris Lattner nub_process_t waitfor_pid = INVALID_NUB_PROCESS; 73130fdc8d8SChris Lattner 73230fdc8d8SChris Lattner while (waitfor_pid == INVALID_NUB_PROCESS) 73330fdc8d8SChris Lattner { 73430fdc8d8SChris Lattner if (attach_token != NULL) 73530fdc8d8SChris Lattner { 73630fdc8d8SChris Lattner nub_process_t pid; 73730fdc8d8SChris Lattner pid = MachProcess::CheckForProcess(attach_token); 73830fdc8d8SChris Lattner if (pid != INVALID_NUB_PROCESS) 73930fdc8d8SChris Lattner { 74030fdc8d8SChris Lattner waitfor_pid = pid; 74130fdc8d8SChris Lattner break; 74230fdc8d8SChris Lattner } 74330fdc8d8SChris Lattner } 74430fdc8d8SChris Lattner else 74530fdc8d8SChris Lattner { 74630fdc8d8SChris Lattner 74730fdc8d8SChris Lattner // Get the current process list, and check for matches that 74830fdc8d8SChris Lattner // aren't in our original list. If anyone wants to attach 74930fdc8d8SChris Lattner // to an existing process by name, they should do it with 75030fdc8d8SChris Lattner // --attach=PROCNAME. Else we will wait for the first matching 75130fdc8d8SChris Lattner // process that wasn't in our exclusion list. 75230fdc8d8SChris Lattner std::vector<struct kinfo_proc> proc_infos; 75330fdc8d8SChris Lattner const size_t num_proc_infos = GetAllInfosMatchingName (waitfor_process_name, proc_infos); 75430fdc8d8SChris Lattner for (size_t i=0; i<num_proc_infos; i++) 75530fdc8d8SChris Lattner { 75630fdc8d8SChris Lattner nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid; 75730fdc8d8SChris Lattner for (size_t j=0; j<num_exclude_proc_infos; j++) 75830fdc8d8SChris Lattner { 75930fdc8d8SChris Lattner if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid) 76030fdc8d8SChris Lattner { 76130fdc8d8SChris Lattner // This process was in our exclusion list, don't use it. 76230fdc8d8SChris Lattner curr_pid = INVALID_NUB_PROCESS; 76330fdc8d8SChris Lattner break; 76430fdc8d8SChris Lattner } 76530fdc8d8SChris Lattner } 76630fdc8d8SChris Lattner 76730fdc8d8SChris Lattner // If we didn't find CURR_PID in our exclusion list, then use it. 76830fdc8d8SChris Lattner if (curr_pid != INVALID_NUB_PROCESS) 76930fdc8d8SChris Lattner { 77030fdc8d8SChris Lattner // We found our process! 77130fdc8d8SChris Lattner waitfor_pid = curr_pid; 77230fdc8d8SChris Lattner break; 77330fdc8d8SChris Lattner } 77430fdc8d8SChris Lattner } 77530fdc8d8SChris Lattner } 77630fdc8d8SChris Lattner 77730fdc8d8SChris Lattner // If we haven't found our process yet, check for a timeout 77830fdc8d8SChris Lattner // and then sleep for a bit until we poll again. 77930fdc8d8SChris Lattner if (waitfor_pid == INVALID_NUB_PROCESS) 78030fdc8d8SChris Lattner { 78130fdc8d8SChris Lattner if (timeout_abstime != NULL) 78230fdc8d8SChris Lattner { 78330fdc8d8SChris Lattner // Check to see if we have a waitfor-duration option that 78430fdc8d8SChris Lattner // has timed out? 78530fdc8d8SChris Lattner if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime)) 78630fdc8d8SChris Lattner { 78730fdc8d8SChris Lattner if (err_str && err_len > 0) 78830fdc8d8SChris Lattner snprintf(err_str, err_len, "operation timed out"); 78930fdc8d8SChris Lattner DNBLogError ("error: waiting for process '%s' timed out.\n", waitfor_process_name); 79030fdc8d8SChris Lattner return INVALID_NUB_PROCESS; 79130fdc8d8SChris Lattner } 79230fdc8d8SChris Lattner } 79330fdc8d8SChris Lattner 79430fdc8d8SChris Lattner // Call the should cancel callback as well... 79530fdc8d8SChris Lattner 79630fdc8d8SChris Lattner if (should_cancel_callback != NULL 79730fdc8d8SChris Lattner && should_cancel_callback (callback_data)) 79830fdc8d8SChris Lattner { 79930fdc8d8SChris Lattner DNBLogThreadedIf (LOG_PROCESS, "DNBProcessAttachWait cancelled by should_cancel callback."); 80030fdc8d8SChris Lattner waitfor_pid = INVALID_NUB_PROCESS; 80130fdc8d8SChris Lattner break; 80230fdc8d8SChris Lattner } 80330fdc8d8SChris Lattner 80430fdc8d8SChris Lattner ::usleep (waitfor_interval); // Sleep for WAITFOR_INTERVAL, then poll again 80530fdc8d8SChris Lattner } 80630fdc8d8SChris Lattner } 80730fdc8d8SChris Lattner 80830fdc8d8SChris Lattner if (waitfor_pid != INVALID_NUB_PROCESS) 80930fdc8d8SChris Lattner { 81030fdc8d8SChris Lattner DNBLogThreadedIf (LOG_PROCESS, "Attaching to %s with pid %i...\n", waitfor_process_name, waitfor_pid); 81130fdc8d8SChris Lattner waitfor_pid = DNBProcessAttach (waitfor_pid, timeout_abstime, err_str, err_len); 81230fdc8d8SChris Lattner } 81330fdc8d8SChris Lattner 81430fdc8d8SChris Lattner bool success = waitfor_pid != INVALID_NUB_PROCESS; 81530fdc8d8SChris Lattner MachProcess::CleanupAfterAttach (attach_token, success, prepare_error); 81630fdc8d8SChris Lattner 81730fdc8d8SChris Lattner return waitfor_pid; 81830fdc8d8SChris Lattner } 81930fdc8d8SChris Lattner 82030fdc8d8SChris Lattner nub_bool_t 82130fdc8d8SChris Lattner DNBProcessDetach (nub_process_t pid) 82230fdc8d8SChris Lattner { 82330fdc8d8SChris Lattner MachProcessSP procSP; 82430fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 82530fdc8d8SChris Lattner { 8265881318cSJim Ingham const bool remove = true; 8275881318cSJim Ingham DNBLogThreaded("Disabling breakpoints and watchpoints, and detaching from %d.", pid); 8285881318cSJim Ingham procSP->DisableAllBreakpoints(remove); 8295881318cSJim Ingham procSP->DisableAllWatchpoints (remove); 83030fdc8d8SChris Lattner return procSP->Detach(); 83130fdc8d8SChris Lattner } 83230fdc8d8SChris Lattner return false; 83330fdc8d8SChris Lattner } 83430fdc8d8SChris Lattner 83530fdc8d8SChris Lattner nub_bool_t 83630fdc8d8SChris Lattner DNBProcessKill (nub_process_t pid) 83730fdc8d8SChris Lattner { 83830fdc8d8SChris Lattner MachProcessSP procSP; 83930fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 84030fdc8d8SChris Lattner { 84130fdc8d8SChris Lattner return procSP->Kill (); 84230fdc8d8SChris Lattner } 84330fdc8d8SChris Lattner return false; 84430fdc8d8SChris Lattner } 84530fdc8d8SChris Lattner 84630fdc8d8SChris Lattner nub_bool_t 84730fdc8d8SChris Lattner DNBProcessSignal (nub_process_t pid, int signal) 84830fdc8d8SChris Lattner { 84930fdc8d8SChris Lattner MachProcessSP procSP; 85030fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 85130fdc8d8SChris Lattner { 85230fdc8d8SChris Lattner return procSP->Signal (signal); 85330fdc8d8SChris Lattner } 85430fdc8d8SChris Lattner return false; 85530fdc8d8SChris Lattner } 85630fdc8d8SChris Lattner 8574296c221SGreg Clayton 8584296c221SGreg Clayton nub_bool_t 8594296c221SGreg Clayton DNBProcessInterrupt(nub_process_t pid) 8604296c221SGreg Clayton { 8614296c221SGreg Clayton MachProcessSP procSP; 8624296c221SGreg Clayton if (GetProcessSP (pid, procSP)) 8634296c221SGreg Clayton return procSP->Interrupt(); 8644296c221SGreg Clayton return false; 8654296c221SGreg Clayton } 8664296c221SGreg Clayton 867a332978bSJason Molenda nub_bool_t 868a332978bSJason Molenda DNBProcessSendEvent (nub_process_t pid, const char *event) 869a332978bSJason Molenda { 870a332978bSJason Molenda MachProcessSP procSP; 871a332978bSJason Molenda if (GetProcessSP (pid, procSP)) 872a332978bSJason Molenda { 873a332978bSJason Molenda // FIXME: Do something with the error... 874a332978bSJason Molenda DNBError send_error; 875a332978bSJason Molenda return procSP->SendEvent (event, send_error); 876a332978bSJason Molenda } 877a332978bSJason Molenda return false; 878a332978bSJason Molenda } 879a332978bSJason Molenda 88030fdc8d8SChris Lattner 88130fdc8d8SChris Lattner nub_bool_t 88230fdc8d8SChris Lattner DNBProcessIsAlive (nub_process_t pid) 88330fdc8d8SChris Lattner { 88430fdc8d8SChris Lattner MachProcessSP procSP; 88530fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 88630fdc8d8SChris Lattner { 88730fdc8d8SChris Lattner return MachTask::IsValid (procSP->Task().TaskPort()); 88830fdc8d8SChris Lattner } 88930fdc8d8SChris Lattner return eStateInvalid; 89030fdc8d8SChris Lattner } 89130fdc8d8SChris Lattner 89230fdc8d8SChris Lattner //---------------------------------------------------------------------- 89330fdc8d8SChris Lattner // Process and Thread state information 89430fdc8d8SChris Lattner //---------------------------------------------------------------------- 89530fdc8d8SChris Lattner nub_state_t 89630fdc8d8SChris Lattner DNBProcessGetState (nub_process_t pid) 89730fdc8d8SChris Lattner { 89830fdc8d8SChris Lattner MachProcessSP procSP; 89930fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 90030fdc8d8SChris Lattner { 90130fdc8d8SChris Lattner return procSP->GetState(); 90230fdc8d8SChris Lattner } 90330fdc8d8SChris Lattner return eStateInvalid; 90430fdc8d8SChris Lattner } 90530fdc8d8SChris Lattner 90630fdc8d8SChris Lattner //---------------------------------------------------------------------- 90730fdc8d8SChris Lattner // Process and Thread state information 90830fdc8d8SChris Lattner //---------------------------------------------------------------------- 90930fdc8d8SChris Lattner nub_bool_t 91030fdc8d8SChris Lattner DNBProcessGetExitStatus (nub_process_t pid, int* status) 91130fdc8d8SChris Lattner { 91230fdc8d8SChris Lattner MachProcessSP procSP; 91330fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 91430fdc8d8SChris Lattner { 91530fdc8d8SChris Lattner return procSP->GetExitStatus(status); 91630fdc8d8SChris Lattner } 91730fdc8d8SChris Lattner return false; 91830fdc8d8SChris Lattner } 91930fdc8d8SChris Lattner 92030fdc8d8SChris Lattner nub_bool_t 92130fdc8d8SChris Lattner DNBProcessSetExitStatus (nub_process_t pid, int status) 92230fdc8d8SChris Lattner { 92330fdc8d8SChris Lattner MachProcessSP procSP; 92430fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 92530fdc8d8SChris Lattner { 92630fdc8d8SChris Lattner procSP->SetExitStatus(status); 92730fdc8d8SChris Lattner return true; 92830fdc8d8SChris Lattner } 92930fdc8d8SChris Lattner return false; 93030fdc8d8SChris Lattner } 93130fdc8d8SChris Lattner 932a332978bSJason Molenda const char * 933a332978bSJason Molenda DNBProcessGetExitInfo (nub_process_t pid) 934a332978bSJason Molenda { 935a332978bSJason Molenda MachProcessSP procSP; 936a332978bSJason Molenda if (GetProcessSP (pid, procSP)) 937a332978bSJason Molenda { 938a332978bSJason Molenda return procSP->GetExitInfo(); 939a332978bSJason Molenda } 940a332978bSJason Molenda return NULL; 941a332978bSJason Molenda } 942a332978bSJason Molenda 943a332978bSJason Molenda nub_bool_t 944a332978bSJason Molenda DNBProcessSetExitInfo (nub_process_t pid, const char *info) 945a332978bSJason Molenda { 946a332978bSJason Molenda MachProcessSP procSP; 947a332978bSJason Molenda if (GetProcessSP (pid, procSP)) 948a332978bSJason Molenda { 949a332978bSJason Molenda procSP->SetExitInfo(info); 950a332978bSJason Molenda return true; 951a332978bSJason Molenda } 952a332978bSJason Molenda return false; 953a332978bSJason Molenda } 95430fdc8d8SChris Lattner 95530fdc8d8SChris Lattner const char * 95630fdc8d8SChris Lattner DNBThreadGetName (nub_process_t pid, nub_thread_t tid) 95730fdc8d8SChris Lattner { 95830fdc8d8SChris Lattner MachProcessSP procSP; 95930fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 96030fdc8d8SChris Lattner return procSP->ThreadGetName(tid); 96130fdc8d8SChris Lattner return NULL; 96230fdc8d8SChris Lattner } 96330fdc8d8SChris Lattner 96430fdc8d8SChris Lattner 96530fdc8d8SChris Lattner nub_bool_t 96630fdc8d8SChris Lattner DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info) 96730fdc8d8SChris Lattner { 96830fdc8d8SChris Lattner MachProcessSP procSP; 96930fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 97030fdc8d8SChris Lattner return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info); 97130fdc8d8SChris Lattner return false; 97230fdc8d8SChris Lattner } 97330fdc8d8SChris Lattner 97430fdc8d8SChris Lattner nub_state_t 97530fdc8d8SChris Lattner DNBThreadGetState (nub_process_t pid, nub_thread_t tid) 97630fdc8d8SChris Lattner { 97730fdc8d8SChris Lattner MachProcessSP procSP; 97830fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 97930fdc8d8SChris Lattner { 98030fdc8d8SChris Lattner return procSP->ThreadGetState(tid); 98130fdc8d8SChris Lattner } 98230fdc8d8SChris Lattner return eStateInvalid; 98330fdc8d8SChris Lattner } 98430fdc8d8SChris Lattner 98530fdc8d8SChris Lattner const char * 98630fdc8d8SChris Lattner DNBStateAsString(nub_state_t state) 98730fdc8d8SChris Lattner { 98830fdc8d8SChris Lattner switch (state) 98930fdc8d8SChris Lattner { 990effe5c95SGreg Clayton case eStateInvalid: return "Invalid"; 99130fdc8d8SChris Lattner case eStateUnloaded: return "Unloaded"; 99230fdc8d8SChris Lattner case eStateAttaching: return "Attaching"; 99330fdc8d8SChris Lattner case eStateLaunching: return "Launching"; 99430fdc8d8SChris Lattner case eStateStopped: return "Stopped"; 99530fdc8d8SChris Lattner case eStateRunning: return "Running"; 99630fdc8d8SChris Lattner case eStateStepping: return "Stepping"; 99730fdc8d8SChris Lattner case eStateCrashed: return "Crashed"; 99830fdc8d8SChris Lattner case eStateDetached: return "Detached"; 99930fdc8d8SChris Lattner case eStateExited: return "Exited"; 100030fdc8d8SChris Lattner case eStateSuspended: return "Suspended"; 100130fdc8d8SChris Lattner } 100230fdc8d8SChris Lattner return "nub_state_t ???"; 100330fdc8d8SChris Lattner } 100430fdc8d8SChris Lattner 1005705b1809SJason Molenda Genealogy::ThreadActivitySP 1006705b1809SJason Molenda DNBGetGenealogyInfoForThread (nub_process_t pid, nub_thread_t tid, bool &timed_out) 1007705b1809SJason Molenda { 1008705b1809SJason Molenda Genealogy::ThreadActivitySP thread_activity_sp; 1009705b1809SJason Molenda MachProcessSP procSP; 1010705b1809SJason Molenda if (GetProcessSP (pid, procSP)) 1011705b1809SJason Molenda thread_activity_sp = procSP->GetGenealogyInfoForThread (tid, timed_out); 1012705b1809SJason Molenda return thread_activity_sp; 1013705b1809SJason Molenda } 1014705b1809SJason Molenda 1015705b1809SJason Molenda Genealogy::ProcessExecutableInfoSP 1016705b1809SJason Molenda DNBGetGenealogyImageInfo (nub_process_t pid, size_t idx) 1017705b1809SJason Molenda { 1018705b1809SJason Molenda Genealogy::ProcessExecutableInfoSP image_info_sp; 1019705b1809SJason Molenda MachProcessSP procSP; 1020705b1809SJason Molenda if (GetProcessSP (pid, procSP)) 1021705b1809SJason Molenda { 1022705b1809SJason Molenda image_info_sp = procSP->GetGenealogyImageInfo (idx); 1023705b1809SJason Molenda } 1024705b1809SJason Molenda return image_info_sp; 1025705b1809SJason Molenda } 1026705b1809SJason Molenda 1027705b1809SJason Molenda ThreadInfo::QoS 1028705b1809SJason Molenda DNBGetRequestedQoSForThread (nub_process_t pid, nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index) 1029705b1809SJason Molenda { 1030705b1809SJason Molenda MachProcessSP procSP; 1031705b1809SJason Molenda if (GetProcessSP (pid, procSP)) 1032705b1809SJason Molenda { 1033705b1809SJason Molenda return procSP->GetRequestedQoS (tid, tsd, dti_qos_class_index); 1034705b1809SJason Molenda } 1035705b1809SJason Molenda return ThreadInfo::QoS(); 1036705b1809SJason Molenda } 1037705b1809SJason Molenda 1038705b1809SJason Molenda nub_addr_t 1039705b1809SJason Molenda DNBGetPThreadT (nub_process_t pid, nub_thread_t tid) 1040705b1809SJason Molenda { 1041705b1809SJason Molenda MachProcessSP procSP; 1042705b1809SJason Molenda if (GetProcessSP (pid, procSP)) 1043705b1809SJason Molenda { 1044705b1809SJason Molenda return procSP->GetPThreadT (tid); 1045705b1809SJason Molenda } 1046705b1809SJason Molenda return INVALID_NUB_ADDRESS; 1047705b1809SJason Molenda } 1048705b1809SJason Molenda 1049705b1809SJason Molenda nub_addr_t 1050705b1809SJason Molenda DNBGetDispatchQueueT (nub_process_t pid, nub_thread_t tid) 1051705b1809SJason Molenda { 1052705b1809SJason Molenda MachProcessSP procSP; 1053705b1809SJason Molenda if (GetProcessSP (pid, procSP)) 1054705b1809SJason Molenda { 1055705b1809SJason Molenda return procSP->GetDispatchQueueT (tid); 1056705b1809SJason Molenda } 1057705b1809SJason Molenda return INVALID_NUB_ADDRESS; 1058705b1809SJason Molenda } 1059705b1809SJason Molenda 1060705b1809SJason Molenda nub_addr_t 1061705b1809SJason Molenda 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) 1062705b1809SJason Molenda { 1063705b1809SJason Molenda MachProcessSP procSP; 1064705b1809SJason Molenda if (GetProcessSP (pid, procSP)) 1065705b1809SJason Molenda { 1066705b1809SJason Molenda return procSP->GetTSDAddressForThread (tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size); 1067705b1809SJason Molenda } 1068705b1809SJason Molenda return INVALID_NUB_ADDRESS; 1069705b1809SJason Molenda } 1070705b1809SJason Molenda 107120ee21bdSJason Molenda JSONGenerator::ObjectSP 107220ee21bdSJason Molenda DNBGetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count) 107320ee21bdSJason Molenda { 107420ee21bdSJason Molenda MachProcessSP procSP; 107520ee21bdSJason Molenda if (GetProcessSP (pid, procSP)) 107620ee21bdSJason Molenda { 107720ee21bdSJason Molenda return procSP->GetLoadedDynamicLibrariesInfos (pid, image_list_address, image_count); 107820ee21bdSJason Molenda } 107920ee21bdSJason Molenda return JSONGenerator::ObjectSP(); 108020ee21bdSJason Molenda } 108120ee21bdSJason Molenda 108220ee21bdSJason Molenda 1083705b1809SJason Molenda 108430fdc8d8SChris Lattner const char * 108530fdc8d8SChris Lattner DNBProcessGetExecutablePath (nub_process_t pid) 108630fdc8d8SChris Lattner { 108730fdc8d8SChris Lattner MachProcessSP procSP; 108830fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 108930fdc8d8SChris Lattner { 109030fdc8d8SChris Lattner return procSP->Path(); 109130fdc8d8SChris Lattner } 109230fdc8d8SChris Lattner return NULL; 109330fdc8d8SChris Lattner } 109430fdc8d8SChris Lattner 109530fdc8d8SChris Lattner nub_size_t 109630fdc8d8SChris Lattner DNBProcessGetArgumentCount (nub_process_t pid) 109730fdc8d8SChris Lattner { 109830fdc8d8SChris Lattner MachProcessSP procSP; 109930fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 110030fdc8d8SChris Lattner { 110130fdc8d8SChris Lattner return procSP->ArgumentCount(); 110230fdc8d8SChris Lattner } 110330fdc8d8SChris Lattner return 0; 110430fdc8d8SChris Lattner } 110530fdc8d8SChris Lattner 110630fdc8d8SChris Lattner const char * 110730fdc8d8SChris Lattner DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx) 110830fdc8d8SChris Lattner { 110930fdc8d8SChris Lattner MachProcessSP procSP; 111030fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 111130fdc8d8SChris Lattner { 111230fdc8d8SChris Lattner return procSP->ArgumentAtIndex (idx); 111330fdc8d8SChris Lattner } 111430fdc8d8SChris Lattner return NULL; 111530fdc8d8SChris Lattner } 111630fdc8d8SChris Lattner 111730fdc8d8SChris Lattner 111830fdc8d8SChris Lattner //---------------------------------------------------------------------- 111930fdc8d8SChris Lattner // Execution control 112030fdc8d8SChris Lattner //---------------------------------------------------------------------- 112130fdc8d8SChris Lattner nub_bool_t 112230fdc8d8SChris Lattner DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions) 112330fdc8d8SChris Lattner { 112430fdc8d8SChris Lattner DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid); 112530fdc8d8SChris Lattner MachProcessSP procSP; 112630fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 112730fdc8d8SChris Lattner { 112830fdc8d8SChris Lattner DNBThreadResumeActions thread_actions (actions, num_actions); 112930fdc8d8SChris Lattner 113030fdc8d8SChris Lattner // Below we add a default thread plan just in case one wasn't 113130fdc8d8SChris Lattner // provided so all threads always know what they were supposed to do 113230fdc8d8SChris Lattner if (thread_actions.IsEmpty()) 113330fdc8d8SChris Lattner { 113430fdc8d8SChris Lattner // No thread plans were given, so the default it to run all threads 113530fdc8d8SChris Lattner thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0); 113630fdc8d8SChris Lattner } 113730fdc8d8SChris Lattner else 113830fdc8d8SChris Lattner { 113930fdc8d8SChris Lattner // Some thread plans were given which means anything that wasn't 114030fdc8d8SChris Lattner // specified should remain stopped. 114130fdc8d8SChris Lattner thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0); 114230fdc8d8SChris Lattner } 114330fdc8d8SChris Lattner return procSP->Resume (thread_actions); 114430fdc8d8SChris Lattner } 114530fdc8d8SChris Lattner return false; 114630fdc8d8SChris Lattner } 114730fdc8d8SChris Lattner 114830fdc8d8SChris Lattner nub_bool_t 114930fdc8d8SChris Lattner DNBProcessHalt (nub_process_t pid) 115030fdc8d8SChris Lattner { 115130fdc8d8SChris Lattner DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid); 115230fdc8d8SChris Lattner MachProcessSP procSP; 115330fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 115430fdc8d8SChris Lattner return procSP->Signal (SIGSTOP); 115530fdc8d8SChris Lattner return false; 115630fdc8d8SChris Lattner } 115730fdc8d8SChris Lattner // 115830fdc8d8SChris Lattner //nub_bool_t 115930fdc8d8SChris Lattner //DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step) 116030fdc8d8SChris Lattner //{ 116130fdc8d8SChris Lattner // DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", __FUNCTION__, pid, tid, (uint32_t)step); 116230fdc8d8SChris Lattner // MachProcessSP procSP; 116330fdc8d8SChris Lattner // if (GetProcessSP (pid, procSP)) 116430fdc8d8SChris Lattner // { 116530fdc8d8SChris Lattner // return procSP->Resume(tid, step, 0); 116630fdc8d8SChris Lattner // } 116730fdc8d8SChris Lattner // return false; 116830fdc8d8SChris Lattner //} 116930fdc8d8SChris Lattner // 117030fdc8d8SChris Lattner //nub_bool_t 117130fdc8d8SChris Lattner //DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t step, int signal) 117230fdc8d8SChris Lattner //{ 117330fdc8d8SChris Lattner // DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal); 117430fdc8d8SChris Lattner // MachProcessSP procSP; 117530fdc8d8SChris Lattner // if (GetProcessSP (pid, procSP)) 117630fdc8d8SChris Lattner // { 117730fdc8d8SChris Lattner // return procSP->Resume(tid, step, signal); 117830fdc8d8SChris Lattner // } 117930fdc8d8SChris Lattner // return false; 118030fdc8d8SChris Lattner //} 118130fdc8d8SChris Lattner 118230fdc8d8SChris Lattner nub_event_t 118330fdc8d8SChris Lattner DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout) 118430fdc8d8SChris Lattner { 118530fdc8d8SChris Lattner nub_event_t result = 0; 118630fdc8d8SChris Lattner MachProcessSP procSP; 118730fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 118830fdc8d8SChris Lattner { 118930fdc8d8SChris Lattner if (wait_for_set) 119030fdc8d8SChris Lattner result = procSP->Events().WaitForSetEvents(event_mask, timeout); 119130fdc8d8SChris Lattner else 119230fdc8d8SChris Lattner result = procSP->Events().WaitForEventsToReset(event_mask, timeout); 119330fdc8d8SChris Lattner } 119430fdc8d8SChris Lattner return result; 119530fdc8d8SChris Lattner } 119630fdc8d8SChris Lattner 119730fdc8d8SChris Lattner void 119830fdc8d8SChris Lattner DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask) 119930fdc8d8SChris Lattner { 120030fdc8d8SChris Lattner MachProcessSP procSP; 120130fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 120230fdc8d8SChris Lattner procSP->Events().ResetEvents(event_mask); 120330fdc8d8SChris Lattner } 120430fdc8d8SChris Lattner 120530fdc8d8SChris Lattner // Breakpoints 1206d8cf1a11SGreg Clayton nub_bool_t 120730fdc8d8SChris Lattner DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware) 120830fdc8d8SChris Lattner { 120930fdc8d8SChris Lattner MachProcessSP procSP; 121030fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 1211d8cf1a11SGreg Clayton return procSP->CreateBreakpoint(addr, size, hardware) != NULL; 1212d8cf1a11SGreg Clayton return false; 121330fdc8d8SChris Lattner } 121430fdc8d8SChris Lattner 121530fdc8d8SChris Lattner nub_bool_t 1216d8cf1a11SGreg Clayton DNBBreakpointClear (nub_process_t pid, nub_addr_t addr) 121730fdc8d8SChris Lattner { 121830fdc8d8SChris Lattner MachProcessSP procSP; 121930fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 1220d8cf1a11SGreg Clayton return procSP->DisableBreakpoint(addr, true); 122130fdc8d8SChris Lattner return false; // Failed 122230fdc8d8SChris Lattner } 122330fdc8d8SChris Lattner 122430fdc8d8SChris Lattner 122530fdc8d8SChris Lattner //---------------------------------------------------------------------- 122630fdc8d8SChris Lattner // Watchpoints 122730fdc8d8SChris Lattner //---------------------------------------------------------------------- 1228d8cf1a11SGreg Clayton nub_bool_t 122930fdc8d8SChris Lattner DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware) 123030fdc8d8SChris Lattner { 123130fdc8d8SChris Lattner MachProcessSP procSP; 123230fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 1233d8cf1a11SGreg Clayton return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL; 1234d8cf1a11SGreg Clayton return false; 123530fdc8d8SChris Lattner } 123630fdc8d8SChris Lattner 123730fdc8d8SChris Lattner nub_bool_t 1238d8cf1a11SGreg Clayton DNBWatchpointClear (nub_process_t pid, nub_addr_t addr) 123930fdc8d8SChris Lattner { 124030fdc8d8SChris Lattner MachProcessSP procSP; 124130fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 1242d8cf1a11SGreg Clayton return procSP->DisableWatchpoint(addr, true); 124330fdc8d8SChris Lattner return false; // Failed 124430fdc8d8SChris Lattner } 124530fdc8d8SChris Lattner 124630fdc8d8SChris Lattner //---------------------------------------------------------------------- 124764637205SJohnny Chen // Return the number of supported hardware watchpoints. 124864637205SJohnny Chen //---------------------------------------------------------------------- 124964637205SJohnny Chen uint32_t 125064637205SJohnny Chen DNBWatchpointGetNumSupportedHWP (nub_process_t pid) 125164637205SJohnny Chen { 125264637205SJohnny Chen MachProcessSP procSP; 125364637205SJohnny Chen if (GetProcessSP (pid, procSP)) 125464637205SJohnny Chen return procSP->GetNumSupportedHardwareWatchpoints(); 125564637205SJohnny Chen return 0; 125664637205SJohnny Chen } 125764637205SJohnny Chen 125864637205SJohnny Chen //---------------------------------------------------------------------- 125930fdc8d8SChris Lattner // Read memory in the address space of process PID. This call will take 126030fdc8d8SChris Lattner // care of setting and restoring permissions and breaking up the memory 126130fdc8d8SChris Lattner // read into multiple chunks as required. 126230fdc8d8SChris Lattner // 126330fdc8d8SChris Lattner // RETURNS: number of bytes actually read 126430fdc8d8SChris Lattner //---------------------------------------------------------------------- 126530fdc8d8SChris Lattner nub_size_t 126630fdc8d8SChris Lattner DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf) 126730fdc8d8SChris Lattner { 126830fdc8d8SChris Lattner MachProcessSP procSP; 126930fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 127030fdc8d8SChris Lattner return procSP->ReadMemory(addr, size, buf); 127130fdc8d8SChris Lattner return 0; 127230fdc8d8SChris Lattner } 127330fdc8d8SChris Lattner 12740b90be1cSGreg Clayton uint64_t 12750b90be1cSGreg Clayton DNBProcessMemoryReadInteger (nub_process_t pid, nub_addr_t addr, nub_size_t integer_size, uint64_t fail_value) 12760b90be1cSGreg Clayton { 12770b90be1cSGreg Clayton union Integers 12780b90be1cSGreg Clayton { 12790b90be1cSGreg Clayton uint8_t u8; 12800b90be1cSGreg Clayton uint16_t u16; 12810b90be1cSGreg Clayton uint32_t u32; 12820b90be1cSGreg Clayton uint64_t u64; 12830b90be1cSGreg Clayton }; 12840b90be1cSGreg Clayton 12850b90be1cSGreg Clayton if (integer_size <= sizeof(uint64_t)) 12860b90be1cSGreg Clayton { 12870b90be1cSGreg Clayton Integers ints; 12880b90be1cSGreg Clayton if (DNBProcessMemoryRead(pid, addr, integer_size, &ints) == integer_size) 12890b90be1cSGreg Clayton { 12900b90be1cSGreg Clayton switch (integer_size) 12910b90be1cSGreg Clayton { 12920b90be1cSGreg Clayton case 1: return ints.u8; 12930b90be1cSGreg Clayton case 2: return ints.u16; 12940b90be1cSGreg Clayton case 3: return ints.u32 & 0xffffffu; 12950b90be1cSGreg Clayton case 4: return ints.u32; 12960b90be1cSGreg Clayton case 5: return ints.u32 & 0x000000ffffffffffull; 12970b90be1cSGreg Clayton case 6: return ints.u32 & 0x0000ffffffffffffull; 12980b90be1cSGreg Clayton case 7: return ints.u32 & 0x00ffffffffffffffull; 12990b90be1cSGreg Clayton case 8: return ints.u64; 13000b90be1cSGreg Clayton } 13010b90be1cSGreg Clayton } 13020b90be1cSGreg Clayton } 13030b90be1cSGreg Clayton return fail_value; 13040b90be1cSGreg Clayton 13050b90be1cSGreg Clayton } 13060b90be1cSGreg Clayton 13070b90be1cSGreg Clayton nub_addr_t 13080b90be1cSGreg Clayton DNBProcessMemoryReadPointer (nub_process_t pid, nub_addr_t addr) 13090b90be1cSGreg Clayton { 13100b90be1cSGreg Clayton cpu_type_t cputype = DNBProcessGetCPUType (pid); 13110b90be1cSGreg Clayton if (cputype) 13120b90be1cSGreg Clayton { 13130b90be1cSGreg Clayton const nub_size_t pointer_size = (cputype & CPU_ARCH_ABI64) ? 8 : 4; 13140b90be1cSGreg Clayton return DNBProcessMemoryReadInteger(pid, addr, pointer_size, 0); 13150b90be1cSGreg Clayton } 13160b90be1cSGreg Clayton return 0; 13170b90be1cSGreg Clayton 13180b90be1cSGreg Clayton } 13190b90be1cSGreg Clayton 13200b90be1cSGreg Clayton std::string 13210b90be1cSGreg Clayton DNBProcessMemoryReadCString (nub_process_t pid, nub_addr_t addr) 13220b90be1cSGreg Clayton { 13230b90be1cSGreg Clayton std::string cstr; 13240b90be1cSGreg Clayton char buffer[256]; 13250b90be1cSGreg Clayton const nub_size_t max_buffer_cstr_length = sizeof(buffer)-1; 13260b90be1cSGreg Clayton buffer[max_buffer_cstr_length] = '\0'; 13270b90be1cSGreg Clayton nub_size_t length = 0; 13280b90be1cSGreg Clayton nub_addr_t curr_addr = addr; 13290b90be1cSGreg Clayton do 13300b90be1cSGreg Clayton { 13310b90be1cSGreg Clayton nub_size_t bytes_read = DNBProcessMemoryRead(pid, curr_addr, max_buffer_cstr_length, buffer); 13320b90be1cSGreg Clayton if (bytes_read == 0) 13330b90be1cSGreg Clayton break; 13340b90be1cSGreg Clayton length = strlen(buffer); 13350b90be1cSGreg Clayton cstr.append(buffer, length); 13360b90be1cSGreg Clayton curr_addr += length; 13370b90be1cSGreg Clayton } while (length == max_buffer_cstr_length); 13380b90be1cSGreg Clayton return cstr; 13390b90be1cSGreg Clayton } 13400b90be1cSGreg Clayton 13410b90be1cSGreg Clayton std::string 13420b90be1cSGreg Clayton DNBProcessMemoryReadCStringFixed (nub_process_t pid, nub_addr_t addr, nub_size_t fixed_length) 13430b90be1cSGreg Clayton { 13440b90be1cSGreg Clayton std::string cstr; 13450b90be1cSGreg Clayton char buffer[fixed_length+1]; 13460b90be1cSGreg Clayton buffer[fixed_length] = '\0'; 13470b90be1cSGreg Clayton nub_size_t bytes_read = DNBProcessMemoryRead(pid, addr, fixed_length, buffer); 13480b90be1cSGreg Clayton if (bytes_read > 0) 13490b90be1cSGreg Clayton cstr.assign(buffer); 13500b90be1cSGreg Clayton return cstr; 13510b90be1cSGreg Clayton } 13520b90be1cSGreg Clayton 13530b90be1cSGreg Clayton 135430fdc8d8SChris Lattner //---------------------------------------------------------------------- 135530fdc8d8SChris Lattner // Write memory to the address space of process PID. This call will take 135630fdc8d8SChris Lattner // care of setting and restoring permissions and breaking up the memory 135730fdc8d8SChris Lattner // write into multiple chunks as required. 135830fdc8d8SChris Lattner // 135930fdc8d8SChris Lattner // RETURNS: number of bytes actually written 136030fdc8d8SChris Lattner //---------------------------------------------------------------------- 136130fdc8d8SChris Lattner nub_size_t 136230fdc8d8SChris Lattner DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf) 136330fdc8d8SChris Lattner { 136430fdc8d8SChris Lattner MachProcessSP procSP; 136530fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 136630fdc8d8SChris Lattner return procSP->WriteMemory(addr, size, buf); 136730fdc8d8SChris Lattner return 0; 136830fdc8d8SChris Lattner } 136930fdc8d8SChris Lattner 137030fdc8d8SChris Lattner nub_addr_t 137130fdc8d8SChris Lattner DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions) 137230fdc8d8SChris Lattner { 137330fdc8d8SChris Lattner MachProcessSP procSP; 137430fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 137530fdc8d8SChris Lattner return procSP->Task().AllocateMemory (size, permissions); 137630fdc8d8SChris Lattner return 0; 137730fdc8d8SChris Lattner } 137830fdc8d8SChris Lattner 137930fdc8d8SChris Lattner nub_bool_t 138030fdc8d8SChris Lattner DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr) 138130fdc8d8SChris Lattner { 138230fdc8d8SChris Lattner MachProcessSP procSP; 138330fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 138430fdc8d8SChris Lattner return procSP->Task().DeallocateMemory (addr); 138530fdc8d8SChris Lattner return 0; 138630fdc8d8SChris Lattner } 138730fdc8d8SChris Lattner 13881f3966beSJason Molenda //---------------------------------------------------------------------- 13893dc8583cSJason Molenda // Find attributes of the memory region that contains ADDR for process PID, 13903dc8583cSJason Molenda // if possible, and return a string describing those attributes. 13911f3966beSJason Molenda // 13923dc8583cSJason Molenda // Returns 1 if we could find attributes for this region and OUTBUF can 13933dc8583cSJason Molenda // be sent to the remote debugger. 13941f3966beSJason Molenda // 13953dc8583cSJason Molenda // Returns 0 if we couldn't find the attributes for a region of memory at 13963dc8583cSJason Molenda // that address and OUTBUF should not be sent. 13973dc8583cSJason Molenda // 13983dc8583cSJason Molenda // Returns -1 if this platform cannot look up information about memory regions 13993dc8583cSJason Molenda // or if we do not yet have a valid launched process. 14003dc8583cSJason Molenda // 14011f3966beSJason Molenda //---------------------------------------------------------------------- 14021f3966beSJason Molenda int 1403fc5dd29eSGreg Clayton DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info) 14041f3966beSJason Molenda { 14051f3966beSJason Molenda MachProcessSP procSP; 14061f3966beSJason Molenda if (GetProcessSP (pid, procSP)) 140746fb558dSGreg Clayton return procSP->Task().GetMemoryRegionInfo (addr, region_info); 140846fb558dSGreg Clayton 14091f3966beSJason Molenda return -1; 14101f3966beSJason Molenda } 14111f3966beSJason Molenda 1412929a94f0SHan Ming Ong std::string 14138764fe7dSHan Ming Ong DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType) 1414ab3b8b22SHan Ming Ong { 1415ab3b8b22SHan Ming Ong MachProcessSP procSP; 1416ab3b8b22SHan Ming Ong if (GetProcessSP (pid, procSP)) 14178764fe7dSHan Ming Ong return procSP->Task().GetProfileData(scanType); 1418ab3b8b22SHan Ming Ong 1419929a94f0SHan Ming Ong return std::string(""); 1420ab3b8b22SHan Ming Ong } 1421ab3b8b22SHan Ming Ong 1422ab3b8b22SHan Ming Ong nub_bool_t 14238764fe7dSHan Ming Ong DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type) 1424ab3b8b22SHan Ming Ong { 1425ab3b8b22SHan Ming Ong MachProcessSP procSP; 1426ab3b8b22SHan Ming Ong if (GetProcessSP (pid, procSP)) 1427ab3b8b22SHan Ming Ong { 14288764fe7dSHan Ming Ong procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type); 1429ab3b8b22SHan Ming Ong return true; 1430ab3b8b22SHan Ming Ong } 1431ab3b8b22SHan Ming Ong 1432ab3b8b22SHan Ming Ong return false; 1433ab3b8b22SHan Ming Ong } 143430fdc8d8SChris Lattner 143530fdc8d8SChris Lattner //---------------------------------------------------------------------- 143630fdc8d8SChris Lattner // Get the number of threads for the specified process. 143730fdc8d8SChris Lattner //---------------------------------------------------------------------- 143830fdc8d8SChris Lattner nub_size_t 143930fdc8d8SChris Lattner DNBProcessGetNumThreads (nub_process_t pid) 144030fdc8d8SChris Lattner { 144130fdc8d8SChris Lattner MachProcessSP procSP; 144230fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 144330fdc8d8SChris Lattner return procSP->GetNumThreads(); 144430fdc8d8SChris Lattner return 0; 144530fdc8d8SChris Lattner } 144630fdc8d8SChris Lattner 144730fdc8d8SChris Lattner //---------------------------------------------------------------------- 144830fdc8d8SChris Lattner // Get the thread ID of the current thread. 144930fdc8d8SChris Lattner //---------------------------------------------------------------------- 145030fdc8d8SChris Lattner nub_thread_t 145130fdc8d8SChris Lattner DNBProcessGetCurrentThread (nub_process_t pid) 145230fdc8d8SChris Lattner { 145330fdc8d8SChris Lattner MachProcessSP procSP; 145430fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 145530fdc8d8SChris Lattner return procSP->GetCurrentThread(); 145630fdc8d8SChris Lattner return 0; 145730fdc8d8SChris Lattner } 145830fdc8d8SChris Lattner 145930fdc8d8SChris Lattner //---------------------------------------------------------------------- 1460d5318c0cSJason Molenda // Get the mach port number of the current thread. 1461d5318c0cSJason Molenda //---------------------------------------------------------------------- 1462d5318c0cSJason Molenda nub_thread_t 1463d5318c0cSJason Molenda DNBProcessGetCurrentThreadMachPort (nub_process_t pid) 1464d5318c0cSJason Molenda { 1465d5318c0cSJason Molenda MachProcessSP procSP; 1466d5318c0cSJason Molenda if (GetProcessSP (pid, procSP)) 1467d5318c0cSJason Molenda return procSP->GetCurrentThreadMachPort(); 1468d5318c0cSJason Molenda return 0; 1469d5318c0cSJason Molenda } 1470d5318c0cSJason Molenda 1471d5318c0cSJason Molenda //---------------------------------------------------------------------- 147230fdc8d8SChris Lattner // Change the current thread. 147330fdc8d8SChris Lattner //---------------------------------------------------------------------- 147430fdc8d8SChris Lattner nub_thread_t 147530fdc8d8SChris Lattner DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid) 147630fdc8d8SChris Lattner { 147730fdc8d8SChris Lattner MachProcessSP procSP; 147830fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 147930fdc8d8SChris Lattner return procSP->SetCurrentThread (tid); 148030fdc8d8SChris Lattner return INVALID_NUB_THREAD; 148130fdc8d8SChris Lattner } 148230fdc8d8SChris Lattner 148330fdc8d8SChris Lattner 148430fdc8d8SChris Lattner //---------------------------------------------------------------------- 148530fdc8d8SChris Lattner // Dump a string describing a thread's stop reason to the specified file 148630fdc8d8SChris Lattner // handle 148730fdc8d8SChris Lattner //---------------------------------------------------------------------- 148830fdc8d8SChris Lattner nub_bool_t 148930fdc8d8SChris Lattner DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, struct DNBThreadStopInfo *stop_info) 149030fdc8d8SChris Lattner { 149130fdc8d8SChris Lattner MachProcessSP procSP; 149230fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 149330fdc8d8SChris Lattner return procSP->GetThreadStoppedReason (tid, stop_info); 149430fdc8d8SChris Lattner return false; 149530fdc8d8SChris Lattner } 149630fdc8d8SChris Lattner 149730fdc8d8SChris Lattner //---------------------------------------------------------------------- 149830fdc8d8SChris Lattner // Return string description for the specified thread. 149930fdc8d8SChris Lattner // 150030fdc8d8SChris Lattner // RETURNS: NULL if the thread isn't valid, else a NULL terminated C 150130fdc8d8SChris Lattner // string from a static buffer that must be copied prior to subsequent 150230fdc8d8SChris Lattner // calls. 150330fdc8d8SChris Lattner //---------------------------------------------------------------------- 150430fdc8d8SChris Lattner const char * 150530fdc8d8SChris Lattner DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid) 150630fdc8d8SChris Lattner { 150730fdc8d8SChris Lattner MachProcessSP procSP; 150830fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 150930fdc8d8SChris Lattner return procSP->GetThreadInfo (tid); 151030fdc8d8SChris Lattner return NULL; 151130fdc8d8SChris Lattner } 151230fdc8d8SChris Lattner 151330fdc8d8SChris Lattner //---------------------------------------------------------------------- 151430fdc8d8SChris Lattner // Get the thread ID given a thread index. 151530fdc8d8SChris Lattner //---------------------------------------------------------------------- 151630fdc8d8SChris Lattner nub_thread_t 151730fdc8d8SChris Lattner DNBProcessGetThreadAtIndex (nub_process_t pid, size_t thread_idx) 151830fdc8d8SChris Lattner { 151930fdc8d8SChris Lattner MachProcessSP procSP; 152030fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 152130fdc8d8SChris Lattner return procSP->GetThreadAtIndex (thread_idx); 152230fdc8d8SChris Lattner return INVALID_NUB_THREAD; 152330fdc8d8SChris Lattner } 152430fdc8d8SChris Lattner 1525279ceecfSJim Ingham //---------------------------------------------------------------------- 1526279ceecfSJim Ingham // Do whatever is needed to sync the thread's register state with it's kernel values. 1527279ceecfSJim Ingham //---------------------------------------------------------------------- 1528279ceecfSJim Ingham nub_bool_t 1529279ceecfSJim Ingham DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid) 1530279ceecfSJim Ingham { 1531279ceecfSJim Ingham MachProcessSP procSP; 1532279ceecfSJim Ingham if (GetProcessSP (pid, procSP)) 1533279ceecfSJim Ingham return procSP->SyncThreadState (tid); 1534279ceecfSJim Ingham return false; 1535279ceecfSJim Ingham 1536279ceecfSJim Ingham } 1537279ceecfSJim Ingham 153830fdc8d8SChris Lattner nub_addr_t 153930fdc8d8SChris Lattner DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid) 154030fdc8d8SChris Lattner { 154130fdc8d8SChris Lattner MachProcessSP procSP; 154230fdc8d8SChris Lattner DNBError err; 154330fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 154430fdc8d8SChris Lattner return procSP->Task().GetDYLDAllImageInfosAddress (err); 154530fdc8d8SChris Lattner return INVALID_NUB_ADDRESS; 154630fdc8d8SChris Lattner } 154730fdc8d8SChris Lattner 154830fdc8d8SChris Lattner 154930fdc8d8SChris Lattner nub_bool_t 155030fdc8d8SChris Lattner DNBProcessSharedLibrariesUpdated(nub_process_t pid) 155130fdc8d8SChris Lattner { 155230fdc8d8SChris Lattner MachProcessSP procSP; 155330fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 155430fdc8d8SChris Lattner { 155530fdc8d8SChris Lattner procSP->SharedLibrariesUpdated (); 155630fdc8d8SChris Lattner return true; 155730fdc8d8SChris Lattner } 155830fdc8d8SChris Lattner return false; 155930fdc8d8SChris Lattner } 156030fdc8d8SChris Lattner 156130fdc8d8SChris Lattner //---------------------------------------------------------------------- 156230fdc8d8SChris Lattner // Get the current shared library information for a process. Only return 156330fdc8d8SChris Lattner // the shared libraries that have changed since the last shared library 156430fdc8d8SChris Lattner // state changed event if only_changed is non-zero. 156530fdc8d8SChris Lattner //---------------------------------------------------------------------- 156630fdc8d8SChris Lattner nub_size_t 156730fdc8d8SChris Lattner DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, struct DNBExecutableImageInfo **image_infos) 156830fdc8d8SChris Lattner { 156930fdc8d8SChris Lattner MachProcessSP procSP; 157030fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 157130fdc8d8SChris Lattner return procSP->CopyImageInfos (image_infos, only_changed); 157230fdc8d8SChris Lattner 157330fdc8d8SChris Lattner // If we have no process, then return NULL for the shared library info 157430fdc8d8SChris Lattner // and zero for shared library count 157530fdc8d8SChris Lattner *image_infos = NULL; 157630fdc8d8SChris Lattner return 0; 157730fdc8d8SChris Lattner } 157830fdc8d8SChris Lattner 1579d04f0edaSGreg Clayton uint32_t 1580d04f0edaSGreg Clayton DNBGetRegisterCPUType() 1581d04f0edaSGreg Clayton { 1582d04f0edaSGreg Clayton return DNBArchProtocol::GetRegisterCPUType (); 1583d04f0edaSGreg Clayton 1584d04f0edaSGreg Clayton } 158530fdc8d8SChris Lattner //---------------------------------------------------------------------- 158630fdc8d8SChris Lattner // Get the register set information for a specific thread. 158730fdc8d8SChris Lattner //---------------------------------------------------------------------- 158830fdc8d8SChris Lattner const DNBRegisterSetInfo * 158930fdc8d8SChris Lattner DNBGetRegisterSetInfo (nub_size_t *num_reg_sets) 159030fdc8d8SChris Lattner { 15913af9ea56SGreg Clayton return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets); 159230fdc8d8SChris Lattner } 159330fdc8d8SChris Lattner 159430fdc8d8SChris Lattner 159530fdc8d8SChris Lattner //---------------------------------------------------------------------- 159630fdc8d8SChris Lattner // Read a register value by register set and register index. 159730fdc8d8SChris Lattner //---------------------------------------------------------------------- 159830fdc8d8SChris Lattner nub_bool_t 159930fdc8d8SChris Lattner DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value) 160030fdc8d8SChris Lattner { 160130fdc8d8SChris Lattner MachProcessSP procSP; 160230fdc8d8SChris Lattner ::bzero (value, sizeof(DNBRegisterValue)); 160330fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 160430fdc8d8SChris Lattner { 160530fdc8d8SChris Lattner if (tid != INVALID_NUB_THREAD) 160630fdc8d8SChris Lattner return procSP->GetRegisterValue (tid, set, reg, value); 160730fdc8d8SChris Lattner } 160830fdc8d8SChris Lattner return false; 160930fdc8d8SChris Lattner } 161030fdc8d8SChris Lattner 161130fdc8d8SChris Lattner nub_bool_t 161230fdc8d8SChris Lattner DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value) 161330fdc8d8SChris Lattner { 161430fdc8d8SChris Lattner if (tid != INVALID_NUB_THREAD) 161530fdc8d8SChris Lattner { 161630fdc8d8SChris Lattner MachProcessSP procSP; 161730fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 161830fdc8d8SChris Lattner return procSP->SetRegisterValue (tid, set, reg, value); 161930fdc8d8SChris Lattner } 162030fdc8d8SChris Lattner return false; 162130fdc8d8SChris Lattner } 162230fdc8d8SChris Lattner 162330fdc8d8SChris Lattner nub_size_t 162430fdc8d8SChris Lattner DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len) 162530fdc8d8SChris Lattner { 162630fdc8d8SChris Lattner MachProcessSP procSP; 162730fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 162830fdc8d8SChris Lattner { 162930fdc8d8SChris Lattner if (tid != INVALID_NUB_THREAD) 163030fdc8d8SChris Lattner return procSP->GetThreadList().GetRegisterContext (tid, buf, buf_len); 163130fdc8d8SChris Lattner } 163230fdc8d8SChris Lattner ::bzero (buf, buf_len); 163330fdc8d8SChris Lattner return 0; 163430fdc8d8SChris Lattner 163530fdc8d8SChris Lattner } 163630fdc8d8SChris Lattner 163730fdc8d8SChris Lattner nub_size_t 163830fdc8d8SChris Lattner DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len) 163930fdc8d8SChris Lattner { 164030fdc8d8SChris Lattner MachProcessSP procSP; 164130fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 164230fdc8d8SChris Lattner { 164330fdc8d8SChris Lattner if (tid != INVALID_NUB_THREAD) 164430fdc8d8SChris Lattner return procSP->GetThreadList().SetRegisterContext (tid, buf, buf_len); 164530fdc8d8SChris Lattner } 164630fdc8d8SChris Lattner return 0; 164730fdc8d8SChris Lattner } 164830fdc8d8SChris Lattner 1649f74cf86bSGreg Clayton uint32_t 1650f74cf86bSGreg Clayton DNBThreadSaveRegisterState (nub_process_t pid, nub_thread_t tid) 1651f74cf86bSGreg Clayton { 1652f74cf86bSGreg Clayton if (tid != INVALID_NUB_THREAD) 1653f74cf86bSGreg Clayton { 1654f74cf86bSGreg Clayton MachProcessSP procSP; 1655f74cf86bSGreg Clayton if (GetProcessSP (pid, procSP)) 1656f74cf86bSGreg Clayton return procSP->GetThreadList().SaveRegisterState (tid); 1657f74cf86bSGreg Clayton } 1658f74cf86bSGreg Clayton return 0; 1659f74cf86bSGreg Clayton } 1660f74cf86bSGreg Clayton nub_bool_t 1661f74cf86bSGreg Clayton DNBThreadRestoreRegisterState (nub_process_t pid, nub_thread_t tid, uint32_t save_id) 1662f74cf86bSGreg Clayton { 1663f74cf86bSGreg Clayton if (tid != INVALID_NUB_THREAD) 1664f74cf86bSGreg Clayton { 1665f74cf86bSGreg Clayton MachProcessSP procSP; 1666f74cf86bSGreg Clayton if (GetProcessSP (pid, procSP)) 1667f74cf86bSGreg Clayton return procSP->GetThreadList().RestoreRegisterState (tid, save_id); 1668f74cf86bSGreg Clayton } 1669f74cf86bSGreg Clayton return false; 1670f74cf86bSGreg Clayton } 1671f74cf86bSGreg Clayton 1672f74cf86bSGreg Clayton 1673f74cf86bSGreg Clayton 167430fdc8d8SChris Lattner //---------------------------------------------------------------------- 167530fdc8d8SChris Lattner // Read a register value by name. 167630fdc8d8SChris Lattner //---------------------------------------------------------------------- 167730fdc8d8SChris Lattner nub_bool_t 167830fdc8d8SChris Lattner DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t reg_set, const char *reg_name, DNBRegisterValue *value) 167930fdc8d8SChris Lattner { 168030fdc8d8SChris Lattner MachProcessSP procSP; 168130fdc8d8SChris Lattner ::bzero (value, sizeof(DNBRegisterValue)); 168230fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 168330fdc8d8SChris Lattner { 168430fdc8d8SChris Lattner const struct DNBRegisterSetInfo *set_info; 168530fdc8d8SChris Lattner nub_size_t num_reg_sets = 0; 168630fdc8d8SChris Lattner set_info = DNBGetRegisterSetInfo (&num_reg_sets); 168730fdc8d8SChris Lattner if (set_info) 168830fdc8d8SChris Lattner { 168930fdc8d8SChris Lattner uint32_t set = reg_set; 169030fdc8d8SChris Lattner uint32_t reg; 169130fdc8d8SChris Lattner if (set == REGISTER_SET_ALL) 169230fdc8d8SChris Lattner { 169330fdc8d8SChris Lattner for (set = 1; set < num_reg_sets; ++set) 169430fdc8d8SChris Lattner { 169530fdc8d8SChris Lattner for (reg = 0; reg < set_info[set].num_registers; ++reg) 169630fdc8d8SChris Lattner { 169730fdc8d8SChris Lattner if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0) 169830fdc8d8SChris Lattner return procSP->GetRegisterValue (tid, set, reg, value); 169930fdc8d8SChris Lattner } 170030fdc8d8SChris Lattner } 170130fdc8d8SChris Lattner } 170230fdc8d8SChris Lattner else 170330fdc8d8SChris Lattner { 170430fdc8d8SChris Lattner for (reg = 0; reg < set_info[set].num_registers; ++reg) 170530fdc8d8SChris Lattner { 170630fdc8d8SChris Lattner if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0) 170730fdc8d8SChris Lattner return procSP->GetRegisterValue (tid, set, reg, value); 170830fdc8d8SChris Lattner } 170930fdc8d8SChris Lattner } 171030fdc8d8SChris Lattner } 171130fdc8d8SChris Lattner } 171230fdc8d8SChris Lattner return false; 171330fdc8d8SChris Lattner } 171430fdc8d8SChris Lattner 171530fdc8d8SChris Lattner 171630fdc8d8SChris Lattner //---------------------------------------------------------------------- 171730fdc8d8SChris Lattner // Read a register set and register number from the register name. 171830fdc8d8SChris Lattner //---------------------------------------------------------------------- 171930fdc8d8SChris Lattner nub_bool_t 172030fdc8d8SChris Lattner DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info) 172130fdc8d8SChris Lattner { 172230fdc8d8SChris Lattner const struct DNBRegisterSetInfo *set_info; 172330fdc8d8SChris Lattner nub_size_t num_reg_sets = 0; 172430fdc8d8SChris Lattner set_info = DNBGetRegisterSetInfo (&num_reg_sets); 172530fdc8d8SChris Lattner if (set_info) 172630fdc8d8SChris Lattner { 172730fdc8d8SChris Lattner uint32_t set, reg; 172830fdc8d8SChris Lattner for (set = 1; set < num_reg_sets; ++set) 172930fdc8d8SChris Lattner { 173030fdc8d8SChris Lattner for (reg = 0; reg < set_info[set].num_registers; ++reg) 173130fdc8d8SChris Lattner { 173230fdc8d8SChris Lattner if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0) 173330fdc8d8SChris Lattner { 173430fdc8d8SChris Lattner *info = set_info[set].registers[reg]; 173530fdc8d8SChris Lattner return true; 173630fdc8d8SChris Lattner } 173730fdc8d8SChris Lattner } 173830fdc8d8SChris Lattner } 173930fdc8d8SChris Lattner 174030fdc8d8SChris Lattner for (set = 1; set < num_reg_sets; ++set) 174130fdc8d8SChris Lattner { 174230fdc8d8SChris Lattner uint32_t reg; 174330fdc8d8SChris Lattner for (reg = 0; reg < set_info[set].num_registers; ++reg) 174430fdc8d8SChris Lattner { 174530fdc8d8SChris Lattner if (set_info[set].registers[reg].alt == NULL) 174630fdc8d8SChris Lattner continue; 174730fdc8d8SChris Lattner 174830fdc8d8SChris Lattner if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0) 174930fdc8d8SChris Lattner { 175030fdc8d8SChris Lattner *info = set_info[set].registers[reg]; 175130fdc8d8SChris Lattner return true; 175230fdc8d8SChris Lattner } 175330fdc8d8SChris Lattner } 175430fdc8d8SChris Lattner } 175530fdc8d8SChris Lattner } 175630fdc8d8SChris Lattner 175730fdc8d8SChris Lattner ::bzero (info, sizeof(DNBRegisterInfo)); 175830fdc8d8SChris Lattner return false; 175930fdc8d8SChris Lattner } 176030fdc8d8SChris Lattner 176130fdc8d8SChris Lattner 176230fdc8d8SChris Lattner //---------------------------------------------------------------------- 176330fdc8d8SChris Lattner // Set the name to address callback function that this nub can use 176430fdc8d8SChris Lattner // for any name to address lookups that are needed. 176530fdc8d8SChris Lattner //---------------------------------------------------------------------- 176630fdc8d8SChris Lattner nub_bool_t 176730fdc8d8SChris Lattner DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton) 176830fdc8d8SChris Lattner { 176930fdc8d8SChris Lattner MachProcessSP procSP; 177030fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 177130fdc8d8SChris Lattner { 177230fdc8d8SChris Lattner procSP->SetNameToAddressCallback (callback, baton); 177330fdc8d8SChris Lattner return true; 177430fdc8d8SChris Lattner } 177530fdc8d8SChris Lattner return false; 177630fdc8d8SChris Lattner } 177730fdc8d8SChris Lattner 177830fdc8d8SChris Lattner 177930fdc8d8SChris Lattner //---------------------------------------------------------------------- 178030fdc8d8SChris Lattner // Set the name to address callback function that this nub can use 178130fdc8d8SChris Lattner // for any name to address lookups that are needed. 178230fdc8d8SChris Lattner //---------------------------------------------------------------------- 178330fdc8d8SChris Lattner nub_bool_t 178430fdc8d8SChris Lattner DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void *baton) 178530fdc8d8SChris Lattner { 178630fdc8d8SChris Lattner MachProcessSP procSP; 178730fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 178830fdc8d8SChris Lattner { 178930fdc8d8SChris Lattner procSP->SetSharedLibraryInfoCallback (callback, baton); 179030fdc8d8SChris Lattner return true; 179130fdc8d8SChris Lattner } 179230fdc8d8SChris Lattner return false; 179330fdc8d8SChris Lattner } 179430fdc8d8SChris Lattner 179530fdc8d8SChris Lattner nub_addr_t 179630fdc8d8SChris Lattner DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib) 179730fdc8d8SChris Lattner { 179830fdc8d8SChris Lattner MachProcessSP procSP; 179930fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 180030fdc8d8SChris Lattner { 180130fdc8d8SChris Lattner return procSP->LookupSymbol (name, shlib); 180230fdc8d8SChris Lattner } 180330fdc8d8SChris Lattner return INVALID_NUB_ADDRESS; 180430fdc8d8SChris Lattner } 180530fdc8d8SChris Lattner 180630fdc8d8SChris Lattner 180730fdc8d8SChris Lattner nub_size_t 180830fdc8d8SChris Lattner DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size) 180930fdc8d8SChris Lattner { 181030fdc8d8SChris Lattner MachProcessSP procSP; 181130fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 181230fdc8d8SChris Lattner return procSP->GetAvailableSTDOUT (buf, buf_size); 181330fdc8d8SChris Lattner return 0; 181430fdc8d8SChris Lattner } 181530fdc8d8SChris Lattner 181630fdc8d8SChris Lattner nub_size_t 181730fdc8d8SChris Lattner DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size) 181830fdc8d8SChris Lattner { 181930fdc8d8SChris Lattner MachProcessSP procSP; 182030fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 182130fdc8d8SChris Lattner return procSP->GetAvailableSTDERR (buf, buf_size); 182230fdc8d8SChris Lattner return 0; 182330fdc8d8SChris Lattner } 182430fdc8d8SChris Lattner 182530fdc8d8SChris Lattner nub_size_t 1826ab3b8b22SHan Ming Ong DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size) 1827ab3b8b22SHan Ming Ong { 1828ab3b8b22SHan Ming Ong MachProcessSP procSP; 1829ab3b8b22SHan Ming Ong if (GetProcessSP (pid, procSP)) 1830ab3b8b22SHan Ming Ong return procSP->GetAsyncProfileData (buf, buf_size); 1831ab3b8b22SHan Ming Ong return 0; 1832ab3b8b22SHan Ming Ong } 1833ab3b8b22SHan Ming Ong 1834ab3b8b22SHan Ming Ong nub_size_t 183530fdc8d8SChris Lattner DNBProcessGetStopCount (nub_process_t pid) 183630fdc8d8SChris Lattner { 183730fdc8d8SChris Lattner MachProcessSP procSP; 183830fdc8d8SChris Lattner if (GetProcessSP (pid, procSP)) 183930fdc8d8SChris Lattner return procSP->StopCount(); 184030fdc8d8SChris Lattner return 0; 184130fdc8d8SChris Lattner } 184230fdc8d8SChris Lattner 184371337622SGreg Clayton uint32_t 184471337622SGreg Clayton DNBProcessGetCPUType (nub_process_t pid) 184571337622SGreg Clayton { 184671337622SGreg Clayton MachProcessSP procSP; 184771337622SGreg Clayton if (GetProcessSP (pid, procSP)) 184871337622SGreg Clayton return procSP->GetCPUType (); 184971337622SGreg Clayton return 0; 185071337622SGreg Clayton 185171337622SGreg Clayton } 185271337622SGreg Clayton 185330fdc8d8SChris Lattner nub_bool_t 185430fdc8d8SChris Lattner DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size) 185530fdc8d8SChris Lattner { 185630fdc8d8SChris Lattner if (path == NULL || path[0] == '\0') 185730fdc8d8SChris Lattner return false; 185830fdc8d8SChris Lattner 185930fdc8d8SChris Lattner char max_path[PATH_MAX]; 186030fdc8d8SChris Lattner std::string result; 186130fdc8d8SChris Lattner CFString::GlobPath(path, result); 186230fdc8d8SChris Lattner 186330fdc8d8SChris Lattner if (result.empty()) 186430fdc8d8SChris Lattner result = path; 186530fdc8d8SChris Lattner 186648baf7a7SGreg Clayton struct stat path_stat; 186748baf7a7SGreg Clayton if (::stat(path, &path_stat) == 0) 186848baf7a7SGreg Clayton { 186948baf7a7SGreg Clayton if ((path_stat.st_mode & S_IFMT) == S_IFDIR) 187048baf7a7SGreg Clayton { 187148baf7a7SGreg Clayton CFBundle bundle (path); 187248baf7a7SGreg Clayton CFReleaser<CFURLRef> url(bundle.CopyExecutableURL ()); 187348baf7a7SGreg Clayton if (url.get()) 187448baf7a7SGreg Clayton { 187548baf7a7SGreg Clayton if (::CFURLGetFileSystemRepresentation (url.get(), true, (UInt8*)resolved_path, resolved_path_size)) 187648baf7a7SGreg Clayton return true; 187748baf7a7SGreg Clayton } 187848baf7a7SGreg Clayton } 187948baf7a7SGreg Clayton } 188048baf7a7SGreg Clayton 188130fdc8d8SChris Lattner if (realpath(path, max_path)) 188230fdc8d8SChris Lattner { 188330fdc8d8SChris Lattner // Found the path relatively... 188430fdc8d8SChris Lattner ::strncpy(resolved_path, max_path, resolved_path_size); 188530fdc8d8SChris Lattner return strlen(resolved_path) + 1 < resolved_path_size; 188630fdc8d8SChris Lattner } 188730fdc8d8SChris Lattner else 188830fdc8d8SChris Lattner { 188930fdc8d8SChris Lattner // Not a relative path, check the PATH environment variable if the 189030fdc8d8SChris Lattner const char *PATH = getenv("PATH"); 189130fdc8d8SChris Lattner if (PATH) 189230fdc8d8SChris Lattner { 189330fdc8d8SChris Lattner const char *curr_path_start = PATH; 189430fdc8d8SChris Lattner const char *curr_path_end; 189530fdc8d8SChris Lattner while (curr_path_start && *curr_path_start) 189630fdc8d8SChris Lattner { 189730fdc8d8SChris Lattner curr_path_end = strchr(curr_path_start, ':'); 189830fdc8d8SChris Lattner if (curr_path_end == NULL) 189930fdc8d8SChris Lattner { 190030fdc8d8SChris Lattner result.assign(curr_path_start); 190130fdc8d8SChris Lattner curr_path_start = NULL; 190230fdc8d8SChris Lattner } 190330fdc8d8SChris Lattner else if (curr_path_end > curr_path_start) 190430fdc8d8SChris Lattner { 190530fdc8d8SChris Lattner size_t len = curr_path_end - curr_path_start; 190630fdc8d8SChris Lattner result.assign(curr_path_start, len); 190730fdc8d8SChris Lattner curr_path_start += len + 1; 190830fdc8d8SChris Lattner } 190930fdc8d8SChris Lattner else 191030fdc8d8SChris Lattner break; 191130fdc8d8SChris Lattner 191230fdc8d8SChris Lattner result += '/'; 191330fdc8d8SChris Lattner result += path; 191430fdc8d8SChris Lattner struct stat s; 191530fdc8d8SChris Lattner if (stat(result.c_str(), &s) == 0) 191630fdc8d8SChris Lattner { 191730fdc8d8SChris Lattner ::strncpy(resolved_path, result.c_str(), resolved_path_size); 191830fdc8d8SChris Lattner return result.size() + 1 < resolved_path_size; 191930fdc8d8SChris Lattner } 192030fdc8d8SChris Lattner } 192130fdc8d8SChris Lattner } 192230fdc8d8SChris Lattner } 192330fdc8d8SChris Lattner return false; 192430fdc8d8SChris Lattner } 192530fdc8d8SChris Lattner 19263af9ea56SGreg Clayton 19273af9ea56SGreg Clayton void 19283af9ea56SGreg Clayton DNBInitialize() 19293af9ea56SGreg Clayton { 19303af9ea56SGreg Clayton DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()"); 19313af9ea56SGreg Clayton #if defined (__i386__) || defined (__x86_64__) 19323af9ea56SGreg Clayton DNBArchImplI386::Initialize(); 19333af9ea56SGreg Clayton DNBArchImplX86_64::Initialize(); 1934013434e5STodd Fiala #elif defined (__arm__) || defined (__arm64__) || defined (__aarch64__) 19353af9ea56SGreg Clayton DNBArchMachARM::Initialize(); 1936a332978bSJason Molenda DNBArchMachARM64::Initialize(); 19373af9ea56SGreg Clayton #endif 19383af9ea56SGreg Clayton } 19393af9ea56SGreg Clayton 19403af9ea56SGreg Clayton void 19413af9ea56SGreg Clayton DNBTerminate() 19423af9ea56SGreg Clayton { 19433af9ea56SGreg Clayton } 19443c14438fSGreg Clayton 19453c14438fSGreg Clayton nub_bool_t 19463c14438fSGreg Clayton DNBSetArchitecture (const char *arch) 19473c14438fSGreg Clayton { 19483c14438fSGreg Clayton if (arch && arch[0]) 19493c14438fSGreg Clayton { 19503c14438fSGreg Clayton if (strcasecmp (arch, "i386") == 0) 19513c14438fSGreg Clayton return DNBArchProtocol::SetArchitecture (CPU_TYPE_I386); 1952a86dc433SGreg Clayton else if ((strcasecmp (arch, "x86_64") == 0) || (strcasecmp (arch, "x86_64h") == 0)) 19533c14438fSGreg Clayton return DNBArchProtocol::SetArchitecture (CPU_TYPE_X86_64); 1954013434e5STodd Fiala else if (strstr (arch, "arm64") == arch || strstr (arch, "armv8") == arch || strstr (arch, "aarch64") == arch) 1955a332978bSJason Molenda return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM64); 19563c14438fSGreg Clayton else if (strstr (arch, "arm") == arch) 19573c14438fSGreg Clayton return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM); 19583c14438fSGreg Clayton } 19593c14438fSGreg Clayton return false; 19603c14438fSGreg Clayton } 1961