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