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
29 #include "nsk_tools.h"
30 #include "JVMTITools.h"
31 #include "jvmti_tools.h"
32
33 extern "C" {
34
35 #define METH_NUM 3 /* overall number of methods */
36
37 #define STATUS_FAILED 2
38 #define PASSED 0
39
40 typedef struct { /* local variable info */
41 char *v_name; /* a variable name */
42 char *v_sign; /* JVM type signature */
43 } localVar;
44
45 /* expected local variable info are below */
46 static localVar constr_lv[] = { /* constructor's local variables */
47 { (char*) "this", (char*) "Lnsk/jvmti/GetLocalVariableTable/localtab004a;" },
48 { (char*) "constr_i", (char*) "I" },
49 { (char*) "constr_l", (char*) "J" },
50 { (char*) "constr_d", (char*) "D" },
51 { (char*) "constr_f", (char*) "F" },
52 { (char*) "constr_c", (char*) "C" }
53 };
54
55 static localVar finMeth_lv[] = { /* finMethod()'s local variables */
56 { (char*) "this", (char*) "Lnsk/jvmti/GetLocalVariableTable/localtab004a;" },
57 { (char*) "fin_c", (char*) "C" },
58 { (char*) "fin_i", (char*) "J" },
59 { (char*) "fin_j", (char*) "I" },
60 { (char*) "fin_k", (char*) "J" },
61 { (char*) "fin_l", (char*) "J" },
62 { (char*) "fin_f", (char*) "F" }
63 };
64
65 static localVar statMeth_lv[] = { /* statMethod()'s local variables */
66 { (char*) "stat_x", (char*) "I" },
67 { (char*) "stat_y", (char*) "I" },
68 { (char*) "stat_z", (char*) "I" },
69 { (char*) "stat_j", (char*) "D" },
70 { (char*) "stat_i", (char*) "I" }
71 };
72
73 typedef struct { /* local variables of a method */
74 int inst; /* type of a method: 0- static; 1- instance */
75 char *m_name; /* a method name */
76 char *m_sign; /* JVM signature of a method */
77 int vcount; /* overall number of local variables */
78 localVar *vars;
79 jmethodID mid; /* JNI's method ID */
80 } methodInfo;
81
82 /* list of tested methods */
83 static methodInfo methInfo[] = {
84 { 1, (char*) "<init>", (char*) "()V", 6, constr_lv, NULL },
85 { 1, (char*) "finMethod", (char*) "(CJIJ)V", 7, finMeth_lv, NULL },
86 { 0, (char*) "statMethod", (char*) "(III)D", 5, statMeth_lv, NULL }
87 };
88
89 static jvmtiEnv *jvmti = NULL;
90 static jvmtiCapabilities caps;
91
checkAttr(JNIEnv * jni_env,jclass testedCls)92 static int checkAttr(JNIEnv *jni_env, jclass testedCls) {
93 int i, j, k;
94 int totRes = PASSED;
95 jint count = -1;
96 jvmtiLocalVariableEntry *lv_table;
97
98 for (i=0; i<METH_NUM; i++) {
99 /* get the JNI method ID for a method with name m_name and
100 signature m_sign */
101 if (methInfo[i].inst) /* an instance method */
102 methInfo[i].mid = jni_env->GetMethodID(testedCls, methInfo[i].m_name, methInfo[i].m_sign);
103 else /* a static method */
104 methInfo[i].mid = jni_env->GetStaticMethodID(testedCls, methInfo[i].m_name, methInfo[i].m_sign);
105 if (methInfo[i].mid == NULL) {
106 NSK_COMPLAIN3("TEST FAILURE: unable to get the method ID for the %s method \"%s\", signature \"%s\"\n\n",
107 methInfo[i].inst ? "instance" : "static",
108 methInfo[i].m_name, methInfo[i].m_sign);
109 return STATUS_FAILED;
110 }
111
112 /* get the LocalVariableTable attribute */
113 if (!NSK_JVMTI_VERIFY(jvmti->GetLocalVariableTable(methInfo[i].mid, &count, &lv_table))) {
114 NSK_COMPLAIN3("TEST FAILED: unable to get local variable table\n\tfor the %s method \"%s\", signature \"%s\"\n\n",
115 methInfo[i].inst ? "instance" : "static",
116 methInfo[i].m_name, methInfo[i].m_sign);
117 return STATUS_FAILED;
118 } else {
119 if (count != methInfo[i].vcount) {
120 totRes = STATUS_FAILED;
121 NSK_COMPLAIN5(
122 "TEST FAILED: %s method \"%s\", signature \"%s\": found %d vars in the LocalVariableTable, expected %d\n"
123 "\tHere are the found vars:\n",
124 methInfo[i].inst ? "instance" : "static",
125 methInfo[i].m_name, methInfo[i].m_sign,
126 count, methInfo[i].vcount);
127 for (j=0; j<count; j++)
128 NSK_COMPLAIN3("\t#%d) name: \"%s\", signature: \"%s\"\n",
129 j+1, lv_table[j].name, lv_table[j].signature);
130 NSK_COMPLAIN0("\n");
131
132 continue;
133 }
134 else {
135 NSK_DISPLAY4(
136 "Checking vars in the LocalVariableTable of the %s method \"%s\", signature \"%s\" ...\n"
137 "\tfound %d local vars as expected\n",
138 methInfo[i].inst ? "instance" : "static",
139 methInfo[i].m_name, methInfo[i].m_sign, count);
140 }
141
142 for (j=0; j<count; j++) {
143 for (k=0; k<count; k++) {
144 if (strcmp(lv_table[j].name, methInfo[i].vars[k].v_name) == 0) {
145 if (strcmp(lv_table[j].signature, methInfo[i].vars[k].v_sign) != 0) {
146 NSK_COMPLAIN6(
147 "TEST FAILED: %s method: \"%s\", signature: \"%s\": var \"%s\" "
148 "has signature \"%s\" in the LocalVariableTable, expected \"%s\"\n\n",
149 methInfo[i].inst ? "instance" : "static",
150 methInfo[i].m_name, methInfo[i].m_sign,
151 lv_table[j].name, lv_table[j].signature,
152 methInfo[i].vars[k].v_sign);
153 totRes = STATUS_FAILED;
154 break;
155 }
156 else
157 NSK_DISPLAY2("\tfound var \"%s\", signature: \"%s\" as expected\n",
158 lv_table[j].name, lv_table[j].signature);
159 }
160 }
161 }
162
163 NSK_DISPLAY0("\n");
164 }
165 }
166
167 return totRes;
168 }
169
170 JNIEXPORT jint JNICALL
Java_nsk_jvmti_GetLocalVariableTable_localtab004_check(JNIEnv * env,jobject obj,jobject testedObj)171 Java_nsk_jvmti_GetLocalVariableTable_localtab004_check(
172 JNIEnv *env, jobject obj, jobject testedObj) {
173 jclass testedCls = env->GetObjectClass(testedObj);
174
175 if (!caps.can_access_local_variables)
176 return PASSED;
177
178 return checkAttr(env, testedCls);
179 }
180
181 #ifdef STATIC_BUILD
Agent_OnLoad_localtab004(JavaVM * jvm,char * options,void * reserved)182 JNIEXPORT jint JNICALL Agent_OnLoad_localtab004(JavaVM *jvm, char *options, void *reserved) {
183 return Agent_Initialize(jvm, options, reserved);
184 }
Agent_OnAttach_localtab004(JavaVM * jvm,char * options,void * reserved)185 JNIEXPORT jint JNICALL Agent_OnAttach_localtab004(JavaVM *jvm, char *options, void *reserved) {
186 return Agent_Initialize(jvm, options, reserved);
187 }
JNI_OnLoad_localtab004(JavaVM * jvm,char * options,void * reserved)188 JNIEXPORT jint JNI_OnLoad_localtab004(JavaVM *jvm, char *options, void *reserved) {
189 return JNI_VERSION_1_8;
190 }
191 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)192 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
193 /* init framework and parse options */
194 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
195 return JNI_ERR;
196
197 /* create JVMTI environment */
198 if (!NSK_VERIFY((jvmti =
199 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
200 return JNI_ERR;
201
202 /* add capability to access local variables */
203 memset(&caps, 0, sizeof(jvmtiCapabilities));
204 caps.can_access_local_variables = 1;
205 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps)))
206 return JNI_ERR;
207
208 if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps)))
209 return JNI_ERR;
210
211 if (!caps.can_access_local_variables)
212 NSK_DISPLAY0("Warning: access to local variables is not implemented\n");
213
214 return JNI_OK;
215 }
216
217 }
218