1 /*
  2  * Copyright (c) 2003, 2020, 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 "jvmti_common.h"
 28 
 29 extern "C" {
 30 
 31 #define PASSED 0
 32 #define STATUS_FAILED 2
 33 
 34 typedef struct {
 35   const char *cls_sig;
 36   const char *name;
 37   const char *sig;
 38   jlocation loc;
 39 } frame_info;
 40 
 41 static jvmtiEnv *jvmti_env = NULL;
 42 static jint result = PASSED;
 43 static frame_info fi =
 44     {"Lframeloc02;", "check",
 45         "(Ljava/lang/Thread;)I", -1};
 46 
 47 jint Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
 48   jint res = jvm->GetEnv((void **) &jvmti_env, JVMTI_VERSION_1_1);
 49   if (res != JNI_OK || jvmti_env == NULL) {
 50     LOG("Wrong result of a valid call to GetEnv!\n");
 51     return JNI_ERR;
 52   }
 53 
 54   return JNI_OK;
 55 }
 56 
 57 JNIEXPORT jint JNICALL
 58 Java_frameloc02_check(JNIEnv *env, jclass cls, jthread thr) {
 59   jvmtiError err;
 60   jclass klass;
 61   jmethodID mid;
 62   jlocation loc;
 63   char *cls_sig, *name, *sig, *generic;
 64   char buffer[32];
 65 
 66   LOG(">>> acquiring frame location ...\n");
 67 
 68   err = jvmti_env->GetFrameLocation(thr, 0, &mid, &loc);
 69   if (err != JVMTI_ERROR_NONE) {
 70     LOG("(GetFrameLocation) unexpected error: %s (%d)\n", TranslateError(err), err);
 71     result = STATUS_FAILED;
 72     return result;
 73   }
 74 
 75   LOG(">>> retrieving class/method info ...\n");
 76 
 77   err = jvmti_env->GetMethodDeclaringClass(mid, &klass);
 78   if (err != JVMTI_ERROR_NONE) {
 79     LOG("(GetMethodDeclaringClass) unexpected error: %s (%d)\n", TranslateError(err), err);
 80     result = STATUS_FAILED;
 81     return result;
 82   }
 83   err = jvmti_env->GetClassSignature(klass, &cls_sig, &generic);
 84   if (err != JVMTI_ERROR_NONE) {
 85     LOG("(GetClassSignature) unexpected error: %s (%d)\n", TranslateError(err), err);
 86     result = STATUS_FAILED;
 87     return result;
 88   }
 89   err = jvmti_env->GetMethodName(mid, &name, &sig, &generic);
 90   if (err != JVMTI_ERROR_NONE) {
 91     LOG("(GetMethodName) unexpected error: %s (%d)\n", TranslateError(err), err);
 92     result = STATUS_FAILED;
 93     return result;
 94   }
 95 
 96   LOG(">>>      class: \"%s\"\n", cls_sig);
 97   LOG(">>>     method: \"%s%s\"\n", name, sig);
 98   LOG(">>>   location: %s\n", jlong_to_string(loc, buffer));
 99 
100   if (cls_sig == NULL || strcmp(cls_sig, fi.cls_sig) != 0) {
101     LOG("(GetFrameLocation) wrong class: \"%s\"\n", cls_sig);
102     LOG(", expected: \"%s\"\n", fi.cls_sig);
103     result = STATUS_FAILED;
104   }
105   if (name == NULL || strcmp(name, fi.name) != 0) {
106     LOG("(GetFrameLocation) wrong method name: \"%s\"", name);
107     LOG(", expected: \"%s\"\n", fi.name);
108     result = STATUS_FAILED;
109   }
110   if (sig == NULL || strcmp(sig, fi.sig) != 0) {
111     LOG("(GetFrameLocation) wrong method signature: \"%s\"", sig);
112     LOG(", expected: \"%s\"\n", fi.sig);
113     result = STATUS_FAILED;
114   }
115   if (loc != fi.loc) {
116     LOG("(GetFrameLocation) wrong location: %s", jlong_to_string(loc, buffer));
117     LOG(", expected: %s\n", jlong_to_string(fi.loc, buffer));
118     result = STATUS_FAILED;
119   }
120 
121   LOG(">>> ... done\n");
122 
123   return result;
124 }
125 
126 }