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 #include "JVMTITools.h" 29 30 extern "C" { 31 32 33 #define PASSED 0 34 #define STATUS_FAILED 2 35 36 static jvmtiEnv *jvmti = NULL; 37 static jvmtiCapabilities caps; 38 static jvmtiEventCallbacks callbacks; 39 static jint result = PASSED; 40 static jmethodID mid1, mid2, mid3, mid4; 41 static jlong longVal = 22L; 42 static jfloat floatVal; 43 static jdouble doubleVal; 44 static jobject objVal; 45 static jobject arrVal; 46 47 void JNICALL Breakpoint(jvmtiEnv *jvmti_env, JNIEnv *env, 48 jthread thr, jmethodID method, jlocation location) { 49 jvmtiError err; 50 jmethodID mid; 51 jlocation loc; 52 jint entryCount; 53 jvmtiLocalVariableEntry *table = NULL; 54 int i; 55 56 err = jvmti_env->GetFrameLocation(thr, 1, &mid, &loc); 57 if (err != JVMTI_ERROR_NONE) { 58 printf("(GetFrameLocation) unexpected error: %s (%d)\n", 59 TranslateError(err), err); 60 result = STATUS_FAILED; 61 } 62 63 err = jvmti_env->GetLocalVariableTable(mid, 64 &entryCount, &table); 65 if (err != JVMTI_ERROR_NONE) { 66 printf("(GetLocalVariableTable) unexpected error: %s (%d)\n", 67 TranslateError(err), err); 68 return; 69 } 70 71 if (mid == mid1) { 72 for (i = 0; i < entryCount; i++) { 73 if (strcmp(table[i].name, "l") == 0) { 74 err = jvmti_env->SetLocalLong(thr, 1, 75 table[i].slot, longVal); 76 if (err != JVMTI_ERROR_NONE) { 77 printf("(SetLocalLong) unexpected error: %s (%d)\n", 78 TranslateError(err), err); 79 result = STATUS_FAILED; 80 } 81 } else if (strcmp(table[i].name, "f") == 0) { 82 err = jvmti_env->SetLocalFloat(thr, 1, 83 table[i].slot, floatVal); 84 if (err != JVMTI_ERROR_NONE) { 85 printf("(SetLocalFloat) unexpected error: %s (%d)\n", 86 TranslateError(err), err); 87 result = STATUS_FAILED; 88 } 89 } else if (strcmp(table[i].name, "d") == 0) { 90 err = jvmti_env->SetLocalDouble(thr, 1, 91 table[i].slot, doubleVal); 92 if (err != JVMTI_ERROR_NONE) { 93 printf("(SetLocalDouble) unexpected error: %s (%d)\n", 94 TranslateError(err), err); 95 result = STATUS_FAILED; 96 } 97 } 98 } 99 } else if (mid == mid2) { 100 for (i = 0; i < entryCount; i++) { 101 if (strcmp(table[i].name, "i1") == 0) { 102 err = jvmti_env->SetLocalInt(thr, 1, 103 table[i].slot, 1); 104 if (err != JVMTI_ERROR_NONE) { 105 printf("(SetLocalInt#i1) unexpected error: %s (%d)\n", 106 TranslateError(err), err); 107 result = STATUS_FAILED; 108 } 109 } else if (strcmp(table[i].name, "i2") == 0) { 110 err = jvmti_env->SetLocalInt(thr, 1, 111 table[i].slot, 1); 112 if (err != JVMTI_ERROR_NONE) { 113 printf("(SetLocalInt#i2) unexpected error: %s (%d)\n", 114 TranslateError(err), err); 115 result = STATUS_FAILED; 116 } 117 } else if (strcmp(table[i].name, "i3") == 0) { 118 err = jvmti_env->SetLocalInt(thr, 1, 119 table[i].slot, 1); 120 if (err != JVMTI_ERROR_NONE) { 121 printf("(SetLocalInt#i3) unexpected error: %s (%d)\n", 122 TranslateError(err), err); 123 result = STATUS_FAILED; 124 } 125 } else if (strcmp(table[i].name, "i4") == 0) { 126 err = jvmti_env->SetLocalInt(thr, 1, 127 table[i].slot, 1); 128 if (err != JVMTI_ERROR_NONE) { 129 printf("(SetLocalInt#i4) unexpected error: %s (%d)\n", 130 TranslateError(err), err); 131 result = STATUS_FAILED; 132 } 133 } else if (strcmp(table[i].name, "i5") == 0) { 134 err = jvmti_env->SetLocalInt(thr, 1, 135 table[i].slot, 1); 136 if (err != JVMTI_ERROR_NONE) { 137 printf("(SetLocalInt#i5) unexpected error: %s (%d)\n", 138 TranslateError(err), err); 139 result = STATUS_FAILED; 140 } 141 } 142 } 143 } else if (mid == mid3) { 144 for (i = 0; i < entryCount; i++) { 145 if (strcmp(table[i].name, "ob1") == 0) { 146 err = jvmti_env->SetLocalObject(thr, 1, 147 table[i].slot, objVal); 148 if (err != JVMTI_ERROR_NONE) { 149 printf("(SetLocalObject#ob1) unexpected error: %s (%d)\n", 150 TranslateError(err), err); 151 result = STATUS_FAILED; 152 } 153 } else if (strcmp(table[i].name, "ob2") == 0) { 154 err = jvmti_env->SetLocalObject(thr, 1, 155 table[i].slot, arrVal); 156 if (err != JVMTI_ERROR_NONE) { 157 printf("(SetLocalObject#ob2) unexpected error: %s (%d)\n", 158 TranslateError(err), err); 159 result = STATUS_FAILED; 160 } 161 } 162 } 163 } else if (mid == mid4) { 164 for (i = 0; i < entryCount; i++) { 165 if (strcmp(table[i].name, "i1") == 0) { 166 err = jvmti_env->SetLocalInt(thr, 1, 167 table[i].slot, 1); 168 if (err != JVMTI_ERROR_NONE) { 169 printf("(SetLocalInt#i1,param) unexpected error: %s (%d)\n", 170 TranslateError(err), err); 171 result = STATUS_FAILED; 172 } 173 } else if (strcmp(table[i].name, "i2") == 0) { 174 err = jvmti_env->SetLocalInt(thr, 1, 175 table[i].slot, 2); 176 if (err != JVMTI_ERROR_NONE) { 177 printf("(SetLocalInt#i2,param) unexpected error: %s (%d)\n", 178 TranslateError(err), err); 179 result = STATUS_FAILED; 180 } 181 } else if (strcmp(table[i].name, "i3") == 0) { 182 err = jvmti_env->SetLocalInt(thr, 1, 183 table[i].slot, 3); 184 if (err != JVMTI_ERROR_NONE) { 185 printf("(SetLocalInt#i3,param) unexpected error: %s (%d)\n", 186 TranslateError(err), err); 187 result = STATUS_FAILED; 188 } 189 } else if (strcmp(table[i].name, "i4") == 0) { 190 err = jvmti_env->SetLocalInt(thr, 1, 191 table[i].slot, 4); 192 if (err != JVMTI_ERROR_NONE) { 193 printf("(SetLocalInt#i4,param) unexpected error: %s (%d)\n", 194 TranslateError(err), err); 195 result = STATUS_FAILED; 196 } 197 } else if (strcmp(table[i].name, "b") == 0) { 198 err = jvmti_env->SetLocalInt(thr, 1, 199 table[i].slot, JNI_TRUE); 200 if (err != JVMTI_ERROR_NONE) { 201 printf("(SetLocalInt#b,param) unexpected error: %s (%d)\n", 202 TranslateError(err), err); 203 result = STATUS_FAILED; 204 } 205 } else if (strcmp(table[i].name, "l") == 0) { 206 err = jvmti_env->SetLocalLong(thr, 1, 207 table[i].slot, longVal); 208 if (err != JVMTI_ERROR_NONE) { 209 printf("(SetLocalLong,param) unexpected error: %s (%d)\n", 210 TranslateError(err), err); 211 result = STATUS_FAILED; 212 } 213 } else if (strcmp(table[i].name, "f") == 0) { 214 err = jvmti_env->SetLocalFloat(thr, 1, 215 table[i].slot, floatVal); 216 if (err != JVMTI_ERROR_NONE) { 217 printf("(SetLocalFloat,param) unexpected error: %s (%d)\n", 218 TranslateError(err), err); 219 result = STATUS_FAILED; 220 } 221 } else if (strcmp(table[i].name, "d") == 0) { 222 err = jvmti_env->SetLocalDouble(thr, 1, 223 table[i].slot, doubleVal); 224 if (err != JVMTI_ERROR_NONE) { 225 printf("(SetLocalDouble,param) unexpected error: %s (%d)\n", 226 TranslateError(err), err); 227 result = STATUS_FAILED; 228 } 229 } 230 } 231 } else { 232 printf("ERROR: didn't know where we got called from"); 233 result = STATUS_FAILED; 234 } 235 236 if (table != NULL) { 237 for (i = 0; i < entryCount; i++) { 238 jvmti_env->Deallocate((unsigned char*)table[i].name); 239 jvmti_env->Deallocate((unsigned char*)table[i].signature); 240 } 241 jvmti_env->Deallocate((unsigned char*)table); 242 } 243 } 244 245 #ifdef STATIC_BUILD 246 JNIEXPORT jint JNICALL Agent_OnLoad_setlocal001(JavaVM *jvm, char *options, void *reserved) { 247 return Agent_Initialize(jvm, options, reserved); 248 } 249 JNIEXPORT jint JNICALL Agent_OnAttach_setlocal001(JavaVM *jvm, char *options, void *reserved) { 250 return Agent_Initialize(jvm, options, reserved); 251 } 252 JNIEXPORT jint JNI_OnLoad_setlocal001(JavaVM *jvm, char *options, void *reserved) { 253 return JNI_VERSION_1_8; 254 } 255 #endif 256 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 257 jint res; 258 jvmtiError err; 259 260 res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1); 261 if (res != JNI_OK || jvmti == NULL) { 262 printf("Wrong result of a valid call to GetEnv !\n"); 263 return JNI_ERR; 264 } 265 266 err = jvmti->GetPotentialCapabilities(&caps); 267 if (err != JVMTI_ERROR_NONE) { 268 printf("(GetPotentialCapabilities) unexpected error: %s (%d)\n", 269 TranslateError(err), err); 270 return JNI_ERR; 271 } 272 273 err = jvmti->AddCapabilities(&caps); 274 if (err != JVMTI_ERROR_NONE) { 275 printf("(AddCapabilities) unexpected error: %s (%d)\n", 276 TranslateError(err), err); 277 return JNI_ERR; 278 } 279 280 err = jvmti->GetCapabilities(&caps); 281 if (err != JVMTI_ERROR_NONE) { 282 printf("(GetCapabilities) unexpected error: %s (%d)\n", 283 TranslateError(err), err); 284 return JNI_ERR; 285 } 286 287 if (!caps.can_access_local_variables) { 288 printf("Warning: access to local variables is not implemented\n"); 289 } else if (caps.can_generate_breakpoint_events) { 290 callbacks.Breakpoint = &Breakpoint; 291 err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)); 292 if (err != JVMTI_ERROR_NONE) { 293 printf("(SetEventCallbacks) unexpected error: %s (%d)\n", 294 TranslateError(err), err); 295 return JNI_ERR; 296 } 297 } else { 298 printf("Warning: Breakpoint event is not implemented\n"); 299 } 300 301 return JNI_OK; 302 } 303 304 JNIEXPORT void JNICALL 305 Java_nsk_jvmti_SetLocalVariable_setlocal001_getMethReady(JNIEnv *env, 306 jclass cls, jfloat f, jdouble d, jobject o, jobject a) { 307 jvmtiError err; 308 jmethodID mid; 309 310 if (jvmti == NULL) { 311 printf("JVMTI client was not properly loaded!\n"); 312 result = STATUS_FAILED; 313 return; 314 } 315 316 if (!caps.can_access_local_variables || 317 !caps.can_generate_breakpoint_events) return; 318 319 mid = env->GetStaticMethodID(cls, "checkPoint", "()V"); 320 mid1 = env->GetMethodID(cls, "meth01", "()D"); 321 mid2 = env->GetMethodID(cls, "meth02", "(I)V"); 322 mid3 = env->GetStaticMethodID(cls, "meth03", "()V"); 323 mid4 = env->GetStaticMethodID(cls, "meth04", "(IJSDCFBZ)V"); 324 if (mid == 0 || mid1 == 0 || mid2 == 0 || mid3 == 0 || mid4 == 0) { 325 printf("Cannot find Method ID for a method\n"); 326 } 327 floatVal = f; 328 doubleVal = d; 329 objVal = env->NewGlobalRef(o); 330 arrVal = env->NewGlobalRef(a); 331 332 err = jvmti->SetBreakpoint(mid, 0); 333 if (err != JVMTI_ERROR_NONE) { 334 printf("Failed to SetBreakpoint: %s (%d)\n", TranslateError(err), err); 335 result = STATUS_FAILED; 336 return; 337 } 338 339 err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, 340 JVMTI_EVENT_BREAKPOINT, NULL); 341 if (err != JVMTI_ERROR_NONE) { 342 printf("Failed to enable BREAKPOINT event: %s (%d)\n", 343 TranslateError(err), err); 344 result = STATUS_FAILED; 345 } 346 } 347 348 JNIEXPORT jint JNICALL 349 Java_nsk_jvmti_SetLocalVariable_setlocal001_getRes(JNIEnv *env, jclass cls) { 350 return result; 351 } 352 353 }