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