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 }