8080406: VM_GetOrSetLocal doesn't check local slot type against requested type
Summary: Provide possible type checks when LVT is absent
Reviewed-by: jcbeyler, cjplummer
--- a/src/hotspot/share/prims/jvmtiImpl.cpp Thu Nov 08 02:47:50 2018 +0100
+++ b/src/hotspot/share/prims/jvmtiImpl.cpp Thu Nov 08 00:07:48 2018 -0800
@@ -635,18 +635,8 @@
// JVMTI_ERROR_TYPE_MISMATCH
// Returns: 'true' - everything is Ok, 'false' - error code
-bool VM_GetOrSetLocal::check_slot_type(javaVFrame* jvf) {
+bool VM_GetOrSetLocal::check_slot_type_lvt(javaVFrame* jvf) {
Method* method_oop = jvf->method();
- if (!method_oop->has_localvariable_table()) {
- // Just to check index boundaries
- jint extra_slot = (_type == T_LONG || _type == T_DOUBLE) ? 1 : 0;
- if (_index < 0 || _index + extra_slot >= method_oop->max_locals()) {
- _result = JVMTI_ERROR_INVALID_SLOT;
- return false;
- }
- return true;
- }
-
jint num_entries = method_oop->localvariable_table_length();
if (num_entries == 0) {
_result = JVMTI_ERROR_INVALID_SLOT;
@@ -711,6 +701,35 @@
return true;
}
+bool VM_GetOrSetLocal::check_slot_type_no_lvt(javaVFrame* jvf) {
+ Method* method_oop = jvf->method();
+ jint extra_slot = (_type == T_LONG || _type == T_DOUBLE) ? 1 : 0;
+
+ if (_index < 0 || _index + extra_slot >= method_oop->max_locals()) {
+ _result = JVMTI_ERROR_INVALID_SLOT;
+ return false;
+ }
+ StackValueCollection *locals = _jvf->locals();
+ BasicType slot_type = locals->at(_index)->type();
+
+ if (slot_type == T_CONFLICT) {
+ _result = JVMTI_ERROR_INVALID_SLOT;
+ return false;
+ }
+ if (extra_slot) {
+ BasicType extra_slot_type = locals->at(_index + 1)->type();
+ if (extra_slot_type != T_INT) {
+ _result = JVMTI_ERROR_INVALID_SLOT;
+ return false;
+ }
+ }
+ if (_type != slot_type && (_type == T_OBJECT || slot_type != T_INT)) {
+ _result = JVMTI_ERROR_TYPE_MISMATCH;
+ return false;
+ }
+ return true;
+}
+
static bool can_be_deoptimized(vframe* vf) {
return (vf->is_compiled_frame() && vf->fr().can_be_deoptimized());
}
@@ -719,8 +738,9 @@
_jvf = get_java_vframe();
NULL_CHECK(_jvf, false);
- if (_jvf->method()->is_native()) {
- if (getting_receiver() && !_jvf->method()->is_static()) {
+ Method* method_oop = _jvf->method();
+ if (method_oop->is_native()) {
+ if (getting_receiver() && !method_oop->is_static()) {
return true;
} else {
_result = JVMTI_ERROR_OPAQUE_FRAME;
@@ -728,8 +748,10 @@
}
}
- if (!check_slot_type(_jvf)) {
- return false;
+ if (method_oop->has_localvariable_table()) {
+ return check_slot_type_lvt(_jvf);
+ } else {
+ return check_slot_type_no_lvt(_jvf);
}
return true;
}
@@ -796,12 +818,6 @@
} else {
StackValueCollection *locals = _jvf->locals();
- if (locals->at(_index)->type() == T_CONFLICT) {
- memset(&_value, 0, sizeof(_value));
- _value.l = NULL;
- return;
- }
-
switch (_type) {
case T_INT: _value.i = locals->int_at (_index); break;
case T_LONG: _value.j = locals->long_at (_index); break;
--- a/src/hotspot/share/prims/jvmtiImpl.hpp Thu Nov 08 02:47:50 2018 +0100
+++ b/src/hotspot/share/prims/jvmtiImpl.hpp Thu Nov 08 00:07:48 2018 -0800
@@ -382,7 +382,8 @@
vframe* get_vframe();
javaVFrame* get_java_vframe();
- bool check_slot_type(javaVFrame* vf);
+ bool check_slot_type_lvt(javaVFrame* vf);
+ bool check_slot_type_no_lvt(javaVFrame* vf);
public:
// Constructor for non-object getter
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/GetLocalVariable/GetLocalVars.java Thu Nov 08 00:07:48 2018 -0800
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8080406
+ * @summary VM_GetOrSetLocal doesn't check local slot type against requested type
+ *
+ * @compile GetLocalVars.java
+ * @run main/othervm/native -Xcomp -agentlib:GetLocalVars GetLocalVars
+ */
+
+
+public class GetLocalVars {
+ private static final String agentLib = "GetLocalVars";
+
+ static native void testLocals(Thread thread);
+ static native int getStatus();
+
+ public static
+ void main(String[] args) throws Exception {
+ try {
+ System.loadLibrary(agentLib);
+ } catch (UnsatisfiedLinkError ex) {
+ System.err.println("Failed to load " + agentLib + " lib");
+ System.err.println("java.library.path: " + System.getProperty("java.library.path"));
+ throw ex;
+ }
+ run(args);
+ int status = getStatus();
+ if (status != 0) {
+ throw new RuntimeException("Test GetLocalVars failed with a bad status: " + status);
+ }
+ }
+
+ public static
+ void run(String argv[]) {
+ GetLocalVars testedObj = new GetLocalVars();
+ double pi = 3.14d;
+ byte sym = 'X';
+ int year = 2018;
+
+ staticMeth(sym, testedObj, pi, year);
+ }
+
+ public static synchronized
+ int staticMeth(byte byteArg, Object objArg, double dblArg, int intArg) {
+ testLocals(Thread.currentThread());
+ {
+ int intLoc = 9999;
+ intArg = intLoc;
+ }
+ return intArg;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/GetLocalVariable/libGetLocalVars.cpp Thu Nov 08 00:07:48 2018 -0800
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define STATUS_PASSED 0
+#define STATUS_FAILED 2
+#define TranslateError(err) "JVMTI error"
+
+static jint result = STATUS_PASSED;
+static jvmtiEnv *jvmti = NULL;
+
+#define DECL_TEST_FUNC(type, Type) \
+static void \
+test_##type(jthread thr, int depth, int slot, const char* exp_type) { \
+ j##type val; \
+ jvmtiError err = jvmti->GetLocal##Type(thr, depth, slot, &val); \
+ \
+ printf(" GetLocal%s: %s (%d)\n", #Type, TranslateError(err), err); \
+ if (err != JVMTI_ERROR_NONE) { \
+ printf(" FAIL: GetLocal%s failed to get value from a local %s\n", #Type, exp_type); \
+ result = STATUS_FAILED; \
+ } else { \
+ printf(" GetLocal%s got value from a local %s as expected\n", #Type, exp_type); \
+ } \
+}
+
+#define DECL_TEST_INV_SLOT_FUNC(type, Type) \
+static void \
+test_##type##_inv_slot(jthread thr, int depth, int slot, const char* exp_type) { \
+ j##type val; \
+ jvmtiError err = jvmti->GetLocal##Type(thr, depth, slot, &val); \
+ \
+ printf(" GetLocal%s: %s (%d)\n", #Type, TranslateError(err), err); \
+ if (err != JVMTI_ERROR_INVALID_SLOT) { \
+ printf(" FAIL: GetLocal%s failed to return JVMTI_ERROR_INVALID_SLOT for local %s\n", #Type, exp_type); \
+ result = STATUS_FAILED; \
+ } else { \
+ printf(" GetLocal%s returned JVMTI_ERROR_INVALID_SLOT for local %s as expected\n", #Type, exp_type); \
+ } \
+}
+
+#define DECL_TEST_TYPE_MISMATCH_FUNC(type, Type) \
+static void \
+test_##type##_type_mismatch(jthread thr, int depth, int slot, const char* exp_type) { \
+ j##type val; \
+ jvmtiError err = jvmti->GetLocal##Type(thr, depth, slot, &val); \
+ \
+ printf(" GetLocal%s: %s (%d)\n", #Type, TranslateError(err), err); \
+ if (err != JVMTI_ERROR_TYPE_MISMATCH) { \
+ printf(" FAIL: GetLocal%s failed to return JVMTI_ERROR_TYPE_MISMATCH for local %s\n", #Type, exp_type); \
+ result = STATUS_FAILED; \
+ } else { \
+ printf(" GetLocal%s returned JVMTI_ERROR_TYPE_MISMATCH for local %s as expected\n", #Type, exp_type); \
+ } \
+}
+
+DECL_TEST_FUNC(int, Int);
+DECL_TEST_FUNC(float, Float);
+DECL_TEST_FUNC(long, Long);
+DECL_TEST_FUNC(double, Double);
+DECL_TEST_FUNC(object, Object);
+
+DECL_TEST_INV_SLOT_FUNC(int, Int);
+DECL_TEST_INV_SLOT_FUNC(float, Float);
+DECL_TEST_INV_SLOT_FUNC(long, Long);
+DECL_TEST_INV_SLOT_FUNC(double, Double);
+DECL_TEST_INV_SLOT_FUNC(object, Object);
+
+DECL_TEST_TYPE_MISMATCH_FUNC(int, Int);
+DECL_TEST_TYPE_MISMATCH_FUNC(float, Float);
+DECL_TEST_TYPE_MISMATCH_FUNC(long, Long);
+DECL_TEST_TYPE_MISMATCH_FUNC(double, Double);
+DECL_TEST_TYPE_MISMATCH_FUNC(object, Object);
+
+static void
+test_local_byte(jthread thr, int depth, int slot) {
+ printf("\n test_local_byte: BEGIN\n\n");
+
+ test_int(thr, depth, slot, "byte");
+ test_long_inv_slot(thr, depth, slot, "byte");
+ test_float(thr, depth, slot, "byte");
+ test_double_inv_slot(thr, depth, slot, "byte");
+ test_object_type_mismatch(thr, depth, slot, "byte");
+
+ printf("\n test_local_byte: END\n\n");
+}
+
+static void
+test_local_object(jthread thr, int depth, int slot) {
+ printf("\n test_local_object: BEGIN\n\n");
+
+ test_int_type_mismatch(thr, depth, slot, "object");
+ test_long_type_mismatch(thr, depth, slot, "object");
+ test_float_type_mismatch(thr, depth, slot, "object");
+ test_double_type_mismatch(thr, depth, slot, "object");
+ test_object(thr, depth, slot, "object");
+
+ printf("\n test_local_object: END\n\n");
+}
+
+static void
+test_local_double(jthread thr, int depth, int slot) {
+ printf("\n test_local_double: BEGIN\n\n");
+
+ test_int(thr, depth, slot, "double");
+ test_long(thr, depth, slot, "double");
+ test_float(thr, depth, slot, "double");
+ test_double(thr, depth, slot, "double");
+ test_object_type_mismatch(thr, depth, slot, "double");
+
+ printf("\n test_local_double: END\n\n");
+}
+
+static void
+test_local_integer(jthread thr, int depth, int slot) {
+ printf("\n test_local_integer: BEGIN\n\n");
+
+ test_int(thr, depth, slot, "int");
+ test_long_inv_slot(thr, depth, slot, "int");
+ test_float(thr, depth, slot, "int");
+ test_double_inv_slot(thr, depth, slot, "int");
+ test_object_type_mismatch(thr, depth, slot, "double");
+
+ printf("\n test_local_integer: END\n\n");
+}
+
+static void
+test_local_invalid(jthread thr, int depth, int slot) {
+ printf("\n test_local_invalid: BEGIN\n\n");
+
+ test_int_inv_slot(thr, depth, slot, "invalid");
+ test_long_inv_slot(thr, depth, slot, "invalid");
+ test_float_inv_slot(thr, depth, slot, "invalid");
+ test_double_inv_slot(thr, depth, slot, "invalid");
+ test_object_inv_slot(thr, depth, slot, "invalid");
+
+ printf("\n test_local_invalid: END\n\n");
+}
+
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+ jint res;
+ jvmtiError err;
+ static jvmtiCapabilities caps;
+
+ res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_9);
+ if (res != JNI_OK || jvmti == NULL) {
+ printf("Wrong result of a valid call to GetEnv!\n");
+ return JNI_ERR;
+ }
+ caps.can_access_local_variables = 1;
+
+ err = jvmti->AddCapabilities(&caps);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("AddCapabilities: unexpected error: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+ err = jvmti->GetCapabilities(&caps);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("GetCapabilities: unexpected error: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+ if (!caps.can_access_local_variables) {
+ printf("Warning: Access to local variables is not implemented\n");
+ return JNI_ERR;
+ }
+ return JNI_OK;
+}
+
+JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT jint JNICALL
+Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT void JNICALL
+Java_GetLocalVars_testLocals(JNIEnv *env, jclass cls, jobject thread) {
+ static const char* METHOD_NAME = "staticMeth";
+ static const char* METHOD_SIGN = "(BLjava/lang/Object;DI)I";
+ static const int Depth = 1;
+ static const int ByteSlot = 0;
+ static const int ObjSlot = 1;
+ static const int DblSlot = 2;
+ static const int IntSlot = 4;
+ static const int InvalidSlot = 5;
+
+ jmethodID mid = NULL;
+
+ if (jvmti == NULL) {
+ printf("JVMTI client was not properly loaded!\n");
+ result = STATUS_FAILED;
+ return;
+ }
+
+ mid = env->GetStaticMethodID(cls, METHOD_NAME, METHOD_SIGN);
+ if (mid == NULL) {
+ printf("Cannot find Method ID for %s%s\n", METHOD_NAME, METHOD_SIGN);
+ result = STATUS_FAILED;
+ return;
+ }
+
+ test_local_byte(thread, Depth, ByteSlot);
+ test_local_object(thread, Depth, ObjSlot);
+ test_local_double(thread, Depth, DblSlot);
+ test_local_integer(thread, Depth, IntSlot);
+ test_local_invalid(thread, Depth, InvalidSlot);
+}
+
+JNIEXPORT jint JNICALL
+Java_GetLocalVars_getStatus(JNIEnv *env, jclass cls) {
+ return result;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/GetLocalVariable/getlocal003/getlocal003.cpp Thu Nov 08 02:47:50 2018 +0100
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/GetLocalVariable/getlocal003/getlocal003.cpp Thu Nov 08 00:07:48 2018 -0800
@@ -21,9 +21,6 @@
* questions.
*/
-/*
- */
-
#include <stdio.h>
#include <string.h>
#include "jvmti.h"
@@ -34,13 +31,12 @@
extern "C" {
-#define PASSED 0
+#define STATUS_PASSED 0
#define STATUS_FAILED 2
static jvmtiEnv *jvmti = NULL;
-static jvmtiCapabilities caps;
static jvmtiEventCallbacks callbacks;
-static jint result = PASSED;
+static jint result = STATUS_PASSED;
static jboolean printdump = JNI_FALSE;
static jmethodID mid = NULL;
static jvmtiLocalVariableEntry *table = NULL;
@@ -54,69 +50,112 @@
printf(", signature: %s\n", lvt_elem->signature);
}
-void JNICALL MethodExit(jvmtiEnv *jvmti_env, JNIEnv *env,
- jthread thr, jmethodID method,
- jboolean was_poped_by_exception, jvalue return_value) {
+static void
+test_locals(jvmtiEnv *jvmti, jthread thr, jlocation location) {
jvmtiError err;
- jint i;
- jmethodID frame_method;
- jlocation location;
jint intVal;
+ jlong longVal;
jfloat floatVal;
jdouble doubleVal;
jobject obj;
+ jint i;
- if (mid == method) {
+ for (i = 0; i < entryCount; i++) {
+ if (table[i].start_location > location ||
+ table[i].start_location + table[i].length < location) {
+ continue; /* The local variable is not visible */
+ }
+ print_LocalVariableEntry(&table[i]);
+ char sig = table[i].signature[0];
- err = jvmti_env->GetFrameLocation(thr, 0,
- &frame_method, &location);
- if (err != JVMTI_ERROR_NONE) {
- printf("\t failure: %s (%d)\n", TranslateError(err), err);
+ if (sig == 'Z' || sig == 'B' || sig == 'C' || sig == 'S') {
+ sig = 'I'; // covered by GetLocalInt
+ }
+ err = jvmti->GetLocalInt(thr, 0, table[i].slot, &intVal);
+ printf(" GetLocalInt: %s (%d)\n", TranslateError(err), err);
+ if (err != JVMTI_ERROR_NONE && sig == 'I') {
+ printf("FAIL: GetLocalInt failed to get value of int\n");
+ result = STATUS_FAILED;
+ } else if (err != JVMTI_ERROR_TYPE_MISMATCH && sig != 'I') {
+ printf("FAIL: GetLocalInt did not return JVMTI_ERROR_TYPE_MISMATCH for non-int\n");
result = STATUS_FAILED;
- return;
}
- if (frame_method != method) {
- printf("\t failure: GetFrameLocation returned wrong jmethodID\n");
+
+ err = jvmti->GetLocalLong(thr, 0, table[i].slot, &longVal);
+ printf(" GetLocalLong: %s (%d)\n", TranslateError(err), err);
+ if (err != JVMTI_ERROR_NONE && sig == 'J') {
+ printf("FAIL: GetLocalLong failed to get value of long\n");
+ result = STATUS_FAILED;
+ } else if (err != JVMTI_ERROR_TYPE_MISMATCH && sig != 'J') {
+ printf("FAIL: GetLocalLong did not return JVMTI_ERROR_TYPE_MISMATCH for non-long\n");
result = STATUS_FAILED;
- return;
+ }
+
+ err = jvmti->GetLocalFloat(thr, 0, table[i].slot, &floatVal);
+ printf(" GetLocalFloat: %s (%d)\n", TranslateError(err), err);
+ if (err != JVMTI_ERROR_NONE && table[i].signature[0] == 'F') {
+ printf("FAIL: GetLocalFloat failed to get value of float\n");
+ result = STATUS_FAILED;
+ } else if (err != JVMTI_ERROR_TYPE_MISMATCH && table[i].signature[0] != 'F') {
+ printf("FAIL: GetLocalFloat did not return JVMTI_ERROR_TYPE_MISMATCH for non-float\n");
+ result = STATUS_FAILED;
}
- printf("\n MethodExit: BEGIN %d, Current frame bci: %" LL "d\n\n",
- ++methodExitCnt, location);
- for (i = 0; i < entryCount; i++) {
- if (table[i].start_location > location ||
- table[i].start_location + table[i].length < location) {
- continue; /* The local variable is not visible */
- }
- print_LocalVariableEntry(&table[i]);
+ err = jvmti->GetLocalDouble(thr, 0, table[i].slot, &doubleVal);
+ printf(" GetLocalDouble: %s (%d)\n", TranslateError(err), err);
+ if (err != JVMTI_ERROR_NONE && table[i].signature[0] == 'D') {
+ printf("FAIL: GetLocalDouble failed to get value of double\n");
+ result = STATUS_FAILED;
+ } else if (err != JVMTI_ERROR_TYPE_MISMATCH && table[i].signature[0] != 'D') {
+ printf("FAIL: GetLocalDouble did not return JVMTI_ERROR_TYPE_MISMATCH for non-double\n");
+ result = STATUS_FAILED;
+ }
- err = jvmti->GetLocalInt(thr, 0, table[i].slot, &intVal);
- printf(" GetLocalInt: %s (%d)\n", TranslateError(err), err);
- if (err != JVMTI_ERROR_NONE && table[i].signature[0] == 'I') {
- result = STATUS_FAILED;
- }
+ err = jvmti->GetLocalObject(thr, 0, table[i].slot, &obj);
+ printf(" GetLocalObject: %s (%d)\n", TranslateError(err), err);
+ if (err != JVMTI_ERROR_NONE && table[i].signature[0] == 'L') {
+ printf("FAIL: GetLocalObject failed to get value of object\n");
+ result = STATUS_FAILED;
+ } else if (err != JVMTI_ERROR_TYPE_MISMATCH && table[i].signature[0] != 'L') {
+ printf("FAIL: GetLocalObject did not return JVMTI_ERROR_TYPE_MISMATCH for non-object\n");
+ result = STATUS_FAILED;
+ }
+ }
+}
- err = jvmti->GetLocalFloat(thr, 0, table[i].slot, &floatVal);
- printf(" GetLocalFloat: %s (%d)\n", TranslateError(err), err);
- if (err != JVMTI_ERROR_NONE && table[i].signature[0] == 'F') {
- result = STATUS_FAILED;
- }
+static void JNICALL
+MethodExit(jvmtiEnv *jvmti_env,
+ JNIEnv *env,
+ jthread thr,
+ jmethodID method,
+ jboolean was_poped_by_exception,
+ jvalue return_value) {
+
+ jvmtiError err;
+ jlocation location;
+ jmethodID frame_method = NULL;
- err = jvmti->GetLocalDouble(thr, 0, table[i].slot, &doubleVal);
- printf(" GetLocalDouble: %s (%d)\n", TranslateError(err), err);
- if (err != JVMTI_ERROR_NONE && table[i].signature[0] == 'D') {
- result = STATUS_FAILED;
- }
+ if (mid != method) {
+ return;
+ }
+ err = jvmti->GetFrameLocation(thr, 0, &frame_method, &location);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("\t failure: %s (%d)\n", TranslateError(err), err);
+ result = STATUS_FAILED;
+ return;
+ }
+ if (frame_method != method) {
+ printf("\t failure: GetFrameLocation returned wrong jmethodID\n");
+ result = STATUS_FAILED;
+ return;
+ }
- err = jvmti->GetLocalObject(thr, 0, table[i].slot, &obj);
- printf(" GetLocalObject: %s (%d)\n", TranslateError(err), err);
- if (err != JVMTI_ERROR_NONE && table[i].signature[0] == 'L') {
- result = STATUS_FAILED;
- }
- }
- printf("\n MethodExit: END %d\n\n", methodExitCnt);
- fflush(stdout);
- }
+ printf("\n MethodExit: BEGIN %d\n", ++methodExitCnt);
+
+ test_locals(jvmti, thr, location);
+
+ printf("\n MethodExit: END %d\n\n", methodExitCnt);
+ fflush(stdout);
}
#ifdef STATIC_BUILD
@@ -133,6 +172,7 @@
jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
jint res;
jvmtiError err;
+ static jvmtiCapabilities caps;
if (options != NULL && strcmp(options, "printdump") == 0) {
printdump = JNI_TRUE;
@@ -167,18 +207,19 @@
if (!caps.can_access_local_variables) {
printf("Warning: Access to local variables is not implemented\n");
- } else if (caps.can_generate_method_exit_events) {
- callbacks.MethodExit = &MethodExit;
- err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
- if (err != JVMTI_ERROR_NONE) {
- printf("(SetEventCallbacks) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- return JNI_ERR;
- }
- } else {
+ return JNI_ERR;
+ }
+ if (!caps.can_generate_method_exit_events) {
printf("Warning: MethodExit event is not implemented\n");
+ return JNI_ERR;
}
-
+ callbacks.MethodExit = &MethodExit;
+ err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
+ if (err != JVMTI_ERROR_NONE) {
+ printf("(SetEventCallbacks) unexpected error: %s (%d)\n",
+ TranslateError(err), err);
+ return JNI_ERR;
+ }
return JNI_OK;
}
@@ -192,9 +233,6 @@
return;
}
- if (!caps.can_access_local_variables ||
- !caps.can_generate_method_exit_events) return;
-
mid = env->GetStaticMethodID(cls, "staticMeth", "(I)I");
if (mid == NULL) {
printf("Cannot find Method ID for staticMeth\n");
@@ -204,14 +242,13 @@
err = jvmti->GetLocalVariableTable(mid, &entryCount, &table);
if (err != JVMTI_ERROR_NONE) {
- printf("(GetLocalVariableTable) unexpected error: %s (%d)\n",
- TranslateError(err), err);
- result = STATUS_FAILED;
- return;
+ printf("(GetLocalVariableTable) unexpected error: %s (%d)\n",
+ TranslateError(err), err);
+ result = STATUS_FAILED;
+ return;
}
- err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
- JVMTI_EVENT_METHOD_EXIT, NULL);
+ err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_EXIT, NULL);
if (err != JVMTI_ERROR_NONE) {
printf("Failed to enable metod exit event: %s (%d)\n",
TranslateError(err), err);
@@ -232,8 +269,11 @@
int overlap = 0;
if (jvmti == NULL) {
+ printf("JVMTI client was not properly loaded!\n");
+ result = STATUS_FAILED;
return;
}
+ printf("\n checkLoc: START\n");
mid = env->GetStaticMethodID(cls, "staticMeth", "(I)I");
if (mid == NULL) {
@@ -255,20 +295,22 @@
err = jvmti->GetLocalInt(thr, 1, table[i].slot, &locVar);
- printf(" GetLocalInt: %s (%d)\n", TranslateError(err), err);
if (strcmp(table[i].name, "intArg") == 0) {
if (err != JVMTI_ERROR_NONE) {
- printf(" failure: JVMTI_ERROR_NONE is expected\n");
- result = STATUS_FAILED;
+ printf(" GetLocalInt: %s (%d)\n", TranslateError(err), err);
+ printf(" failure: JVMTI_ERROR_NONE is expected\n");
+ result = STATUS_FAILED;
}
}
else if (strcmp(table[i].name, "pi") == 0) {
if (err != JVMTI_ERROR_TYPE_MISMATCH) {
- printf(" failure: JVMTI_ERROR_TYPE_MISMATCH is expected\n");
- result = STATUS_FAILED;
+ printf(" GetLocalInt: %s (%d)\n", TranslateError(err), err);
+ printf(" failure: JVMTI_ERROR_TYPE_MISMATCH is expected\n");
+ result = STATUS_FAILED;
}
} else {
if (err != JVMTI_ERROR_INVALID_SLOT) {
+ printf(" GetLocalInt: %s (%d)\n", TranslateError(err), err);
printf(" failure: JVMTI_ERROR_INVALID_SLOT is expected\n");
result = STATUS_FAILED;
}
@@ -290,7 +332,7 @@
continue; /* Everything is Ok */
}
- printf(" failure: locations of vars with slot #2 are overlaped:\n");
+ printf(" failure: locations of vars with slot #2 are overlapped:\n");
print_LocalVariableEntry(&table[i]);
print_LocalVariableEntry(&table[j]);
overlap++;
@@ -298,8 +340,9 @@
}
}
if (!overlap) {
- printf("\n Succes: locations of vars with slot #2 are NOT overlaped\n\n");
+ printf("\n Success: locations of vars with slot #2 are NOT overlapped\n");
}
+ printf("\n checkLoc: END\n\n");
fflush(stdout);
}
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/GetLocalVariable/getlocal004/getlocal004.cpp Thu Nov 08 02:47:50 2018 +0100
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/GetLocalVariable/getlocal004/getlocal004.cpp Thu Nov 08 00:07:48 2018 -0800
@@ -21,9 +21,6 @@
* questions.
*/
-/*
- */
-
#include <stdio.h>
#include <string.h>
#include "jvmti.h"
@@ -34,14 +31,12 @@
extern "C" {
-#define PASSED 0
+#define STATUS_PASSED 0
#define STATUS_FAILED 2
static jvmtiEnv *jvmti = NULL;
-static jvmtiCapabilities caps;
-static jint result = PASSED;
+static jint result = STATUS_PASSED;
static jboolean printdump = JNI_FALSE;
-static jmethodID mid = NULL;
void print_LocalVariableEntry(jvmtiLocalVariableEntry *lvt_elem) {
printf("\n Var name: %s, slot: %d", lvt_elem->name, lvt_elem->slot);
@@ -64,6 +59,7 @@
jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
jint res;
jvmtiError err;
+ static jvmtiCapabilities caps;
if (options != NULL && strcmp(options, "printdump") == 0) {
printdump = JNI_TRUE;
@@ -98,29 +94,31 @@
if (!caps.can_access_local_variables) {
printf("Warning: Access to local variables is not implemented\n");
+ return JNI_ERR;
}
-
+ if (!caps.can_access_local_variables) {
+ printf("Warning: Access to local variables is not implemented\n");
+ return JNI_ERR;
+ }
return JNI_OK;
}
JNIEXPORT void JNICALL
Java_nsk_jvmti_unit_GetLocalVariable_getlocal004_getMeth(JNIEnv *env, jclass cls) {
+ jmethodID mid = NULL;
+
if (jvmti == NULL) {
printf("JVMTI client was not properly loaded!\n");
result = STATUS_FAILED;
return;
}
- if (!caps.can_access_local_variables ||
- !caps.can_generate_method_exit_events) return;
-
mid = env->GetStaticMethodID(cls, "staticMeth", "(I)I");
if (mid == NULL) {
printf("Cannot find Method ID for staticMeth\n");
result = STATUS_FAILED;
return;
}
-
fflush(stdout);
}