agent/src/os/bsd/MacosxDebuggerLocal.m

changeset 4603
5d5c577296fd
parent 4564
758935f7c23f
child 4688
40b7c6b800ab
equal deleted inserted replaced
4601:3a531d40ad93 4603:5d5c577296fd
36 #import <stdlib.h> 36 #import <stdlib.h>
37 #import <strings.h> 37 #import <strings.h>
38 #import <dlfcn.h> 38 #import <dlfcn.h>
39 #import <limits.h> 39 #import <limits.h>
40 #import <errno.h> 40 #import <errno.h>
41 #import <sys/types.h>
42 #import <sys/ptrace.h>
41 43
42 jboolean debug = JNI_FALSE; 44 jboolean debug = JNI_FALSE;
43 45
44 static jfieldID symbolicatorID = 0; // set in _init0 46 static jfieldID symbolicatorID = 0; // set in _init0
45 static jfieldID taskID = 0; // set in _init0 47 static jfieldID taskID = 0; // set in _init0
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 }

mercurial