1 /*
   2  * Copyright (c) 2007, 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 #ifdef __cplusplus
  31 extern "C" {
  32 #endif
  33 
  34 #ifndef JNI_ENV_ARG
  35 
  36 #ifdef __cplusplus
  37 #define JNI_ENV_ARG(x, y) y
  38 #define JNI_ENV_PTR(x) x
  39 #else
  40 #define JNI_ENV_ARG(x,y) x, y
  41 #define JNI_ENV_PTR(x) (*x)
  42 #endif
  43 
  44 #endif
  45 
  46 #define PASSED 0
  47 #define STATUS_FAILED 2
  48 
  49 static jvmtiCapabilities caps;
  50 static jvmtiEventCallbacks callbacks;
  51 
  52 #define RETURN_FAILED errCode = STATUS_FAILED; fflush(0); return
  53 
  54 static jint      errCode       = PASSED;
  55 static jvmtiEnv *jvmti         = NULL;
  56 static jmethodID midCheckPoint = NULL;
  57 
  58 
  59 JNIEXPORT void JNICALL
  60 Java_nsk_jvmti_unit_GetConstantPool_getcpool001_getCP(
  61     JNIEnv *env, jclass c, jint id, jclass cls) {
  62     jvmtiError    err;
  63     int           idx          = 0;
  64     int           rep          = 0;
  65     jint          cp_cnt       = 0;
  66     jint          cp_bytes_cnt = 0;
  67     unsigned char *cp_bytes    = NULL;
  68 
  69     err = jvmti->GetConstantPool(cls, &cp_cnt, &cp_bytes_cnt, &cp_bytes);
  70     if (err != JVMTI_ERROR_NONE) {
  71         printf("(GetConstantPool) unexpected error: %s (%d)\n",
  72                TranslateError(err), err);
  73         RETURN_FAILED;
  74     }
  75 
  76     /* Print Constant Pool attrs*/
  77     printf("getCP: id = %d, cnt = %03d, bytes_cnt = %04d\n",
  78             id, cp_cnt, cp_bytes_cnt);
  79     fflush(0);
  80 }
  81 
  82 void JNICALL Breakpoint(jvmtiEnv *jvmti_env, JNIEnv *env,
  83         jthread thread, jmethodID method, jlocation location) {
  84     jvmtiError     err;
  85 
  86     if (midCheckPoint != method) {
  87         printf("bp: don't know where we get called from");
  88         RETURN_FAILED;
  89     }
  90 
  91     printf(">>> breakpoint in checkPoint\n");
  92 
  93     err = jvmti_env->ClearBreakpoint(midCheckPoint, 0);
  94     if (err != JVMTI_ERROR_NONE) {
  95         printf("(ClearBreakpoint) unexpected error: %s (%d)\n",
  96                TranslateError(err), err);
  97         RETURN_FAILED;
  98     }
  99     fflush(0);
 100 }
 101 
 102 #ifdef STATIC_BUILD
 103 JNIEXPORT jint JNICALL Agent_OnLoad_getcpool001(JavaVM *jvm, char *options, void *reserved) {
 104     return Agent_Initialize(jvm, options, reserved);
 105 }
 106 JNIEXPORT jint JNICALL Agent_OnAttach_getcpool001(JavaVM *jvm, char *options, void *reserved) {
 107     return Agent_Initialize(jvm, options, reserved);
 108 }
 109 JNIEXPORT jint JNI_OnLoad_getcpool001(JavaVM *jvm, char *options, void *reserved) {
 110     return JNI_VERSION_1_8;
 111 }
 112 #endif
 113 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 114     jvmtiError err;
 115     jint res;
 116 
 117     res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
 118         JVMTI_VERSION_1_1);
 119     if (res != JNI_OK || jvmti == NULL) {
 120         printf("Wrong result of a valid call to GetEnv!\n");
 121         return JNI_ERR;
 122     }
 123 
 124     err = jvmti->GetPotentialCapabilities(&caps);
 125     if (err != JVMTI_ERROR_NONE) {
 126         printf("(GetPotentialCapabilities) unexpected error: %s (%d)\n",
 127                TranslateError(err), err);
 128         return JNI_ERR;
 129     }
 130 
 131     err = jvmti->AddCapabilities(&caps);
 132     if (err != JVMTI_ERROR_NONE) {
 133         printf("(AddCapabilities) unexpected error: %s (%d)\n",
 134                TranslateError(err), err);
 135         return JNI_ERR;
 136     }
 137 
 138     err = jvmti->GetCapabilities(&caps);
 139     if (err != JVMTI_ERROR_NONE) {
 140         printf("(GetCapabilities) unexpected error: %s (%d)\n",
 141                TranslateError(err), err);
 142         return JNI_ERR;
 143     }
 144 
 145     if (!caps.can_force_early_return) {
 146         printf("Warning: GetConstantPool is not implemented\n");
 147     }
 148 
 149     if (caps.can_generate_breakpoint_events &&
 150             caps.can_generate_single_step_events) {
 151         callbacks.Breakpoint = &Breakpoint;
 152         err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
 153         if (err != JVMTI_ERROR_NONE) {
 154             printf("(SetEventCallbacks) unexpected error: %s (%d)\n",
 155                    TranslateError(err), err);
 156             return JNI_ERR;
 157         }
 158     }
 159 
 160     return JNI_OK;
 161 }
 162 
 163 JNIEXPORT void JNICALL
 164 Java_nsk_jvmti_unit_GetConstantPool_getcpool001_getReady(
 165     JNIEnv *env, jclass c, jclass cls) {
 166     jvmtiError err;
 167 
 168     if (jvmti == NULL) {
 169         printf("JVMTI client was not properly loaded!\n");
 170         RETURN_FAILED;
 171     }
 172 
 173     if (!caps.can_force_early_return ||
 174         !caps.can_generate_breakpoint_events ||
 175         !caps.can_generate_single_step_events) {
 176         return;
 177     }
 178 
 179     midCheckPoint = JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG(env, cls),
 180          "checkPoint", "()V");
 181     if (midCheckPoint == NULL) {
 182         printf("Cannot find Method ID for method checkPoint\n");
 183         RETURN_FAILED;
 184     }
 185 
 186     err = jvmti->SetBreakpoint(midCheckPoint, 0);
 187     if (err != JVMTI_ERROR_NONE) {
 188         printf("(SetBreakpoint) unexpected error: %s (%d)\n",
 189                TranslateError(err), err);
 190         RETURN_FAILED;
 191     }
 192 
 193     err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
 194         JVMTI_EVENT_BREAKPOINT, NULL);
 195     if (err != JVMTI_ERROR_NONE) {
 196         printf("Failed to enable BREAKPOINT event: %s (%d)\n",
 197                TranslateError(err), err);
 198         RETURN_FAILED;
 199     }
 200 
 201 }
 202 
 203 JNIEXPORT jint JNICALL
 204 Java_nsk_jvmti_unit_GetConstantPool_getcpool001_check(JNIEnv *env, jclass cls) {
 205     return errCode;
 206 }
 207 
 208 #ifdef __cplusplus
 209 }
 210 #endif