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");
|