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 "jvmti_common.h"
 28 
 29 extern "C" {
 30 
 31 
 32 #define PASSED 0
 33 #define STATUS_FAILED 2
 34 
 35 static jvmtiEnv *jvmti = NULL;
 36 static jvmtiCapabilities caps;
 37 static jint result = PASSED;
 38 static jboolean printdump = JNI_FALSE;
 39 
 40 
 41 jint Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
 42     jvmtiError err;
 43     jint res;
 44 
 45     if (options != NULL && strcmp(options, "printdump") == 0) {
 46         printdump = JNI_TRUE;
 47     }
 48 
 49     res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);
 50     if (res != JNI_OK || jvmti == NULL) {
 51         LOG("Wrong result of a valid call to GetEnv!\n");
 52         return JNI_ERR;
 53     }
 54 
 55     err = jvmti->GetPotentialCapabilities(&caps);
 56     if (err != JVMTI_ERROR_NONE) {
 57         LOG("(GetPotentialCapabilities) unexpected error: %s (%d)\n",
 58                TranslateError(err), err);
 59         return JNI_ERR;
 60     }
 61 
 62     err = jvmti->AddCapabilities(&caps);
 63     if (err != JVMTI_ERROR_NONE) {
 64         LOG("(AddCapabilities) unexpected error: %s (%d)\n",
 65                TranslateError(err), err);
 66         return JNI_ERR;
 67     }
 68 
 69     err = jvmti->GetCapabilities(&caps);
 70     if (err != JVMTI_ERROR_NONE) {
 71         LOG("(GetCapabilities) unexpected error: %s (%d)\n",
 72                TranslateError(err), err);
 73         return JNI_ERR;
 74     }
 75 
 76     if (!caps.can_suspend) {
 77         LOG("Warning: suspend/resume is not implemented\n");
 78     }
 79 
 80     return JNI_OK;
 81 }
 82 
 83 JNIEXPORT jint JNICALL
 84 Java_frameloc03_check(JNIEnv *env, jclass cls, jthread thr) {
 85     jvmtiError err;
 86     jmethodID mid;
 87     jlocation loc;
 88 
 89     if (jvmti == NULL) {
 90         LOG("JVMTI client was not properly loaded!\n");
 91         return STATUS_FAILED;
 92     }
 93 
 94     if (printdump == JNI_TRUE) {
 95         LOG(">>> invalid thread check ...\n");
 96     }
 97     err = jvmti->GetFrameLocation(cls, 0, &mid, &loc);
 98     if (err != JVMTI_ERROR_INVALID_THREAD) {
 99         LOG("Error expected: JVMTI_ERROR_INVALID_THREAD,\n");
100         LOG("        actual: %s (%d)\n", TranslateError(err), err);
101         result = STATUS_FAILED;
102     }
103 
104     if (!caps.can_suspend) {
105         return result;
106     }
107 
108     err = jvmti->SuspendThread(thr);
109     if (err != JVMTI_ERROR_NONE) {
110         LOG("(SuspendThread) unexpected error: %s (%d)\n",
111                TranslateError(err), err);
112         result = STATUS_FAILED;
113     }
114 
115     if (printdump == JNI_TRUE) {
116         LOG(">>> invalid depth check ...\n");
117     }
118     err = jvmti->GetFrameLocation(thr, -1, &mid, &loc);
119     if (err != JVMTI_ERROR_ILLEGAL_ARGUMENT) {
120         LOG("Error expected: JVMTI_ERROR_ILLEGAL_ARGUMENT,\n");
121         LOG("        actual: %s (%d)\n", TranslateError(err), err);
122         result = STATUS_FAILED;
123     }
124 
125     if (printdump == JNI_TRUE) {
126         LOG(">>> (methodPtr) null pointer check ...\n");
127     }
128     err = jvmti->GetFrameLocation(thr, 0, NULL, &loc);
129     if (err != JVMTI_ERROR_NULL_POINTER) {
130         LOG("Error expected: JVMTI_ERROR_NULL_POINTER,\n");
131         LOG("        actual: %s (%d)\n", TranslateError(err), err);
132         result = STATUS_FAILED;
133     }
134 
135     if (printdump == JNI_TRUE) {
136         LOG(">>> (locationPtr) null pointer check ...\n");
137     }
138     err = jvmti->GetFrameLocation(thr, 0, &mid, NULL);
139     if (err != JVMTI_ERROR_NULL_POINTER) {
140         LOG("Error expected: JVMTI_ERROR_NULL_POINTER,\n");
141         LOG("        actual: %s (%d)\n", TranslateError(err), err);
142         result = STATUS_FAILED;
143     }
144 
145     err = jvmti->ResumeThread(thr);
146     if (err != JVMTI_ERROR_NONE) {
147         LOG("(ResumeThread) unexpected error: %s (%d)\n",
148                TranslateError(err), err);
149         result = STATUS_FAILED;
150     }
151 
152     if (printdump == JNI_TRUE) {
153         LOG(">>> ... done\n");
154     }
155 
156     return result;
157 }
158 
159 }