1 /* 2 * Copyright (c) 2004, 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 <string.h> 25 #include <stdlib.h> 26 #include "jvmti.h" 27 #include "agent_common.h" 28 #include "jni_tools.h" 29 #include "jvmti_tools.h" 30 #include "JVMTITools.h" 31 #include "nsk_list.h" 32 #include "nsk_mutex.h" 33 34 extern "C" { 35 36 /* ============================================================================= */ 37 38 /* scaffold objects */ 39 static jvmtiEnv *jvmti = NULL; 40 static jlong timeout = 0; 41 const void *plist = NULL; 42 43 #define NAME_LENGTH 50 44 45 typedef struct nsk_jvmti_DCG_paramsStruct { 46 char name[NAME_LENGTH]; 47 const void *address; 48 jint length; 49 int sign; 50 } nsk_jvmti_DCG_params; 51 52 static MUTEX* mutex = NULL; 53 54 /* ============================================================================= */ 55 56 /* callbacks */ 57 void JNICALL 58 cbDynamicCodeGenerated1(jvmtiEnv *jvmti_env, const char *name, 59 const void *address, jint length) { 60 nsk_jvmti_DCG_params *rec; 61 int b; 62 63 rec = (nsk_jvmti_DCG_params *)malloc(sizeof(nsk_jvmti_DCG_params)); 64 strncpy(rec->name, name, NAME_LENGTH); 65 rec->name[NAME_LENGTH - 1] = '\0'; 66 rec->address = address; 67 rec->length = length; 68 rec->sign = 0; 69 70 NSK_DISPLAY3("received: 0x%p %7d %s\n", rec->address, rec->length, rec->name); 71 72 MUTEX_acquire(mutex); 73 74 b = NSK_VERIFY(nsk_list_add(plist, rec)); 75 76 MUTEX_release(mutex); 77 78 if (!b) { 79 nsk_jvmti_setFailStatus(); 80 free((void *)rec); 81 } 82 } 83 84 void JNICALL 85 cbDynamicCodeGenerated2(jvmtiEnv *jvmti_env, const char *name, 86 const void *address, jint length) { 87 88 int i; 89 nsk_jvmti_DCG_params *rec; 90 int count = nsk_list_getCount(plist); 91 int compLength = NAME_LENGTH - 1; 92 93 for (i = 0; i < count; i ++) { 94 rec = (nsk_jvmti_DCG_params *)nsk_list_get(plist, i); 95 if ((rec->address == address) && (rec->length == length)) { 96 rec->sign = 1; 97 NSK_DISPLAY3("checked: 0x%p %7d %s\n", rec->address, rec->length, 98 rec->name); 99 if (strncmp(rec->name, name, compLength)!=0) { 100 NSK_DISPLAY2("\t<%s> was renamed to <%s>\n", rec->name, name); 101 } 102 return; 103 } 104 105 } 106 NSK_DISPLAY3("NOT FOUND: 0x%p %7d %s\n", address, length, name); 107 108 } 109 110 /* ============================================================================= */ 111 112 static int 113 enableEvent(jvmtiEventMode enable, jvmtiEvent event) { 114 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(enable, event, NULL))) { 115 nsk_jvmti_setFailStatus(); 116 return NSK_FALSE; 117 } 118 119 return NSK_TRUE; 120 } 121 122 int setCallBacks(int stage) { 123 124 jvmtiEventCallbacks eventCallbacks; 125 memset(&eventCallbacks, 0, sizeof(eventCallbacks)); 126 127 eventCallbacks.DynamicCodeGenerated = (stage == 1) ? 128 cbDynamicCodeGenerated1 : cbDynamicCodeGenerated2; 129 130 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks)))) 131 return NSK_FALSE; 132 133 return NSK_TRUE; 134 } 135 136 /* ============================================================================= */ 137 138 /** Agent algorithm. */ 139 static void JNICALL 140 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { 141 142 NSK_DISPLAY0("Wait for debuggee to become ready\n"); 143 if (!nsk_jvmti_waitForSync(timeout)) 144 return; 145 146 /* stage 2 */ 147 if (!setCallBacks(2)) { 148 return; 149 } 150 151 if (!NSK_JVMTI_VERIFY(jvmti->GenerateEvents(JVMTI_EVENT_DYNAMIC_CODE_GENERATED))) 152 nsk_jvmti_setFailStatus(); 153 154 { 155 int i; 156 const nsk_jvmti_DCG_params *rec; 157 int count = nsk_list_getCount(plist); 158 159 for (i = 0; i < count; i++) { 160 rec = (const nsk_jvmti_DCG_params *)nsk_list_get(plist, 0); 161 if (!rec->sign) { 162 NSK_COMPLAIN3("missed event for\n\t0x%p %7d %s\n", rec->address, rec->length, rec->name); 163 nsk_jvmti_setFailStatus(); 164 } 165 free((void *)rec); 166 nsk_list_remove(plist, 0); 167 } 168 169 } 170 171 NSK_DISPLAY0("Let debuggee to finish\n"); 172 if (!nsk_jvmti_resumeSync()) 173 return; 174 175 } 176 177 /* ============================================================================= */ 178 179 /** Agent library initialization. */ 180 #ifdef STATIC_BUILD 181 JNIEXPORT jint JNICALL Agent_OnLoad_em04t001(JavaVM *jvm, char *options, void *reserved) { 182 return Agent_Initialize(jvm, options, reserved); 183 } 184 JNIEXPORT jint JNICALL Agent_OnAttach_em04t001(JavaVM *jvm, char *options, void *reserved) { 185 return Agent_Initialize(jvm, options, reserved); 186 } 187 JNIEXPORT jint JNI_OnLoad_em04t001(JavaVM *jvm, char *options, void *reserved) { 188 return JNI_VERSION_1_8; 189 } 190 #endif 191 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 192 193 mutex = MUTEX_create(); 194 if (!mutex) 195 return JNI_ERR; 196 197 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 198 return JNI_ERR; 199 200 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 201 202 jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved); 203 if (!NSK_VERIFY(jvmti != NULL)) 204 return JNI_ERR; 205 206 plist = (const void *)nsk_list_create(); 207 if (!NSK_VERIFY(plist != NULL)) 208 return JNI_ERR; 209 210 NSK_DISPLAY1("plist = 0x%p\n", plist); 211 212 if (!setCallBacks(1)) { 213 return JNI_ERR; 214 } 215 216 if (!enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT) 217 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH) 218 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_DYNAMIC_CODE_GENERATED)) { 219 return JNI_ERR; 220 } 221 222 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 223 return JNI_ERR; 224 225 return JNI_OK; 226 } 227 228 /* ============================================================================= */ 229 230 JNIEXPORT void JNICALL 231 #ifdef STATIC_BUILD 232 Agent_OnUnload_em04t001(JavaVM *jvm) 233 #else 234 Agent_OnUnload(JavaVM *jvm) 235 #endif 236 { 237 238 if (!NSK_VERIFY(nsk_list_destroy(plist))) { 239 nsk_jvmti_setFailStatus(); 240 } 241 242 if (mutex) { 243 MUTEX_destroy(mutex); 244 mutex = NULL; 245 } 246 } 247 248 }