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 
  30 extern "C" {
  31 
  32 /* ========================================================================== */
  33 
  34 /* scaffold objects */
  35 static jlong timeout = 0;
  36 
  37 /* ========================================================================== */
  38 
  39 static int lookup(jvmtiEnv* jvmti,
  40         jint classCount, jclass *classes, const char *exp_sig) {
  41     char *signature, *generic;
  42     int found = NSK_FALSE;
  43     jint i;
  44 
  45     for (i = 0; i < classCount && !found; i++) {
  46         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature, jvmti,
  47                 classes[i], &signature, &generic)))
  48             break;
  49 
  50         if (signature != NULL && strcmp(signature, exp_sig) == 0) {
  51             found = NSK_TRUE;
  52         }
  53 
  54         if (signature != NULL)
  55             NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)signature);
  56 
  57         if (generic != NULL)
  58             NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)generic);
  59     }
  60 
  61     return found;
  62 }
  63 
  64 /* ========================================================================== */
  65 
  66 JNIEXPORT void JNICALL
  67 VMObjectAlloc(jvmtiEnv *jvmti, JNIEnv* jni, jthread thread, jobject object,
  68               jclass object_klass, jlong size) {
  69 
  70     char *signature, *generic;
  71     jvmtiThreadInfo threadInfo;
  72 
  73     /* Check that event is received in Live phase
  74     */
  75     {
  76         jvmtiPhase phase;
  77         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetPhase, jvmti, &phase ))) {
  78             nsk_jvmti_setFailStatus();
  79             return;
  80         }
  81         if (phase != JVMTI_PHASE_LIVE) {
  82             NSK_COMPLAIN1("VMObjectAlloc event was received in wrong phase: %s\n", TranslatePhase(phase));
  83             return;
  84         }
  85     }
  86 
  87     do {
  88         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature, jvmti,
  89                 object_klass, &signature, &generic))) {
  90             nsk_jvmti_setFailStatus();
  91             break;
  92         }
  93 
  94         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetThreadInfo, jvmti,
  95                 thread, &threadInfo))) {
  96             nsk_jvmti_setFailStatus();
  97             break;
  98         }
  99 
 100         NSK_DISPLAY2("VMObjectAlloc in \"%s\" thread: \"%s\"\n", threadInfo.name, signature);
 101     } while (0);
 102 
 103     /* Check that event's thread is live thread
 104     */
 105     do {
 106         jint threadCount;
 107         jthread *threads;
 108         jint i;
 109         jboolean found = JNI_FALSE;
 110 
 111         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetAllThreads, jvmti,
 112                  &threadCount, &threads))) {
 113             nsk_jvmti_setFailStatus();
 114             break;
 115         }
 116 
 117         for (i = 0; i < threadCount && !found; i++) {
 118             found = NSK_CPP_STUB3(IsSameObject, jni, threads[i], thread);
 119             if (found == JNI_TRUE) {
 120                 break;
 121             }
 122         }
 123 
 124         if (!found) {
 125             nsk_jvmti_setFailStatus();
 126             NSK_COMPLAIN1("VMObjectAlloc: event's thread was found in the list of live threads: %s\n\n", threadInfo.name);
 127         }
 128     } while(0);
 129 
 130 
 131     /* Check that object_klass is loaded class
 132     */
 133     do {
 134         jint classCount;
 135         jclass *classes;
 136 
 137         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetLoadedClasses, jvmti,
 138                  &classCount, &classes))) {
 139             nsk_jvmti_setFailStatus();
 140             break;
 141         }
 142 
 143         if (!lookup(jvmti, classCount, classes, signature)) {
 144             nsk_jvmti_setFailStatus();
 145             NSK_COMPLAIN1("VMObjectAlloc: object_klass is not found in the list of loaded classes: %s\n", signature);
 146             return;
 147         }
 148 
 149         if (classes != NULL)
 150             NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)classes);
 151     } while(0);
 152 
 153 
 154     /* Check for object_klass
 155     */
 156     {
 157         jclass klass;
 158         klass = NSK_CPP_STUB2(GetObjectClass, jni, object);
 159         if (!(NSK_CPP_STUB3(IsSameObject, jni, object_klass, klass))) {
 160             nsk_jvmti_setFailStatus();
 161             NSK_COMPLAIN1("VMObjectAlloc: unexpected object_klass : \"%s\"\n\n", signature);
 162         }
 163     }
 164 
 165     /* Check for object size
 166     */
 167 
 168     do {
 169         jlong objSize;
 170         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetObjectSize, jvmti,
 171                  object, &objSize))) {
 172             nsk_jvmti_setFailStatus();
 173             break;
 174         }
 175 
 176         if (objSize != size) {
 177             nsk_jvmti_setFailStatus();
 178             NSK_COMPLAIN2("VMObjectAlloc: inconsistent object size data\n\t"
 179                " size passed in to callback: %d\n\t size returned by GetObjectSize: %d\n\n", (long)size, (long)objSize);
 180         }
 181     } while(0);
 182 
 183     if (signature != NULL)
 184         NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)signature);
 185 
 186     if (generic != NULL)
 187         NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)generic);
 188 }
 189 
 190 /* ========================================================================== */
 191 
 192 /* agent algorithm */
 193 static void JNICALL
 194 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
 195 
 196     /* wait for debuggee start */
 197     if (!nsk_jvmti_waitForSync(timeout))
 198         return;
 199     /* resume debugee after last sync */
 200     if (!nsk_jvmti_resumeSync())
 201         return;
 202 }
 203 
 204 /* ========================================================================== */
 205 
 206 /* agent library initialization */
 207 #ifdef STATIC_BUILD
 208 JNIEXPORT jint JNICALL Agent_OnLoad_ap11t001(JavaVM *jvm, char *options, void *reserved) {
 209     return Agent_Initialize(jvm, options, reserved);
 210 }
 211 JNIEXPORT jint JNICALL Agent_OnAttach_ap11t001(JavaVM *jvm, char *options, void *reserved) {
 212     return Agent_Initialize(jvm, options, reserved);
 213 }
 214 JNIEXPORT jint JNI_OnLoad_ap11t001(JavaVM *jvm, char *options, void *reserved) {
 215     return JNI_VERSION_1_8;
 216 }
 217 #endif
 218 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 219     jvmtiEnv* jvmti = NULL;
 220     jvmtiCapabilities caps;
 221     jvmtiEventCallbacks callbacks;
 222 
 223     /* init framework and parse options */
 224     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
 225         return JNI_ERR;
 226 
 227     timeout = nsk_jvmti_getWaitTime() * 60000;
 228     NSK_DISPLAY1("Timeout: %d msc\n", (int)timeout);
 229 
 230     /* create JVMTI environment */
 231     if (!NSK_VERIFY((jvmti =
 232             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
 233         return JNI_ERR;
 234 
 235     memset(&caps, 0, sizeof(caps));
 236     caps.can_generate_vm_object_alloc_events = 1;
 237     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, jvmti, &caps))) {
 238         return JNI_ERR;
 239     }
 240 
 241     memset(&callbacks, 0, sizeof(callbacks));
 242     callbacks.VMObjectAlloc= &VMObjectAlloc;
 243     if (!NSK_JVMTI_VERIFY(
 244             NSK_CPP_STUB3(SetEventCallbacks, jvmti,
 245                 &callbacks, sizeof(callbacks))))
 246         return JNI_ERR;
 247 
 248     /* enable VMObjectAlloc event */
 249     if (!NSK_JVMTI_VERIFY(
 250             NSK_CPP_STUB4(SetEventNotificationMode, jvmti, JVMTI_ENABLE,
 251                 JVMTI_EVENT_VM_OBJECT_ALLOC, NULL)))
 252         return JNI_ERR;
 253 
 254     /* register agent proc and arg */
 255     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
 256         return JNI_ERR;
 257 
 258     return JNI_OK;
 259 }
 260 
 261 /* ========================================================================== */
 262 
 263 }