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 jint result = PASSED;
39 static jboolean printdump = JNI_FALSE;
40 
41 #ifdef STATIC_BUILD
Agent_OnLoad_localtab002(JavaVM * jvm,char * options,void * reserved)42 JNIEXPORT jint JNICALL Agent_OnLoad_localtab002(JavaVM *jvm, char *options, void *reserved) {
43     return Agent_Initialize(jvm, options, reserved);
44 }
Agent_OnAttach_localtab002(JavaVM * jvm,char * options,void * reserved)45 JNIEXPORT jint JNICALL Agent_OnAttach_localtab002(JavaVM *jvm, char *options, void *reserved) {
46     return Agent_Initialize(jvm, options, reserved);
47 }
JNI_OnLoad_localtab002(JavaVM * jvm,char * options,void * reserved)48 JNIEXPORT jint JNI_OnLoad_localtab002(JavaVM *jvm, char *options, void *reserved) {
49     return JNI_VERSION_1_8;
50 }
51 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)52 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
53     jint res;
54     jvmtiError err;
55 
56     if (options != NULL && strcmp(options, "printdump") == 0) {
57         printdump = JNI_TRUE;
58     }
59 
60     res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);
61     if (res != JNI_OK || jvmti == NULL) {
62         printf("Wrong result of a valid call to GetEnv!\n");
63         return JNI_ERR;
64     }
65 
66     err = jvmti->GetPotentialCapabilities(&caps);
67     if (err != JVMTI_ERROR_NONE) {
68         printf("(GetPotentialCapabilities) unexpected error: %s (%d)\n",
69                TranslateError(err), err);
70         return JNI_ERR;
71     }
72 
73     err = jvmti->AddCapabilities(&caps);
74     if (err != JVMTI_ERROR_NONE) {
75         printf("(AddCapabilities) unexpected error: %s (%d)\n",
76                TranslateError(err), err);
77         return JNI_ERR;
78     }
79 
80     err = jvmti->GetCapabilities(&caps);
81     if (err != JVMTI_ERROR_NONE) {
82         printf("(GetCapabilities) unexpected error: %s (%d)\n",
83                TranslateError(err), err);
84         return JNI_ERR;
85     }
86 
87     if (!caps.can_access_local_variables) {
88         printf("Warning: Access to local variables is not implemented\n");
89     }
90 
91     return JNI_OK;
92 }
93 
94 JNIEXPORT jint JNICALL
Java_nsk_jvmti_GetLocalVariableTable_localtab002_check(JNIEnv * env,jclass cls)95 Java_nsk_jvmti_GetLocalVariableTable_localtab002_check(JNIEnv *env, jclass cls) {
96     jvmtiError err;
97     jmethodID mid;
98     jint entryCount;
99     jvmtiLocalVariableEntry *table;
100 
101     if (jvmti == NULL) {
102         printf("JVMTI client was not properly loaded!\n");
103         return STATUS_FAILED;
104     }
105 
106     if (!caps.can_access_local_variables) return result;
107 
108     mid = env->GetMethodID(cls, "<init>", "()V");
109     if (mid == NULL) {
110         printf("Cannot get method ID for \"<init>\"!\n");
111         return STATUS_FAILED;
112     }
113 
114     if (printdump == JNI_TRUE) {
115         printf(">>> invalid method check ...\n");
116     }
117     err = jvmti->GetLocalVariableTable(NULL, &entryCount, &table);
118     if (err != JVMTI_ERROR_INVALID_METHODID) {
119         printf("Error expected: JVMTI_ERROR_INVALID_METHODID,\n");
120         printf("\tactual: %s (%d)\n", TranslateError(err), err);
121         result = STATUS_FAILED;
122     }
123 
124     if (printdump == JNI_TRUE) {
125         printf(">>> (entryCountPtr) null pointer check ...\n");
126     }
127     err = jvmti->GetLocalVariableTable(mid, NULL, &table);
128     if (err != JVMTI_ERROR_NULL_POINTER) {
129         printf("Error expected: JVMTI_ERROR_NULL_POINTER,\n");
130         printf("\tactual: %s (%d)\n", TranslateError(err), err);
131         result = STATUS_FAILED;
132     }
133 
134     if (printdump == JNI_TRUE) {
135         printf(">>> (tablePtr) null pointer check ...\n");
136     }
137     err = jvmti->GetLocalVariableTable(mid, &entryCount, NULL);
138     if (err != JVMTI_ERROR_NULL_POINTER) {
139         printf("Error expected: JVMTI_ERROR_NULL_POINTER,\n");
140         printf("\tactual: %s (%d)\n", TranslateError(err), err);
141         result = STATUS_FAILED;
142     }
143 
144     mid = env->GetStaticMethodID(cls, "check", "()I");
145     if (mid == NULL) {
146         printf("Cannot get method ID for \"check\"!\n");
147         return STATUS_FAILED;
148     }
149 
150     if (printdump == JNI_TRUE) {
151         printf(">>> native method check ...\n");
152     }
153     err = jvmti->GetLocalVariableTable(mid, &entryCount, &table);
154     if (err != JVMTI_ERROR_NATIVE_METHOD) {
155         printf("Error expected: JVMTI_ERROR_NATIVE_METHOD,\n");
156         printf("\tactual: %s (%d)\n", TranslateError(err), err);
157         result = STATUS_FAILED;
158     }
159 
160     if (printdump == JNI_TRUE) {
161         printf(">>> ... done\n");
162     }
163 
164     return result;
165 }
166 
167 }
168