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:
parent
f838846500
commit
bf16c3a479
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user