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