1 /*
2  * Copyright (c) 2007, 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 #include <stdlib.h>
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 #define STATUS_FAIL     97
37 
38 #define EVENTS_COUNT    2
39 
40 static jvmtiEvent events[EVENTS_COUNT] = {
41     JVMTI_EVENT_VM_INIT,
42     JVMTI_EVENT_VM_DEATH
43 };
44 
45 static jvmtiCapabilities initCaps;
46 
47 /* ============================================================================= */
48 
49 /**
50  * Get and check current capabilities.
51  * @returns NSK_FALSE if any error occured.
52  */
checkCapabilities(jvmtiEnv * jvmti,jvmtiCapabilities * initCaps,const char where[])53 static int checkCapabilities(jvmtiEnv* jvmti, jvmtiCapabilities* initCaps, const char where[]) {
54     int success = NSK_TRUE;
55     jvmtiCapabilities caps;
56 
57     memset(&caps, 0, sizeof(jvmtiCapabilities));
58 
59     NSK_DISPLAY0("GetCapabilities() for current JVMTI env\n");
60     if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps))) {
61         return NSK_FALSE;
62     }
63 
64     return success;
65 }
66 
67 /**
68  * Add given capabilities list.
69  * @returns NSK_FALSE if any error occured.
70  */
addCapabilities(jvmtiEnv * jvmti,jvmtiCapabilities * caps,const char where[])71 static int addCapabilities(jvmtiEnv* jvmti, jvmtiCapabilities* caps, const char where[]) {
72     NSK_DISPLAY0("AddCapabilities() for current JVMTI env\n");
73     if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(caps))) {
74         return NSK_FALSE;
75     }
76     NSK_DISPLAY0("  ... set\n");
77 
78     return NSK_TRUE;
79 }
80 
81 /**
82  * Get potential capabilities to the given list.
83  * @returns NSK_FALSE if any error occured.
84  */
getPotentialCapabilities(jvmtiEnv * jvmti,jvmtiCapabilities * caps)85 static int getPotentialCapabilities(jvmtiEnv* jvmti, jvmtiCapabilities* caps) {
86     NSK_DISPLAY0("GetPotentialCapabilities() for current JVMTI env\n");
87     if (!NSK_JVMTI_VERIFY(jvmti->GetPotentialCapabilities(caps))) {
88         return NSK_FALSE;
89     }
90 
91     return NSK_TRUE;
92 }
93 
94 /* ============================================================================= */
95 
96 /** Agent algorithm. */
97 static void JNICALL
agentProc(jvmtiEnv * jvmti,JNIEnv * jni,void * arg)98 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
99     NSK_DISPLAY0("Wait for debugee to become ready\n");
100     if (!nsk_jvmti_waitForSync(timeout))
101         return;
102 
103     NSK_DISPLAY0(">>> Testcase #3: Check capabilities in agent thread\n");
104     if (!checkCapabilities(jvmti, &initCaps, "agent thread")) {
105         nsk_jvmti_setFailStatus();
106     }
107 
108     NSK_DISPLAY0("Let debugee to finish\n");
109     if (!nsk_jvmti_resumeSync())
110         return;
111 }
112 
113 /* ============================================================================= */
114 
115 /**
116  * Callback for VM_INIT event.
117  */
118 JNIEXPORT void JNICALL
callbackVMInit(jvmtiEnv * jvmti,JNIEnv * jni,jthread thread)119 callbackVMInit(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) {
120 
121     NSK_DISPLAY0(">>> Testcase #2: Check capabilities in VM_INIT callback\n");
122     if (!checkCapabilities(jvmti, &initCaps, "VM_INIT callback")) {
123         nsk_jvmti_setFailStatus();
124     }
125 
126 }
127 
128 /**
129  * Callback for VM_DEATH event.
130  */
131 JNIEXPORT void JNICALL
callbackVMDeath(jvmtiEnv * jvmti,JNIEnv * jni)132 callbackVMDeath(jvmtiEnv* jvmti, JNIEnv* jni) {
133     int success = NSK_TRUE;
134 
135     NSK_DISPLAY0(">>> Testcase #4: Check capabilities in VM_DEATH callback\n");
136     success = checkCapabilities(jvmti, &initCaps, "VM_DEATH callback");
137 
138     NSK_DISPLAY1("Disable events: %d events\n", EVENTS_COUNT);
139     if (!nsk_jvmti_enableEvents(JVMTI_DISABLE, EVENTS_COUNT, events, NULL)) {
140         success = NSK_FALSE;
141     } else {
142         NSK_DISPLAY0("  ... disabled\n");
143     }
144 
145     if (!success) {
146         NSK_DISPLAY1("Exit with FAIL exit status: %d\n", STATUS_FAIL);
147         NSK_BEFORE_TRACE(exit(STATUS_FAIL));
148     }
149 }
150 
151 /* ============================================================================= */
152 
153 /** Agent library initialization. */
154 #ifdef STATIC_BUILD
Agent_OnLoad_addcaps003(JavaVM * jvm,char * options,void * reserved)155 JNIEXPORT jint JNICALL Agent_OnLoad_addcaps003(JavaVM *jvm, char *options, void *reserved) {
156     return Agent_Initialize(jvm, options, reserved);
157 }
Agent_OnAttach_addcaps003(JavaVM * jvm,char * options,void * reserved)158 JNIEXPORT jint JNICALL Agent_OnAttach_addcaps003(JavaVM *jvm, char *options, void *reserved) {
159     return Agent_Initialize(jvm, options, reserved);
160 }
JNI_OnLoad_addcaps003(JavaVM * jvm,char * options,void * reserved)161 JNIEXPORT jint JNI_OnLoad_addcaps003(JavaVM *jvm, char *options, void *reserved) {
162     return JNI_VERSION_1_8;
163 }
164 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)165 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
166     jvmtiEnv* jvmti = NULL;
167 
168     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
169         return JNI_ERR;
170 
171     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
172 
173     if (!NSK_VERIFY((jvmti =
174             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
175         return JNI_ERR;
176 
177     {
178         jvmtiEventCallbacks eventCallbacks;
179 
180         memset(&eventCallbacks, 0, sizeof(eventCallbacks));
181         eventCallbacks.VMInit = callbackVMInit;
182         eventCallbacks.VMDeath = callbackVMDeath;
183         if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks)))) {
184             return JNI_ERR;
185         }
186 
187     }
188 
189     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
190         return JNI_ERR;
191 
192     memset(&initCaps, 0, sizeof(jvmtiCapabilities));
193     if (!getPotentialCapabilities(jvmti, &initCaps)) {
194         return JNI_ERR;
195     }
196 
197     NSK_DISPLAY0(">>> Testcase #0: Add all potential capabilities in Agent_OnLoad()\n");
198     if (!addCapabilities(jvmti, &initCaps, "Agent_OnLoad()")) {
199         nsk_jvmti_setFailStatus();
200     }
201 
202     NSK_DISPLAY0(">>> Testcase #1: Check capabilities in Agent_OnLoad()\n");
203     if (!checkCapabilities(jvmti, &initCaps, "Agent_OnLoad()")) {
204         nsk_jvmti_setFailStatus();
205     }
206 
207     NSK_DISPLAY1("Enable events: %d events\n", EVENTS_COUNT);
208     if (nsk_jvmti_enableEvents(JVMTI_ENABLE, EVENTS_COUNT, events, NULL)) {
209         NSK_DISPLAY0("  ... enabled\n");
210     }
211 
212     return JNI_OK;
213 }
214 
215 /* ============================================================================= */
216 
217 }
218