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