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
markTagSet(jlong tag_val)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
markTagVisited(jlong tag_val)76 void markTagVisited(jlong tag_val)
77 {
78 if (tag_val > 0 && tag_val < MAX_TAG) {
79 g_tagVisitCount[tag_val]++;
80 }
81 }
82
checkThatAllTagsVisited()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
Java_nsk_jvmti_unit_FollowReferences_FollowRefObjects_resetTags(JNIEnv * jni,jclass klass)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
Java_nsk_jvmti_unit_FollowReferences_FollowRefObjects_setTag(JNIEnv * jni,jclass klass,jobject o,jlong tag,jstring sInfo)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
Java_nsk_jvmti_unit_FollowReferences_FollowRefObjects_getTag(JNIEnv * jni,jclass klass,jobject o)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
Java_nsk_jvmti_unit_FollowReferences_FollowRefObjects_resetRefsToVerify(JNIEnv * jni,jclass klass)179 JNIEXPORT void JNICALL Java_nsk_jvmti_unit_FollowReferences_FollowRefObjects_resetRefsToVerify(JNIEnv* jni, jclass klass)
180 {
181 g_refsToVerifyCnt = 0;
182 }
183
findRefToVerify(jlong tagFrom,jlong tagTo,jint refKind)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
addRefToVerify(jlong tagFrom,jlong tagTo,jint refKind,int expectedCount,int actualCount)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
Java_nsk_jvmti_unit_FollowReferences_FollowRefObjects_addRefToVerify(JNIEnv * jni,jclass klass,jobject from,jobject to,jint refKind,jint count)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 pRefRec = findRefToVerify(tagFrom, tagTo, refKind);
241 if (pRefRec != NULL) {
242 pRefRec->_expectedCount += count;
243 return JNI_TRUE;
244 }
245
246 return addRefToVerify(tagFrom, tagTo, refKind, count, 0);
247 }
248
markRefToVerify(jlong tagFrom,jlong tagTo,int refKind)249 jboolean markRefToVerify(jlong tagFrom, jlong tagTo, int refKind)
250 {
251 RefToVerify * pRefRec;
252
253 pRefRec = findRefToVerify(tagFrom, tagTo, refKind);
254 if (pRefRec != NULL) {
255 pRefRec->_actualCount++;
256 return JNI_TRUE;
257 }
258
259 return addRefToVerify(tagFrom, tagTo, refKind, 0, 1);
260 }
261
262 /* ============================================================================= */
263
checkUserData(const char * szFile,const int line,void * user_data)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
printHeapRefCallbackInfo(jvmtiHeapReferenceKind reference_kind,const jvmtiHeapReferenceInfo * reference_info,jlong class_tag,jlong referrer_class_tag,jlong size,jlong * tag_ptr,jlong * referrer_tag_ptr,jint length)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
wrongHeapReferenceCallback(jvmtiHeapReferenceKind reference_kind,const jvmtiHeapReferenceInfo * reference_info,jlong class_tag,jlong referrer_class_tag,jlong size,jlong * tag_ptr,jlong * referrer_tag_ptr,jint length,void * user_data)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
wrongPrimitiveFieldCallback(jvmtiHeapReferenceKind reference_kind,const jvmtiHeapReferenceInfo * reference_info,jlong class_tag,jlong * tag_ptr,jvalue value,jvmtiPrimitiveType value_type,void * user_data)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
wrongArrayPrimitiveValueCallback(jlong class_tag,jlong size,jlong * tag_ptr,jint element_count,jvmtiPrimitiveType element_type,const void * elements,void * user_data)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
wrongStringPrimitiveValueCallback(jlong class_tag,jlong size,jlong * tag_ptr,const jchar * value,jint value_length,void * user_data)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
jvmti_FollowRefObject_init()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 }
396