1 /*
2  * Copyright (c) 2004, 2019, 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.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 #include <string.h>
25 #include "jvmti.h"
26 #include "agent_common.h"
27 #include "ExceptionCheckingJniEnv.hpp"
28 #include "jni_tools.h"
29 #include "jvmti_tools.h"
30 #include "JVMTITools.h"
31 
32 extern "C" {
33 
34 /* ============================================================================= */
35 
36 /* scaffold objects */
37 static JNIEnv* jni = NULL;
38 static jvmtiEnv *jvmti = NULL;
39 static jlong timeout = 0;
40 static jrawMonitorID syncLock = NULL;
41 
42 /* constant names */
43 #define JVMTI_EVENT_COUNT   (int)(JVMTI_MAX_EVENT_TYPE_VAL - JVMTI_MIN_EVENT_TYPE_VAL + 1)
44 #define EXPECTED_CLASS_NAME "Lnsk/jvmti/scenarios/events/EM01/em01t002a;"
45 #define CLASS_LOADER_COUNT_PARAM "classLoaderCount"
46 
47 static int eventCount[JVMTI_EVENT_COUNT];
48 
49 static int classLoaderCount = 0;
50 
51 static jvmtiPhase currentPhase;
52 
53 /* ============================================================================= */
54 /* ============================================================================= */
55 
56 
57 /*
58  * Class:     nsk_jvmti_scenarios_events_EM01_em01t002
59  * Method:    loadClass
60  * Signature: (Lnsk/share/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;
61  */
62 JNIEXPORT jclass JNICALL
Java_nsk_jvmti_scenarios_events_EM01_em01t002_loadClass(JNIEnv * jni_env,jobject o,jobject loader,jstring className)63 Java_nsk_jvmti_scenarios_events_EM01_em01t002_loadClass(JNIEnv *jni_env,
64                         jobject o, jobject loader, jstring className) {
65     ExceptionCheckingJniEnvPtr ec_jni(jni_env);
66     jclass klass;
67     jmethodID methodID;
68     jclass loadedClass;
69 
70     klass = ec_jni->GetObjectClass(loader, TRACE_JNI_CALL);
71     methodID = ec_jni->GetMethodID(
72             klass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;", TRACE_JNI_CALL);
73     loadedClass = (jclass) ec_jni->CallObjectMethod(loader, methodID,
74                                                     TRACE_JNI_CALL_VARARGS(className));
75 
76     return loadedClass;
77 }
78 
79 /*
80  * Class:     nsk_jvmti_scenarios_events_EM01_em01t002
81  * Method:    prepareClass
82  * Signature: (Ljava/lang/Class;)Z
83  */
84 JNIEXPORT jboolean JNICALL
Java_nsk_jvmti_scenarios_events_EM01_em01t002_prepareClass(JNIEnv * jni,jobject o,jclass klass)85 Java_nsk_jvmti_scenarios_events_EM01_em01t002_prepareClass(JNIEnv *jni,
86                         jobject o, jclass klass) {
87     ExceptionCheckingJniEnvPtr ec_jni(jni);
88     jfieldID fieldID;
89 
90     fieldID = ec_jni->GetStaticFieldID(klass, "toProvokePreparation", "I", TRACE_JNI_CALL);
91     return NSK_TRUE;
92 }
93 
94 /*
95  * Class:     nsk_jvmti_scenarios_events_EM01_em01t002
96  * Method:    startThread
97  * Signature: (Ljava/lang/Thread;)Z
98  */
99 JNIEXPORT jboolean JNICALL
Java_nsk_jvmti_scenarios_events_EM01_em01t002_startThread(JNIEnv * jni_env,jobject o,jobject thread)100 Java_nsk_jvmti_scenarios_events_EM01_em01t002_startThread(JNIEnv *jni_env,
101                         jobject o, jobject thread) {
102     ExceptionCheckingJniEnvPtr ec_jni(jni_env);
103     jclass klass;
104     jmethodID methodID;
105 
106     klass = ec_jni->GetObjectClass(thread, TRACE_JNI_CALL);
107     methodID = ec_jni->GetMethodID(klass, "start", "()V", TRACE_JNI_CALL);
108     ec_jni->CallVoidMethod(thread, methodID, TRACE_JNI_CALL);
109     return NSK_TRUE;
110 }
111 
112 /* ============================================================================= */
113 /* ============================================================================= */
114 
115 static void
changeCount(jvmtiEvent event)116 changeCount(jvmtiEvent event) {
117 
118     if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(syncLock)))
119         nsk_jvmti_setFailStatus();
120 
121     eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL]++;
122 
123     if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(syncLock)))
124         nsk_jvmti_setFailStatus();
125 
126 }
127 
128 /* ============================================================================= */
129 
130 static void
showEventStatistics()131 showEventStatistics() {
132     int i;
133     const char* str;
134 
135     NSK_DISPLAY0("Event statistics\n");
136     NSK_DISPLAY0("----------------\n");
137     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
138         if (eventCount[i] > 0) {
139             str = TranslateEvent((jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL));
140             NSK_DISPLAY2("%-40s %7d\n", str, eventCount[i]);
141         }
142     }
143 }
144 
145 /* ========================================================================== */
146 
147 /* callbacks */
148 void
classEventsHandler(jvmtiEvent event,jvmtiEnv * jvmti_env,JNIEnv * jni_env,jclass klass)149 classEventsHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env,
150                             jclass klass) {
151 
152     char *className;
153     char *generic;
154     jvmtiPhase phase;
155 
156     if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(klass, &className, &generic))) {
157         nsk_jvmti_setFailStatus();
158         return;
159     }
160 
161     if (strcmp(className, EXPECTED_CLASS_NAME) == 0) {
162         changeCount(event);
163         NSK_DISPLAY3("%25s(%4d)>>\tclass: %s\n",
164                             TranslateEvent(event),
165                             eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL],
166                             className);
167     }
168 
169     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
170         nsk_jvmti_setFailStatus();
171     }
172 
173     if (phase != currentPhase) {
174         NSK_DISPLAY2("Unexpected phase %s, but supposed %s",
175                 TranslatePhase(phase), TranslatePhase(currentPhase));
176     }
177 
178     if ((phase != JVMTI_PHASE_LIVE) && (phase != JVMTI_PHASE_START)) {
179         NSK_COMPLAIN4("%25s was sent during %s(%d)\n\tclass: %s\n",
180                     TranslateEvent(event),
181                     TranslatePhase(phase),
182                     phase,
183                     className);
184         nsk_jvmti_setFailStatus();
185     }
186 
187     if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)className))) {
188         nsk_jvmti_setFailStatus();
189     }
190     if (generic != NULL)
191         if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic))) {
192             nsk_jvmti_setFailStatus();
193         }
194 }
195 
196 void
threadEventHandler(jvmtiEvent event,jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)197 threadEventHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env,
198                             jthread thread) {
199     ExceptionCheckingJniEnvPtr ec_jni(jni_env);
200     jclass classObject;
201     char *className;
202     char *generic;
203     jvmtiPhase phase;
204 
205 
206     classObject = ec_jni->GetObjectClass(thread, TRACE_JNI_CALL);
207 
208     if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(classObject, &className, &generic))) {
209         nsk_jvmti_setFailStatus();
210         return;
211     }
212 
213     if (strcmp(className, EXPECTED_CLASS_NAME) == 0) {
214         changeCount(event);
215         NSK_DISPLAY3("%25s(%4d)>>\tclass: %s\n",
216                             TranslateEvent(event),
217                             eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL],
218                             className);
219     }
220 
221     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
222         nsk_jvmti_setFailStatus();
223     }
224 
225     if (phase != currentPhase) {
226         NSK_DISPLAY2("Unexpected phase %s, but supposed %s",
227                 TranslatePhase(phase), TranslatePhase(currentPhase));
228     }
229 
230     if ((phase != JVMTI_PHASE_START) && (phase != JVMTI_PHASE_LIVE)) {
231         NSK_COMPLAIN4("%25s was sent during %s(%d)\n\tclass: %s\n",
232                     TranslateEvent(event),
233                     TranslatePhase(phase),
234                     phase,
235                     className);
236         nsk_jvmti_setFailStatus();
237     }
238 
239     if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)className))) {
240         nsk_jvmti_setFailStatus();
241     }
242     if (generic != NULL)
243         if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic))) {
244             nsk_jvmti_setFailStatus();
245         }
246 }
247 
248 JNIEXPORT void JNICALL
cbVMStart(jvmtiEnv * jvmti_env,JNIEnv * jni_env)249 cbVMStart(jvmtiEnv* jvmti_env, JNIEnv* jni_env) {
250 
251     jvmtiPhase phase;
252 
253     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
254         nsk_jvmti_setFailStatus();
255     }
256 
257     if ((phase != JVMTI_PHASE_START) && (phase != JVMTI_PHASE_LIVE)) {
258         NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
259                     TranslateEvent(JVMTI_EVENT_VM_START),
260                     TranslatePhase(phase),
261                     phase);
262         nsk_jvmti_setFailStatus();
263     }
264 
265     changeCount(JVMTI_EVENT_VM_START);
266     currentPhase = JVMTI_PHASE_START;
267 }
268 
269 JNIEXPORT void JNICALL
cbVMInit(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)270 cbVMInit(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
271 
272     jvmtiPhase phase;
273 
274     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
275         nsk_jvmti_setFailStatus();
276     }
277 
278     if (phase != JVMTI_PHASE_LIVE) {
279         NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
280                     TranslateEvent(JVMTI_EVENT_VM_INIT),
281                     TranslatePhase(phase),
282                     phase);
283         nsk_jvmti_setFailStatus();
284     }
285 
286     changeCount(JVMTI_EVENT_VM_INIT);
287     currentPhase = JVMTI_PHASE_LIVE;
288 }
289 
290 JNIEXPORT void JNICALL
cbVMDeath(jvmtiEnv * jvmti_env,JNIEnv * jni_env)291 cbVMDeath(jvmtiEnv* jvmti_env, JNIEnv* jni_env) {
292 
293     jvmtiPhase phase;
294 
295     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
296         nsk_jvmti_setFailStatus();
297     }
298 
299     if (phase != JVMTI_PHASE_LIVE) {
300         NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
301                     TranslateEvent(JVMTI_EVENT_VM_INIT),
302                     TranslatePhase(phase),
303                     phase);
304         nsk_jvmti_setFailStatus();
305     }
306 
307     currentPhase = JVMTI_PHASE_DEAD;
308     changeCount(JVMTI_EVENT_VM_DEATH);
309 
310     if (!NSK_JVMTI_VERIFY(jvmti->DestroyRawMonitor(syncLock)))
311         nsk_jvmti_setFailStatus();
312 
313 }
314 
315 JNIEXPORT void JNICALL
cbClassLoad(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jclass klass)316 cbClassLoad(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread,
317                     jclass klass) {
318 
319     classEventsHandler(JVMTI_EVENT_CLASS_LOAD, jvmti_env, jni_env, klass);
320 }
321 
322 JNIEXPORT void JNICALL
cbClassPrepare(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jclass klass)323 cbClassPrepare(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread,
324                     jclass klass) {
325 
326     classEventsHandler(JVMTI_EVENT_CLASS_PREPARE, jvmti_env, jni_env, klass);
327 }
328 
329 JNIEXPORT void JNICALL
cbThreadStart(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)330 cbThreadStart(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
331 
332     threadEventHandler(JVMTI_EVENT_THREAD_START, jvmti_env, jni_env, thread);
333 }
334 
335 JNIEXPORT void JNICALL
cbThreadEnd(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)336 cbThreadEnd(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
337 
338     threadEventHandler(JVMTI_EVENT_THREAD_END, jvmti_env, jni_env, thread);
339 }
340 
341 /* ============================================================================= */
342 
343 static int
enableEvent(jvmtiEventMode enable,jvmtiEvent event)344 enableEvent(jvmtiEventMode enable, jvmtiEvent event) {
345 
346     if (enable == JVMTI_ENABLE) {
347         NSK_DISPLAY1("enabling %s\n", TranslateEvent(event));
348     } else {
349         NSK_DISPLAY1("disabling %s\n", TranslateEvent(event));
350     }
351 
352 
353     if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(enable, event, NULL))) {
354         nsk_jvmti_setFailStatus();
355         return NSK_FALSE;
356     }
357 
358     return NSK_TRUE;
359 }
360 
361 /* ============================================================================= */
362 
363 /**
364  * Testcase: check tested events.
365  *   - check if expected events received for each method
366  *
367  * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break.
368  */
checkEvents(int step)369 int checkEvents(int step) {
370 
371     int i;
372     jvmtiEvent curr;
373     int result = NSK_TRUE;
374     int mustBeChecked;
375 
376     showEventStatistics();
377 
378     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
379 
380         curr = (jvmtiEvent) (i + JVMTI_MIN_EVENT_TYPE_VAL);
381         switch (step) {
382         case 1:
383             mustBeChecked = ((curr == JVMTI_EVENT_CLASS_LOAD)
384                     || (curr == JVMTI_EVENT_CLASS_PREPARE));
385             break;
386 
387         case 2:
388             mustBeChecked = ((curr == JVMTI_EVENT_CLASS_LOAD)
389                     || (curr == JVMTI_EVENT_CLASS_PREPARE)
390                     || (curr == JVMTI_EVENT_THREAD_START)
391                     || (curr == JVMTI_EVENT_THREAD_END));
392             break;
393         default:
394             mustBeChecked = NSK_TRUE;
395         }
396 
397         if (mustBeChecked && eventCount[i] != classLoaderCount) {
398                 nsk_jvmti_setFailStatus();
399                 NSK_COMPLAIN3("Unexpected number of %s events %7d\n\texpected value %d\n",
400                                     TranslateEvent(curr),
401                                     eventCount[i],
402                                     classLoaderCount);
403                 nsk_jvmti_setFailStatus();
404                 result = NSK_FALSE;
405         }
406     }
407 
408     return result;
409 }
410 
411 /* ============================================================================= */
412 
413 static int
setCallBacks()414 setCallBacks() {
415     jvmtiEventCallbacks eventCallbacks;
416     memset(&eventCallbacks, 0, sizeof(eventCallbacks));
417 
418     eventCallbacks.VMStart      = cbVMStart;
419     eventCallbacks.VMInit       = cbVMInit;
420     eventCallbacks.VMDeath      = cbVMDeath;
421     eventCallbacks.ClassLoad    = cbClassLoad;
422     eventCallbacks.ClassPrepare = cbClassPrepare;
423     eventCallbacks.ThreadStart  = cbThreadStart;
424     eventCallbacks.ThreadEnd    = cbThreadEnd;
425 
426     if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks))))
427         return NSK_FALSE;
428 
429     return NSK_TRUE;
430 }
431 
432 /* ============================================================================= */
433 
434 /** Agent algorithm. */
435 static void JNICALL
agentProc(jvmtiEnv * jvmti,JNIEnv * agentJNI,void * arg)436 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) {
437 
438     NSK_DISPLAY0("Wait for debuggee to become ready\n");
439     if (!nsk_jvmti_waitForSync(timeout))
440         return;
441 
442     NSK_DISPLAY0("Let debuggee to load class\n");
443     if (!nsk_jvmti_resumeSync())
444         return;
445 
446     if (!nsk_jvmti_waitForSync(timeout))
447         return;
448 
449     /* check only CLASS_LOAD and CLASS_PREPARE events */
450     if (!checkEvents(1)) {
451         nsk_jvmti_setFailStatus();
452     }
453 
454     NSK_DISPLAY0("Let debuggee to start threads\n");
455     if (!nsk_jvmti_resumeSync())
456         return;
457 
458     if (!nsk_jvmti_waitForSync(timeout))
459         return;
460 
461     NSK_DISPLAY0("check event 2\n");
462     if (!checkEvents(2)) {
463         nsk_jvmti_setFailStatus();
464     }
465 
466     NSK_DISPLAY0("Let debuggee to finish\n");
467     if (!nsk_jvmti_resumeSync())
468         return;
469 
470 }
471 
472 /* ============================================================================= */
473 
474 /** Agent library initialization. */
475 #ifdef STATIC_BUILD
Agent_OnLoad_em01t002(JavaVM * jvm,char * options,void * reserved)476 JNIEXPORT jint JNICALL Agent_OnLoad_em01t002(JavaVM *jvm, char *options, void *reserved) {
477     return Agent_Initialize(jvm, options, reserved);
478 }
Agent_OnAttach_em01t002(JavaVM * jvm,char * options,void * reserved)479 JNIEXPORT jint JNICALL Agent_OnAttach_em01t002(JavaVM *jvm, char *options, void *reserved) {
480     return Agent_Initialize(jvm, options, reserved);
481 }
JNI_OnLoad_em01t002(JavaVM * jvm,char * options,void * reserved)482 JNIEXPORT jint JNI_OnLoad_em01t002(JavaVM *jvm, char *options, void *reserved) {
483     return JNI_VERSION_1_8;
484 }
485 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)486 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
487 
488     currentPhase = JVMTI_PHASE_ONLOAD;
489 
490     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
491         return JNI_ERR;
492 
493     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
494     classLoaderCount = nsk_jvmti_findOptionIntValue(CLASS_LOADER_COUNT_PARAM, 10);
495 
496     jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved);
497     if (!NSK_VERIFY(jvmti != NULL))
498         return JNI_ERR;
499 
500     if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("_syncLock", &syncLock))) {
501         nsk_jvmti_setFailStatus();
502         return JNI_ERR;
503     }
504 
505     if (!setCallBacks()) {
506         return JNI_ERR;
507     }
508 
509     if (!enableEvent(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD)
510             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE)
511             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_THREAD_START)
512             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_THREAD_END)
513             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_START)
514             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT)
515             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH)
516             ) {
517         NSK_COMPLAIN0("Events could not be enabled");
518         nsk_jvmti_setFailStatus();
519         return JNI_ERR;
520     }
521 
522     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
523         return JNI_ERR;
524 
525     currentPhase = JVMTI_PHASE_PRIMORDIAL;
526 
527     return JNI_OK;
528 }
529 
530 }
531