428 printf("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid); |
430 printf("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid); |
429 |
431 |
430 return (jint) usable_tid; |
432 return (jint) usable_tid; |
431 } |
433 } |
432 |
434 |
|
435 |
|
436 static bool ptrace_continue(pid_t pid, int signal) { |
|
437 // pass the signal to the process so we don't swallow it |
|
438 int res; |
|
439 if ((res = ptrace(PT_CONTINUE, pid, (caddr_t)1, signal)) < 0) { |
|
440 fprintf(stderr, "attach: ptrace(PT_CONTINUE, %d) failed with %d\n", pid, res); |
|
441 return false; |
|
442 } |
|
443 return true; |
|
444 } |
|
445 |
|
446 // waits until the ATTACH has stopped the process |
|
447 // by signal SIGSTOP |
|
448 static bool ptrace_waitpid(pid_t pid) { |
|
449 int ret; |
|
450 int status; |
|
451 while (true) { |
|
452 // Wait for debuggee to stop. |
|
453 ret = waitpid(pid, &status, 0); |
|
454 if (ret >= 0) { |
|
455 if (WIFSTOPPED(status)) { |
|
456 // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP |
|
457 // will still be pending and delivered when the process is DETACHED and the process |
|
458 // will go to sleep. |
|
459 if (WSTOPSIG(status) == SIGSTOP) { |
|
460 // Debuggee stopped by SIGSTOP. |
|
461 return true; |
|
462 } |
|
463 if (!ptrace_continue(pid, WSTOPSIG(status))) { |
|
464 fprintf(stderr, "attach: Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status)); |
|
465 return false; |
|
466 } |
|
467 } else { |
|
468 fprintf(stderr, "attach: waitpid(): Child process exited/terminated (status = 0x%x)\n", status); |
|
469 return false; |
|
470 } |
|
471 } else { |
|
472 switch (errno) { |
|
473 case EINTR: |
|
474 continue; |
|
475 break; |
|
476 case ECHILD: |
|
477 fprintf(stderr, "attach: waitpid() failed. Child process pid (%d) does not exist \n", pid); |
|
478 break; |
|
479 case EINVAL: |
|
480 fprintf(stderr, "attach: waitpid() failed. Invalid options argument.\n"); |
|
481 break; |
|
482 default: |
|
483 fprintf(stderr, "attach: waitpid() failed. Unexpected error %d\n",errno); |
|
484 break; |
|
485 } |
|
486 return false; |
|
487 } |
|
488 } |
|
489 } |
|
490 |
|
491 // attach to a process/thread specified by "pid" |
|
492 static bool ptrace_attach(pid_t pid) { |
|
493 int res; |
|
494 if ((res = ptrace(PT_ATTACH, pid, 0, 0)) < 0) { |
|
495 fprintf(stderr, "ptrace(PT_ATTACH, %d) failed with %d\n", pid, res); |
|
496 return false; |
|
497 } else { |
|
498 return ptrace_waitpid(pid); |
|
499 } |
|
500 } |
|
501 |
433 /* |
502 /* |
434 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal |
503 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal |
435 * Method: attach0 |
504 * Method: attach0 |
436 * Signature: (I)V |
505 * Signature: (I)V |
437 */ |
506 */ |
443 if (getenv("JAVA_SAPROC_DEBUG") != NULL) |
512 if (getenv("JAVA_SAPROC_DEBUG") != NULL) |
444 debug = JNI_TRUE; |
513 debug = JNI_TRUE; |
445 else |
514 else |
446 debug = JNI_FALSE; |
515 debug = JNI_FALSE; |
447 if (debug) printf("attach0 called for jpid=%d\n", (int)jpid); |
516 if (debug) printf("attach0 called for jpid=%d\n", (int)jpid); |
448 |
517 |
|
518 // get the task from the pid |
449 kern_return_t result; |
519 kern_return_t result; |
450 task_t gTask = 0; |
520 task_t gTask = 0; |
451 result = task_for_pid(mach_task_self(), jpid, &gTask); |
521 result = task_for_pid(mach_task_self(), jpid, &gTask); |
452 if (result != KERN_SUCCESS) { |
522 if (result != KERN_SUCCESS) { |
453 fprintf(stderr, "attach: task_for_pid(%d) failed (%d)\n", (int)jpid, result); |
523 fprintf(stderr, "attach: task_for_pid(%d) failed (%d)\n", (int)jpid, result); |
454 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); |
524 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); |
455 } |
525 } |
456 putTask(env, this_obj, gTask); |
526 putTask(env, this_obj, gTask); |
457 |
527 |
|
528 // use ptrace to stop the process |
|
529 // on os x, ptrace only needs to be called on the process, not the individual threads |
|
530 if (ptrace_attach(jpid) != true) { |
|
531 mach_port_deallocate(mach_task_self(), gTask); |
|
532 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); |
|
533 } |
|
534 |
458 id symbolicator = nil; |
535 id symbolicator = nil; |
459 id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator"); |
536 id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator"); |
460 if (jrsSymbolicator != nil) { |
537 if (jrsSymbolicator != nil) { |
461 id (*dynamicCall)(id, SEL, pid_t) = (id (*)(id, SEL, pid_t))&objc_msgSend; |
538 id (*dynamicCall)(id, SEL, pid_t) = (id (*)(id, SEL, pid_t))&objc_msgSend; |
462 symbolicator = dynamicCall(jrsSymbolicator, @selector(symbolicatorForPid:), (pid_t)jpid); |
539 symbolicator = dynamicCall(jrsSymbolicator, @selector(symbolicatorForPid:), (pid_t)jpid); |
484 { |
561 { |
485 JNF_COCOA_ENTER(env); |
562 JNF_COCOA_ENTER(env); |
486 if (debug) printf("detach0 called\n"); |
563 if (debug) printf("detach0 called\n"); |
487 |
564 |
488 task_t gTask = getTask(env, this_obj); |
565 task_t gTask = getTask(env, this_obj); |
|
566 |
|
567 // detach from the ptraced process causing it to resume execution |
|
568 int pid; |
|
569 kern_return_t k_res; |
|
570 k_res = pid_for_task(gTask, &pid); |
|
571 if (k_res != KERN_SUCCESS) { |
|
572 fprintf(stderr, "detach: pid_for_task(%d) failed (%d)\n", pid, k_res); |
|
573 } |
|
574 else { |
|
575 int res = ptrace(PT_DETACH, pid, 0, 0); |
|
576 if (res < 0) { |
|
577 fprintf(stderr, "detach: ptrace(PT_DETACH, %d) failed (%d)\n", pid, res); |
|
578 } |
|
579 } |
|
580 |
489 mach_port_deallocate(mach_task_self(), gTask); |
581 mach_port_deallocate(mach_task_self(), gTask); |
490 id symbolicator = getSymbolicator(env, this_obj); |
582 id symbolicator = getSymbolicator(env, this_obj); |
491 if (symbolicator != nil) { |
583 if (symbolicator != nil) { |
492 CFRelease(symbolicator); |
584 CFRelease(symbolicator); |
493 } |
585 } |