8080406: VM_GetOrSetLocal doesn't check local slot type against requested type

Provide possible type checks when LVT is absent

Reviewed-by: jcbeyler, cjplummer
This commit is contained in:
Serguei Spitsyn 2018-11-08 00:07:48 -08:00
parent f838846500
commit bf16c3a479
6 changed files with 496 additions and 117 deletions

View File

@ -635,18 +635,8 @@ bool VM_GetOrSetLocal::is_assignable(const char* ty_sign, Klass* klass, Thread*
// 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 @@ bool VM_GetOrSetLocal::check_slot_type(javaVFrame* jvf) {
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 @@ bool VM_GetOrSetLocal::doit_prologue() {
_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 @@ bool VM_GetOrSetLocal::doit_prologue() {
}
}
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 @@ void VM_GetOrSetLocal::doit() {
} 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;

View File

@ -382,7 +382,8 @@ class VM_GetOrSetLocal : public VM_Operation {
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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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,71 +50,114 @@ void print_LocalVariableEntry(jvmtiLocalVariableEntry *lvt_elem) {
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;
return;
}
if (frame_method != method) {
printf("\t failure: GetFrameLocation returned wrong jmethodID\n");
} 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;
}
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->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->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;
}
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;
}
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;
}
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;
}
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;
}
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->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;
}
printf("\n MethodExit: END %d\n\n", methodExitCnt);
fflush(stdout);
}
}
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;
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;
}
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
JNIEXPORT jint JNICALL Agent_OnLoad_getlocal003(JavaVM *jvm, char *options, void *reserved) {
return Agent_Initialize(jvm, options, reserved);
@ -133,6 +172,7 @@ JNIEXPORT jint JNI_OnLoad_getlocal003(JavaVM *jvm, char *options, void *reserved
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 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
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 {
printf("Warning: MethodExit event is not implemented\n");
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 @@ Java_nsk_jvmti_unit_GetLocalVariable_getlocal003_getMeth(JNIEnv *env, jclass cls
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 @@ Java_nsk_jvmti_unit_GetLocalVariable_getlocal003_getMeth(JNIEnv *env, jclass cls
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 @@ Java_nsk_jvmti_unit_GetLocalVariable_getlocal003_checkLoc(JNIEnv *env,
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 @@ Java_nsk_jvmti_unit_GetLocalVariable_getlocal003_checkLoc(JNIEnv *env,
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 @@ Java_nsk_jvmti_unit_GetLocalVariable_getlocal003_checkLoc(JNIEnv *env,
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 @@ Java_nsk_jvmti_unit_GetLocalVariable_getlocal003_checkLoc(JNIEnv *env,
}
}
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);
}

View File

@ -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 @@ JNIEXPORT jint JNI_OnLoad_getlocal004(JavaVM *jvm, char *options, void *reserved
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 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
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);
}