< prev index next >

test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/agent_tools.cpp

Print this page
rev 52185 : [mq]: refactor


  60 
  61 /* ============================================================================= */
  62 
  63 void nsk_jvmti_setFailStatus() {
  64     currentAgentStatus = NSK_STATUS_FAILED;
  65 }
  66 
  67 int nsk_jvmti_isFailStatus() {
  68     return (nsk_jvmti_getStatus() != NSK_STATUS_PASSED);
  69 }
  70 
  71 jint nsk_jvmti_getStatus() {
  72     return currentAgentStatus;
  73 }
  74 
  75 /* ============================================================================= */
  76 static jvmtiError init_agent_data(jvmtiEnv *jvmti_env, agent_data_t *data) {
  77     data->thread_state = NEW;
  78     data->last_debuggee_status = NSK_STATUS_PASSED;
  79 
  80     return NSK_CPP_STUB3(CreateRawMonitor, jvmti_env, "agent_data_monitor", &data->monitor);
  81 }
  82 
  83 /** Reset agent data to prepare for another run. */
  84 void nsk_jvmti_resetAgentData() {
  85     rawMonitorEnter(jvmti_env, agent_data.monitor);
  86     /* wait for agentThreadWrapper() to finish */
  87     while (agent_data.thread_state != TERMINATED) {
  88         rawMonitorWait(jvmti_env, agent_data.monitor, 10);
  89     }
  90     agent_data.thread_state = NEW;
  91     agent_data.last_debuggee_status = NSK_STATUS_PASSED;
  92     rawMonitorExit(jvmti_env, agent_data.monitor);
  93 }
  94 
  95 static jvmtiError free_agent_data(jvmtiEnv *jvmti_env, agent_data_t *data) {
  96     return NSK_CPP_STUB2(DestroyRawMonitor, jvmti_env, data->monitor);
  97 }
  98 
  99 /** Create JVMTI environment. */
 100 jvmtiEnv* nsk_jvmti_createJVMTIEnv(JavaVM* javaVM, void* reserved) {
 101     jvm = javaVM;
 102     if (!NSK_VERIFY(
 103             NSK_CPP_STUB3(GetEnv, javaVM, (void **)&jvmti_env, JVMTI_VERSION_1_1) == JNI_OK)) {
 104         nsk_jvmti_setFailStatus();
 105         return NULL;
 106     }
 107 
 108     if (!NSK_JVMTI_VERIFY(init_agent_data(jvmti_env, &agent_data))) {
 109         nsk_jvmti_setFailStatus();
 110         return NULL;
 111     }
 112 
 113     return jvmti_env;
 114 }
 115 
 116 /** Dispose JVMTI environment */
 117 static int nsk_jvmti_disposeJVMTIEnv(jvmtiEnv* jvmti_env) {
 118     if (jvmti_env != NULL) {
 119         if (!NSK_JVMTI_VERIFY(
 120                 NSK_CPP_STUB1(DisposeEnvironment, jvmti_env))) {
 121             nsk_jvmti_setFailStatus();
 122             return NSK_FALSE;
 123         }
 124 
 125         if (!NSK_JVMTI_VERIFY(free_agent_data(jvmti_env, &agent_data))) {
 126             nsk_jvmti_setFailStatus();
 127             return NSK_FALSE;
 128         }
 129     }
 130     return NSK_TRUE;
 131 }
 132 
 133 /** Get JNI environment for agent thread. */
 134 JNIEnv* nsk_jvmti_getAgentJNIEnv() {
 135     return jni_env;
 136 }
 137 
 138 /** Get JVMTI environment for agent */
 139 jvmtiEnv* nsk_jvmti_getAgentJVMTIEnv() {
 140     return jvmti_env;


 148     rawMonitorExit(jvmti_env, agent_data.monitor);
 149 }
 150 
 151 /** Wrapper for user agent thread. */
 152 static void JNICALL
 153 agentThreadWrapper(jvmtiEnv* jvmti_env, JNIEnv* agentJNI, void* arg) {
 154     jni_env = agentJNI;
 155 
 156     /* run user agent proc */
 157     {
 158         set_agent_thread_state(RUNNABLE);
 159 
 160         NSK_TRACE((*agentThreadProc)(jvmti_env, agentJNI, agentThreadArg));
 161 
 162         set_agent_thread_state(TERMINATED);
 163     }
 164 
 165     /* finalize agent thread */
 166     {
 167         /* gelete global ref for agent thread */
 168         NSK_CPP_STUB2(DeleteGlobalRef, agentJNI, agentThread);
 169         agentThread = NULL;
 170     }
 171 }
 172 
 173 /** Start wrapper for user agent thread. */
 174 static jthread startAgentThreadWrapper(JNIEnv *jni_env, jvmtiEnv* jvmti_env) {
 175     const jint  THREAD_PRIORITY = JVMTI_THREAD_MAX_PRIORITY;
 176     const char* THREAD_NAME = "JVMTI agent thread";
 177     const char* THREAD_CLASS_NAME = "java/lang/Thread";
 178     const char* THREAD_CTOR_NAME = "<init>";
 179     const char* THREAD_CTOR_SIGNATURE = "(Ljava/lang/String;)V";
 180 
 181     jobject threadName = NULL;
 182     jclass threadClass = NULL;
 183     jmethodID threadCtor = NULL;
 184     jobject threadObject = NULL;
 185     jobject threadGlobalRef = NULL;
 186 
 187     if (!NSK_JNI_VERIFY(jni_env, (threadClass =
 188             NSK_CPP_STUB2(FindClass, jni_env, THREAD_CLASS_NAME)) != NULL)) {
 189         return NULL;
 190     }
 191 
 192     if (!NSK_JNI_VERIFY(jni_env, (threadCtor =
 193             NSK_CPP_STUB4(GetMethodID, jni_env, threadClass, THREAD_CTOR_NAME, THREAD_CTOR_SIGNATURE)) != NULL))
 194         return NULL;
 195 
 196     if (!NSK_JNI_VERIFY(jni_env, (threadName =
 197             NSK_CPP_STUB2(NewStringUTF, jni_env, THREAD_NAME)) != NULL))
 198         return NULL;
 199 
 200     if (!NSK_JNI_VERIFY(jni_env, (threadObject =
 201             NSK_CPP_STUB4(NewObject, jni_env, threadClass, threadCtor, threadName)) != NULL))
 202         return NULL;
 203 
 204     if (!NSK_JNI_VERIFY(jni_env, (threadGlobalRef =
 205             NSK_CPP_STUB2(NewGlobalRef, jni_env, threadObject)) != NULL)) {
 206         NSK_CPP_STUB2(DeleteLocalRef, jni_env, threadObject);
 207         return NULL;
 208     }
 209     agentThread = (jthread)threadGlobalRef;
 210 
 211     if (!NSK_JVMTI_VERIFY(
 212             NSK_CPP_STUB5(RunAgentThread, jvmti_env, agentThread,
 213                             &agentThreadWrapper, agentThreadArg, THREAD_PRIORITY))) {
 214         NSK_CPP_STUB2(DeleteGlobalRef, jni_env, threadGlobalRef);
 215         NSK_CPP_STUB2(DeleteLocalRef, jni_env, threadObject);
 216         return NULL;
 217     }
 218     return agentThread;
 219 }
 220 
 221 /** Register user agent thread with arg. */
 222 int nsk_jvmti_setAgentProc(jvmtiStartFunction proc, void* arg) {
 223     agentThreadProc = proc;
 224     agentThreadArg = arg;
 225     return NSK_TRUE;
 226 }
 227 
 228 /** Get agent thread ref. */
 229 jthread nsk_jvmti_getAgentThread() {
 230     return agentThread;
 231 }
 232 
 233 /** Run registered user agent thread via wrapper. */
 234 static jthread nsk_jvmti_runAgentThread(JNIEnv *jni_env, jvmtiEnv* jvmti_env) {
 235     /* start agent thread wrapper */


 378 /** Native function for Java code to reset agent data. */
 379 JNIEXPORT void JNICALL
 380 Java_nsk_share_jvmti_DebugeeClass_resetAgentData(JNIEnv* jni_env, jclass cls) {
 381     NSK_TRACE(nsk_jvmti_resetAgentData());
 382 }
 383 
 384 /* ============================================================================= */
 385 
 386 /** Find loaded class by signature. */
 387 jclass nsk_jvmti_classBySignature(const char signature[]) {
 388     jclass* classes = NULL;
 389     jint count = 0;
 390     jclass foundClass = NULL;
 391     int i;
 392 
 393     if (!NSK_VERIFY(signature != NULL)) {
 394         nsk_jvmti_setFailStatus();
 395         return NULL;
 396     }
 397 
 398     if (!NSK_JVMTI_VERIFY(
 399             NSK_CPP_STUB3(GetLoadedClasses, jvmti_env, &count, &classes))) {
 400         nsk_jvmti_setFailStatus();
 401         return NULL;
 402     }
 403 
 404     for (i = 0; i < count; i++) {
 405         char* sig = NULL;
 406         char* generic = NULL;
 407 
 408         if (!NSK_JVMTI_VERIFY(
 409                 NSK_CPP_STUB4(GetClassSignature, jvmti_env, classes[i], &sig, &generic))) {
 410             nsk_jvmti_setFailStatus();
 411             break;
 412         }
 413 
 414         if (sig != NULL && strcmp(signature, sig) == 0) {
 415             foundClass = classes[i];
 416         }
 417 
 418         if (!(NSK_JVMTI_VERIFY(
 419                     NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)sig))
 420                 && NSK_JVMTI_VERIFY(
 421                     NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)generic)))) {
 422             nsk_jvmti_setFailStatus();
 423             break;
 424         }
 425 
 426         if (foundClass != NULL)
 427             break;
 428     }
 429 
 430     if (!NSK_JVMTI_VERIFY(
 431                 NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)classes))) {
 432         nsk_jvmti_setFailStatus();
 433         return NULL;
 434     }
 435 
 436     if (!NSK_JNI_VERIFY(jni_env, (foundClass = (jclass)
 437                 NSK_CPP_STUB2(NewGlobalRef, jni_env, foundClass)) != NULL)) {
 438         nsk_jvmti_setFailStatus();
 439         return NULL;
 440     }
 441 
 442     return foundClass;
 443 }
 444 
 445 /** Find alive thread by name. */
 446 jthread nsk_jvmti_threadByName(const char name[]) {
 447     jthread* threads = NULL;
 448     jint count = 0;
 449     jthread foundThread = NULL;
 450     int i;
 451 
 452     if (!NSK_VERIFY(name != NULL)) {
 453         nsk_jvmti_setFailStatus();
 454         return NULL;
 455     }
 456 
 457     if (!NSK_JVMTI_VERIFY(
 458             NSK_CPP_STUB3(GetAllThreads, jvmti_env, &count, &threads))) {
 459         nsk_jvmti_setFailStatus();
 460         return NULL;
 461     }
 462 
 463     for (i = 0; i < count; i++) {
 464         jvmtiThreadInfo info;
 465 
 466         if (!NSK_JVMTI_VERIFY(
 467                 NSK_CPP_STUB3(GetThreadInfo, jvmti_env, threads[i], &info))) {
 468             nsk_jvmti_setFailStatus();
 469             break;
 470         }
 471 
 472         if (info.name != NULL && strcmp(name, info.name) == 0) {
 473             foundThread = threads[i];
 474             break;
 475         }
 476     }
 477 
 478     if (!NSK_JVMTI_VERIFY(
 479                 NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)threads))) {
 480         nsk_jvmti_setFailStatus();
 481         return NULL;
 482     }
 483 
 484     if (!NSK_JNI_VERIFY(jni_env, (foundThread = (jthread)
 485                 NSK_CPP_STUB2(NewGlobalRef, jni_env, foundThread)) != NULL)) {
 486         nsk_jvmti_setFailStatus();
 487         return NULL;
 488     }
 489 
 490     return foundThread;
 491 }
 492 
 493 
 494 /* ============================================================================= */
 495 
 496 /** Add all capabilities for finding line locations. */
 497 int nsk_jvmti_addLocationCapabilities() {
 498     jvmtiCapabilities caps;
 499 
 500     memset(&caps, 0, sizeof(caps));
 501     caps.can_get_line_numbers = 1;
 502     if (!NSK_JVMTI_VERIFY(
 503             NSK_CPP_STUB2(AddCapabilities, jvmti_env, &caps)))
 504         return NSK_FALSE;
 505 
 506     return NSK_TRUE;
 507 }
 508 
 509 /** Add all capabilities for using breakpoints. */
 510 int nsk_jvmti_addBreakpointCapabilities() {
 511     jvmtiCapabilities caps;
 512 
 513     if (!nsk_jvmti_addLocationCapabilities())
 514         return NSK_FALSE;
 515 
 516     memset(&caps, 0, sizeof(caps));
 517     caps.can_generate_breakpoint_events = 1;
 518     if (!NSK_JVMTI_VERIFY(
 519             NSK_CPP_STUB2(AddCapabilities, jvmti_env, &caps)))
 520         return NSK_FALSE;
 521 
 522     return NSK_TRUE;
 523 }
 524 
 525 /** Find line location. */
 526 jlocation nsk_jvmti_getLineLocation(jclass cls, jmethodID method, int line) {
 527     jint count = 0;
 528     jvmtiLineNumberEntry* table = NULL;
 529     jlocation location = NSK_JVMTI_INVALID_JLOCATION;
 530     int i;
 531 
 532     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetLineNumberTable, jvmti_env, method, &count, &table)))
 533         return NSK_JVMTI_INVALID_JLOCATION;
 534 
 535     for (i = 0; i < count; i++) {
 536         if (table[i].line_number == line) {
 537             location = table[i].start_location;
 538             break;
 539         }
 540     }
 541 
 542     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)table)))
 543         return NSK_JVMTI_INVALID_JLOCATION;
 544 
 545     return location;
 546 }
 547 
 548 /** Set breakpoint to a line. */
 549 jlocation nsk_jvmti_setLineBreakpoint(jclass cls, jmethodID method, int line) {
 550     jlocation location = NSK_JVMTI_INVALID_JLOCATION;
 551 
 552     if (!NSK_VERIFY((location =
 553             nsk_jvmti_getLineLocation(cls, method, line)) != NSK_JVMTI_INVALID_JLOCATION))
 554         return NSK_JVMTI_INVALID_JLOCATION;
 555 
 556     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetBreakpoint, jvmti_env, method, location)))
 557         return NSK_JVMTI_INVALID_JLOCATION;
 558 
 559     return location;
 560 }
 561 
 562 /** Remove breakpoint from a line. */
 563 jlocation nsk_jvmti_clearLineBreakpoint(jclass cls, jmethodID method, int line) {
 564     jlocation location = NSK_JVMTI_INVALID_JLOCATION;
 565 
 566     if (!NSK_VERIFY((location =
 567             nsk_jvmti_getLineLocation(cls, method, line)) != NSK_JVMTI_INVALID_JLOCATION))
 568         return NSK_JVMTI_INVALID_JLOCATION;
 569 
 570     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(ClearBreakpoint, jvmti_env, method, location)))
 571         return NSK_JVMTI_INVALID_JLOCATION;
 572 
 573     return location;
 574 }
 575 
 576 /* ============================================================================= */
 577 
 578 /** Enable or disable given events. */
 579 int nsk_jvmti_enableEvents(jvmtiEventMode enable, int size, jvmtiEvent list[], jthread thread) {
 580     int i;
 581 
 582     for (i = 0; i < size; i++) {
 583         if (!NSK_JVMTI_VERIFY(
 584                 NSK_CPP_STUB4(SetEventNotificationMode, jvmti_env, enable,
 585                                                 list[i], thread))) {
 586             nsk_jvmti_setFailStatus();
 587             return NSK_FALSE;
 588         }
 589     }
 590     return NSK_TRUE;
 591 }
 592 
 593 /* ============================================================================= */
 594 
 595 typedef jint (JNICALL *checkStatus_type)(JNIEnv* jni_env, jclass cls, jint debuggeeStatus);
 596 
 597 static checkStatus_type checkStatus_func = NULL;
 598 
 599 /**
 600  * Proxy function to gain sequential access to checkStatus of each agent
 601  */
 602 JNIEXPORT jint JNICALL
 603 MA_checkStatus(JNIEnv* jni_env, jclass cls, jint debuggeeStatus) {
 604     jint status;
 605 


 607     return (*checkStatus_func)(jni_env, cls, status);
 608 }
 609 
 610 /**
 611  * nativeMethodBind callback:
 612  *      if needed, redirects checkStatus native method call
 613  */
 614 static void JNICALL nativeMethodBind(jvmtiEnv* jvmti_env, JNIEnv *jni_env,
 615                               jthread thread, jmethodID mid,
 616                               void* address, void** new_address_ptr) {
 617     const char* BIND_CLASS_NAME = "Lnsk/share/jvmti/DebugeeClass;";
 618     const char* BIND_METHOD_NAME = "checkStatus";
 619     const char* BIND_METHOD_SIGNATURE = "(I)I";
 620 
 621     jvmtiPhase phase;
 622     jclass cls;
 623     char *class_sig = NULL;
 624     char *name = NULL;
 625     char *sig = NULL;
 626 
 627     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetPhase, jvmti_env, &phase))) {
 628         nsk_jvmti_setFailStatus();
 629         return;
 630     }
 631 
 632     if (phase != JVMTI_PHASE_START && phase != JVMTI_PHASE_LIVE)
 633         return;
 634 
 635     if (NSK_JVMTI_VERIFY(
 636             NSK_CPP_STUB5(GetMethodName, jvmti_env, mid, &name, &sig, NULL))) {
 637         if (strcmp(name, BIND_METHOD_NAME) == 0 &&
 638                 strcmp(sig, BIND_METHOD_SIGNATURE) == 0) {
 639 
 640             if (NSK_JVMTI_VERIFY(
 641                     NSK_CPP_STUB3(GetMethodDeclaringClass, jvmti_env, mid, &cls))
 642              && NSK_JVMTI_VERIFY(
 643                     NSK_CPP_STUB4(GetClassSignature, jvmti_env, cls, &class_sig, NULL))
 644              && strcmp(class_sig, BIND_CLASS_NAME) == 0
 645              && address != (void*)Java_nsk_share_jvmti_DebugeeClass_checkStatus) {
 646                 checkStatus_func = (checkStatus_type)address;
 647                 NSK_TRACE(*new_address_ptr = (void*)MA_checkStatus);
 648             }
 649         }
 650     }
 651 
 652     if (name != NULL)
 653         NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)name);
 654 
 655     if (sig != NULL)
 656         NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)sig);
 657 
 658     if (class_sig != NULL)
 659         NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)class_sig);
 660 }
 661 
 662 /**
 663  * Initialize multiple agent:
 664  *      establish processing of nativeMethodBind events
 665  */
 666 int nsk_jvmti_init_MA(jvmtiEventCallbacks* callbacks) {
 667 
 668     if (callbacks == NULL) {
 669         NSK_COMPLAIN0("callbacks should not be NULL\n");
 670         nsk_jvmti_setFailStatus();
 671         return NSK_FALSE;
 672     }
 673 
 674     if (callbacks->NativeMethodBind != NULL) {
 675         NSK_COMPLAIN0("callbacks.NativeMethodBind should be NULL\n");
 676         nsk_jvmti_setFailStatus();
 677         return NSK_FALSE;
 678     }
 679 
 680     {
 681         jvmtiCapabilities caps;
 682         memset(&caps, 0, sizeof(caps));
 683         caps.can_generate_native_method_bind_events = 1;
 684         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, jvmti_env, &caps)))
 685             return NSK_FALSE;
 686     }
 687 
 688     callbacks->NativeMethodBind = nativeMethodBind;
 689     if (!NSK_JVMTI_VERIFY(
 690             NSK_CPP_STUB3(SetEventCallbacks, jvmti_env, callbacks,
 691                 sizeof(jvmtiEventCallbacks))))
 692         return NSK_FALSE;
 693 
 694     if (!NSK_JVMTI_VERIFY(
 695             NSK_CPP_STUB4(SetEventNotificationMode, jvmti_env, JVMTI_ENABLE,
 696                 JVMTI_EVENT_NATIVE_METHOD_BIND, NULL)))
 697         return NSK_FALSE;
 698 
 699     return NSK_TRUE;
 700 }
 701 
 702 /* ============================================================================= */
 703 
 704 int nsk_jvmti_isOptionalEvent(jvmtiEvent event) {
 705 
 706     return (event == JVMTI_EVENT_EXCEPTION)
 707         || (event == JVMTI_EVENT_EXCEPTION_CATCH)
 708         || (event == JVMTI_EVENT_SINGLE_STEP)
 709         || (event == JVMTI_EVENT_FRAME_POP)
 710         || (event == JVMTI_EVENT_BREAKPOINT)
 711         || (event == JVMTI_EVENT_FIELD_ACCESS)
 712         || (event == JVMTI_EVENT_FIELD_MODIFICATION)
 713         || (event == JVMTI_EVENT_METHOD_ENTRY)
 714         || (event == JVMTI_EVENT_METHOD_EXIT)
 715         || (event == JVMTI_EVENT_NATIVE_METHOD_BIND)
 716         || (event == JVMTI_EVENT_COMPILED_METHOD_LOAD)
 717         || (event == JVMTI_EVENT_COMPILED_METHOD_UNLOAD)
 718         || (event == JVMTI_EVENT_MONITOR_WAIT)
 719         || (event == JVMTI_EVENT_MONITOR_WAITED)
 720         || (event == JVMTI_EVENT_MONITOR_CONTENDED_ENTER)
 721         || (event == JVMTI_EVENT_MONITOR_CONTENDED_ENTERED)
 722         || (event == JVMTI_EVENT_GARBAGE_COLLECTION_START)
 723         || (event == JVMTI_EVENT_GARBAGE_COLLECTION_FINISH)
 724         || (event == JVMTI_EVENT_OBJECT_FREE)
 725         || (event == JVMTI_EVENT_VM_OBJECT_ALLOC);
 726 }
 727 
 728 /* ============================================================================= */
 729 
 730 void nsk_jvmti_showPossessedCapabilities(jvmtiEnv *jvmti_env) {
 731 
 732     jvmtiCapabilities caps;
 733 
 734     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetCapabilities, jvmti_env, &caps))) {
 735         return;
 736     }
 737 
 738     NSK_DISPLAY0("\n");
 739     NSK_DISPLAY0("Possessed capabilities:\n");
 740     NSK_DISPLAY0("-----------------------\n");
 741     if (caps.can_tag_objects)
 742         NSK_DISPLAY0("\tcan_tag_objects\n");
 743     if (caps.can_generate_field_modification_events)
 744         NSK_DISPLAY0("\tcan_generate_field_modification_events\n");
 745     if (caps.can_generate_field_access_events)
 746         NSK_DISPLAY0("\tcan_generate_field_access_events\n");
 747     if (caps.can_get_bytecodes)
 748         NSK_DISPLAY0("\tcan_get_bytecodes\n");
 749     if (caps.can_get_synthetic_attribute)
 750         NSK_DISPLAY0("\tcan_get_synthetic_attribute\n");
 751     if (caps.can_get_owned_monitor_info)
 752         NSK_DISPLAY0("\tcan_get_owned_monitor_info\n");
 753     if (caps.can_get_current_contended_monitor)
 754         NSK_DISPLAY0("\tcan_get_current_contended_monitor\n");




  60 
  61 /* ============================================================================= */
  62 
  63 void nsk_jvmti_setFailStatus() {
  64     currentAgentStatus = NSK_STATUS_FAILED;
  65 }
  66 
  67 int nsk_jvmti_isFailStatus() {
  68     return (nsk_jvmti_getStatus() != NSK_STATUS_PASSED);
  69 }
  70 
  71 jint nsk_jvmti_getStatus() {
  72     return currentAgentStatus;
  73 }
  74 
  75 /* ============================================================================= */
  76 static jvmtiError init_agent_data(jvmtiEnv *jvmti_env, agent_data_t *data) {
  77     data->thread_state = NEW;
  78     data->last_debuggee_status = NSK_STATUS_PASSED;
  79 
  80     return jvmti_env->CreateRawMonitor("agent_data_monitor", &data->monitor);
  81 }
  82 
  83 /** Reset agent data to prepare for another run. */
  84 void nsk_jvmti_resetAgentData() {
  85     rawMonitorEnter(jvmti_env, agent_data.monitor);
  86     /* wait for agentThreadWrapper() to finish */
  87     while (agent_data.thread_state != TERMINATED) {
  88         rawMonitorWait(jvmti_env, agent_data.monitor, 10);
  89     }
  90     agent_data.thread_state = NEW;
  91     agent_data.last_debuggee_status = NSK_STATUS_PASSED;
  92     rawMonitorExit(jvmti_env, agent_data.monitor);
  93 }
  94 
  95 static jvmtiError free_agent_data(jvmtiEnv *jvmti_env, agent_data_t *data) {
  96     return jvmti_env->DestroyRawMonitor(data->monitor);
  97 }
  98 
  99 /** Create JVMTI environment. */
 100 jvmtiEnv* nsk_jvmti_createJVMTIEnv(JavaVM* javaVM, void* reserved) {
 101     jvm = javaVM;
 102     if (!NSK_VERIFY(javaVM->GetEnv((void **)&jvmti_env, JVMTI_VERSION_1_1) == JNI_OK)) {

 103         nsk_jvmti_setFailStatus();
 104         return NULL;
 105     }
 106 
 107     if (!NSK_JVMTI_VERIFY(init_agent_data(jvmti_env, &agent_data))) {
 108         nsk_jvmti_setFailStatus();
 109         return NULL;
 110     }
 111 
 112     return jvmti_env;
 113 }
 114 
 115 /** Dispose JVMTI environment */
 116 static int nsk_jvmti_disposeJVMTIEnv(jvmtiEnv* jvmti_env) {
 117     if (jvmti_env != NULL) {
 118         if (!NSK_JVMTI_VERIFY(jvmti_env->DisposeEnvironment())) {

 119             nsk_jvmti_setFailStatus();
 120             return NSK_FALSE;
 121         }
 122 
 123         if (!NSK_JVMTI_VERIFY(free_agent_data(jvmti_env, &agent_data))) {
 124             nsk_jvmti_setFailStatus();
 125             return NSK_FALSE;
 126         }
 127     }
 128     return NSK_TRUE;
 129 }
 130 
 131 /** Get JNI environment for agent thread. */
 132 JNIEnv* nsk_jvmti_getAgentJNIEnv() {
 133     return jni_env;
 134 }
 135 
 136 /** Get JVMTI environment for agent */
 137 jvmtiEnv* nsk_jvmti_getAgentJVMTIEnv() {
 138     return jvmti_env;


 146     rawMonitorExit(jvmti_env, agent_data.monitor);
 147 }
 148 
 149 /** Wrapper for user agent thread. */
 150 static void JNICALL
 151 agentThreadWrapper(jvmtiEnv* jvmti_env, JNIEnv* agentJNI, void* arg) {
 152     jni_env = agentJNI;
 153 
 154     /* run user agent proc */
 155     {
 156         set_agent_thread_state(RUNNABLE);
 157 
 158         NSK_TRACE((*agentThreadProc)(jvmti_env, agentJNI, agentThreadArg));
 159 
 160         set_agent_thread_state(TERMINATED);
 161     }
 162 
 163     /* finalize agent thread */
 164     {
 165         /* gelete global ref for agent thread */
 166         agentJNI->DeleteGlobalRef(agentThread);
 167         agentThread = NULL;
 168     }
 169 }
 170 
 171 /** Start wrapper for user agent thread. */
 172 static jthread startAgentThreadWrapper(JNIEnv *jni_env, jvmtiEnv* jvmti_env) {
 173     const jint  THREAD_PRIORITY = JVMTI_THREAD_MAX_PRIORITY;
 174     const char* THREAD_NAME = "JVMTI agent thread";
 175     const char* THREAD_CLASS_NAME = "java/lang/Thread";
 176     const char* THREAD_CTOR_NAME = "<init>";
 177     const char* THREAD_CTOR_SIGNATURE = "(Ljava/lang/String;)V";
 178 
 179     jobject threadName = NULL;
 180     jclass threadClass = NULL;
 181     jmethodID threadCtor = NULL;
 182     jobject threadObject = NULL;
 183     jobject threadGlobalRef = NULL;
 184 
 185     if (!NSK_JNI_VERIFY(jni_env, (threadClass = jni_env->FindClass(THREAD_CLASS_NAME)) != NULL)) {

 186         return NULL;
 187     }
 188 
 189     if (!NSK_JNI_VERIFY(jni_env, (threadCtor =
 190             jni_env->GetMethodID(threadClass, THREAD_CTOR_NAME, THREAD_CTOR_SIGNATURE)) != NULL))
 191         return NULL;
 192 
 193     if (!NSK_JNI_VERIFY(jni_env, (threadName = jni_env->NewStringUTF(THREAD_NAME)) != NULL))

 194         return NULL;
 195 
 196     if (!NSK_JNI_VERIFY(jni_env, (threadObject =
 197             jni_env->NewObject(threadClass, threadCtor, threadName)) != NULL))
 198         return NULL;
 199 
 200     if (!NSK_JNI_VERIFY(jni_env, (threadGlobalRef =
 201             jni_env->NewGlobalRef(threadObject)) != NULL)) {
 202         jni_env->DeleteLocalRef(threadObject);
 203         return NULL;
 204     }
 205     agentThread = (jthread)threadGlobalRef;
 206 
 207     if (!NSK_JVMTI_VERIFY(
 208             jvmti_env->RunAgentThread(agentThread, &agentThreadWrapper, agentThreadArg, THREAD_PRIORITY))) {
 209         jni_env->DeleteGlobalRef(threadGlobalRef);
 210         jni_env->DeleteLocalRef(threadObject);

 211         return NULL;
 212     }
 213     return agentThread;
 214 }
 215 
 216 /** Register user agent thread with arg. */
 217 int nsk_jvmti_setAgentProc(jvmtiStartFunction proc, void* arg) {
 218     agentThreadProc = proc;
 219     agentThreadArg = arg;
 220     return NSK_TRUE;
 221 }
 222 
 223 /** Get agent thread ref. */
 224 jthread nsk_jvmti_getAgentThread() {
 225     return agentThread;
 226 }
 227 
 228 /** Run registered user agent thread via wrapper. */
 229 static jthread nsk_jvmti_runAgentThread(JNIEnv *jni_env, jvmtiEnv* jvmti_env) {
 230     /* start agent thread wrapper */


 373 /** Native function for Java code to reset agent data. */
 374 JNIEXPORT void JNICALL
 375 Java_nsk_share_jvmti_DebugeeClass_resetAgentData(JNIEnv* jni_env, jclass cls) {
 376     NSK_TRACE(nsk_jvmti_resetAgentData());
 377 }
 378 
 379 /* ============================================================================= */
 380 
 381 /** Find loaded class by signature. */
 382 jclass nsk_jvmti_classBySignature(const char signature[]) {
 383     jclass* classes = NULL;
 384     jint count = 0;
 385     jclass foundClass = NULL;
 386     int i;
 387 
 388     if (!NSK_VERIFY(signature != NULL)) {
 389         nsk_jvmti_setFailStatus();
 390         return NULL;
 391     }
 392 
 393     if (!NSK_JVMTI_VERIFY(jvmti_env->GetLoadedClasses(&count, &classes))) {

 394         nsk_jvmti_setFailStatus();
 395         return NULL;
 396     }
 397 
 398     for (i = 0; i < count; i++) {
 399         char* sig = NULL;
 400         char* generic = NULL;
 401 
 402         if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(classes[i], &sig, &generic))) {

 403             nsk_jvmti_setFailStatus();
 404             break;
 405         }
 406 
 407         if (sig != NULL && strcmp(signature, sig) == 0) {
 408             foundClass = classes[i];
 409         }
 410 
 411         if (!(NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)sig))
 412                 && NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic)))) {


 413             nsk_jvmti_setFailStatus();
 414             break;
 415         }
 416 
 417         if (foundClass != NULL)
 418             break;
 419     }
 420 
 421     if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)classes))) {

 422         nsk_jvmti_setFailStatus();
 423         return NULL;
 424     }
 425 
 426     if (!NSK_JNI_VERIFY(jni_env, (foundClass = (jclass)
 427                 jni_env->NewGlobalRef(foundClass)) != NULL)) {
 428         nsk_jvmti_setFailStatus();
 429         return NULL;
 430     }
 431 
 432     return foundClass;
 433 }
 434 
 435 /** Find alive thread by name. */
 436 jthread nsk_jvmti_threadByName(const char name[]) {
 437     jthread* threads = NULL;
 438     jint count = 0;
 439     jthread foundThread = NULL;
 440     int i;
 441 
 442     if (!NSK_VERIFY(name != NULL)) {
 443         nsk_jvmti_setFailStatus();
 444         return NULL;
 445     }
 446 
 447     if (!NSK_JVMTI_VERIFY(jvmti_env->GetAllThreads(&count, &threads))) {

 448         nsk_jvmti_setFailStatus();
 449         return NULL;
 450     }
 451 
 452     for (i = 0; i < count; i++) {
 453         jvmtiThreadInfo info;
 454 
 455         if (!NSK_JVMTI_VERIFY(jvmti_env->GetThreadInfo(threads[i], &info))) {

 456             nsk_jvmti_setFailStatus();
 457             break;
 458         }
 459 
 460         if (info.name != NULL && strcmp(name, info.name) == 0) {
 461             foundThread = threads[i];
 462             break;
 463         }
 464     }
 465 
 466     if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)threads))) {

 467         nsk_jvmti_setFailStatus();
 468         return NULL;
 469     }
 470 
 471     if (!NSK_JNI_VERIFY(jni_env, (foundThread = (jthread)
 472                 jni_env->NewGlobalRef(foundThread)) != NULL)) {
 473         nsk_jvmti_setFailStatus();
 474         return NULL;
 475     }
 476 
 477     return foundThread;
 478 }
 479 
 480 
 481 /* ============================================================================= */
 482 
 483 /** Add all capabilities for finding line locations. */
 484 int nsk_jvmti_addLocationCapabilities() {
 485     jvmtiCapabilities caps;
 486 
 487     memset(&caps, 0, sizeof(caps));
 488     caps.can_get_line_numbers = 1;
 489     if (!NSK_JVMTI_VERIFY(jvmti_env->AddCapabilities(&caps)))

 490         return NSK_FALSE;
 491 
 492     return NSK_TRUE;
 493 }
 494 
 495 /** Add all capabilities for using breakpoints. */
 496 int nsk_jvmti_addBreakpointCapabilities() {
 497     jvmtiCapabilities caps;
 498 
 499     if (!nsk_jvmti_addLocationCapabilities())
 500         return NSK_FALSE;
 501 
 502     memset(&caps, 0, sizeof(caps));
 503     caps.can_generate_breakpoint_events = 1;
 504     if (!NSK_JVMTI_VERIFY(jvmti_env->AddCapabilities(&caps)))

 505         return NSK_FALSE;
 506 
 507     return NSK_TRUE;
 508 }
 509 
 510 /** Find line location. */
 511 jlocation nsk_jvmti_getLineLocation(jclass cls, jmethodID method, int line) {
 512     jint count = 0;
 513     jvmtiLineNumberEntry* table = NULL;
 514     jlocation location = NSK_JVMTI_INVALID_JLOCATION;
 515     int i;
 516 
 517     if (!NSK_JVMTI_VERIFY(jvmti_env->GetLineNumberTable(method, &count, &table)))
 518         return NSK_JVMTI_INVALID_JLOCATION;
 519 
 520     for (i = 0; i < count; i++) {
 521         if (table[i].line_number == line) {
 522             location = table[i].start_location;
 523             break;
 524         }
 525     }
 526 
 527     if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)table)))
 528         return NSK_JVMTI_INVALID_JLOCATION;
 529 
 530     return location;
 531 }
 532 
 533 /** Set breakpoint to a line. */
 534 jlocation nsk_jvmti_setLineBreakpoint(jclass cls, jmethodID method, int line) {
 535     jlocation location = NSK_JVMTI_INVALID_JLOCATION;
 536 
 537     if (!NSK_VERIFY((location =
 538             nsk_jvmti_getLineLocation(cls, method, line)) != NSK_JVMTI_INVALID_JLOCATION))
 539         return NSK_JVMTI_INVALID_JLOCATION;
 540 
 541     if (!NSK_JVMTI_VERIFY(jvmti_env->SetBreakpoint(method, location)))
 542         return NSK_JVMTI_INVALID_JLOCATION;
 543 
 544     return location;
 545 }
 546 
 547 /** Remove breakpoint from a line. */
 548 jlocation nsk_jvmti_clearLineBreakpoint(jclass cls, jmethodID method, int line) {
 549     jlocation location = NSK_JVMTI_INVALID_JLOCATION;
 550 
 551     if (!NSK_VERIFY((location =
 552             nsk_jvmti_getLineLocation(cls, method, line)) != NSK_JVMTI_INVALID_JLOCATION))
 553         return NSK_JVMTI_INVALID_JLOCATION;
 554 
 555     if (!NSK_JVMTI_VERIFY(jvmti_env->ClearBreakpoint(method, location)))
 556         return NSK_JVMTI_INVALID_JLOCATION;
 557 
 558     return location;
 559 }
 560 
 561 /* ============================================================================= */
 562 
 563 /** Enable or disable given events. */
 564 int nsk_jvmti_enableEvents(jvmtiEventMode enable, int size, jvmtiEvent list[], jthread thread) {
 565     int i;
 566 
 567     for (i = 0; i < size; i++) {
 568         if (!NSK_JVMTI_VERIFY(jvmti_env->SetEventNotificationMode(enable, list[i], thread))) {


 569             nsk_jvmti_setFailStatus();
 570             return NSK_FALSE;
 571         }
 572     }
 573     return NSK_TRUE;
 574 }
 575 
 576 /* ============================================================================= */
 577 
 578 typedef jint (JNICALL *checkStatus_type)(JNIEnv* jni_env, jclass cls, jint debuggeeStatus);
 579 
 580 static checkStatus_type checkStatus_func = NULL;
 581 
 582 /**
 583  * Proxy function to gain sequential access to checkStatus of each agent
 584  */
 585 JNIEXPORT jint JNICALL
 586 MA_checkStatus(JNIEnv* jni_env, jclass cls, jint debuggeeStatus) {
 587     jint status;
 588 


 590     return (*checkStatus_func)(jni_env, cls, status);
 591 }
 592 
 593 /**
 594  * nativeMethodBind callback:
 595  *      if needed, redirects checkStatus native method call
 596  */
 597 static void JNICALL nativeMethodBind(jvmtiEnv* jvmti_env, JNIEnv *jni_env,
 598                               jthread thread, jmethodID mid,
 599                               void* address, void** new_address_ptr) {
 600     const char* BIND_CLASS_NAME = "Lnsk/share/jvmti/DebugeeClass;";
 601     const char* BIND_METHOD_NAME = "checkStatus";
 602     const char* BIND_METHOD_SIGNATURE = "(I)I";
 603 
 604     jvmtiPhase phase;
 605     jclass cls;
 606     char *class_sig = NULL;
 607     char *name = NULL;
 608     char *sig = NULL;
 609 
 610     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
 611         nsk_jvmti_setFailStatus();
 612         return;
 613     }
 614 
 615     if (phase != JVMTI_PHASE_START && phase != JVMTI_PHASE_LIVE)
 616         return;
 617 
 618     if (NSK_JVMTI_VERIFY(jvmti_env->GetMethodName(mid, &name, &sig, NULL))) {

 619         if (strcmp(name, BIND_METHOD_NAME) == 0 &&
 620                 strcmp(sig, BIND_METHOD_SIGNATURE) == 0) {
 621 
 622             if (NSK_JVMTI_VERIFY(jvmti_env->GetMethodDeclaringClass(mid, &cls))
 623              && NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(cls, &class_sig, NULL))


 624              && strcmp(class_sig, BIND_CLASS_NAME) == 0
 625              && address != (void*)Java_nsk_share_jvmti_DebugeeClass_checkStatus) {
 626                 checkStatus_func = (checkStatus_type)address;
 627                 NSK_TRACE(*new_address_ptr = (void*)MA_checkStatus);
 628             }
 629         }
 630     }
 631 
 632     if (name != NULL)
 633         jvmti_env->Deallocate((unsigned char*)name);
 634 
 635     if (sig != NULL)
 636         jvmti_env->Deallocate((unsigned char*)sig);
 637 
 638     if (class_sig != NULL)
 639         jvmti_env->Deallocate((unsigned char*)class_sig);
 640 }
 641 
 642 /**
 643  * Initialize multiple agent:
 644  *      establish processing of nativeMethodBind events
 645  */
 646 int nsk_jvmti_init_MA(jvmtiEventCallbacks* callbacks) {
 647 
 648     if (callbacks == NULL) {
 649         NSK_COMPLAIN0("callbacks should not be NULL\n");
 650         nsk_jvmti_setFailStatus();
 651         return NSK_FALSE;
 652     }
 653 
 654     if (callbacks->NativeMethodBind != NULL) {
 655         NSK_COMPLAIN0("callbacks.NativeMethodBind should be NULL\n");
 656         nsk_jvmti_setFailStatus();
 657         return NSK_FALSE;
 658     }
 659 
 660     {
 661         jvmtiCapabilities caps;
 662         memset(&caps, 0, sizeof(caps));
 663         caps.can_generate_native_method_bind_events = 1;
 664         if (!NSK_JVMTI_VERIFY(jvmti_env->AddCapabilities(&caps)))
 665             return NSK_FALSE;
 666     }
 667 
 668     callbacks->NativeMethodBind = nativeMethodBind;
 669     if (!NSK_JVMTI_VERIFY(jvmti_env->SetEventCallbacks(callbacks, sizeof(jvmtiEventCallbacks))))


 670         return NSK_FALSE;
 671 
 672     if (!NSK_JVMTI_VERIFY(
 673             jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_NATIVE_METHOD_BIND, NULL)))

 674         return NSK_FALSE;
 675 
 676     return NSK_TRUE;
 677 }
 678 
 679 /* ============================================================================= */
 680 
 681 int nsk_jvmti_isOptionalEvent(jvmtiEvent event) {
 682 
 683     return (event == JVMTI_EVENT_EXCEPTION)
 684         || (event == JVMTI_EVENT_EXCEPTION_CATCH)
 685         || (event == JVMTI_EVENT_SINGLE_STEP)
 686         || (event == JVMTI_EVENT_FRAME_POP)
 687         || (event == JVMTI_EVENT_BREAKPOINT)
 688         || (event == JVMTI_EVENT_FIELD_ACCESS)
 689         || (event == JVMTI_EVENT_FIELD_MODIFICATION)
 690         || (event == JVMTI_EVENT_METHOD_ENTRY)
 691         || (event == JVMTI_EVENT_METHOD_EXIT)
 692         || (event == JVMTI_EVENT_NATIVE_METHOD_BIND)
 693         || (event == JVMTI_EVENT_COMPILED_METHOD_LOAD)
 694         || (event == JVMTI_EVENT_COMPILED_METHOD_UNLOAD)
 695         || (event == JVMTI_EVENT_MONITOR_WAIT)
 696         || (event == JVMTI_EVENT_MONITOR_WAITED)
 697         || (event == JVMTI_EVENT_MONITOR_CONTENDED_ENTER)
 698         || (event == JVMTI_EVENT_MONITOR_CONTENDED_ENTERED)
 699         || (event == JVMTI_EVENT_GARBAGE_COLLECTION_START)
 700         || (event == JVMTI_EVENT_GARBAGE_COLLECTION_FINISH)
 701         || (event == JVMTI_EVENT_OBJECT_FREE)
 702         || (event == JVMTI_EVENT_VM_OBJECT_ALLOC);
 703 }
 704 
 705 /* ============================================================================= */
 706 
 707 void nsk_jvmti_showPossessedCapabilities(jvmtiEnv *jvmti_env) {
 708 
 709     jvmtiCapabilities caps;
 710 
 711     if (!NSK_JVMTI_VERIFY(jvmti_env->GetCapabilities(&caps))) {
 712         return;
 713     }
 714 
 715     NSK_DISPLAY0("\n");
 716     NSK_DISPLAY0("Possessed capabilities:\n");
 717     NSK_DISPLAY0("-----------------------\n");
 718     if (caps.can_tag_objects)
 719         NSK_DISPLAY0("\tcan_tag_objects\n");
 720     if (caps.can_generate_field_modification_events)
 721         NSK_DISPLAY0("\tcan_generate_field_modification_events\n");
 722     if (caps.can_generate_field_access_events)
 723         NSK_DISPLAY0("\tcan_generate_field_access_events\n");
 724     if (caps.can_get_bytecodes)
 725         NSK_DISPLAY0("\tcan_get_bytecodes\n");
 726     if (caps.can_get_synthetic_attribute)
 727         NSK_DISPLAY0("\tcan_get_synthetic_attribute\n");
 728     if (caps.can_get_owned_monitor_info)
 729         NSK_DISPLAY0("\tcan_get_owned_monitor_info\n");
 730     if (caps.can_get_current_contended_monitor)
 731         NSK_DISPLAY0("\tcan_get_current_contended_monitor\n");


< prev index next >