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/em01t001a;"
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 static void
changeCount(jvmtiEvent event)56 changeCount(jvmtiEvent event) {
57 
58     if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(syncLock)))
59         nsk_jvmti_setFailStatus();
60 
61     eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL]++;
62 
63     if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(syncLock)))
64         nsk_jvmti_setFailStatus();
65 
66 }
67 
68 /* ============================================================================= */
69 
70 static void
showEventStatistics()71 showEventStatistics() {
72     int i;
73     const char* str;
74 
75     NSK_DISPLAY0("Event statistics\n");
76     NSK_DISPLAY0("----------------\n");
77     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
78         if (eventCount[i] > 0) {
79             str = TranslateEvent((jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL));
80             NSK_DISPLAY2("%-40s %7d\n", str, eventCount[i]);
81         }
82     }
83 }
84 
85 /* ========================================================================== */
86 
87 /* callbacks */
88 void
classEventsHandler(jvmtiEvent event,jvmtiEnv * jvmti_env,JNIEnv * jni_env,jclass klass)89 classEventsHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env,
90                             jclass klass) {
91 
92     char *className;
93     char *generic;
94     jvmtiPhase phase;
95 
96     if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(klass, &className, &generic))) {
97         nsk_jvmti_setFailStatus();
98         return;
99     }
100 
101     if (strcmp(className, EXPECTED_CLASS_NAME) == 0) {
102         changeCount(event);
103         NSK_DISPLAY3("%25s(%4d)>>\tclass: %s\n",
104                             TranslateEvent(event),
105                             eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL],
106                             className);
107     }
108 
109     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
110         nsk_jvmti_setFailStatus();
111     }
112 
113     if (phase != currentPhase) {
114         NSK_DISPLAY2("Unexpected phase %s, but supposed %s",
115                 TranslatePhase(phase), TranslatePhase(currentPhase));
116     }
117 
118     if ((phase != JVMTI_PHASE_LIVE) && (phase != JVMTI_PHASE_START)) {
119         NSK_COMPLAIN4("%25s was sent during %s(%d)\n\tclass: %s\n",
120                     TranslateEvent(event),
121                     TranslatePhase(phase),
122                     phase,
123                     className);
124         nsk_jvmti_setFailStatus();
125     }
126 
127     if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)className))) {
128         nsk_jvmti_setFailStatus();
129     }
130     if (generic != NULL)
131         if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic))) {
132             nsk_jvmti_setFailStatus();
133         }
134 }
135 
136 void
threadEventHandler(jvmtiEvent event,jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)137 threadEventHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env,
138                             jthread thread) {
139     ExceptionCheckingJniEnvPtr ec_jni(jni_env);
140     jclass classObject;
141     char *className;
142     char *generic;
143     jvmtiPhase phase;
144 
145     classObject = ec_jni->GetObjectClass(thread, TRACE_JNI_CALL);
146 
147     if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(classObject, &className, &generic))) {
148         nsk_jvmti_setFailStatus();
149         return;
150     }
151 
152     if (strcmp(className, EXPECTED_CLASS_NAME) == 0) {
153         changeCount(event);
154         NSK_DISPLAY3("%25s(%4d)>>\tclass: %s\n",
155                             TranslateEvent(event),
156                             eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL],
157                             className);
158     }
159 
160     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
161         nsk_jvmti_setFailStatus();
162     }
163 
164     if (phase != currentPhase) {
165         NSK_DISPLAY2("Unexpected phase %s, but supposed %s",
166                 TranslatePhase(phase), TranslatePhase(currentPhase));
167     }
168 
169     if ((phase != JVMTI_PHASE_START) && (phase != JVMTI_PHASE_LIVE)) {
170         NSK_COMPLAIN4("%25s was sent during %s(%d)\n\tclass: %s\n",
171                     TranslateEvent(event),
172                     TranslatePhase(phase),
173                     phase,
174                     className);
175         nsk_jvmti_setFailStatus();
176     }
177 
178     if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)className))) {
179         nsk_jvmti_setFailStatus();
180     }
181     if (generic != NULL)
182         if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic))) {
183             nsk_jvmti_setFailStatus();
184         }
185 }
186 
187 JNIEXPORT void JNICALL
cbVMStart(jvmtiEnv * jvmti_env,JNIEnv * jni_env)188 cbVMStart(jvmtiEnv* jvmti_env, JNIEnv* jni_env) {
189 
190     jvmtiPhase phase;
191 
192     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
193         nsk_jvmti_setFailStatus();
194     }
195 
196     if ((phase != JVMTI_PHASE_START) && (phase != JVMTI_PHASE_LIVE)) {
197         NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
198                     TranslateEvent(JVMTI_EVENT_VM_START),
199                     TranslatePhase(phase),
200                     phase);
201         nsk_jvmti_setFailStatus();
202     }
203 
204     changeCount(JVMTI_EVENT_VM_START);
205     currentPhase = JVMTI_PHASE_START;
206 }
207 
208 JNIEXPORT void JNICALL
cbVMInit(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)209 cbVMInit(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
210 
211     jvmtiPhase phase;
212 
213     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
214         nsk_jvmti_setFailStatus();
215     }
216 
217     if (phase != JVMTI_PHASE_LIVE) {
218         NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
219                     TranslateEvent(JVMTI_EVENT_VM_INIT),
220                     TranslatePhase(phase),
221                     phase);
222         nsk_jvmti_setFailStatus();
223     }
224 
225     changeCount(JVMTI_EVENT_VM_INIT);
226     currentPhase = JVMTI_PHASE_LIVE;
227 }
228 
229 JNIEXPORT void JNICALL
cbVMDeath(jvmtiEnv * jvmti_env,JNIEnv * jni_env)230 cbVMDeath(jvmtiEnv* jvmti_env, JNIEnv* jni_env) {
231 
232     jvmtiPhase phase;
233 
234     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
235         nsk_jvmti_setFailStatus();
236     }
237 
238     if (phase != JVMTI_PHASE_LIVE) {
239         NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
240                     TranslateEvent(JVMTI_EVENT_VM_INIT),
241                     TranslatePhase(phase),
242                     phase);
243         nsk_jvmti_setFailStatus();
244     }
245 
246     currentPhase = JVMTI_PHASE_DEAD;
247     changeCount(JVMTI_EVENT_VM_DEATH);
248 
249     if (!NSK_JVMTI_VERIFY(jvmti->DestroyRawMonitor(syncLock)))
250         nsk_jvmti_setFailStatus();
251 
252 }
253 
254 JNIEXPORT void JNICALL
cbClassLoad(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jclass klass)255 cbClassLoad(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread,
256                     jclass klass) {
257 
258     classEventsHandler(JVMTI_EVENT_CLASS_LOAD, jvmti_env, jni_env, klass);
259 }
260 
261 JNIEXPORT void JNICALL
cbClassPrepare(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jclass klass)262 cbClassPrepare(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread,
263                     jclass klass) {
264 
265     classEventsHandler(JVMTI_EVENT_CLASS_PREPARE, jvmti_env, jni_env, klass);
266 }
267 
268 JNIEXPORT void JNICALL
cbThreadStart(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)269 cbThreadStart(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
270 
271     threadEventHandler(JVMTI_EVENT_THREAD_START, jvmti_env, jni_env, thread);
272 }
273 
274 JNIEXPORT void JNICALL
cbThreadEnd(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)275 cbThreadEnd(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
276 
277     threadEventHandler(JVMTI_EVENT_THREAD_END, jvmti_env, jni_env, thread);
278 }
279 
280 /* ============================================================================= */
281 
282 static int
enableEvent(jvmtiEventMode enable,jvmtiEvent event)283 enableEvent(jvmtiEventMode enable, jvmtiEvent event) {
284     NSK_DISPLAY1("enabling %s\n", TranslateEvent(event));
285     if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(enable, event, NULL))) {
286         nsk_jvmti_setFailStatus();
287         return NSK_FALSE;
288     }
289 
290     return NSK_TRUE;
291 }
292 
293 /* ============================================================================= */
294 
295 /**
296  * Testcase: check tested events.
297  *   - check if expected events received for each method
298  *
299  * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break.
300  */
checkEvents(int step)301 int checkEvents(int step) {
302 
303     int i;
304     jvmtiEvent curr;
305     int result = NSK_TRUE;
306     int mustBeChecked;
307 
308     showEventStatistics();
309 
310     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
311 
312         curr = (jvmtiEvent) (i + JVMTI_MIN_EVENT_TYPE_VAL);
313         switch (step) {
314         case 1:
315             mustBeChecked = ((curr == JVMTI_EVENT_CLASS_LOAD)
316                     || (curr == JVMTI_EVENT_CLASS_PREPARE));
317             break;
318 
319         case 2:
320             mustBeChecked = ((curr == JVMTI_EVENT_CLASS_LOAD)
321                     || (curr == JVMTI_EVENT_CLASS_PREPARE)
322                     || (curr == JVMTI_EVENT_THREAD_START)
323                     || (curr == JVMTI_EVENT_THREAD_END));
324             break;
325         default:
326             mustBeChecked = NSK_TRUE;
327         }
328 
329         if (mustBeChecked && eventCount[i] != classLoaderCount) {
330                 nsk_jvmti_setFailStatus();
331                 NSK_COMPLAIN3("Unexpected number of %s events %7d\n\texpected value %d\n",
332                                     TranslateEvent(curr),
333                                     eventCount[i],
334                                     classLoaderCount);
335                 nsk_jvmti_setFailStatus();
336                 result = NSK_FALSE;
337         }
338     }
339 
340     return result;
341 }
342 
343 /* ============================================================================= */
344 
345 static int
setCallBacks()346 setCallBacks() {
347     jvmtiEventCallbacks eventCallbacks;
348     memset(&eventCallbacks, 0, sizeof(eventCallbacks));
349 
350     eventCallbacks.VMStart      = cbVMStart;
351     eventCallbacks.VMInit       = cbVMInit;
352     eventCallbacks.VMDeath      = cbVMDeath;
353     eventCallbacks.ClassLoad    = cbClassLoad;
354     eventCallbacks.ClassPrepare = cbClassPrepare;
355     eventCallbacks.ThreadStart  = cbThreadStart;
356     eventCallbacks.ThreadEnd    = cbThreadEnd;
357 
358     if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks))))
359         return NSK_FALSE;
360 
361     return NSK_TRUE;
362 }
363 
364 /* ============================================================================= */
365 
366 /** Agent algorithm. */
367 static void JNICALL
agentProc(jvmtiEnv * jvmti,JNIEnv * agentJNI,void * arg)368 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) {
369 
370     NSK_DISPLAY0("Wait for debuggee to become ready\n");
371     if (!nsk_jvmti_waitForSync(timeout))
372         return;
373 
374     NSK_DISPLAY0("Let debuggee to load class\n");
375     if (!nsk_jvmti_resumeSync())
376         return;
377 
378     if (!nsk_jvmti_waitForSync(timeout))
379         return;
380 
381     /* check only CLASS_LOAD and CLASS_PREPARE events */
382     if (!checkEvents(1)) {
383         nsk_jvmti_setFailStatus();
384     }
385 
386     NSK_DISPLAY0("Let debuggee to start threads\n");
387     if (!nsk_jvmti_resumeSync())
388         return;
389 
390     if (!nsk_jvmti_waitForSync(timeout))
391         return;
392 
393     NSK_DISPLAY0("check event 2\n");
394     if (!checkEvents(2)) {
395         nsk_jvmti_setFailStatus();
396         NSK_DISPLAY0("fail\n");
397     }
398 
399     NSK_DISPLAY0("Let debuggee to finish\n");
400     if (!nsk_jvmti_resumeSync())
401         return;
402 
403 }
404 
405 /* ============================================================================= */
406 
407 /** Agent library initialization. */
408 #ifdef STATIC_BUILD
Agent_OnLoad_em01t001(JavaVM * jvm,char * options,void * reserved)409 JNIEXPORT jint JNICALL Agent_OnLoad_em01t001(JavaVM *jvm, char *options, void *reserved) {
410     return Agent_Initialize(jvm, options, reserved);
411 }
Agent_OnAttach_em01t001(JavaVM * jvm,char * options,void * reserved)412 JNIEXPORT jint JNICALL Agent_OnAttach_em01t001(JavaVM *jvm, char *options, void *reserved) {
413     return Agent_Initialize(jvm, options, reserved);
414 }
JNI_OnLoad_em01t001(JavaVM * jvm,char * options,void * reserved)415 JNIEXPORT jint JNI_OnLoad_em01t001(JavaVM *jvm, char *options, void *reserved) {
416     return JNI_VERSION_1_8;
417 }
418 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)419 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
420 
421     currentPhase = JVMTI_PHASE_ONLOAD;
422 
423     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
424         return JNI_ERR;
425 
426     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
427     classLoaderCount = nsk_jvmti_findOptionIntValue(CLASS_LOADER_COUNT_PARAM, 10);
428 
429     jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved);
430     if (!NSK_VERIFY(jvmti != NULL))
431         return JNI_ERR;
432 
433     if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("_syncLock", &syncLock))) {
434         nsk_jvmti_setFailStatus();
435         return JNI_ERR;
436     }
437 
438     if (!setCallBacks()) {
439         return JNI_ERR;
440     }
441 
442     if (!enableEvent(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD)
443             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE)
444             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_THREAD_START)
445             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_THREAD_END)
446             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_START)
447             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT)
448             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH)
449             ) {
450         NSK_COMPLAIN0("Events could not be enabled");
451         nsk_jvmti_setFailStatus();
452         return JNI_ERR;
453     }
454 
455     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
456         return JNI_ERR;
457 
458     currentPhase = JVMTI_PHASE_PRIMORDIAL;
459 
460     return JNI_OK;
461 }
462 
463 }
464