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 <stdlib.h> 25 #include <string.h> 26 #include "jvmti.h" 27 #include "agent_common.h" 28 #include "jni_tools.h" 29 #include "jvmti_tools.h" 30 31 extern "C" { 32 33 /* ============================================================================= */ 34 35 static jlong timeout = 0; 36 37 #define STATUS_FAIL 97 38 39 /* events */ 40 41 #define EVENTS_COUNT 2 42 static jvmtiEvent events[EVENTS_COUNT] = { 43 JVMTI_EVENT_VM_INIT, 44 JVMTI_EVENT_VM_DEATH 45 }; 46 47 /* storage data */ 48 49 #define STORAGE_DATA_SIZE 1024 50 #define STORAGE_DATA_CHAR 'X' 51 52 typedef struct _StorageStructure { 53 char data[STORAGE_DATA_SIZE]; 54 } StorageStructure; 55 56 static StorageStructure storageData; 57 static StorageStructure* initialStorage = &storageData; 58 59 /* ============================================================================= */ 60 61 /** Fill storage data with given char */ 62 static void fillEnvStorage(StorageStructure* storage) { 63 NSK_DISPLAY2("Fill storage data with char %c for size: %d bytes\n", 64 (char)STORAGE_DATA_CHAR, (int)STORAGE_DATA_SIZE); 65 memset(storage->data, STORAGE_DATA_CHAR, STORAGE_DATA_SIZE); 66 NSK_DISPLAY0(" ... ok\n"); 67 } 68 69 /** 70 * Set JVMTI environment local storage with given pinter. 71 * @returns NSK_FALSE if any error occured. 72 */ 73 static int setEnvStorage(jvmtiEnv* jvmti, StorageStructure* storage, const char where[]) { 74 75 NSK_DISPLAY1("Set local storage for current JVMTI env: 0x%p\n", (void*)storage); 76 if (!NSK_JVMTI_VERIFY(jvmti->SetEnvironmentLocalStorage(storage))) { 77 return NSK_FALSE; 78 } 79 NSK_DISPLAY0(" ... ok\n"); 80 return NSK_TRUE; 81 } 82 83 /** 84 * Check JVMTI environment local storage. 85 * @returns NSK_FALSE if any error occured. 86 */ 87 static int checkEnvStorage(jvmtiEnv* jvmti, StorageStructure* initialStorage, const char where[]) { 88 StorageStructure* storage = NULL; 89 90 NSK_DISPLAY0("Get local storage for current JVMTI env\n"); 91 if (!NSK_JVMTI_VERIFY(jvmti->GetEnvironmentLocalStorage((void**)&storage))) { 92 return NSK_FALSE; 93 } 94 NSK_DISPLAY1(" ... got storage: 0x%p\n", (void*)storage); 95 96 if (storage != initialStorage) { 97 NSK_COMPLAIN3("Wrong storage pointer returned for current JVMTI env in %s:\n" 98 "# got pointer: %p\n" 99 "# expected: %p\n", 100 where, 101 (void*)storage, (void*)initialStorage); 102 return NSK_FALSE; 103 } 104 105 { 106 int changed = 0; 107 int i; 108 109 for (i = 0; i < STORAGE_DATA_SIZE; i++) { 110 if (storage->data[i] != STORAGE_DATA_CHAR) { 111 changed++; 112 } 113 } 114 115 if (changed > 0) { 116 NSK_COMPLAIN3("Data changed in returned storage for current JVMTI env in %s:\n" 117 "# changed bytes: %d\n" 118 "# total bytes: %d\n", 119 where, 120 changed, STORAGE_DATA_SIZE); 121 return NSK_FALSE; 122 } 123 } 124 125 return NSK_TRUE; 126 } 127 128 /* ============================================================================= */ 129 130 /** Agent algorithm. */ 131 static void JNICALL 132 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 133 NSK_DISPLAY0("Wait for debugee to become ready\n"); 134 if (!nsk_jvmti_waitForSync(timeout)) 135 return; 136 137 { 138 NSK_DISPLAY0(">>> Testcase #0: Set env storage in agent thread()\n"); 139 if (!setEnvStorage(jvmti, initialStorage, "agent thread")) { 140 nsk_jvmti_setFailStatus(); 141 } 142 143 NSK_DISPLAY0("Let debugee to run\n"); 144 if (!nsk_jvmti_resumeSync()) 145 return; 146 NSK_DISPLAY0("Wait for debugee to run some code\n"); 147 if (!nsk_jvmti_waitForSync(timeout)) 148 return; 149 150 NSK_DISPLAY0(">>> Testcase #3: Check env storage in agent thread\n"); 151 if (!checkEnvStorage(jvmti, initialStorage, "agent thread")) { 152 nsk_jvmti_setFailStatus(); 153 } 154 } 155 156 NSK_DISPLAY0("Let debugee to finish\n"); 157 if (!nsk_jvmti_resumeSync()) 158 return; 159 } 160 161 /* ============================================================================= */ 162 163 /** 164 * Callback for VM_INIT event. 165 */ 166 JNIEXPORT void JNICALL 167 callbackVMInit(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) { 168 } 169 170 /** 171 * Callback for VM_DEATH event. 172 */ 173 JNIEXPORT void JNICALL 174 callbackVMDeath(jvmtiEnv* jvmti, JNIEnv* jni) { 175 int success = NSK_TRUE; 176 177 NSK_DISPLAY0(">>> Testcase #4: Check env storage in VM_DEATH callback\n"); 178 success = checkEnvStorage(jvmti, initialStorage, "VM_DEATH callback"); 179 180 NSK_DISPLAY1("Disable events: %d events\n", EVENTS_COUNT); 181 if (!nsk_jvmti_enableEvents(JVMTI_DISABLE, EVENTS_COUNT, events, NULL)) { 182 success = NSK_FALSE; 183 } else { 184 NSK_DISPLAY0(" ... disabled\n"); 185 } 186 187 if (!success) { 188 NSK_DISPLAY1("Exit with FAIL exit status: %d\n", STATUS_FAIL); 189 NSK_BEFORE_TRACE(exit(STATUS_FAIL)); 190 } 191 } 192 193 /* ============================================================================= */ 194 195 /** Agent library initialization. */ 196 #ifdef STATIC_BUILD 197 JNIEXPORT jint JNICALL Agent_OnLoad_setenvstor003(JavaVM *jvm, char *options, void *reserved) { 198 return Agent_Initialize(jvm, options, reserved); 199 } 200 JNIEXPORT jint JNICALL Agent_OnAttach_setenvstor003(JavaVM *jvm, char *options, void *reserved) { 201 return Agent_Initialize(jvm, options, reserved); 202 } 203 JNIEXPORT jint JNI_OnLoad_setenvstor003(JavaVM *jvm, char *options, void *reserved) { 204 return JNI_VERSION_1_8; 205 } 206 #endif 207 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 208 jvmtiEnv* jvmti = NULL; 209 210 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 211 return JNI_ERR; 212 213 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 214 215 if (!NSK_VERIFY((jvmti = 216 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 217 return JNI_ERR; 218 219 { 220 jvmtiEventCallbacks eventCallbacks; 221 222 memset(&eventCallbacks, 0, sizeof(eventCallbacks)); 223 eventCallbacks.VMInit = callbackVMInit; 224 eventCallbacks.VMDeath = callbackVMDeath; 225 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks)))) { 226 return JNI_ERR; 227 } 228 229 } 230 231 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 232 return JNI_ERR; 233 234 NSK_DISPLAY1(">>> Prepare storage data at pointer: 0x%p\n", initialStorage); 235 fillEnvStorage(initialStorage); 236 237 NSK_DISPLAY1("Enable events: %d events\n", EVENTS_COUNT); 238 if (nsk_jvmti_enableEvents(JVMTI_ENABLE, EVENTS_COUNT, events, NULL)) { 239 NSK_DISPLAY0(" ... enabled\n"); 240 } 241 242 return JNI_OK; 243 } 244 245 /* ============================================================================= */ 246 247 }