1 /* 2 * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "util.h" 27 #include "stepControl.h" 28 #include "eventHandler.h" 29 #include "eventHelper.h" 30 #include "threadControl.h" 31 #include "SDE.h" 32 33 static jrawMonitorID stepLock; 34 35 static jint 36 getFrameCount(jthread thread) 37 { 38 jint count = 0; 39 jvmtiError error; 40 41 error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount) 42 (gdata->jvmti, thread, &count); 43 if (error != JVMTI_ERROR_NONE) { 44 EXIT_ERROR(error, "getting frame count"); 45 } 46 return count; 47 } 48 49 /* 50 * Most enabling/disabling of JVMTI events happens implicitly through 51 * the inserting and freeing of handlers for those events. Stepping is 52 * different because requested steps are usually not identical to JVMTI steps. 53 * They usually require multiple events step, and otherwise, before they 54 * complete. While a step request is pending, we may need to temporarily 55 * disable and re-enable stepping, but we can't just remove the handlers 56 * because that would break the application's ability to remove the 57 * events. So, for step events only, we directly enable and disable stepping. 58 * This is safe because there can only ever be one pending step request 59 * per thread. 60 */ 61 static void 62 enableStepping(jthread thread) 63 { 64 jvmtiError error; 65 66 LOG_STEP(("enableStepping: thread=%p", thread)); 67 68 error = threadControl_setEventMode(JVMTI_ENABLE, EI_SINGLE_STEP, 69 thread); 70 if (error != JVMTI_ERROR_NONE) { 71 EXIT_ERROR(error, "enabling single step"); 72 } 73 } 74 75 static void 76 disableStepping(jthread thread) 77 { 78 jvmtiError error; 79 80 LOG_STEP(("disableStepping: thread=%p", thread)); 81 82 error = threadControl_setEventMode(JVMTI_DISABLE, EI_SINGLE_STEP, 83 thread); 84 if (error != JVMTI_ERROR_NONE) { 85 EXIT_ERROR(error, "disabling single step"); 86 } 87 } 88 89 static jvmtiError 90 getFrameLocation(jthread thread, 91 jclass *pclazz, jmethodID *pmethod, jlocation *plocation) 92 { 93 jvmtiError error; 94 95 *pclazz = NULL; 96 *pmethod = NULL; 97 *plocation = -1; 98 99 error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation) 100 (gdata->jvmti, thread, 0, pmethod, plocation); 101 if (error == JVMTI_ERROR_NONE && *pmethod!=NULL ) { 102 /* This also serves to verify that the methodID is valid */ 103 error = methodClass(*pmethod, pclazz); 104 } 105 return error; 106 } 107 108 static void 109 getLineNumberTable(jmethodID method, jint *pcount, 110 jvmtiLineNumberEntry **ptable) 111 { 112 jvmtiError error; 113 114 *pcount = 0; 115 *ptable = NULL; 116 117 /* If the method is native or obsolete, don't even ask for the line table */ 118 if ( isMethodObsolete(method) || isMethodNative(method)) { 119 return; 120 } 121 122 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLineNumberTable) 123 (gdata->jvmti, method, pcount, ptable); 124 if (error != JVMTI_ERROR_NONE) { 125 *pcount = 0; 126 } 127 } 128 129 static jint 130 findLineNumber(jthread thread, jlocation location, 131 jvmtiLineNumberEntry *lines, jint count) 132 { 133 jint line = -1; 134 135 if (location != -1) { 136 if (count > 0) { 137 jint i; 138 /* any preface before first line is assigned to first line */ 139 for (i=1; i<count; i++) { 140 if (location < lines[i].start_location) { 141 break; 142 } 143 } 144 line = lines[i-1].line_number; 145 } 146 } 147 return line; 148 } 149 150 static jboolean 151 hasLineNumbers(jmethodID method) 152 { 153 jint count; 154 jvmtiLineNumberEntry *table; 155 156 getLineNumberTable(method, &count, &table); 157 if ( count == 0 ) { 158 return JNI_FALSE; 159 } else { 160 jvmtiDeallocate(table); 161 } 162 return JNI_TRUE; 163 } 164 165 static jvmtiError 166 initState(JNIEnv *env, jthread thread, StepRequest *step) 167 { 168 jvmtiError error; 169 170 /* 171 * Initial values that may be changed below 172 */ 173 step->fromLine = -1; 174 step->fromNative = JNI_FALSE; 175 step->frameExited = JNI_FALSE; 176 step->fromStackDepth = getFrameCount(thread); 177 178 if (step->fromStackDepth <= 0) { 179 /* 180 * If there are no stack frames, treat the step as though 181 * from a native frame. This is most likely to occur at the 182 * beginning of a debug session, right after the VM_INIT event, 183 * so we need to do something intelligent. 184 */ 185 step->fromNative = JNI_TRUE; 186 return JVMTI_ERROR_NONE; 187 } 188 189 /* 190 * Try to get a notification on frame pop. If we're in an opaque frame 191 * we won't be able to, but we can use other methods to detect that 192 * a native frame has exited. 193 * 194 * TO DO: explain the need for this notification. 195 */ 196 error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop) 197 (gdata->jvmti, thread, 0); 198 if (error == JVMTI_ERROR_OPAQUE_FRAME) { 199 step->fromNative = JNI_TRUE; 200 error = JVMTI_ERROR_NONE; 201 /* continue without error */ 202 } else if (error == JVMTI_ERROR_DUPLICATE) { 203 error = JVMTI_ERROR_NONE; 204 /* Already being notified, continue without error */ 205 } else if (error != JVMTI_ERROR_NONE) { 206 return error; 207 } 208 209 LOG_STEP(("initState(): frame=%d", step->fromStackDepth)); 210 211 /* 212 * Note: we can't undo the frame pop notify, so 213 * we'll just have to let the handler ignore it if 214 * there are any errors below. 215 */ 216 217 if (step->granularity == JDWP_STEP_SIZE(LINE) ) { 218 219 LOG_STEP(("initState(): Begin line step")); 220 221 WITH_LOCAL_REFS(env, 1) { 222 223 jclass clazz; 224 jmethodID method; 225 jlocation location; 226 227 error = getFrameLocation(thread, &clazz, &method, &location); 228 if (error == JVMTI_ERROR_NONE) { 229 /* Clear out previous line table only if we changed methods */ 230 if ( method != step->method ) { 231 step->lineEntryCount = 0; 232 if (step->lineEntries != NULL) { 233 jvmtiDeallocate(step->lineEntries); 234 step->lineEntries = NULL; 235 } 236 step->method = method; 237 getLineNumberTable(step->method, 238 &step->lineEntryCount, &step->lineEntries); 239 if (step->lineEntryCount > 0) { 240 convertLineNumberTable(env, clazz, 241 &step->lineEntryCount, &step->lineEntries); 242 } 243 } 244 step->fromLine = findLineNumber(thread, location, 245 step->lineEntries, step->lineEntryCount); 246 } 247 248 } END_WITH_LOCAL_REFS(env); 249 250 } 251 252 return error; 253 } 254 255 /* 256 * TO DO: The step handlers (handleFrameChange and handleStep can 257 * be broken down and made simpler now that we can install and de-install event 258 * handlers. 259 */ 260 static void 261 handleFramePopEvent(JNIEnv *env, EventInfo *evinfo, 262 HandlerNode *node, 263 struct bag *eventBag) 264 { 265 StepRequest *step; 266 jthread thread = evinfo->thread; 267 268 stepControl_lock(); 269 270 step = threadControl_getStepRequest(thread); 271 if (step == NULL) { 272 EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request"); 273 } 274 275 if (step->pending) { 276 /* 277 * Note: current depth is reported as *before* the pending frame 278 * pop. 279 */ 280 jint currentDepth; 281 jint fromDepth; 282 jint afterPopDepth; 283 284 currentDepth = getFrameCount(thread); 285 fromDepth = step->fromStackDepth; 286 afterPopDepth = currentDepth-1; 287 288 LOG_STEP(("handleFramePopEvent: BEGIN fromDepth=%d, currentDepth=%d", 289 fromDepth, currentDepth)); 290 291 /* 292 * If we are exiting the original stepping frame, record that 293 * fact here. Once the next step event comes in, we can safely 294 * stop stepping there. 295 */ 296 if (fromDepth > afterPopDepth ) { 297 step->frameExited = JNI_TRUE; 298 } 299 300 if (step->depth == JDWP_STEP_DEPTH(OVER)) { 301 /* 302 * Either 303 * 1) the original stepping frame is about to be popped 304 * [fromDepth == currentDepth]. Re-enable stepping to 305 * reach a point where we can stop. 306 * 2) a method called from the stepping frame has returned 307 * (during which we had stepping disabled) 308 * [fromDepth == currentDepth - 1]. Re-enable stepping 309 * so that we can continue instructions steps in the 310 * original stepping frame. 311 * 3) a method further down the call chain has notified 312 * of a frame pop [fromDepth < currentDepth - 1]. This 313 * *might* represent case (2) above if the stepping frame 314 * was calling a native method which in turn called a 315 * java method. If so, we must enable stepping to 316 * ensure that we get control back after the intervening 317 * native frame is popped (you can't get frame pop 318 * notifications on native frames). If the native caller 319 * calls another Java method before returning, 320 * stepping will be diabled again and another frame pop 321 * will be awaited. 322 * 323 * If it turns out that this is not case (2) with native 324 * methods, then the enabled stepping is benign and 325 * will be disabled again on the next step event. 326 * 327 * Note that the condition not covered above, 328 * [fromDepth > currentDepth] shouldn't happen since it means 329 * that too many frames have been popped. For robustness, 330 * we enable stepping in that case too, so that the errant 331 * step-over can be stopped. 332 * 333 */ 334 LOG_STEP(("handleFramePopEvent: starting singlestep, depth==OVER")); 335 enableStepping(thread); 336 } else if (step->depth == JDWP_STEP_DEPTH(OUT) && 337 fromDepth > afterPopDepth) { 338 /* 339 * The original stepping frame is about to be popped. Step 340 * until we reach the next safe place to stop. 341 */ 342 LOG_STEP(("handleFramePopEvent: starting singlestep, depth==OUT && fromDepth > afterPopDepth (%d>%d)",fromDepth, afterPopDepth)); 343 enableStepping(thread); 344 } else if (step->methodEnterHandlerNode != NULL && 345 fromDepth >= afterPopDepth) { 346 /* 347 * We installed a method entry event handler as part of a 348 * step into operation. We've popped back to the original 349 * stepping frame without finding a place to stop. 350 * Resume stepping in the original frame. 351 */ 352 LOG_STEP(("handleFramePopEvent: starting singlestep, have methodEnter handler && depth==OUT && fromDepth >= afterPopDepth (%d>%d)",fromDepth, afterPopDepth)); 353 enableStepping(thread); 354 (void)eventHandler_free(step->methodEnterHandlerNode); 355 step->methodEnterHandlerNode = NULL; 356 } 357 LOG_STEP(("handleFramePopEvent: finished")); 358 } 359 360 stepControl_unlock(); 361 } 362 363 static void 364 handleExceptionCatchEvent(JNIEnv *env, EventInfo *evinfo, 365 HandlerNode *node, 366 struct bag *eventBag) 367 { 368 StepRequest *step; 369 jthread thread = evinfo->thread; 370 371 stepControl_lock(); 372 373 step = threadControl_getStepRequest(thread); 374 if (step == NULL) { 375 EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request"); 376 } 377 378 if (step->pending) { 379 /* 380 * Determine where we are on the call stack relative to where 381 * we started. 382 */ 383 jint currentDepth = getFrameCount(thread); 384 jint fromDepth = step->fromStackDepth; 385 386 LOG_STEP(("handleExceptionCatchEvent: fromDepth=%d, currentDepth=%d", 387 fromDepth, currentDepth)); 388 389 /* 390 * If we are exiting the original stepping frame, record that 391 * fact here. Once the next step event comes in, we can safely 392 * stop stepping there. 393 */ 394 if (fromDepth > currentDepth) { 395 step->frameExited = JNI_TRUE; 396 } 397 398 if (step->depth == JDWP_STEP_DEPTH(OVER) && 399 fromDepth >= currentDepth) { 400 /* 401 * Either the original stepping frame is done, 402 * or a called method has returned (during which we had stepping 403 * disabled). In either case we must resume stepping. 404 */ 405 enableStepping(thread); 406 } else if (step->depth == JDWP_STEP_DEPTH(OUT) && 407 fromDepth > currentDepth) { 408 /* 409 * The original stepping frame is done. Step 410 * until we reach the next safe place to stop. 411 */ 412 enableStepping(thread); 413 } else if (step->methodEnterHandlerNode != NULL && 414 fromDepth >= currentDepth) { 415 /* 416 * We installed a method entry event handler as part of a 417 * step into operation. We've popped back to the original 418 * stepping frame or higher without finding a place to stop. 419 * Resume stepping in the original frame. 420 */ 421 enableStepping(thread); 422 (void)eventHandler_free(step->methodEnterHandlerNode); 423 step->methodEnterHandlerNode = NULL; 424 } 425 } 426 427 stepControl_unlock(); 428 } 429 430 static void 431 handleMethodEnterEvent(JNIEnv *env, EventInfo *evinfo, 432 HandlerNode *node, 433 struct bag *eventBag) 434 { 435 StepRequest *step; 436 jthread thread; 437 438 thread = evinfo->thread; 439 440 stepControl_lock(); 441 442 step = threadControl_getStepRequest(thread); 443 if (step == NULL) { 444 EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request"); 445 } 446 447 if (step->pending) { 448 jclass clazz; 449 jmethodID method; 450 char *classname; 451 452 LOG_STEP(("handleMethodEnterEvent: thread=%p", thread)); 453 454 clazz = evinfo->clazz; 455 method = evinfo->method; 456 classname = getClassname(clazz); 457 458 /* 459 * This handler is relevant only to step into 460 */ 461 JDI_ASSERT(step->depth == JDWP_STEP_DEPTH(INTO)); 462 463 if ( (!eventFilter_predictFiltering(step->stepHandlerNode, 464 clazz, classname)) 465 && ( step->granularity != JDWP_STEP_SIZE(LINE) 466 || hasLineNumbers(method) ) ) { 467 /* 468 * We've found a suitable method in which to stop. Step 469 * until we reach the next safe location to complete the step->, 470 * and we can get rid of the method entry handler. 471 */ 472 enableStepping(thread); 473 if ( step->methodEnterHandlerNode != NULL ) { 474 (void)eventHandler_free(step->methodEnterHandlerNode); 475 step->methodEnterHandlerNode = NULL; 476 } 477 } 478 jvmtiDeallocate(classname); 479 classname = NULL; 480 } 481 482 stepControl_unlock(); 483 } 484 485 static void 486 completeStep(JNIEnv *env, jthread thread, StepRequest *step) 487 { 488 jvmtiError error; 489 490 /* 491 * We've completed a step; reset state for the next one, if any 492 */ 493 494 LOG_STEP(("completeStep: thread=%p", thread)); 495 496 if (step->methodEnterHandlerNode != NULL) { 497 (void)eventHandler_free(step->methodEnterHandlerNode); 498 step->methodEnterHandlerNode = NULL; 499 } 500 501 error = initState(env, thread, step); 502 if (error != JVMTI_ERROR_NONE) { 503 /* 504 * None of the initState errors should happen after one step 505 * has successfully completed. 506 */ 507 EXIT_ERROR(error, "initializing step state"); 508 } 509 } 510 511 jboolean 512 stepControl_handleStep(JNIEnv *env, jthread thread, 513 jclass clazz, jmethodID method) 514 { 515 jboolean completed = JNI_FALSE; 516 StepRequest *step; 517 jint currentDepth; 518 jint fromDepth; 519 jvmtiError error; 520 char *classname; 521 522 classname = NULL; 523 stepControl_lock(); 524 525 step = threadControl_getStepRequest(thread); 526 if (step == NULL) { 527 EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request"); 528 } 529 530 /* 531 * If no step is currently pending, ignore the event 532 */ 533 if (!step->pending) { 534 goto done; 535 } 536 537 LOG_STEP(("stepControl_handleStep: thread=%p", thread)); 538 539 /* 540 * We never filter step into instruction. It's always over on the 541 * first step event. 542 */ 543 if (step->depth == JDWP_STEP_DEPTH(INTO) && 544 step->granularity == JDWP_STEP_SIZE(MIN)) { 545 completed = JNI_TRUE; 546 LOG_STEP(("stepControl_handleStep: completed, into min")); 547 goto done; 548 } 549 550 /* 551 * If we have left the method in which 552 * stepping started, the step is always complete. 553 */ 554 if (step->frameExited) { 555 completed = JNI_TRUE; 556 LOG_STEP(("stepControl_handleStep: completed, frame exited")); 557 goto done; 558 } 559 560 /* 561 * Determine where we are on the call stack relative to where 562 * we started. 563 */ 564 currentDepth = getFrameCount(thread); 565 fromDepth = step->fromStackDepth; 566 567 if (fromDepth > currentDepth) { 568 /* 569 * We have returned from the caller. There are cases where 570 * we don't get frame pop notifications 571 * (e.g. stepping from opaque frames), and that's when 572 * this code will be reached. Complete the step-> 573 */ 574 completed = JNI_TRUE; 575 LOG_STEP(("stepControl_handleStep: completed, fromDepth>currentDepth(%d>%d)", fromDepth, currentDepth)); 576 } else if (fromDepth < currentDepth) { 577 /* We have dropped into a called method. */ 578 if ( step->depth == JDWP_STEP_DEPTH(INTO) 579 && (!eventFilter_predictFiltering(step->stepHandlerNode, clazz, 580 (classname = getClassname(clazz)))) 581 && hasLineNumbers(method) ) { 582 583 /* Stepped into a method with lines, so we're done */ 584 completed = JNI_TRUE; 585 LOG_STEP(("stepControl_handleStep: completed, fromDepth<currentDepth(%d<%d) and into method with lines", fromDepth, currentDepth)); 586 } else { 587 /* 588 * We need to continue, but don't want the overhead of step 589 * events from this method. So, we disable stepping and 590 * enable a frame pop. If we're stepping into, we also 591 * enable method enter events because a called frame may be 592 * where we want to stop. 593 */ 594 disableStepping(thread); 595 596 if (step->depth == JDWP_STEP_DEPTH(INTO)) { 597 step->methodEnterHandlerNode = 598 eventHandler_createInternalThreadOnly( 599 EI_METHOD_ENTRY, 600 handleMethodEnterEvent, thread); 601 if (step->methodEnterHandlerNode == NULL) { 602 EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE, 603 "installing event method enter handler"); 604 } 605 } 606 607 error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop) 608 (gdata->jvmti, thread, 0); 609 if (error == JVMTI_ERROR_DUPLICATE) { 610 error = JVMTI_ERROR_NONE; 611 } else if (error != JVMTI_ERROR_NONE) { 612 EXIT_ERROR(error, "setting up notify frame pop"); 613 } 614 } 615 jvmtiDeallocate(classname); 616 classname = NULL; 617 } else { 618 /* 619 * We are at the same stack depth where stepping started. 620 * Instruction steps are complete at this point. For line 621 * steps we must check to see whether we've moved to a 622 * different line. 623 */ 624 if (step->granularity == JDWP_STEP_SIZE(MIN)) { 625 completed = JNI_TRUE; 626 LOG_STEP(("stepControl_handleStep: completed, fromDepth==currentDepth(%d) and min", fromDepth)); 627 } else { 628 if (step->fromLine != -1) { 629 jint line = -1; 630 jlocation location; 631 jmethodID method; 632 WITH_LOCAL_REFS(env, 1) { 633 jclass clazz; 634 error = getFrameLocation(thread, 635 &clazz, &method, &location); 636 if ( isMethodObsolete(method)) { 637 method = NULL; 638 location = -1; 639 } 640 if (error != JVMTI_ERROR_NONE || location == -1) { 641 EXIT_ERROR(error, "getting frame location"); 642 } 643 if ( method == step->method ) { 644 LOG_STEP(("stepControl_handleStep: checking line location")); 645 log_debugee_location("stepControl_handleStep: checking line loc", 646 thread, method, location); 647 line = findLineNumber(thread, location, 648 step->lineEntries, step->lineEntryCount); 649 } 650 if (line != step->fromLine) { 651 completed = JNI_TRUE; 652 LOG_STEP(("stepControl_handleStep: completed, fromDepth==currentDepth(%d) and different line", fromDepth)); 653 } 654 } END_WITH_LOCAL_REFS(env); 655 } else { 656 /* 657 * This is a rare case. We have stepped from a location 658 * inside a native method to a location within a Java 659 * method at the same stack depth. This means that 660 * the original native method returned to another 661 * native method which, in turn, invoked a Java method. 662 * 663 * Since the original frame was native, we were unable 664 * to ask for a frame pop event, and, thus, could not 665 * set the step->frameExited flag when the original 666 * method was done. Instead we end up here 667 * and act just as though the frameExited flag was set 668 * and complete the step immediately. 669 */ 670 completed = JNI_TRUE; 671 LOG_STEP(("stepControl_handleStep: completed, fromDepth==currentDepth(%d) and no line", fromDepth)); 672 } 673 } 674 LOG_STEP(("stepControl_handleStep: finished")); 675 } 676 done: 677 if (completed) { 678 completeStep(env, thread, step); 679 } 680 stepControl_unlock(); 681 return completed; 682 } 683 684 685 void 686 stepControl_initialize(void) 687 { 688 stepLock = debugMonitorCreate("JDWP Step Handler Lock"); 689 } 690 691 void 692 stepControl_reset(void) 693 { 694 } 695 696 /* 697 * Reset step control request stack depth and line number. 698 */ 699 void 700 stepControl_resetRequest(jthread thread) 701 { 702 703 StepRequest *step; 704 jvmtiError error; 705 706 LOG_STEP(("stepControl_resetRequest: thread=%p", thread)); 707 708 stepControl_lock(); 709 710 step = threadControl_getStepRequest(thread); 711 712 if (step != NULL) { 713 JNIEnv *env; 714 env = getEnv(); 715 error = initState(env, thread, step); 716 if (error != JVMTI_ERROR_NONE) { 717 EXIT_ERROR(error, "initializing step state"); 718 } 719 } else { 720 EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request"); 721 } 722 723 stepControl_unlock(); 724 } 725 726 static void 727 initEvents(jthread thread, StepRequest *step) 728 { 729 /* Need to install frame pop handler and exception catch handler when 730 * single-stepping is enabled (i.e. step-into or step-over/step-out 731 * when fromStackDepth > 0). 732 */ 733 if (step->depth == JDWP_STEP_DEPTH(INTO) || step->fromStackDepth > 0) { 734 /* 735 * TO DO: These might be able to applied more selectively to 736 * boost performance. 737 */ 738 step->catchHandlerNode = eventHandler_createInternalThreadOnly( 739 EI_EXCEPTION_CATCH, 740 handleExceptionCatchEvent, 741 thread); 742 step->framePopHandlerNode = eventHandler_createInternalThreadOnly( 743 EI_FRAME_POP, 744 handleFramePopEvent, 745 thread); 746 747 if (step->catchHandlerNode == NULL || 748 step->framePopHandlerNode == NULL) { 749 EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE, 750 "installing step event handlers"); 751 } 752 753 } 754 /* 755 * Initially enable stepping: 756 * 1) For step into, always 757 * 2) For step over, unless right after the VM_INIT. 758 * Enable stepping for STEP_MIN or STEP_LINE with or without line numbers. 759 * If the class is redefined then non EMCP methods may not have line 760 * number info. So enable line stepping for non line number so that it 761 * behaves like STEP_MIN/STEP_OVER. 762 * 3) For step out, only if stepping from native, except right after VM_INIT 763 * 764 * (right after VM_INIT, a step->over or out is identical to running 765 * forever) 766 */ 767 switch (step->depth) { 768 case JDWP_STEP_DEPTH(INTO): 769 enableStepping(thread); 770 break; 771 case JDWP_STEP_DEPTH(OVER): 772 if (step->fromStackDepth > 0 && !step->fromNative ) { 773 enableStepping(thread); 774 } 775 break; 776 case JDWP_STEP_DEPTH(OUT): 777 if (step->fromNative && 778 (step->fromStackDepth > 0)) { 779 enableStepping(thread); 780 } 781 break; 782 default: 783 JDI_ASSERT(JNI_FALSE); 784 } 785 } 786 787 jvmtiError 788 stepControl_beginStep(JNIEnv *env, jthread thread, jint size, jint depth, 789 HandlerNode *node) 790 { 791 StepRequest *step; 792 jvmtiError error; 793 jvmtiError error2; 794 795 LOG_STEP(("stepControl_beginStep: thread=%p,size=%d,depth=%d", 796 thread, size, depth)); 797 798 eventHandler_lock(); /* for proper lock order */ 799 stepControl_lock(); 800 801 step = threadControl_getStepRequest(thread); 802 if (step == NULL) { 803 error = AGENT_ERROR_INVALID_THREAD; 804 /* Normally not getting a StepRequest struct pointer is a fatal error 805 * but on a beginStep, we just return an error code. 806 */ 807 } else { 808 /* 809 * In case the thread isn't already suspended, do it again. 810 */ 811 error = threadControl_suspendThread(thread, JNI_FALSE); 812 if (error == JVMTI_ERROR_NONE) { 813 /* 814 * Overwrite any currently executing step. 815 */ 816 step->granularity = size; 817 step->depth = depth; 818 step->catchHandlerNode = NULL; 819 step->framePopHandlerNode = NULL; 820 step->methodEnterHandlerNode = NULL; 821 step->stepHandlerNode = node; 822 error = initState(env, thread, step); 823 if (error == JVMTI_ERROR_NONE) { 824 initEvents(thread, step); 825 } 826 /* false means it is not okay to unblock the commandLoop thread */ 827 error2 = threadControl_resumeThread(thread, JNI_FALSE); 828 if (error2 != JVMTI_ERROR_NONE && error == JVMTI_ERROR_NONE) { 829 error = error2; 830 } 831 832 /* 833 * If everything went ok, indicate a step is pending. 834 */ 835 if (error == JVMTI_ERROR_NONE) { 836 step->pending = JNI_TRUE; 837 } 838 } else { 839 EXIT_ERROR(error, "stepControl_beginStep: cannot suspend thread"); 840 } 841 } 842 843 stepControl_unlock(); 844 eventHandler_unlock(); 845 846 return error; 847 } 848 849 850 static void 851 clearStep(jthread thread, StepRequest *step) 852 { 853 if (step->pending) { 854 855 disableStepping(thread); 856 if ( step->catchHandlerNode != NULL ) { 857 (void)eventHandler_free(step->catchHandlerNode); 858 step->catchHandlerNode = NULL; 859 } 860 if ( step->framePopHandlerNode!= NULL ) { 861 (void)eventHandler_free(step->framePopHandlerNode); 862 step->framePopHandlerNode = NULL; 863 } 864 if ( step->methodEnterHandlerNode != NULL ) { 865 (void)eventHandler_free(step->methodEnterHandlerNode); 866 step->methodEnterHandlerNode = NULL; 867 } 868 step->pending = JNI_FALSE; 869 870 /* 871 * Warning: Do not clear step->method, step->lineEntryCount, 872 * or step->lineEntries here, they will likely 873 * be needed on the next step. 874 */ 875 876 } 877 } 878 879 jvmtiError 880 stepControl_endStep(jthread thread) 881 { 882 StepRequest *step; 883 jvmtiError error; 884 885 LOG_STEP(("stepControl_endStep: thread=%p", thread)); 886 887 eventHandler_lock(); /* for proper lock order */ 888 stepControl_lock(); 889 890 step = threadControl_getStepRequest(thread); 891 if (step != NULL) { 892 clearStep(thread, step); 893 error = JVMTI_ERROR_NONE; 894 } else { 895 /* If the stepRequest can't be gotten, then this thread no longer 896 * exists, just return, don't die here, this is normal at 897 * termination time. Return JVMTI_ERROR_NONE so the thread Ref 898 * can be tossed. 899 */ 900 error = JVMTI_ERROR_NONE; 901 } 902 903 stepControl_unlock(); 904 eventHandler_unlock(); 905 906 return error; 907 } 908 909 void 910 stepControl_clearRequest(jthread thread, StepRequest *step) 911 { 912 LOG_STEP(("stepControl_clearRequest: thread=%p", thread)); 913 clearStep(thread, step); 914 } 915 916 void 917 stepControl_lock(void) 918 { 919 debugMonitorEnter(stepLock); 920 } 921 922 void 923 stepControl_unlock(void) 924 { 925 debugMonitorExit(stepLock); 926 } 927