1 /*
2  * Copyright (c) 2003, 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 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /* ============================================================================= */
35 
36 /* scaffold objects */
37 static jlong timeout = 0;
38 
39 /* constant names */
40 #define DEBUGEE_CLASS_NAME    "nsk/jvmti/GetObjectsWithTags/objwithtags001"
41 #define OBJECT_CLASS_NAME     "nsk/jvmti/GetObjectsWithTags/objwithtags001TestedClass"
42 #define OBJECT_CLASS_SIG      "L"OBJECT_CLASS_NAME";"
43 #define OBJECTS_FIELD_NAME    "objects"
44 #define OBJECTS_FIELD_SIG     "["OBJECT_CLASS_SIG
45 
46 /* constants */
47 #define DEFAULT_TAGS_COUNT    4
48 #define DEFAULT_OBJECTS_COUNT 5
49 
50 static int tagsCount = 0;
51 static int objectsCount = 0;
52 
53 /* 2-dim indexing for flat list */
54 #define ITEM(list, i, j)      (((list) + (i * objectsCount))[j])
55 
56 /* ============================================================================= */
57 
58 /** Obtain tested objects from static field of debugee class. */
getTestedObjects(jvmtiEnv * jvmti,JNIEnv * jni,int tagsCount,int objectsCount,jobject ** objects,jlong ** tags)59 static int getTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int tagsCount, int objectsCount,
60                                                 jobject* *objects, jlong* *tags) {
61     jclass debugeeClass = NULL;
62     jfieldID objectField = NULL;
63     jobjectArray arrayObject = NULL;
64     int size = tagsCount * objectsCount;
65 
66     NSK_DISPLAY2("Allocate memory for lists: %d objects for %d tags\n",
67                                                             objectsCount, tagsCount);
68     if (!NSK_JVMTI_VERIFY(
69             NSK_CPP_STUB3(Allocate, jvmti, (size * sizeof(jobject)),
70                                                     (unsigned char**)objects))) {
71         nsk_jvmti_setFailStatus();
72         return NSK_FALSE;
73     }
74     NSK_DISPLAY1("  ... allocated objects list: 0x%p\n", (void*)objects);
75 
76     if (!NSK_JVMTI_VERIFY(
77             NSK_CPP_STUB3(Allocate, jvmti, (tagsCount * sizeof(jlong)),
78                                                     (unsigned char**)tags))) {
79         nsk_jvmti_setFailStatus();
80         return NSK_FALSE;
81     }
82     NSK_DISPLAY1("  ... allocated tags list: 0x%p\n", (void*)tags);
83 
84     {
85         int i, k;
86         for (k = 0; k < size; k++) {
87             (*objects)[k] = NULL;
88         }
89 
90         for (i = 0; i < tagsCount; i++) {
91             (*tags)[i] = 100 * (jlong)(i + 1);
92         }
93     }
94 
95     NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_CLASS_NAME);
96     if (!NSK_JNI_VERIFY(jni, (debugeeClass =
97             NSK_CPP_STUB2(FindClass, jni, DEBUGEE_CLASS_NAME)) != NULL)) {
98         nsk_jvmti_setFailStatus();
99         return NSK_FALSE;
100     }
101     NSK_DISPLAY1("  ... found class: 0x%p\n", (void*)debugeeClass);
102 
103     NSK_DISPLAY1("Find static field: %s\n", OBJECTS_FIELD_NAME);
104     if (!NSK_JNI_VERIFY(jni, (objectField =
105             NSK_CPP_STUB4(GetStaticFieldID, jni, debugeeClass,
106                             OBJECTS_FIELD_NAME, OBJECTS_FIELD_SIG)) != NULL)) {
107         nsk_jvmti_setFailStatus();
108         return NSK_FALSE;
109     }
110     NSK_DISPLAY1("  ... got fieldID: 0x%p\n", (void*)objectField);
111 
112     NSK_DISPLAY1("Get objects array from static field: %s\n", OBJECTS_FIELD_NAME);
113     if (!NSK_JNI_VERIFY(jni, (arrayObject = (jobjectArray)
114             NSK_CPP_STUB3(GetStaticObjectField, jni, debugeeClass,
115                                                     objectField)) != NULL)) {
116         nsk_jvmti_setFailStatus();
117         return NSK_FALSE;
118     }
119     NSK_DISPLAY1("  ... got array object: 0x%p\n", (void*)arrayObject);
120 
121     {
122         jsize arrayLen = 0;
123         jsize k;
124 
125         if (!NSK_JNI_VERIFY(jni, (arrayLen =
126                 NSK_CPP_STUB2(GetArrayLength, jni, arrayObject)) == size)) {
127             NSK_DISPLAY1("  ... got array length: %d\n", (int)size);
128             nsk_jvmti_setFailStatus();
129             return NSK_FALSE;
130         }
131         NSK_DISPLAY1("  ... got array length: %d\n", (int)size);
132 
133         for (k = 0; k < size; k++) {
134             jobject object = NULL;
135 
136             if (!NSK_JNI_VERIFY(jni, (object =
137                 NSK_CPP_STUB3(GetObjectArrayElement, jni, arrayObject, k)) != NULL)) {
138                 nsk_jvmti_setFailStatus();
139                 return NSK_FALSE;
140             }
141             if (!NSK_JNI_VERIFY(jni, (object =
142                 NSK_CPP_STUB2(NewGlobalRef, jni, object)) != NULL)) {
143                 nsk_jvmti_setFailStatus();
144                 return NSK_FALSE;
145             }
146 
147             (*objects)[k] = object;
148         }
149     }
150     NSK_DISPLAY1("  ... object references created: %d objects\n", size);
151 
152     return NSK_TRUE;
153 }
154 
155 /** Release references to the tested objects and free allocated memory. */
releaseTestedObjects(jvmtiEnv * jvmti,JNIEnv * jni,int tagsCount,int objectsCount,jobject * objects,jlong * tags)156 static int releaseTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int tagsCount, int objectsCount,
157                                                         jobject *objects, jlong *tags) {
158     int size = tagsCount * objectsCount;
159     int k;
160 
161     if (objects == NULL)
162         return NSK_TRUE;
163 
164     NSK_DISPLAY1("Release objects references: %d objects\n", size);
165     for (k = 0; k < size; k++) {
166         if (objects[k] != NULL) {
167             NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, objects[k]));
168         }
169     }
170     NSK_DISPLAY1("  ... object references released: %d objects\n", size);
171 
172     NSK_DISPLAY1("Deallocate objects list: 0x%p\n", (void*)objects);
173     if (!NSK_JVMTI_VERIFY(
174             NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)objects))) {
175         nsk_jvmti_setFailStatus();
176     }
177 
178     if (tags == NULL)
179         return NSK_FALSE;
180 
181     NSK_DISPLAY1("Deallocate tags list: 0x%p\n", (void*)tags);
182     if (!NSK_JVMTI_VERIFY(
183             NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)tags))) {
184         nsk_jvmti_setFailStatus();
185     }
186 
187     return NSK_TRUE;
188 }
189 
190 /** Get and check tagged objects. */
checkTestedObjects(jvmtiEnv * jvmti,JNIEnv * jni,int tagsCount,int objectsCount,jlong tags[],jobject objects[],const char kind[],int expectedCount)191 static int checkTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int tagsCount, int objectsCount,
192                                                 jlong tags[], jobject objects[],
193                                                 const char kind[], int expectedCount) {
194     jint taggedObjectsCount = 0;
195     jobject* taggedObjectsList = NULL;
196     jlong* taggedObjectsTags = NULL;
197     jlong expectedTag = 0;
198     int k;
199 
200     NSK_DISPLAY1("Get tagged objects: %d tags\n", tagsCount);
201     if (!NSK_JVMTI_VERIFY(
202             NSK_CPP_STUB6(GetObjectsWithTags, jvmti, tagsCount, tags,
203                 &taggedObjectsCount, &taggedObjectsList, &taggedObjectsTags))) {
204         nsk_jvmti_setFailStatus();
205         return NSK_TRUE;
206     }
207     NSK_DISPLAY1("  ... got tagged objects: %d\n", (int)taggedObjectsCount);
208 
209     if (taggedObjectsCount != expectedCount) {
210         NSK_COMPLAIN3("GetObjectsWithTags() returns unexpected number of objects %s:\n"
211                       "#   got objects:  %d\n"
212                       "#   expected:     %d\n",
213                       kind, (int)taggedObjectsCount, (int)expectedCount);
214         nsk_jvmti_setFailStatus();
215     }
216 
217     if (taggedObjectsList == NULL && taggedObjectsCount > 0) {
218         NSK_COMPLAIN2("GetObjectsWithTags() returns NULL list of objects %s: 0x%p\n",
219                         kind, (void*)taggedObjectsList);
220         nsk_jvmti_setFailStatus();
221         return NSK_TRUE;
222     }
223 
224     if (taggedObjectsTags == NULL && taggedObjectsCount > 0) {
225         NSK_COMPLAIN2("GetObjectsWithTags() returns NULL list of tags for objects %s: 0x%p\n",
226                         kind, (void*)taggedObjectsTags);
227         nsk_jvmti_setFailStatus();
228         return NSK_TRUE;
229     }
230 
231     for (k = 0; k < taggedObjectsCount; k++) {
232         jobject object = taggedObjectsList[k];
233         jlong tag = taggedObjectsTags[k];
234         int objectsFound = 0;
235         int i, j, l;
236 
237         NSK_DISPLAY3("   #%d: object: 0x%p, tag: %ld\n", k, (void*)object, (long)tag);
238 
239         if (object == NULL) {
240             NSK_COMPLAIN3("GetObjectsWithTags() returns NULL for object #%d %s: 0x%p\n",
241                         k, kind, (void*)object);
242             nsk_jvmti_setFailStatus();
243             continue;
244         }
245 
246         objectsFound = 0;
247         for (l = k + 1; l < taggedObjectsCount; l++) {
248             if (object == taggedObjectsList[l])
249                 objectsFound++;
250         }
251         if (objectsFound > 0) {
252             NSK_COMPLAIN4("GetObjectsWithTags() returns %d duplicates for object #%d %s: 0x%p\n",
253                         objectsFound, k, kind, (void*)object);
254             nsk_jvmti_setFailStatus();
255             continue;
256         }
257 
258         objectsFound = 0;
259         for (i = 0; i < tagsCount; i++) {
260             for (j = 0; j < objectsCount; j++) {
261                 jobject foundObject = ITEM(objects, i, j);
262 
263                 if (NSK_CPP_STUB3(IsSameObject, jni, object, foundObject)) {
264                     objectsFound++;
265 
266                     if (expectedCount > 0)
267                         expectedTag = tags[i];
268 
269                     if (tag != expectedTag) {
270                         NSK_COMPLAIN6("GetObjectsWithTags() returns wrong tag for object #%d %s:\n"
271                                       "#   got object: 0x%p\n"
272                                       "#   original:   0x%p\n"
273                                       "#   got tag:    %ld\n"
274                                       "#   original:   %ld\n",
275                                         k, kind,
276                                         (void*)object, (void*)foundObject,
277                                         (long)tag, (long)expectedTag);
278                         nsk_jvmti_setFailStatus();
279                     }
280                     break;
281                 }
282             }
283 
284             if (objectsFound > 0)
285                 break;
286         }
287 
288         if (objectsFound <= 0) {
289             NSK_COMPLAIN4("GetObjectsWithTags() returns unexpected #%d object %s:\n"
290                           "#   got object: 0x%p\n"
291                           "#   got tag:    %ld\n",
292                             k, kind,
293                             (void*)object, (long)tag);
294             nsk_jvmti_setFailStatus();
295         }
296     }
297 
298     NSK_DISPLAY1("Deallocate got objects list: 0x%p\n", (void*)taggedObjectsList);
299     if (!NSK_JVMTI_VERIFY(
300             NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)taggedObjectsList))) {
301         nsk_jvmti_setFailStatus();
302     }
303     NSK_DISPLAY1("Deallocate got tags list: 0x%p\n", (void*)taggedObjectsTags);
304     if (!NSK_JVMTI_VERIFY(
305             NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)taggedObjectsTags))) {
306         nsk_jvmti_setFailStatus();
307     }
308 
309     return NSK_TRUE;
310 }
311 
312 /** Agent algorithm. */
313 static void JNICALL
agentProc(jvmtiEnv * jvmti,JNIEnv * jni,void * arg)314 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
315     NSK_DISPLAY0("Wait for objects created\n");
316     if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
317         return;
318 
319     /* perform testing */
320     {
321         int size = tagsCount * objectsCount;
322         jobject* objects = NULL;
323         jlong* tags = NULL;
324 
325         NSK_DISPLAY0(">>> Obtain tested objects list from a static field of debugee class\n");
326         {
327             if (!NSK_VERIFY(getTestedObjects(jvmti, jni, tagsCount, objectsCount,
328                                                                     &objects, &tags)))
329                 return;
330         }
331 
332         NSK_DISPLAY0(">>> Tagging tested objects with different tags\n");
333         {
334             int i, j;
335 
336             for (i = 0; i < tagsCount; i++) {
337                 NSK_DISPLAY2("  tagging with %ld: %d objects\n", (long)tags[i], objectsCount);
338                 for (j = 0; j < objectsCount; j++) {
339                     jobject object = ITEM(objects, i, j);
340 
341                     NSK_DISPLAY3("    #%d: object: 0x%p, tag: %ld\n",
342                                             j, (void*)object, (long)tags[i]);
343                     if (!NSK_JVMTI_VERIFY(
344                             NSK_CPP_STUB3(SetTag, jvmti, object, tags[i]))) {
345                         nsk_jvmti_setFailStatus();
346                         return;
347                     }
348                 }
349             }
350             NSK_DISPLAY1("  ... objects tagged: %d objects\n", (tagsCount * objectsCount));
351         }
352 
353         NSK_DISPLAY0(">>> Testcase #1: get tagged objects before objects data changed\n");
354         {
355             if (!NSK_VERIFY(
356                     checkTestedObjects(jvmti, jni, tagsCount, objectsCount,
357                                                 tags, objects, "before changed", size)))
358                 return;
359         }
360 
361         NSK_DISPLAY0(">>> Let debugee to change object data\n");
362         {
363             if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
364                 return;
365             if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
366                 return;
367         }
368 
369         NSK_DISPLAY0(">>> Testcase #2: get tagged objects after objects data are changed\n");
370         {
371             if (!NSK_VERIFY(
372                     checkTestedObjects(jvmti, jni, tagsCount, objectsCount,
373                                                 tags, objects, "after changed", size)))
374                 return;
375         }
376 
377         NSK_DISPLAY0(">>> Untagging all tested objects (i.e., tagging with zero tag)\n");
378         {
379             jlong tag = 0;
380             int i, j;
381 
382             for (i = 0; i < tagsCount; i++) {
383                 NSK_DISPLAY2("  tagging with %ld: %d objects\n", (long)tag, objectsCount);
384                 for (j = 0; j < objectsCount; j++) {
385                     jobject object = ITEM(objects, i , j);
386 
387                     NSK_DISPLAY3("    #%d: object: 0x%p, tag: %ld\n",
388                                             j, (void*)object, (long)tag);
389                     if (!NSK_JVMTI_VERIFY(
390                             NSK_CPP_STUB3(SetTag, jvmti, object, tag))) {
391                         nsk_jvmti_setFailStatus();
392                         return;
393                     }
394                 }
395             }
396             NSK_DISPLAY1("  ... objects untagged: %d objects\n", (tagsCount * objectsCount));
397         }
398 
399         NSK_DISPLAY0(">>> Testcase #3: get tagged objects after objects untagged\n");
400         {
401             if (!NSK_VERIFY(
402                     checkTestedObjects(jvmti, jni, tagsCount, objectsCount,
403                                                 tags, objects, "after untagged", 0)))
404                 return;
405         }
406 
407         NSK_DISPLAY0(">>> Clean used data\n");
408         {
409             if (!NSK_VERIFY(releaseTestedObjects(jvmti, jni, tagsCount, objectsCount,
410                                                                         objects, tags)))
411                 return;
412         }
413     }
414 
415     NSK_DISPLAY0("Let debugee to finish\n");
416     if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
417         return;
418 }
419 
420 /* ============================================================================= */
421 
422 /** Agent library initialization. */
423 #ifdef STATIC_BUILD
Agent_OnLoad_objwithtags001(JavaVM * jvm,char * options,void * reserved)424 JNIEXPORT jint JNICALL Agent_OnLoad_objwithtags001(JavaVM *jvm, char *options, void *reserved) {
425     return Agent_Initialize(jvm, options, reserved);
426 }
Agent_OnAttach_objwithtags001(JavaVM * jvm,char * options,void * reserved)427 JNIEXPORT jint JNICALL Agent_OnAttach_objwithtags001(JavaVM *jvm, char *options, void *reserved) {
428     return Agent_Initialize(jvm, options, reserved);
429 }
JNI_OnLoad_objwithtags001(JavaVM * jvm,char * options,void * reserved)430 JNIEXPORT jint JNI_OnLoad_objwithtags001(JavaVM *jvm, char *options, void *reserved) {
431     return JNI_VERSION_1_8;
432 }
433 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)434 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
435     jvmtiEnv* jvmti = NULL;
436 
437     /* init framework and parse options */
438     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
439         return JNI_ERR;
440 
441     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
442 
443     /* get option values */
444     tagsCount = nsk_jvmti_findOptionIntValue("tags", DEFAULT_TAGS_COUNT);
445     objectsCount = nsk_jvmti_findOptionIntValue("objects", DEFAULT_OBJECTS_COUNT);
446     if (!NSK_VERIFY(tagsCount > 0 && objectsCount > 0))
447         return JNI_ERR;
448 
449     /* create JVMTI environment */
450     if (!NSK_VERIFY((jvmti =
451             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
452         return JNI_ERR;
453 
454     /* add required capabilities */
455     {
456         jvmtiCapabilities caps;
457 
458         memset(&caps, 0, sizeof(caps));
459         caps.can_tag_objects = 1;
460         if (!NSK_JVMTI_VERIFY(
461                 NSK_CPP_STUB2(AddCapabilities, jvmti, &caps))) {
462             return JNI_ERR;
463         }
464     }
465 
466     /* register agent proc and arg */
467     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
468         return JNI_ERR;
469 
470     return JNI_OK;
471 }
472 
473 /* ============================================================================= */
474 
475 #ifdef __cplusplus
476 }
477 #endif
478