1 /*
   2  * Copyright (c) 2003, 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 
  30 extern "C" {
  31 
  32 /* ============================================================================= */
  33 
  34 /* scaffold objects */
  35 static jlong timeout = 0;
  36 
  37 /* constants */
  38 #define EVENTS_COUNT    3
  39 
  40 /* tested events */
  41 static jvmtiEvent eventsList[EVENTS_COUNT] = {
  42     JVMTI_EVENT_COMPILED_METHOD_LOAD,
  43     JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
  44     JVMTI_EVENT_DYNAMIC_CODE_GENERATED
  45 };
  46 
  47 /* event counts */
  48 static int eventsCountList[EVENTS_COUNT];
  49 
  50 /* ============================================================================= */
  51 
  52 /** Check if all expected events received. */
  53 static int checkEvents() {
  54     int success = NSK_TRUE;
  55 
  56     NSK_DISPLAY0("Events received:\n");
  57     NSK_DISPLAY1("   COMPILED_METHOD_LOAD:   %d events\n", eventsCountList[0]);
  58     NSK_DISPLAY1("   COMPILED_METHOD_UNLOAD: %d events\n", eventsCountList[1]);
  59     NSK_DISPLAY1("   DYNAMIC_CODE_GENERATED: %d events\n", eventsCountList[2]);
  60 
  61     if (eventsCountList[0] <= 0) {
  62         NSK_DISPLAY0("# WARNING: GenerateEvents() produced no COMPILED_METHOD_LOAD events\n");
  63         NSK_DISPLAY0("#    (but methods may not be compiled)\n");
  64     }
  65 
  66     if (eventsCountList[2] <= 0) {
  67         NSK_DISPLAY0("# WARNING: GenerateEvents() produced no DYNAMIC_CODE_GENERATED events\n");
  68         NSK_DISPLAY0("#    (but dynamic code may not be generated)\n");
  69     }
  70 
  71     if (eventsCountList[1] > 0) {
  72         NSK_DISPLAY1("# WARNING: COMPILED_METHOD_UNLOAD events were received: %d events\n",
  73                      eventsCountList[1]);
  74     }
  75 
  76     return success;
  77 }
  78 
  79 /* ============================================================================= */
  80 
  81 /** Agent algorithm. */
  82 static void JNICALL
  83 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
  84     NSK_DISPLAY0("Wait for tested method forced to compile\n");
  85     if (!nsk_jvmti_waitForSync(timeout))
  86         return;
  87 
  88     NSK_DISPLAY0(">>> Testcase #1: Check if GenerateEvents() sends missed events\n");
  89     {
  90         int i;
  91 
  92         for (i = 0; i < EVENTS_COUNT; i++) {
  93             eventsCountList[i] = 0;
  94         }
  95 
  96         NSK_DISPLAY1("Enable events: %d events\n", EVENTS_COUNT);
  97         if (!nsk_jvmti_enableEvents(JVMTI_ENABLE, EVENTS_COUNT, eventsList, NULL)) {
  98             nsk_jvmti_setFailStatus();
  99         }
 100 
 101         NSK_DISPLAY0("Call GenerateEvents() to send missed events\n");
 102         if (!NSK_JVMTI_VERIFY(jvmti->GenerateEvents(JVMTI_EVENT_COMPILED_METHOD_LOAD))) {
 103             nsk_jvmti_setFailStatus();
 104         }
 105 
 106         if (!NSK_JVMTI_VERIFY(jvmti->GenerateEvents(JVMTI_EVENT_DYNAMIC_CODE_GENERATED))) {
 107             nsk_jvmti_setFailStatus();
 108         }
 109 
 110         NSK_DISPLAY1("Disable events: %d events\n", EVENTS_COUNT);
 111         if (!nsk_jvmti_enableEvents(JVMTI_DISABLE, EVENTS_COUNT, eventsList, NULL)) {
 112             nsk_jvmti_setFailStatus();
 113         }
 114 
 115         NSK_DISPLAY0("Check received events\n");
 116         if (!checkEvents()) {
 117             nsk_jvmti_setFailStatus();
 118         }
 119     }
 120 
 121     NSK_DISPLAY0("Let debugee to finish\n");
 122     if (!nsk_jvmti_resumeSync())
 123         return;
 124 }
 125 
 126 /* ============================================================================= */
 127 
 128 /**
 129  * Callback for COMPILED_METHOD_LOAD event.
 130  */
 131 JNIEXPORT void JNICALL
 132 callbackCompiledMethodLoad(jvmtiEnv* jvmti, jmethodID method,
 133                             jint code_size, const void* code_addr,
 134                             jint map_length, const jvmtiAddrLocationMap* map,
 135                             const void* compile_info) {
 136     NSK_DISPLAY3("  <COMPILED_METHOD_LOAD>:   method: 0x%p, code: 0x%p, size: %d\n",
 137                         (void*)method, (void*)code_addr, (int)code_size);
 138     eventsCountList[0]++;
 139 }
 140 
 141 /**
 142  * Callback for COMPILED_METHOD_UNLOAD event.
 143  */
 144 JNIEXPORT void JNICALL
 145 callbackCompiledMethodUnload(jvmtiEnv* jvmti, jmethodID method,
 146                              const void* code_addr) {
 147     NSK_DISPLAY1("  <COMPILED_METHOD_UNLOAD>: method: 0x%p\n",
 148                         (void*)method);
 149     eventsCountList[1]++;
 150 }
 151 
 152 /**
 153  * Callback for DYNAMIC_CODE_GENERATED event.
 154  */
 155 JNIEXPORT void JNICALL
 156 callbackDynamicCodeGenerated(jvmtiEnv* jvmti, const char* name, const void* address, jint length) {
 157     NSK_DISPLAY3("  <DYNAMIC_CODE_GENERATED>: name: %s, address: 0x%p, length: %d\n",
 158                         nsk_null_string(name), (void*)address, (int)length);
 159     eventsCountList[2]++;
 160 }
 161 
 162 /* ============================================================================= */
 163 
 164 /** Agent library initialization. */
 165 #ifdef STATIC_BUILD
 166 JNIEXPORT jint JNICALL Agent_OnLoad_genevents001(JavaVM *jvm, char *options, void *reserved) {
 167     return Agent_Initialize(jvm, options, reserved);
 168 }
 169 JNIEXPORT jint JNICALL Agent_OnAttach_genevents001(JavaVM *jvm, char *options, void *reserved) {
 170     return Agent_Initialize(jvm, options, reserved);
 171 }
 172 JNIEXPORT jint JNI_OnLoad_genevents001(JavaVM *jvm, char *options, void *reserved) {
 173     return JNI_VERSION_1_8;
 174 }
 175 #endif
 176 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 177     jvmtiEnv* jvmti = NULL;
 178 
 179     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
 180         return JNI_ERR;
 181 
 182     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
 183 
 184     if (!NSK_VERIFY((jvmti =
 185             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
 186         return JNI_ERR;
 187 
 188     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
 189         return JNI_ERR;
 190 
 191     /* add required capabilities */
 192     {
 193         jvmtiCapabilities caps;
 194         memset(&caps, 0, sizeof(caps));
 195         caps.can_generate_compiled_method_load_events = 1;
 196         if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps)))
 197             return JNI_ERR;
 198     }
 199 
 200     /* set event callbacks */
 201     {
 202         jvmtiEventCallbacks eventCallbacks;
 203         memset(&eventCallbacks, 0, sizeof(eventCallbacks));
 204         eventCallbacks.CompiledMethodLoad = callbackCompiledMethodLoad;
 205         eventCallbacks.CompiledMethodUnload = callbackCompiledMethodUnload;
 206         eventCallbacks.DynamicCodeGenerated = callbackDynamicCodeGenerated;
 207         if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks))))
 208             return JNI_ERR;
 209     }
 210 
 211     return JNI_OK;
 212 }
 213 
 214 /* ============================================================================= */
 215 
 216 }