1 /* 2 * Copyright (c) 2006, 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 "jni_tools.h" 27 #include "jvmti_tools.h" 28 #include "jvmti_FollowRefObjects.h" 29 30 extern "C" { 31 32 /* ============================================================================= */ 33 34 int g_fakeUserData = 0; 35 int g_userDataError = 0; 36 jvmtiHeapCallbacks g_wrongHeapCallbacks; 37 38 /* This array has to be up-to-date with the jvmtiHeapReferenceKind enum */ 39 const char * const g_refKindStr[28] = { 40 "unknown_0", 41 "JVMTI_HEAP_REFERENCE_CLASS", 42 "JVMTI_HEAP_REFERENCE_FIELD", 43 "JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT", 44 "JVMTI_HEAP_REFERENCE_CLASS_LOADER", 45 "JVMTI_HEAP_REFERENCE_SIGNERS", 46 "JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN", 47 "JVMTI_HEAP_REFERENCE_INTERFACE", 48 "JVMTI_HEAP_REFERENCE_STATIC_FIELD", 49 "JVMTI_HEAP_REFERENCE_CONSTANT_POOL", 50 "JVMTI_HEAP_REFERENCE_SUPERCLASS", 51 "unknown_11", "unknown_12", "unknown_13", "unknown_14", "unknown_15", 52 "unknown_16", "unknown_17", "unknown_18", "unknown_19", "unknown_20", 53 "JVMTI_HEAP_REFERENCE_JNI_GLOBAL", 54 "JVMTI_HEAP_REFERENCE_SYSTEM_CLASS", 55 "JVMTI_HEAP_REFERENCE_MONITOR", 56 "JVMTI_HEAP_REFERENCE_STACK_LOCAL", 57 "JVMTI_HEAP_REFERENCE_JNI_LOCAL", 58 "JVMTI_HEAP_REFERENCE_THREAD", 59 "JVMTI_HEAP_REFERENCE_OTHER" 60 }; 61 62 /* ============================================================================= */ 63 64 char * g_szTagInfo[MAX_TAG]; 65 char g_tagFlags[MAX_TAG]; 66 int g_tagVisitCount[MAX_TAG]; 67 68 /* ============================================================================= */ 69 70 void markTagSet(jlong tag_val) 71 { 72 if ( tag_val > 0 && tag_val < MAX_TAG ) 73 g_tagFlags[tag_val] |= FLAG_TAG_SET; 74 } 75 76 void markTagVisited(jlong tag_val) 77 { 78 if ( tag_val > 0 && tag_val < MAX_TAG ) { 79 g_tagVisitCount[tag_val]++; 80 } 81 } 82 83 jboolean checkThatAllTagsVisited() 84 { 85 jboolean ok = JNI_TRUE; 86 jlong i; 87 88 NSK_DISPLAY0("Checking that all set tags have been visited\n"); 89 90 for ( i = 1; i < MAX_TAG; i++ ) { 91 char flags = g_tagFlags[i]; 92 93 if ( (g_tagFlags[i] & FLAG_TAG_SET) ) { 94 if ( g_tagVisitCount[i] == 0 ) { 95 NSK_COMPLAIN1("Tag %" LL "d has not been visited: %x\n", i); 96 ok = JNI_FALSE; 97 } 98 99 DBG(printf(">>> Tag %" LL "d has been visited %i times: %s\n", i, g_tagVisitCount[i], g_szTagInfo[i])); 100 } 101 } 102 103 return ok; 104 } 105 106 JNIEXPORT void JNICALL Java_nsk_jvmti_unit_FollowReferences_FollowRefObjects_resetTags(JNIEnv* jni, jclass klass) 107 { 108 memset(g_szTagInfo, 0, sizeof(g_szTagInfo)); 109 memset(g_tagFlags, 0, sizeof(g_tagFlags)); 110 memset(g_tagVisitCount, 0, sizeof(g_tagVisitCount)); 111 } 112 113 JNIEXPORT jboolean JNICALL Java_nsk_jvmti_unit_FollowReferences_FollowRefObjects_setTag(JNIEnv* jni, jclass klass, jobject o, jlong tag, jstring sInfo) 114 { 115 jvmtiEnv * jvmti = nsk_jvmti_getAgentJVMTIEnv(); 116 jint hashCode; 117 118 if ( ! NSK_VERIFY(jvmti->SetTag(o, tag) == JVMTI_ERROR_NONE) ) { 119 NSK_COMPLAIN2("Can't set tag %li for object %lx\n", tag, o); 120 return JNI_FALSE; 121 } 122 123 if ( ! NSK_VERIFY(jvmti->GetObjectHashCode(o, &hashCode) == JVMTI_ERROR_NONE) ) { 124 NSK_COMPLAIN1("Can't get hash object %lx\n", o); 125 return JNI_FALSE; 126 } 127 128 NSK_DISPLAY2("setTag: %08x <- % 3li", hashCode, tag); 129 130 if ( tag > 0 && tag < MAX_TAG ) { 131 jboolean fCopy; 132 const char * s; 133 134 if ( ! NSK_VERIFY((s = jni->GetStringUTFChars(sInfo, &fCopy)) != NULL) ) { 135 NSK_COMPLAIN1("Can't get string at %#p\n", sInfo); 136 return JNI_FALSE; 137 } 138 139 if ( ! s ) { 140 NSK_COMPLAIN1("Can't get string at %#p: NULL\n", sInfo); 141 return JNI_FALSE; 142 } 143 144 g_szTagInfo[tag] = strdup(s); 145 146 jni->ReleaseStringUTFChars(sInfo, s); 147 148 NSK_DISPLAY1(" // %s", g_szTagInfo[tag]); 149 150 } 151 152 markTagSet(tag); 153 154 return JNI_TRUE; 155 } 156 157 JNIEXPORT jlong JNICALL Java_nsk_jvmti_unit_FollowReferences_FollowRefObjects_getTag(JNIEnv* jni, jclass klass, jobject o) 158 { 159 jvmtiEnv * jvmti = nsk_jvmti_getAgentJVMTIEnv(); 160 161 jlong tag; 162 jvmtiError r; 163 if ( ! NSK_VERIFY((r = jvmti->GetTag(o, &tag)) == JVMTI_ERROR_NONE) ) { 164 NSK_COMPLAIN2("Can't GetTag for object %lx. Return code: %i\n", o, r); 165 return -1; 166 } 167 168 return tag; 169 } 170 171 /* ============================================================================= */ 172 173 int g_refsToVerifyCnt; 174 175 RefToVerify g_refsToVerify[MAX_REFS]; 176 177 /* ============================================================================= */ 178 179 JNIEXPORT void JNICALL Java_nsk_jvmti_unit_FollowReferences_FollowRefObjects_resetRefsToVerify(JNIEnv* jni, jclass klass) 180 { 181 g_refsToVerifyCnt = 0; 182 } 183 184 static RefToVerify * findRefToVerify(jlong tagFrom, jlong tagTo, jint refKind) 185 { 186 int i; 187 RefToVerify * pRefRec = g_refsToVerify; 188 189 for ( i = g_refsToVerifyCnt; i > 0; i--, pRefRec++ ) { 190 pRefRec = &g_refsToVerify[i]; 191 if ( pRefRec->_tagFrom == tagFrom && pRefRec->_tagTo == tagTo && pRefRec->_refKind == refKind ) { 192 return pRefRec; 193 } 194 } 195 196 return NULL; 197 } 198 199 static jboolean addRefToVerify(jlong tagFrom, jlong tagTo, jint refKind, int expectedCount, int actualCount) 200 { 201 RefToVerify * pRefRec; 202 203 if ( g_refsToVerifyCnt >= MAX_REFS ) { 204 NSK_COMPLAIN0("TEST_BUG: Max. number of refs reached!"); 205 nsk_jvmti_setFailStatus(); 206 return JNI_FALSE; 207 } 208 209 pRefRec = &g_refsToVerify[g_refsToVerifyCnt++]; 210 211 pRefRec->_tagFrom = tagFrom; 212 pRefRec->_tagTo = tagTo; 213 pRefRec->_refKind = refKind; 214 pRefRec->_expectedCount = expectedCount; 215 pRefRec->_actualCount = actualCount; 216 217 return JNI_TRUE; 218 } 219 220 JNIEXPORT jboolean JNICALL Java_nsk_jvmti_unit_FollowReferences_FollowRefObjects_addRefToVerify(JNIEnv* jni, jclass klass, jobject from, jobject to, jint refKind, jint count) 221 { 222 jvmtiEnv * jvmti = nsk_jvmti_getAgentJVMTIEnv(); 223 jvmtiError r; 224 jlong tagFrom, tagTo; 225 RefToVerify * pRefRec; 226 227 if ( ! NSK_VERIFY((r = jvmti->GetTag(from, &tagFrom)) == JVMTI_ERROR_NONE) ) { 228 NSK_COMPLAIN2("TEST_BUG: Can't GetTag for object %lx. Return code: %i\n", from, r); 229 nsk_jvmti_setFailStatus(); 230 return JNI_FALSE; 231 } 232 233 234 if ( ! NSK_VERIFY((r = jvmti->GetTag(to, &tagTo)) == JVMTI_ERROR_NONE) ) { 235 NSK_COMPLAIN2("TEST_BUG: Can't GetTag for object %lx. Return code: %i\n", to, r); 236 nsk_jvmti_setFailStatus(); 237 return JNI_FALSE; 238 } 239 240 if ( (pRefRec = findRefToVerify(tagFrom, tagTo, refKind)) != NULL ) { 241 pRefRec->_expectedCount += count; 242 return JNI_TRUE; 243 } 244 245 return addRefToVerify(tagFrom, tagTo, refKind, count, 0); 246 } 247 248 jboolean markRefToVerify(jlong tagFrom, jlong tagTo, int refKind) 249 { 250 RefToVerify * pRefRec; 251 252 if ( (pRefRec = findRefToVerify(tagFrom, tagTo, refKind)) != NULL ) { 253 pRefRec->_actualCount++; 254 return JNI_TRUE; 255 } 256 257 return addRefToVerify(tagFrom, tagTo, refKind, 0, 1); 258 } 259 260 /* ============================================================================= */ 261 262 void checkUserData(const char * szFile, const int line, void * user_data) 263 { 264 if (user_data != &g_fakeUserData && !g_userDataError) { 265 NSK_COMPLAIN4("%s, %i: Unexpected user_data is passed" 266 " to heapReferenceCallback:\n" 267 " expected: 0x%p\n" 268 " actual: 0x%p\n", 269 szFile, line, 270 &g_fakeUserData, 271 user_data); 272 g_userDataError++; 273 } 274 } 275 276 #define CHECK_USER_DATA(p) checkUserData(__FILE__, __LINE__, (p)) 277 278 void printHeapRefCallbackInfo( 279 jvmtiHeapReferenceKind reference_kind, 280 const jvmtiHeapReferenceInfo* reference_info, 281 jlong class_tag, 282 jlong referrer_class_tag, 283 jlong size, 284 jlong* tag_ptr, 285 jlong* referrer_tag_ptr, 286 jint length) 287 { 288 const char * szInfo, * szRefInfo; 289 jlong tag_val = tag_ptr ? *tag_ptr : 0; 290 291 NSK_DISPLAY1("heapReferenceCallback: %s", g_refKindStr[reference_kind]); 292 293 NSK_DISPLAY3(" reference_info: %#lx, class_tag: %#" LL "d, referrer_class_tag: %#" LL "d\n", 294 reference_info, class_tag, referrer_class_tag); 295 296 NSK_DISPLAY4(" size: %" LL "d, tag_ptr: %p, referrer_tag_ptr: %p, length: %-ld\n", 297 size, tag_ptr, referrer_tag_ptr, length); 298 299 NSK_DISPLAY2(" tag: %" LL "d, referrer_tag: %" LL "d\n", 300 tag_val, DEREF(referrer_tag_ptr)); 301 302 szInfo = ( tag_val > 0 && tag_val < MAX_TAG ) ? g_szTagInfo[tag_val] : "<none>"; 303 szRefInfo = ( referrer_tag_ptr && *referrer_tag_ptr > 0 && *referrer_tag_ptr < MAX_TAG ) ? g_szTagInfo[*referrer_tag_ptr] : "<none>"; 304 305 NSK_DISPLAY3(" summary: %s: %s <- %s\n", 306 g_refKindStr[reference_kind], szInfo, szRefInfo); 307 } 308 309 /* ============================================================================= */ 310 311 jint JNICALL wrongHeapReferenceCallback( 312 jvmtiHeapReferenceKind reference_kind, 313 const jvmtiHeapReferenceInfo* reference_info, 314 jlong class_tag, 315 jlong referrer_class_tag, 316 jlong size, 317 jlong* tag_ptr, 318 jlong* referrer_tag_ptr, 319 jint length, 320 void* user_data) 321 { 322 CHECK_USER_DATA(user_data); 323 NSK_COMPLAIN0("heap reference callback was called, where it should not be\n"); 324 nsk_jvmti_setFailStatus(); 325 printHeapRefCallbackInfo(reference_kind, reference_info, class_tag, referrer_class_tag, size, tag_ptr, referrer_tag_ptr, length); 326 327 return JVMTI_VISIT_OBJECTS; 328 } 329 330 jint JNICALL wrongPrimitiveFieldCallback( 331 jvmtiHeapReferenceKind reference_kind, 332 const jvmtiHeapReferenceInfo* reference_info, 333 jlong class_tag, 334 jlong* tag_ptr, 335 jvalue value, 336 jvmtiPrimitiveType value_type, 337 void* user_data) 338 { 339 CHECK_USER_DATA(user_data); 340 NSK_COMPLAIN0("primitive field callback was called, where it should not be\n"); 341 nsk_jvmti_setFailStatus(); 342 343 return JVMTI_VISIT_OBJECTS; 344 } 345 346 jint JNICALL wrongArrayPrimitiveValueCallback( 347 jlong class_tag, 348 jlong size, 349 jlong* tag_ptr, 350 jint element_count, 351 jvmtiPrimitiveType element_type, 352 const void* elements, 353 void* user_data) 354 { 355 CHECK_USER_DATA(user_data); 356 NSK_COMPLAIN0("array primitive value callback was called, where it should not be\n"); 357 nsk_jvmti_setFailStatus(); 358 359 return JVMTI_VISIT_OBJECTS; 360 } 361 362 jint JNICALL wrongStringPrimitiveValueCallback( 363 jlong class_tag, 364 jlong size, 365 jlong* tag_ptr, 366 const jchar* value, 367 jint value_length, 368 void* user_data) 369 { 370 CHECK_USER_DATA(user_data); 371 NSK_COMPLAIN0("string primitive value callback was called, where it should not be\n"); 372 nsk_jvmti_setFailStatus(); 373 374 return JVMTI_VISIT_OBJECTS; 375 } 376 377 /* ============================================================================= */ 378 379 void jvmti_FollowRefObject_init() 380 { 381 g_wrongHeapCallbacks.heap_iteration_callback = NULL; 382 g_wrongHeapCallbacks.heap_reference_callback = wrongHeapReferenceCallback; 383 g_wrongHeapCallbacks.primitive_field_callback = wrongPrimitiveFieldCallback; 384 g_wrongHeapCallbacks.array_primitive_value_callback = wrongArrayPrimitiveValueCallback; 385 g_wrongHeapCallbacks.string_primitive_value_callback = wrongStringPrimitiveValueCallback; 386 387 Java_nsk_jvmti_unit_FollowReferences_FollowRefObjects_resetTags(NULL, NULL); 388 Java_nsk_jvmti_unit_FollowReferences_FollowRefObjects_resetRefsToVerify(NULL, NULL); 389 } 390 391 /* ============================================================================= */ 392 393 }