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
24 #include <stdlib.h>
25 #include <string.h>
26 #include "jvmti.h"
27 #include "jni_tools.h"
28 #include "jvmti_tools.h"
29 #include "agent_common.h"
30
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35 /* ============================================================================= */
36
37 static jlong timeout = 0;
38
39 static char segment1[3000] = "";
40 static char segment2[3000] = "";
41
42 static const char* const illegal_segments[] = {"", "tmp/"};
43
44 jboolean use_segment2 = JNI_FALSE;
45
46 jvmtiPhase jvmti_phase_to_check = JVMTI_PHASE_ONLOAD;
47
48 /* ============================================================================= */
49
50 /**
51 * Add segment to bootstrap classloader path.
52 * @returns NSK_FALSE if any error occured.
53 */
addSegment(jvmtiEnv * jvmti,const char segment[],const char where[])54 static int addSegment(jvmtiEnv* jvmti, const char segment[], const char where[]) {
55 NSK_DISPLAY1("Add segment: \"%s\"\n", segment);
56 if (!NSK_JVMTI_VERIFY(
57 NSK_CPP_STUB2(AddToBootstrapClassLoaderSearch, jvmti, segment))) {
58 NSK_COMPLAIN1("TEST FAILURE: failed to add segment %s\n", segment);
59 return NSK_FALSE;
60 }
61 NSK_DISPLAY0(" ... added\n");
62
63 return NSK_TRUE;
64 }
65
66 /**
67 * Try to add illegal segment to bootstrap classloader path and check that expected error
68 * (expectedError) is returned.
69 * @returns NSK_FALSE if no error or wronf error is occured.
70 */
addIllegalSegment(jvmtiEnv * jvmti,const char segment[],const char where[],jvmtiError expectedError)71 static int addIllegalSegment(jvmtiEnv* jvmti, const char segment[], const char where[], jvmtiError expectedError) {
72 NSK_DISPLAY1("Add illegal segment: \"%s\"\n", segment);
73 if (!NSK_JVMTI_VERIFY_CODE(expectedError,
74 NSK_CPP_STUB2(AddToBootstrapClassLoaderSearch, jvmti, segment))) {
75
76 NSK_COMPLAIN2("TEST FAILURE: got wrong error when tried to add segment %s (expected error=%s)\n",
77 segment, TranslateError(expectedError));
78 return NSK_FALSE;
79 }
80 NSK_DISPLAY0(" ... not added\n");
81
82 return NSK_TRUE;
83 }
84
85 /*
86 * Check that attempt to add illegal segment causes the error.
87 */
checkLivePhaseForIllegalArgs(jvmtiEnv * jvmti,const char where[])88 static void checkLivePhaseForIllegalArgs (jvmtiEnv* jvmti, const char where[]) {
89 size_t i;
90
91 for (i = 0; i < sizeof(illegal_segments)/sizeof(char*); i++) {
92 if (!addIllegalSegment(jvmti, illegal_segments[i], where, JVMTI_ERROR_ILLEGAL_ARGUMENT)) {
93 nsk_jvmti_setFailStatus();
94 NSK_BEFORE_TRACE(exit(nsk_jvmti_getStatus()));
95 }
96 }
97 }
98
99 /* ============================================================================= */
100
101 void JNICALL
callbackVMInit(jvmtiEnv * jvmti,JNIEnv * env,jthread thread)102 callbackVMInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread) {
103 NSK_DISPLAY0(">>> Testcase #1: Add bootstrap class load segment(s) in VMInit (live phase)\n");
104
105 // At first check that it is not possible to add anything other than an existing JAR file
106 checkLivePhaseForIllegalArgs(jvmti, "VMInit()");
107
108 if (!addSegment(jvmti, segment1, "VMInit()")) {
109 nsk_jvmti_setFailStatus();
110 NSK_BEFORE_TRACE(exit(nsk_jvmti_getStatus()));
111 }
112
113 if (use_segment2 == JNI_FALSE) return;
114
115 if (!addSegment(jvmti, segment2, "VMInit()")) {
116 nsk_jvmti_setFailStatus();
117 NSK_BEFORE_TRACE(exit(nsk_jvmti_getStatus()));
118 }
119 }
120
121 /*
122 * Check that it is possible to add to the boot class path before VMDeath event return.
123 */
124 void JNICALL
callbackVMDeath(jvmtiEnv * jvmti,JNIEnv * jni)125 callbackVMDeath(jvmtiEnv *jvmti, JNIEnv* jni) {
126 jvmtiPhase phase;
127
128 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetPhase, jvmti, &phase))) {
129 NSK_COMPLAIN0("TEST FAILURE: unable to get phase\n");
130 nsk_jvmti_setFailStatus();
131 NSK_BEFORE_TRACE(exit(nsk_jvmti_getStatus()));
132 }
133
134 if (!NSK_VERIFY(phase == JVMTI_PHASE_LIVE)) {
135 NSK_DISPLAY0(">>> Testcase #1: Add bootstrap class load segment(s) in VMDeath (live phase)\n");
136
137 // At first check that it is not possible to add anything other than an existing JAR file
138 checkLivePhaseForIllegalArgs(jvmti, "VMDeath()");
139
140 /* Check, that it is possible to add a JAR file containing a class that is already
141 * loaded (or is in the process of being loaded) by a _bootstrap_ class loader.
142 */
143
144 if (!addSegment(jvmti, segment1, "VMDeath()")) {
145 nsk_jvmti_setFailStatus();
146 NSK_BEFORE_TRACE(exit(nsk_jvmti_getStatus()));
147 }
148
149 if (use_segment2 == JNI_FALSE) return;
150 // otherwise add to classpath
151 if (!addSegment(jvmti, segment2, "VMDeath()")) {
152 nsk_jvmti_setFailStatus();
153 NSK_BEFORE_TRACE(exit(nsk_jvmti_getStatus()));
154 }
155 }
156 }
157
158 /** Agent library initialization. */
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)159 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
160 jvmtiEnv* jvmti;
161 const char *p_segment1, *p_segment2, *phase_to_check;
162
163 jvmti = NULL;
164 p_segment1 = p_segment2 = phase_to_check = NULL;
165
166 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
167 return JNI_ERR;
168
169 timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
170
171 p_segment1 = nsk_jvmti_findOptionStringValue("segment1", NULL);
172 if (!NSK_VERIFY(p_segment1 != NULL)) {
173 return JNI_ERR;
174 } else {
175 strncpy(segment1, p_segment1, (size_t) sizeof(segment1)/sizeof(char));
176 segment1[(size_t) sizeof(segment1)/sizeof(char) - 1] = 0;
177 }
178
179 // 'segment2' parameter is not mandatory
180 p_segment2 = nsk_jvmti_findOptionStringValue("segment2", NULL);
181 if (p_segment2 != NULL) {
182 strncpy(segment2, p_segment2, (size_t) sizeof(segment2)/sizeof(char));
183 segment2[(size_t) sizeof(segment2)/sizeof(char) - 1] = 0;
184 use_segment2 = JNI_TRUE;
185 }
186
187 if (!NSK_VERIFY((jvmti =
188 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
189 return JNI_ERR;
190
191 // Check what phase(s) we are going to test
192 phase_to_check = nsk_jvmti_findOptionStringValue("phasetocheck", NULL);
193 if (!NSK_VERIFY(phase_to_check != NULL)) {
194 return JNI_ERR;
195 } else if (strcmp(phase_to_check, "onload") == 0) {
196 jvmti_phase_to_check = JVMTI_PHASE_ONLOAD;
197 } else if (strcmp(phase_to_check, "live") == 0) {
198 jvmti_phase_to_check = JVMTI_PHASE_LIVE;
199 }
200
201 if (jvmti_phase_to_check == JVMTI_PHASE_ONLOAD) {
202 NSK_DISPLAY0(">>> Testcase #1: Add bootstrap class load segment in Agent_OnLoad()\n");
203 if (!addSegment(jvmti, segment1, "Agent_OnLoad()")) {
204 return JNI_ERR;
205 }
206
207 if (!addSegment(jvmti, segment2, "Agent_OnLoad()")) {
208 return JNI_ERR;
209 }
210
211 return JNI_OK;
212 }
213
214 /* For Live phase enable events and set callbacks for them */
215 NSK_DISPLAY1("Set callback for events: %s\n", "VM_INIT, VM_DEATH");
216 {
217 jvmtiEventCallbacks eventCallbacks;
218 memset(&eventCallbacks, 0, sizeof(eventCallbacks));
219
220 eventCallbacks.VMInit = callbackVMInit;
221 eventCallbacks.VMDeath = callbackVMDeath;
222
223 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetEventCallbacks, jvmti,
224 &eventCallbacks, sizeof(eventCallbacks)))) {
225 return JNI_ERR;
226 }
227 }
228 NSK_DISPLAY0(" ... set\n");
229
230 NSK_DISPLAY1("Enable events: %s\n", "VM_INIT, VM_DEATH");
231 {
232
233 jvmtiEvent eventsList[] = { JVMTI_EVENT_VM_INIT, JVMTI_EVENT_VM_DEATH };
234 if (!NSK_VERIFY(nsk_jvmti_enableEvents(
235 JVMTI_ENABLE, sizeof(eventsList)/sizeof(jvmtiEvent), eventsList, NULL))) {
236 return JNI_ERR;
237 }
238 }
239 NSK_DISPLAY0(" ... enabled\n");
240
241 return JNI_OK;
242 }
243
244 /* ============================================================================= */
245
246 #ifdef __cplusplus
247 }
248 #endif
249