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 static jlong timeout = 0;
  35 
  36 static long objCounter = 0;
  37 static int userData = 0;
  38 static jvmtiEnv* st_jvmti = NULL;
  39 static const char *storage_data = "local_storage_data";
  40 static void *storage_ptr = NULL;
  41 
  42 /* ============================================================================= */
  43 
  44 /* ============================================================================= */
  45 
  46 
  47 /* jvmtiHeapRootCallback */
  48 jvmtiIterationControl JNICALL
  49 heapRootCallback( jvmtiHeapRootKind root_kind,
  50                   jlong class_tag,
  51                   jlong size,
  52                   jlong* tag_ptr,
  53                   void* user_data) {
  54 
  55     *tag_ptr = (jlong)++objCounter;
  56 
  57     if (!NSK_JVMTI_VERIFY(st_jvmti->SetEnvironmentLocalStorage(storage_data))) {
  58         nsk_jvmti_setFailStatus();
  59         return JVMTI_ITERATION_ABORT;
  60     }
  61 
  62     if (!NSK_JVMTI_VERIFY(st_jvmti->GetEnvironmentLocalStorage(&storage_ptr))) {
  63         nsk_jvmti_setFailStatus();
  64         return JVMTI_ITERATION_ABORT;
  65     }
  66 
  67     if (storage_data != storage_ptr) {
  68         NSK_COMPLAIN2("heapRootCallback: Local storage address was corrupted: %p ,\n\texpected value: %p\n",
  69                          storage_ptr, storage_data);
  70         nsk_jvmti_setFailStatus();
  71         return JVMTI_ITERATION_ABORT;
  72     }
  73 
  74     if (strcmp(storage_data, (char *)storage_ptr) != 0) {
  75         NSK_COMPLAIN2("heapRootCallback: Local storage was corrupted: %s ,\n\texpected value: %s\n",
  76                          (char *)storage_ptr, storage_data );
  77         nsk_jvmti_setFailStatus();
  78         return JVMTI_ITERATION_ABORT;
  79     }
  80 
  81 /*
  82     NSK_DISPLAY1("heapRootCallback: %d\n", objCounter);
  83 */
  84     return JVMTI_ITERATION_CONTINUE;
  85 }
  86 
  87 /* jvmtiStackReferenceCallback */
  88 jvmtiIterationControl JNICALL
  89 stackReferenceCallback( jvmtiHeapRootKind root_kind,
  90                         jlong     class_tag,
  91                         jlong     size,
  92                         jlong*    tag_ptr,
  93                         jlong     thread_tag,
  94                         jint      depth,
  95                         jmethodID method,
  96                         jint      slot,
  97                         void*     user_data) {
  98 
  99     *tag_ptr = (jlong)++objCounter;
 100 
 101     if (!NSK_JVMTI_VERIFY(st_jvmti->SetEnvironmentLocalStorage(storage_data))) {
 102         nsk_jvmti_setFailStatus();
 103         return JVMTI_ITERATION_ABORT;
 104     }
 105 
 106     if (!NSK_JVMTI_VERIFY(st_jvmti->GetEnvironmentLocalStorage(&storage_ptr))) {
 107         nsk_jvmti_setFailStatus();
 108         return JVMTI_ITERATION_ABORT;
 109     }
 110 
 111     if (storage_data != storage_ptr) {
 112         NSK_COMPLAIN2("stackReferenceCallback: Local storage address was corrupted: %p ,\n\texpected value: %p\n",
 113                          storage_ptr, storage_data);
 114         nsk_jvmti_setFailStatus();
 115         return JVMTI_ITERATION_ABORT;
 116     }
 117 
 118     if (strcmp(storage_data, (char *)storage_ptr) != 0) {
 119         NSK_COMPLAIN2("stackReferenceCallback: Local storage was corrupted: %s ,\n\texpected value: %s\n",
 120                          (char *)storage_ptr, storage_data );
 121         nsk_jvmti_setFailStatus();
 122         return JVMTI_ITERATION_ABORT;
 123     }
 124 
 125 /*
 126     NSK_DISPLAY1("stackRefenceCallback: %d\n", objCounter);
 127 */
 128     return JVMTI_ITERATION_CONTINUE;
 129 }
 130 
 131 
 132 /* jvmtiObjectReferenceCallback */
 133 jvmtiIterationControl JNICALL
 134 objectReferenceCallback( jvmtiObjectReferenceKind reference_kind,
 135                          jlong  class_tag,
 136                          jlong  size,
 137                          jlong* tag_ptr,
 138                          jlong  referrer_tag,
 139                          jint   referrer_index,
 140                          void*  user_data) {
 141 
 142     *tag_ptr = (jlong)++objCounter;
 143 
 144     if (!NSK_JVMTI_VERIFY(st_jvmti->SetEnvironmentLocalStorage(storage_data))) {
 145         nsk_jvmti_setFailStatus();
 146         return JVMTI_ITERATION_ABORT;
 147     }
 148 
 149     if (!NSK_JVMTI_VERIFY(st_jvmti->GetEnvironmentLocalStorage(&storage_ptr))) {
 150         nsk_jvmti_setFailStatus();
 151         return JVMTI_ITERATION_ABORT;
 152     }
 153 
 154     if (storage_data != storage_ptr) {
 155         NSK_COMPLAIN2("objectReferenceCallback: Local storage address was corrupted: %p ,\n\texpected value: %p\n",
 156                          storage_ptr, storage_data);
 157         nsk_jvmti_setFailStatus();
 158         return JVMTI_ITERATION_ABORT;
 159     }
 160 
 161     if (strcmp(storage_data, (char *)storage_ptr) != 0) {
 162         NSK_COMPLAIN2("objectReferenceCallback: Local storage was corrupted: %s ,\n\texpected value: %s\n",
 163                          (char *)storage_ptr, storage_data );
 164         nsk_jvmti_setFailStatus();
 165         return JVMTI_ITERATION_ABORT;
 166     }
 167 
 168     NSK_DISPLAY1("objectRefenceCallback: %d\n", objCounter);
 169     return JVMTI_ITERATION_ABORT;
 170 }
 171 
 172 /* ============================================================================= */
 173 
 174 /** Agent algorithm. */
 175 static void JNICALL
 176 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
 177 
 178     NSK_DISPLAY0("Wait for debugee start\n");
 179     if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
 180         return;
 181 
 182     {
 183         do {
 184             NSK_DISPLAY0("Calling IterateOverReachableObjects\n");
 185             {
 186                 if (!NSK_JVMTI_VERIFY(
 187                         jvmti->IterateOverReachableObjects(heapRootCallback,
 188                                                            stackReferenceCallback,
 189                                                            objectReferenceCallback,
 190                                                            &userData))) {
 191                     nsk_jvmti_setFailStatus();
 192                     break;
 193                 }
 194             }
 195 
 196             if (objCounter == 0) {
 197                 NSK_COMPLAIN0("IterateOverReachableObjects call had not visited any object\n");
 198                 nsk_jvmti_setFailStatus();
 199                 break;
 200             } else {
 201                 NSK_DISPLAY1("Number of objects the IterateOverReachableObjects visited: %d\n", objCounter);
 202             }
 203 
 204         } while (0);
 205     }
 206 
 207     NSK_DISPLAY0("Let debugee to finish\n");
 208     if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
 209         return;
 210 }
 211 
 212 /* ============================================================================= */
 213 
 214 /* ============================================================================= */
 215 
 216 /** Agent library initialization. */
 217 #ifdef STATIC_BUILD
 218 JNIEXPORT jint JNICALL Agent_OnLoad_iterreachobj004(JavaVM *jvm, char *options, void *reserved) {
 219     return Agent_Initialize(jvm, options, reserved);
 220 }
 221 JNIEXPORT jint JNICALL Agent_OnAttach_iterreachobj004(JavaVM *jvm, char *options, void *reserved) {
 222     return Agent_Initialize(jvm, options, reserved);
 223 }
 224 JNIEXPORT jint JNI_OnLoad_iterreachobj004(JavaVM *jvm, char *options, void *reserved) {
 225     return JNI_VERSION_1_8;
 226 }
 227 #endif
 228 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 229     jvmtiEnv* jvmti = NULL;
 230 
 231     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
 232         return JNI_ERR;
 233 
 234     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
 235 
 236     if (!NSK_VERIFY((jvmti =
 237             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
 238         return JNI_ERR;
 239 
 240     /* save pointer to environment to use it in callbacks */
 241     st_jvmti = jvmti;
 242 
 243     {
 244         jvmtiCapabilities caps;
 245 
 246         memset(&caps, 0, sizeof(caps));
 247         caps.can_tag_objects = 1;
 248         if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {
 249             return JNI_ERR;
 250         }
 251     }
 252 
 253     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
 254         return JNI_ERR;
 255 
 256     return JNI_OK;
 257 }
 258 
 259 /* ============================================================================= */
 260 
 261 }