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 <stdio.h> 25 #include <string.h> 26 #include "jvmti.h" 27 #include "agent_common.h" 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 #ifndef JNI_ENV_ARG 34 35 #ifdef __cplusplus 36 #define JNI_ENV_ARG(x, y) y 37 #define JNI_ENV_ARG1(x) 38 #define JNI_ENV_PTR(x) x 39 #else 40 #define JNI_ENV_ARG(x,y) x, y 41 #define JNI_ENV_ARG1(x) x 42 #define JNI_ENV_PTR(x) (*x) 43 #endif 44 45 #endif 46 47 #define JVMTI_ENV_ARG JNI_ENV_ARG 48 #define JVMTI_ENV_ARG1 JNI_ENV_ARG1 49 #define JVMTI_ENV_PTR JNI_ENV_PTR 50 51 #define JVMTI_ERROR_CHECK(str,res) if ( res != JVMTI_ERROR_NONE) { printf(str); printf("%d\n",res); return res;} 52 #define JVMTI_ERROR_CHECK_EXPECTED_ERROR(str,res,err) if ( res != err) { printf(str); printf("unexpected error %d\n",res); return res;} 53 54 #define JVMTI_ERROR_CHECK_VOID(str,res) if ( res != JVMTI_ERROR_NONE) { printf(str); printf("%d\n",res); iGlobalStatus = 2; } 55 56 #define JVMTI_ERROR_CHECK_EXPECTED_ERROR_VOID(str,res,err) if ( res != err) { printf(str); printf("unexpected error %d\n",res); iGlobalStatus = 2; } 57 58 #define THREADS_LIMIT 2000 59 60 61 jvmtiEnv *jvmti; 62 jint iGlobalStatus = 0; 63 jthread susp_thrd[THREADS_LIMIT]; 64 static jvmtiEventCallbacks callbacks; 65 static jvmtiCapabilities jvmti_caps; 66 jrawMonitorID jraw_monitor[20]; 67 int process_once = 0; 68 69 /* forward decl */ 70 void print_method_name(jmethodID mid); 71 72 int printdump = 0; 73 74 75 void debug_printf(const char *fmt, ...) { 76 va_list args; 77 78 va_start(args, fmt); 79 if (printdump) { 80 vprintf(fmt, args); 81 } 82 va_end(args); 83 } 84 85 void JNICALL vmInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) { 86 debug_printf("VMInit event\n"); 87 } 88 89 void JNICALL vmExit(jvmtiEnv *jvmti_env, JNIEnv *env) { 90 debug_printf("VMDeath event\n"); 91 } 92 93 typedef jclass (*findLoadClass_type) (JNIEnv *env, jobject loader, jstring name); 94 95 findLoadClass_type findLoadedClass_func; 96 97 JNIEXPORT jclass JNICALL 98 my_findLoadedClass(JNIEnv *env, jobject loader, jstring name) { 99 const char* sname = env->GetStringUTFChars(name, NULL); 100 debug_printf("Intercepted findLoadedClass, name = %s\n", sname); 101 return (*findLoadedClass_func)(env, loader, name); 102 } 103 104 void JNICALL testNativeMethodBind(jvmtiEnv* jvmti_env, JNIEnv *jni_env, 105 jthread thread, jmethodID mid, void* func, void** func_ptr) { 106 jvmtiPhase phase; 107 char *mname; 108 char *signature; 109 jint ret; 110 111 ret = jvmti_env->GetPhase(&phase); 112 if (ret != JVMTI_ERROR_NONE) { 113 printf("Error: GetPhase %d\n", ret); 114 iGlobalStatus = 2; 115 return; 116 } 117 118 if (phase != JVMTI_PHASE_START && phase != JVMTI_PHASE_LIVE) 119 return; 120 121 debug_printf("bind event: \n"); 122 print_method_name(mid); 123 124 ret = jvmti_env->GetMethodName(mid, &mname, &signature, NULL); 125 if (ret == JVMTI_ERROR_NONE) { 126 if (strcmp(mname, "findLoadedClass") == 0) { 127 findLoadedClass_func = (findLoadClass_type)func; 128 *func_ptr = (void*)my_findLoadedClass; 129 debug_printf("REDIRECTED findLoadedClass\n"); 130 } 131 } 132 } 133 134 135 136 void init_callbacks() { 137 memset((void *)&callbacks, 0, sizeof(jvmtiEventCallbacks)); 138 callbacks.VMInit = vmInit; 139 callbacks.VMDeath = vmExit; 140 callbacks.NativeMethodBind = testNativeMethodBind; 141 } 142 143 144 #ifdef STATIC_BUILD 145 JNIEXPORT jint JNICALL Agent_OnLoad_JvmtiTest(JavaVM *jvm, char *options, void *reserved) { 146 return Agent_Initialize(jvm, options, reserved); 147 } 148 JNIEXPORT jint JNICALL Agent_OnAttach_JvmtiTest(JavaVM *jvm, char *options, void *reserved) { 149 return Agent_Initialize(jvm, options, reserved); 150 } 151 JNIEXPORT jint JNI_OnLoad_JvmtiTest(JavaVM *jvm, char *options, void *reserved) { 152 return JNI_VERSION_1_8; 153 } 154 #endif 155 jint Agent_Initialize(JavaVM * jvm, char *options, void *reserved) { 156 jint res; 157 158 if (options && strlen(options) > 0) { 159 if (strstr(options, "printdump")) { 160 printdump = 1; 161 } 162 } 163 164 res = JNI_ENV_PTR(jvm)-> 165 GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), JVMTI_VERSION_1_1); 166 if (res < 0) { 167 printf("Wrong result of a valid call to GetEnv!\n"); 168 return JNI_ERR; 169 } 170 171 172 /* Add capabilities */ 173 res = JVMTI_ENV_PTR(jvmti)->GetPotentialCapabilities(JVMTI_ENV_ARG(jvmti, &jvmti_caps)); 174 JVMTI_ERROR_CHECK("GetPotentialCapabilities returned error", res); 175 176 res = JVMTI_ENV_PTR(jvmti)->AddCapabilities(JVMTI_ENV_ARG(jvmti, &jvmti_caps)); 177 JVMTI_ERROR_CHECK("AddCapabilities returned error", res); 178 179 /* Enable events */ 180 init_callbacks(); 181 res = JVMTI_ENV_PTR(jvmti)->SetEventCallbacks(JVMTI_ENV_ARG(jvmti, &callbacks), sizeof(callbacks)); 182 JVMTI_ERROR_CHECK("SetEventCallbacks returned error", res); 183 184 res = JVMTI_ENV_PTR(jvmti)->SetEventNotificationMode(JVMTI_ENV_ARG(jvmti,JVMTI_ENABLE),JVMTI_EVENT_VM_INIT,NULL); 185 JVMTI_ERROR_CHECK("SetEventNotificationMode for VM_INIT returned error", res); 186 187 res = JVMTI_ENV_PTR(jvmti)->SetEventNotificationMode(JVMTI_ENV_ARG(jvmti,JVMTI_ENABLE),JVMTI_EVENT_VM_DEATH,NULL); 188 JVMTI_ERROR_CHECK("SetEventNotificationMode for vm death event returned error", res); 189 190 res = JVMTI_ENV_PTR(jvmti)->SetEventNotificationMode(JVMTI_ENV_ARG(jvmti,JVMTI_ENABLE),JVMTI_EVENT_NATIVE_METHOD_BIND,NULL); 191 JVMTI_ERROR_CHECK("SetEventNotificationMode for native method bind event returned error", res); 192 193 return JNI_OK; 194 } 195 196 197 JNIEXPORT jint JNICALL 198 Java_nsk_jvmti_unit_MethodBind_JvmtiTest_GetResult(JNIEnv * env, jclass cls) { 199 return iGlobalStatus; 200 } 201 202 203 JNIEXPORT void JNICALL 204 Java_nsk_jvmti_unit_MethodBind_JvmtiTest_CreateRawMonitor(JNIEnv * env, jclass cls, jint i) { 205 jvmtiError ret; 206 char sz[128]; 207 208 sprintf(sz, "Rawmonitor-%d",i); 209 debug_printf("jvmti create raw monitor \n"); 210 ret = JVMTI_ENV_PTR(jvmti)->CreateRawMonitor(JVMTI_ENV_ARG(jvmti, sz), &jraw_monitor[i]); 211 212 if (ret != JVMTI_ERROR_NONE) { 213 printf("Error: ForceGarbageCollection %d \n", ret); 214 iGlobalStatus = 2; 215 } 216 } 217 218 JNIEXPORT void JNICALL 219 Java_nsk_jvmti_unit_MethodBind_JvmtiTest_RawMonitorEnter(JNIEnv * env, jclass cls, jint i) { 220 jvmtiError ret; 221 222 debug_printf("jvmti Raw monitor enter \n"); 223 ret = JVMTI_ENV_PTR(jvmti)->RawMonitorEnter(JVMTI_ENV_ARG(jvmti, jraw_monitor[i])); 224 225 if (ret != JVMTI_ERROR_NONE) { 226 printf("Error: Raw monitor enter %d \n", ret); 227 iGlobalStatus = 2; 228 } 229 } 230 231 JNIEXPORT void JNICALL 232 Java_nsk_jvmti_unit_MethodBind_JvmtiTest_RawMonitorExit(JNIEnv * env, jclass cls, jint i) { 233 jvmtiError ret; 234 235 debug_printf("jvmti raw monitor exit \n"); 236 ret = JVMTI_ENV_PTR(jvmti)->RawMonitorExit(JVMTI_ENV_ARG(jvmti, jraw_monitor[i])); 237 238 if (ret != JVMTI_ERROR_NONE) { 239 printf("Error: RawMonitorExit %d \n", ret); 240 iGlobalStatus = 2; 241 } 242 } 243 244 JNIEXPORT void JNICALL 245 Java_nsk_jvmti_unit_MethodBind_JvmtiTest_RawMonitorWait(JNIEnv * env, jclass cls, jint i) { 246 jvmtiError ret; 247 248 debug_printf("jvmti RawMonitorWait \n"); 249 ret = JVMTI_ENV_PTR(jvmti)->RawMonitorWait(JVMTI_ENV_ARG(jvmti, jraw_monitor[i]), -1); 250 251 if (ret != JVMTI_ERROR_NONE) { 252 printf("Error: RawMonitorWait %d \n", ret); 253 iGlobalStatus = 2; 254 } 255 } 256 257 JNIEXPORT void JNICALL 258 Java_nsk_jvmti_unit_MethodBind_JvmtiTest_RawMonitorNotify(JNIEnv * env, jclass cls, jint i) { 259 jvmtiError ret; 260 261 debug_printf("jvmti RawMonitorNotify \n"); 262 ret = JVMTI_ENV_PTR(jvmti)->RawMonitorNotifyAll(JVMTI_ENV_ARG(jvmti, jraw_monitor[i])); 263 264 if (ret != JVMTI_ERROR_NONE) { 265 printf("Error: RawMonitorNotify %d \n", ret); 266 iGlobalStatus = 2; 267 } 268 } 269 270 JNIEXPORT int JNICALL 271 Java_nsk_jvmti_unit_MethodBind_JvmtiTest_GetFrameCount(JNIEnv * env, jclass cls, jobject thr) { 272 jvmtiError ret; 273 jint count; 274 275 debug_printf("jvmti GetFrameCount \n"); 276 ret = JVMTI_ENV_PTR(jvmti)->GetFrameCount(JVMTI_ENV_ARG(jvmti, (jthread)thr), &count); 277 if (ret != JVMTI_ERROR_NONE) { 278 printf("Error: GetFrameCount returned %d \n", ret); 279 iGlobalStatus = 2; 280 } 281 return count; 282 } 283 284 void 285 print_method_name(jmethodID mid) { 286 jvmtiError ret; 287 jclass klass; 288 char *mname; 289 char *signature; 290 char *clname = (char*) "unknown"; 291 ret = JVMTI_ENV_PTR(jvmti)->GetMethodDeclaringClass(JVMTI_ENV_ARG(jvmti, mid), &klass); 292 if (ret != JVMTI_ERROR_NONE) { 293 printf("Error: GetMethodDeclaringClass %d \n", ret); 294 iGlobalStatus = 2; 295 return; 296 } 297 298 ret = JVMTI_ENV_PTR(jvmti)->GetClassSignature(JVMTI_ENV_ARG(jvmti, klass), &clname, NULL); 299 if (ret != JVMTI_ERROR_NONE) { 300 printf("Error: GetClassSignature %d \n", ret); 301 iGlobalStatus = 2; 302 return; 303 } 304 305 ret = JVMTI_ENV_PTR(jvmti)->GetMethodName(JVMTI_ENV_ARG(jvmti, mid), &mname, &signature, NULL); 306 if (ret != JVMTI_ERROR_NONE) { 307 printf("Error: GetMethodName %d \n", ret); 308 iGlobalStatus = 2; 309 return; 310 } 311 312 debug_printf("%s::%s(%s)\n", clname, mname, signature); 313 } 314 315 316 JNIEXPORT void JNICALL 317 Java_nsk_jvmti_unit_MethodBind_JvmtiTest_GetStackTrace(JNIEnv * env, jclass cls, jobject thr) { 318 jvmtiError ret; 319 jvmtiFrameInfo *stack_buffer = NULL; 320 jint max_count = 20; 321 jint count; 322 323 324 ret = JVMTI_ENV_PTR(jvmti)->Allocate(JVMTI_ENV_ARG(jvmti, sizeof(jvmtiFrameInfo) * max_count), (unsigned char**)&stack_buffer); 325 if (ret != JVMTI_ERROR_NONE) { 326 printf("Error: Allocate failed with %d \n", ret); 327 iGlobalStatus = 2; 328 } 329 330 ret = JVMTI_ENV_PTR(jvmti)->GetStackTrace(JVMTI_ENV_ARG(jvmti, thr), 0, max_count , stack_buffer, &count); 331 if (ret != JVMTI_ERROR_NONE) { 332 printf("Error: GetStackTrace %d \n", ret); 333 iGlobalStatus = 2; 334 } 335 336 ret = JVMTI_ENV_PTR(jvmti)->Deallocate(JVMTI_ENV_ARG(jvmti, (unsigned char *)stack_buffer)); 337 if (ret != JVMTI_ERROR_NONE) { 338 printf("Error: Deallocate failed with %d \n", ret); 339 iGlobalStatus = 2; 340 } 341 342 343 } 344 345 JNIEXPORT void JNICALL 346 Java_nsk_jvmti_unit_MethodBind_JvmtiTest_SaveThreadInfo(JNIEnv * env, jclass cls, jobject oobj) { 347 348 } 349 350 #ifdef __cplusplus 351 } 352 #endif