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