1 /*
2  * Copyright (c) 2004, 2018, 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 "jni_tools.h"
28 #include "jvmti_tools.h"
29 #include "JVMTITools.h"
30 
31 extern "C" {
32 
33 /* ============================================================================= */
34 
35 /* scaffold objects */
36 static jlong timeout = 0;
37 static jvmtiEnv *jvmti = NULL;
38 static jrawMonitorID syncLock = NULL;
39 
40 /* constant names */
41 #define JVMTI_EVENT_COUNT   (int)(JVMTI_MAX_EVENT_TYPE_VAL - JVMTI_MIN_EVENT_TYPE_VAL + 1)
42 #define EXPECTED_COUNT 0
43 
44 static int eventCount[JVMTI_EVENT_COUNT];
45 
46 /* ============================================================================= */
47 
showEventStatistics()48 void showEventStatistics() {
49     int i;
50     const char* str;
51 
52     NSK_DISPLAY0("\n");
53     NSK_DISPLAY0("Event statistics\n");
54     NSK_DISPLAY0("----------------\n");
55     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
56         if (eventCount[i] > 0) {
57             str = TranslateEvent((jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL));
58             NSK_DISPLAY2("%-40s %7d\n", str, eventCount[i]);
59         }
60     }
61 }
62 
63 /* ========================================================================== */
64 
changeCount(jvmtiEvent event)65 void changeCount(jvmtiEvent event) {
66 
67     if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(syncLock)))
68         nsk_jvmti_setFailStatus();
69 
70     eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL]++;
71 
72     if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(syncLock)))
73         nsk_jvmti_setFailStatus();
74 
75 }
76 
77 /* ============================================================================= */
78 
79 /* callbacks */
80 JNIEXPORT void JNICALL
cbVMInit(jvmtiEnv * jvmti,JNIEnv * jni_env,jthread thread)81 cbVMInit(jvmtiEnv* jvmti, JNIEnv* jni_env, jthread thread) {
82     changeCount(JVMTI_EVENT_VM_INIT);
83     NSK_DISPLAY0("--->VMINit is received\n");
84 }
85 
86 JNIEXPORT void JNICALL
cbVMDeath(jvmtiEnv * jvmti,JNIEnv * jni_env)87 cbVMDeath(jvmtiEnv* jvmti, JNIEnv* jni_env) {
88     changeCount(JVMTI_EVENT_VM_DEATH);
89 
90     if (!NSK_JVMTI_VERIFY(jvmti->DestroyRawMonitor(syncLock)))
91         nsk_jvmti_setFailStatus();
92 
93 }
94 
95 void JNICALL
cbException(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jlocation location,jobject exception,jmethodID catch_method,jlocation catch_location)96 cbException(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
97                 jmethodID method, jlocation location, jobject exception,
98                 jmethodID catch_method, jlocation catch_location) {
99     changeCount(JVMTI_EVENT_EXCEPTION);
100 }
101 
102 void JNICALL
cbExceptionCatch(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jlocation location,jobject exception)103 cbExceptionCatch(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
104                 jmethodID method, jlocation location, jobject exception) {
105     changeCount(JVMTI_EVENT_EXCEPTION_CATCH);
106 }
107 
108 void JNICALL
cbSingleStep(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jlocation location)109 cbSingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
110                 jmethodID method, jlocation location) {
111     changeCount(JVMTI_EVENT_SINGLE_STEP);
112 }
113 
114 void JNICALL
cbFramePop(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jboolean was_popped_by_exception)115 cbFramePop(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
116                 jmethodID method, jboolean was_popped_by_exception) {
117     changeCount(JVMTI_EVENT_FRAME_POP);
118 }
119 
120 void JNICALL
cbBreakpoint(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jlocation location)121 cbBreakpoint(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
122                 jmethodID method, jlocation location) {
123     changeCount(JVMTI_EVENT_BREAKPOINT);
124 }
125 
126 void JNICALL
cbFieldAccess(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jlocation location,jclass field_klass,jobject object,jfieldID field)127 cbFieldAccess(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
128                 jmethodID method, jlocation location, jclass field_klass,
129                 jobject object, jfieldID field) {
130     changeCount(JVMTI_EVENT_FIELD_ACCESS);
131 }
132 
133 void JNICALL
cbFieldModification(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jlocation location,jclass field_klass,jobject object,jfieldID field,char signature_type,jvalue new_value)134 cbFieldModification(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
135                 jmethodID method, jlocation location, jclass field_klass,
136                 jobject object, jfieldID field, char signature_type,
137                 jvalue new_value) {
138     changeCount(JVMTI_EVENT_FIELD_MODIFICATION);
139 }
140 
141 void JNICALL
cbMethodEntry(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method)142 cbMethodEntry(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
143                 jmethodID method) {
144     changeCount(JVMTI_EVENT_METHOD_ENTRY);
145 }
146 
147 void JNICALL
cbMethodExit(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,jboolean was_popped_by_exception,jvalue return_value)148 cbMethodExit(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
149                 jmethodID method, jboolean was_popped_by_exception,
150                 jvalue return_value) {
151     changeCount(JVMTI_EVENT_METHOD_EXIT);
152 }
153 
154 void JNICALL
cbNativeMethodBind(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID method,void * address,void ** new_address_ptr)155 cbNativeMethodBind(jvmtiEnv *jvmti_env, JNIEnv* jni_env,jthread thread,
156                 jmethodID method, void* address, void** new_address_ptr) {
157     changeCount(JVMTI_EVENT_NATIVE_METHOD_BIND);
158 }
159 
160 void JNICALL
cbCompiledMethodLoad(jvmtiEnv * jvmti_env,jmethodID method,jint code_size,const void * code_addr,jint map_length,const jvmtiAddrLocationMap * map,const void * compile_info)161 cbCompiledMethodLoad(jvmtiEnv *jvmti_env, jmethodID method, jint code_size,
162                 const void* code_addr, jint map_length,
163                 const jvmtiAddrLocationMap* map, const void* compile_info) {
164     changeCount(JVMTI_EVENT_COMPILED_METHOD_LOAD);
165 }
166 
167 void JNICALL
cbCompiledMethodUnload(jvmtiEnv * jvmti_env,jmethodID method,const void * code_addr)168 cbCompiledMethodUnload(jvmtiEnv *jvmti_env, jmethodID method,
169                 const void* code_addr) {
170     changeCount(JVMTI_EVENT_COMPILED_METHOD_UNLOAD);
171 }
172 
173 void JNICALL
cbMonitorWait(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jobject object,jlong tout)174 cbMonitorWait(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
175                     jobject object, jlong tout) {
176 
177     changeCount(JVMTI_EVENT_MONITOR_WAIT);
178 }
179 
180 void JNICALL
cbMonitorWaited(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jobject object,jboolean timed_out)181 cbMonitorWaited(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
182                     jobject object, jboolean timed_out) {
183 
184     changeCount(JVMTI_EVENT_MONITOR_WAITED);
185 }
186 
187 JNIEXPORT void JNICALL
cbMonitorContendedEnter(jvmtiEnv * jvmti,JNIEnv * jni_env,jthread thread,jobject object)188 cbMonitorContendedEnter(jvmtiEnv* jvmti, JNIEnv* jni_env, jthread thread,
189                             jobject object) {
190 
191     changeCount(JVMTI_EVENT_MONITOR_CONTENDED_ENTER);
192 }
193 
194 void JNICALL
cbMonitorContendedEntered(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jobject object)195 cbMonitorContendedEntered(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
196                             jobject object) {
197 
198     changeCount(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED);
199 }
200 
201 void JNICALL
cbGarbageCollectionStart(jvmtiEnv * jvmti_env)202 cbGarbageCollectionStart(jvmtiEnv *jvmti_env) {
203     changeCount(JVMTI_EVENT_GARBAGE_COLLECTION_START);
204 }
205 
206 void JNICALL
cbGarbageCollectionFinish(jvmtiEnv * jvmti_env)207 cbGarbageCollectionFinish(jvmtiEnv *jvmti_env) {
208     changeCount(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH);
209 }
210 
211 void JNICALL
cbObjectFree(jvmtiEnv * jvmti_env,jlong tag)212 cbObjectFree(jvmtiEnv *jvmti_env, jlong tag) {
213     changeCount(JVMTI_EVENT_OBJECT_FREE);
214 }
215 
216 void JNICALL
cbVMObjectAlloc(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jobject object,jclass object_klass,jlong size)217 cbVMObjectAlloc(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
218                     jobject object, jclass object_klass, jlong size) {
219 
220     changeCount(JVMTI_EVENT_VM_OBJECT_ALLOC);
221 }
222 
223 /* ============================================================================= */
224 
enableOptionalEvents(jvmtiEnv * jvmti)225 int enableOptionalEvents(jvmtiEnv *jvmti) {
226     int i;
227     int result = NSK_TRUE;
228 
229     NSK_DISPLAY0("Enable events\n");
230 
231     /* enabling optional events */
232     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
233         jvmtiEvent event = (jvmtiEvent)(i + JVMTI_MIN_EVENT_TYPE_VAL);
234         if (nsk_jvmti_isOptionalEvent(event))
235             if (!NSK_JVMTI_VERIFY_CODE(JVMTI_ERROR_MUST_POSSESS_CAPABILITY,
236                     jvmti->SetEventNotificationMode(JVMTI_ENABLE, event, NULL))) {
237                 NSK_COMPLAIN1("Unexpected error enabling %s\n",
238                     TranslateEvent(event));
239                 result = NSK_FALSE;
240             }
241     }
242 
243     return result;
244 }
245 
246 /* ============================================================================= */
247 
248 /**
249  * Testcase: check tested events.
250  *   - check if expected events received for each method
251  *
252  * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break.
253  */
checkEvents()254 int checkEvents() {
255     int i;
256     jvmtiEvent event;
257     int result = NSK_TRUE;
258 
259     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
260 
261         event = (jvmtiEvent) (i + JVMTI_MIN_EVENT_TYPE_VAL);
262 
263         if (nsk_jvmti_isOptionalEvent(event) && eventCount[i] > EXPECTED_COUNT) {
264             nsk_jvmti_setFailStatus();
265             NSK_COMPLAIN3("Unexpected number of %s events:\n\treceived: %7d\n\texpected: %7d\n",
266                                 TranslateEvent(event),
267                                 eventCount[i],
268                                 EXPECTED_COUNT);
269             result = NSK_FALSE;
270         }
271     }
272 
273     return result;
274 }
275 
276 /* ============================================================================= */
277 
setCallBacks(jvmtiEnv * jvmti)278 static int setCallBacks(jvmtiEnv *jvmti) {
279     int i;
280 
281     jvmtiEventCallbacks eventCallbacks;
282     memset(&eventCallbacks, 0, sizeof(eventCallbacks));
283 
284     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
285         eventCount[i] = 0;
286     }
287 
288     eventCallbacks.VMInit                    = cbVMInit;
289     eventCallbacks.VMDeath                   = cbVMDeath;
290     eventCallbacks.Exception                 = cbException;
291     eventCallbacks.ExceptionCatch            = cbExceptionCatch;
292     eventCallbacks.SingleStep                = cbSingleStep;
293     eventCallbacks.FramePop                  = cbFramePop;
294     eventCallbacks.Breakpoint                = cbBreakpoint;
295     eventCallbacks.FieldAccess               = cbFieldAccess;
296     eventCallbacks.FieldModification         = cbFieldModification;
297     eventCallbacks.MethodEntry               = cbMethodEntry;
298     eventCallbacks.MethodExit                = cbMethodExit;
299     eventCallbacks.NativeMethodBind          = cbNativeMethodBind;
300     eventCallbacks.CompiledMethodLoad        = cbCompiledMethodLoad;
301     eventCallbacks.MonitorWait               = cbMonitorWait;
302     eventCallbacks.MonitorWaited             = cbMonitorWaited;
303     eventCallbacks.MonitorContendedEnter     = cbMonitorContendedEnter;
304     eventCallbacks.MonitorContendedEntered   = cbMonitorContendedEntered;
305     eventCallbacks.GarbageCollectionStart    = cbGarbageCollectionStart;
306     eventCallbacks.GarbageCollectionFinish   = cbGarbageCollectionFinish;
307     eventCallbacks.ObjectFree                = cbObjectFree;
308     eventCallbacks.VMObjectAlloc             = cbVMObjectAlloc;
309 
310     if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks))))
311         return NSK_FALSE;
312 
313     return NSK_TRUE;
314 }
315 
316 /* ============================================================================= */
317 
318 /** Agent algorithm. */
319 static void JNICALL
agentProc(jvmtiEnv * jvmti,JNIEnv * agentJNI,void * arg)320 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) {
321 
322     NSK_DISPLAY0("Wait for debuggee to become ready\n");
323     if (!nsk_jvmti_waitForSync(timeout))
324         return;
325 
326     if (!checkEvents()) {
327         nsk_jvmti_setFailStatus();
328     }
329     showEventStatistics();
330 
331     NSK_DISPLAY0("Let debuggee to finish\n");
332     if (!nsk_jvmti_resumeSync())
333         return;
334 
335 }
336 
337 /* ============================================================================= */
338 
339 /** Agent library initialization. */
340 #ifdef STATIC_BUILD
Agent_OnLoad_em07t001(JavaVM * jvm,char * options,void * reserved)341 JNIEXPORT jint JNICALL Agent_OnLoad_em07t001(JavaVM *jvm, char *options, void *reserved) {
342     return Agent_Initialize(jvm, options, reserved);
343 }
Agent_OnAttach_em07t001(JavaVM * jvm,char * options,void * reserved)344 JNIEXPORT jint JNICALL Agent_OnAttach_em07t001(JavaVM *jvm, char *options, void *reserved) {
345     return Agent_Initialize(jvm, options, reserved);
346 }
JNI_OnLoad_em07t001(JavaVM * jvm,char * options,void * reserved)347 JNIEXPORT jint JNI_OnLoad_em07t001(JavaVM *jvm, char *options, void *reserved) {
348     return JNI_VERSION_1_8;
349 }
350 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)351 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
352 
353     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
354         return JNI_ERR;
355 
356     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
357 
358     if (!NSK_VERIFY((jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
359         return JNI_ERR;
360 
361     if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("_syncLock", &syncLock))) {
362         nsk_jvmti_setFailStatus();
363         return JNI_ERR;
364     }
365 
366     if (!setCallBacks(jvmti)) {
367         return JNI_ERR;
368     }
369 
370     nsk_jvmti_showPossessedCapabilities(jvmti);
371 
372     if (!enableOptionalEvents(jvmti)) {
373         return JNI_ERR;
374     }
375 
376     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
377         return JNI_ERR;
378 
379     return JNI_OK;
380 }
381 
382 /* ============================================================================= */
383 
384 
385 }
386