8241080: Consolidate signature parsing code in serviceability tools
Reviewed-by: sspitsyn, cjplummer
This commit is contained in:
parent
fa36d28aff
commit
9d4872f612
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
@ -59,7 +59,8 @@ public class ArrayTypeImpl extends ReferenceTypeImpl
|
||||
}
|
||||
|
||||
public String componentSignature() {
|
||||
return signature().substring(1); // Just skip the leading '['
|
||||
JNITypeParser sig = new JNITypeParser(signature());
|
||||
return sig.componentSignature();
|
||||
}
|
||||
|
||||
public String componentTypeName() {
|
||||
@ -90,8 +91,9 @@ public class ArrayTypeImpl extends ReferenceTypeImpl
|
||||
* this method is sometimes needed for proper type checking.
|
||||
*/
|
||||
Type findComponentType(String signature) throws ClassNotLoadedException {
|
||||
byte tag = (byte)signature.charAt(0);
|
||||
if (PacketStream.isObjectTag(tag)) {
|
||||
|
||||
JNITypeParser sig = new JNITypeParser(signature);
|
||||
if (sig.isReference()) {
|
||||
// It's a reference type
|
||||
JNITypeParser parser = new JNITypeParser(componentSignature());
|
||||
List<ReferenceType> list = vm.classesByName(parser.typeName());
|
||||
@ -109,7 +111,7 @@ public class ArrayTypeImpl extends ReferenceTypeImpl
|
||||
throw new ClassNotLoadedException(componentTypeName());
|
||||
} else {
|
||||
// It's a primitive type
|
||||
return vm.primitiveTypeMirror(tag);
|
||||
return vm.primitiveTypeMirror(sig.jdwpTag());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -425,19 +425,7 @@ public class EventSetImpl extends ArrayList<Event> implements EventSet {
|
||||
}
|
||||
|
||||
public String className() {
|
||||
assert classSignature.startsWith("L") && classSignature.endsWith(";");
|
||||
|
||||
// trim leading "L" and trailing ";"
|
||||
String name = classSignature.substring(1, classSignature.length() - 1);
|
||||
int index = name.indexOf("."); // check if it is a hidden class
|
||||
if (index < 0) {
|
||||
return name.replace('/', '.');
|
||||
} else {
|
||||
// map the type descriptor from: "L" + N + "." + <suffix> + ";"
|
||||
// to class name: N.replace('/', '.') + "/" + <suffix>
|
||||
return name.substring(0, index).replace('/', '.')
|
||||
+ "/" + name.substring(index + 1);
|
||||
}
|
||||
return JNITypeParser.convertSignatureToClassname(classSignature);
|
||||
}
|
||||
|
||||
public String classSignature() {
|
||||
|
@ -113,10 +113,69 @@ public class JNITypeParser {
|
||||
return count;
|
||||
}
|
||||
|
||||
byte jdwpTag() {
|
||||
return (byte) signature().charAt(0);
|
||||
}
|
||||
|
||||
String componentSignature(int level) {
|
||||
assert level <= dimensionCount();
|
||||
return signature().substring(level);
|
||||
}
|
||||
|
||||
String componentSignature() {
|
||||
assert isArray();
|
||||
return componentSignature(1);
|
||||
}
|
||||
|
||||
boolean isArray() {
|
||||
return jdwpTag() == JDWP.Tag.ARRAY;
|
||||
}
|
||||
|
||||
boolean isVoid() {
|
||||
return jdwpTag() == JDWP.Tag.VOID;
|
||||
}
|
||||
|
||||
boolean isBoolean() {
|
||||
return jdwpTag() == JDWP.Tag.BOOLEAN;
|
||||
}
|
||||
|
||||
boolean isReference() {
|
||||
byte tag = jdwpTag();
|
||||
return tag == JDWP.Tag.ARRAY ||
|
||||
tag == JDWP.Tag.OBJECT;
|
||||
}
|
||||
|
||||
boolean isPrimitive() {
|
||||
switch (jdwpTag()) {
|
||||
case (JDWP.Tag.BOOLEAN):
|
||||
case (JDWP.Tag.BYTE):
|
||||
case (JDWP.Tag.CHAR):
|
||||
case (JDWP.Tag.SHORT):
|
||||
case (JDWP.Tag.INT):
|
||||
case (JDWP.Tag.LONG):
|
||||
case (JDWP.Tag.FLOAT):
|
||||
case (JDWP.Tag.DOUBLE):
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static String convertSignatureToClassname(String classSignature) {
|
||||
assert classSignature.startsWith("L") && classSignature.endsWith(";");
|
||||
|
||||
// trim leading "L" and trailing ";"
|
||||
String name = classSignature.substring(1, classSignature.length() - 1);
|
||||
int index = name.indexOf("."); // check if it is a hidden class
|
||||
if (index < 0) {
|
||||
return name.replace('/', '.');
|
||||
} else {
|
||||
// map the type descriptor from: "L" + N + "." + <suffix> + ";"
|
||||
// to class name: N.replace('/', '.') + "/" + <suffix>
|
||||
return name.substring(0, index).replace('/', '.')
|
||||
+ "/" + name.substring(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized List<String> signatureList() {
|
||||
if (signatureList == null) {
|
||||
signatureList = new ArrayList<>(10);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
@ -584,17 +584,16 @@ public class ObjectReferenceImpl extends ValueImpl
|
||||
* type which might cause a confusing ClassNotLoadedException if
|
||||
* the destination is primitive or an array.
|
||||
*/
|
||||
/*
|
||||
* TO DO: Centralize JNI signature knowledge
|
||||
*/
|
||||
if (destination.signature().length() == 1) {
|
||||
|
||||
JNITypeParser destSig = new JNITypeParser(destination.signature());
|
||||
JNITypeParser sourceSig = new JNITypeParser(type().signature());
|
||||
if (destSig.isPrimitive()) {
|
||||
throw new InvalidTypeException("Can't assign object value to primitive");
|
||||
}
|
||||
if ((destination.signature().charAt(0) == '[') &&
|
||||
(type().signature().charAt(0) != '[')) {
|
||||
if (destSig.isArray() && !sourceSig.isArray()) {
|
||||
throw new InvalidTypeException("Can't assign non-array value to an array");
|
||||
}
|
||||
if ("void".equals(destination.typeName())) {
|
||||
if (destSig.isVoid()) {
|
||||
throw new InvalidTypeException("Can't assign object value to a void");
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
@ -105,24 +105,22 @@ public abstract class PrimitiveValueImpl extends ValueImpl
|
||||
ValueImpl convertForAssignmentTo(ValueContainer destination)
|
||||
throws InvalidTypeException
|
||||
{
|
||||
/*
|
||||
* TO DO: Centralize JNI signature knowledge
|
||||
*/
|
||||
if (destination.signature().length() > 1) {
|
||||
JNITypeParser destSig = new JNITypeParser(destination.signature());
|
||||
JNITypeParser sourceSig = new JNITypeParser(type().signature());
|
||||
|
||||
if (destSig.isReference()) {
|
||||
throw new InvalidTypeException("Can't assign primitive value to object");
|
||||
}
|
||||
|
||||
if ((destination.signature().charAt(0) == 'Z') &&
|
||||
(type().signature().charAt(0) != 'Z')) {
|
||||
if (destSig.isBoolean() && !sourceSig.isBoolean()) {
|
||||
throw new InvalidTypeException("Can't assign non-boolean value to a boolean");
|
||||
}
|
||||
|
||||
if ((destination.signature().charAt(0) != 'Z') &&
|
||||
(type().signature().charAt(0) == 'Z')) {
|
||||
if (!destSig.isBoolean() && sourceSig.isBoolean()) {
|
||||
throw new InvalidTypeException("Can't assign boolean value to an non-boolean");
|
||||
}
|
||||
|
||||
if ("void".equals(destination.typeName())) {
|
||||
if (destSig.isVoid()) {
|
||||
throw new InvalidTypeException("Can't assign primitive value to a void");
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
@ -1151,40 +1151,28 @@ public abstract class ReferenceTypeImpl extends TypeImpl implements ReferenceTyp
|
||||
}
|
||||
|
||||
private static boolean isOneDimensionalPrimitiveArray(String signature) {
|
||||
int i = signature.lastIndexOf('[');
|
||||
/*
|
||||
* TO DO: Centralize JNI signature knowledge.
|
||||
*
|
||||
* Ref:
|
||||
* jdk1.4/doc/guide/jpda/jdi/com/sun/jdi/doc-files/signature.html
|
||||
*/
|
||||
boolean isPA;
|
||||
if (i < 0 || signature.startsWith("[[")) {
|
||||
isPA = false;
|
||||
} else {
|
||||
char c = signature.charAt(i + 1);
|
||||
isPA = (c != 'L');
|
||||
JNITypeParser sig = new JNITypeParser(signature);
|
||||
if (sig.isArray()) {
|
||||
JNITypeParser componentSig = new JNITypeParser(sig.componentSignature());
|
||||
return componentSig.isPrimitive();
|
||||
}
|
||||
return isPA;
|
||||
return false;
|
||||
}
|
||||
|
||||
Type findType(String signature) throws ClassNotLoadedException {
|
||||
Type type;
|
||||
if (signature.length() == 1) {
|
||||
/* OTI FIX: Must be a primitive type or the void type */
|
||||
char sig = signature.charAt(0);
|
||||
if (sig == 'V') {
|
||||
type = vm.theVoidType();
|
||||
} else {
|
||||
type = vm.primitiveTypeMirror((byte)sig);
|
||||
}
|
||||
JNITypeParser sig = new JNITypeParser(signature);
|
||||
if (sig.isVoid()) {
|
||||
type = vm.theVoidType();
|
||||
} else if (sig.isPrimitive()) {
|
||||
type = vm.primitiveTypeMirror(sig.jdwpTag());
|
||||
} else {
|
||||
// Must be a reference type.
|
||||
ClassLoaderReferenceImpl loader =
|
||||
(ClassLoaderReferenceImpl)classLoader();
|
||||
(ClassLoaderReferenceImpl) classLoader();
|
||||
if ((loader == null) ||
|
||||
(isOneDimensionalPrimitiveArray(signature)) //Work around 4450091
|
||||
) {
|
||||
(isOneDimensionalPrimitiveArray(signature)) //Work around 4450091
|
||||
) {
|
||||
// Caller wants type of boot class field
|
||||
type = vm.findBootType(signature);
|
||||
} else {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
@ -40,10 +40,8 @@ abstract class ValueImpl extends MirrorImpl implements Value {
|
||||
ValueContainer destination)
|
||||
throws InvalidTypeException, ClassNotLoadedException {
|
||||
if (value == null) {
|
||||
/*
|
||||
* TO DO: Centralize JNI signature knowledge
|
||||
*/
|
||||
if (destination.signature().length() == 1) {
|
||||
JNITypeParser sig = new JNITypeParser(destination.signature());
|
||||
if (sig.isPrimitive()) {
|
||||
throw new InvalidTypeException("Can't set a primitive type to null");
|
||||
}
|
||||
return null; // no further checking or conversion necessary
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
@ -54,7 +54,8 @@ public class VoidValueImpl extends ValueImpl implements VoidValue {
|
||||
ValueImpl prepareForAssignmentTo(ValueContainer destination)
|
||||
throws InvalidTypeException
|
||||
{
|
||||
if ("void".equals(destination.typeName())) {
|
||||
JNITypeParser sig = new JNITypeParser(destination.signature());
|
||||
if (sig.isVoid()) {
|
||||
return this;
|
||||
}
|
||||
throw new InvalidTypeException();
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "ArrayReferenceImpl.h"
|
||||
#include "inStream.h"
|
||||
#include "outStream.h"
|
||||
#include "signature.h"
|
||||
|
||||
static jboolean
|
||||
length(PacketInputStream *in, PacketOutputStream *out)
|
||||
@ -204,7 +205,7 @@ writeDoubleComponents(JNIEnv *env, PacketOutputStream *out,
|
||||
|
||||
static void
|
||||
writeObjectComponents(JNIEnv *env, PacketOutputStream *out,
|
||||
jarray array, jint index, jint length)
|
||||
jarray array, jint index, jint length)
|
||||
{
|
||||
|
||||
WITH_LOCAL_REFS(env, length) {
|
||||
@ -225,6 +226,9 @@ writeObjectComponents(JNIEnv *env, PacketOutputStream *out,
|
||||
} END_WITH_LOCAL_REFS(env);
|
||||
}
|
||||
|
||||
static void writeComponents(JNIEnv *env, PacketOutputStream *out, char *signature,
|
||||
jarray array, jint index, jint length);
|
||||
|
||||
static jboolean
|
||||
getValues(PacketInputStream *in, PacketOutputStream *out)
|
||||
{
|
||||
@ -265,68 +269,14 @@ getValues(PacketInputStream *in, PacketOutputStream *out)
|
||||
|
||||
WITH_LOCAL_REFS(env, 1) {
|
||||
|
||||
jclass arrayClass;
|
||||
char *signature = NULL;
|
||||
char *componentSignature;
|
||||
jbyte typeKey;
|
||||
jvmtiError error;
|
||||
|
||||
arrayClass = JNI_FUNC_PTR(env,GetObjectClass)(env, array);
|
||||
error = classSignature(arrayClass, &signature, NULL);
|
||||
if (error != JVMTI_ERROR_NONE) {
|
||||
goto err;
|
||||
jclass arrayClass = JNI_FUNC_PTR(env,GetObjectClass)(env, array);
|
||||
jvmtiError error = classSignature(arrayClass, &signature, NULL);
|
||||
if (error == JVMTI_ERROR_NONE) {
|
||||
writeComponents(env, out, signature, array, index, length);
|
||||
jvmtiDeallocate(signature);
|
||||
}
|
||||
componentSignature = &signature[1];
|
||||
typeKey = componentSignature[0];
|
||||
|
||||
(void)outStream_writeByte(out, typeKey);
|
||||
(void)outStream_writeInt(out, length);
|
||||
|
||||
if (isObjectTag(typeKey)) {
|
||||
writeObjectComponents(env, out, array, index, length);
|
||||
} else {
|
||||
switch (typeKey) {
|
||||
case JDWP_TAG(BYTE):
|
||||
writeByteComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(CHAR):
|
||||
writeCharComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(FLOAT):
|
||||
writeFloatComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(DOUBLE):
|
||||
writeDoubleComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(INT):
|
||||
writeIntComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(LONG):
|
||||
writeLongComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(SHORT):
|
||||
writeShortComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(BOOLEAN):
|
||||
writeBooleanComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
default:
|
||||
outStream_setError(out, JDWP_ERROR(INVALID_TAG));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
jvmtiDeallocate(signature);
|
||||
|
||||
err:;
|
||||
|
||||
} END_WITH_LOCAL_REFS(env);
|
||||
|
||||
@ -338,6 +288,58 @@ getValues(PacketInputStream *in, PacketOutputStream *out)
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
static void writeComponents(JNIEnv *env, PacketOutputStream *out, char *signature,
|
||||
jarray array, jint index, jint length) {
|
||||
|
||||
char * componentSignature = componentTypeSignature(signature);
|
||||
jbyte typeKey = jdwpTag(componentSignature);
|
||||
|
||||
(void)outStream_writeByte(out, typeKey);
|
||||
(void)outStream_writeInt(out, length);
|
||||
|
||||
if (isReferenceTag(typeKey)) {
|
||||
writeObjectComponents(env, out, array, index, length);
|
||||
return;
|
||||
}
|
||||
switch (typeKey) {
|
||||
case JDWP_TAG(BYTE):
|
||||
writeByteComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(CHAR):
|
||||
writeCharComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(FLOAT):
|
||||
writeFloatComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(DOUBLE):
|
||||
writeDoubleComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(INT):
|
||||
writeIntComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(LONG):
|
||||
writeLongComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(SHORT):
|
||||
writeShortComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(BOOLEAN):
|
||||
writeBooleanComponents(env, out, array, index, length);
|
||||
break;
|
||||
|
||||
default:
|
||||
outStream_setError(out, JDWP_ERROR(INVALID_TAG));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static jdwpError
|
||||
readBooleanComponents(JNIEnv *env, PacketInputStream *in,
|
||||
jarray array, int index, int length)
|
||||
@ -477,6 +479,8 @@ readObjectComponents(JNIEnv *env, PacketInputStream *in,
|
||||
return JDWP_ERROR(NONE);
|
||||
}
|
||||
|
||||
static jdwpError readComponents(JNIEnv *env, PacketInputStream *in, char *signature,
|
||||
jarray array, jint index, jint length);
|
||||
|
||||
static jboolean
|
||||
setValues(PacketInputStream *in, PacketOutputStream *out)
|
||||
@ -515,69 +519,14 @@ setValues(PacketInputStream *in, PacketOutputStream *out)
|
||||
|
||||
WITH_LOCAL_REFS(env, 1) {
|
||||
|
||||
jclass arrayClass;
|
||||
char *signature = NULL;
|
||||
char *componentSignature;
|
||||
jvmtiError error;
|
||||
|
||||
arrayClass = JNI_FUNC_PTR(env,GetObjectClass)(env, array);
|
||||
error = classSignature(arrayClass, &signature, NULL);
|
||||
if (error != JVMTI_ERROR_NONE) {
|
||||
goto err;
|
||||
jclass arrayClass = JNI_FUNC_PTR(env,GetObjectClass)(env, array);
|
||||
jvmtiError error = classSignature(arrayClass, &signature, NULL);
|
||||
if (error == JVMTI_ERROR_NONE) {
|
||||
serror = readComponents(env, in, signature, array, index, length);
|
||||
jvmtiDeallocate(signature);
|
||||
}
|
||||
componentSignature = &signature[1];
|
||||
|
||||
switch (componentSignature[0]) {
|
||||
case JDWP_TAG(OBJECT):
|
||||
case JDWP_TAG(ARRAY):
|
||||
serror = readObjectComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(BYTE):
|
||||
serror = readByteComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(CHAR):
|
||||
serror = readCharComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(FLOAT):
|
||||
serror = readFloatComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(DOUBLE):
|
||||
serror = readDoubleComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(INT):
|
||||
serror = readIntComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(LONG):
|
||||
serror = readLongComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(SHORT):
|
||||
serror = readShortComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(BOOLEAN):
|
||||
serror = readBooleanComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
ERROR_MESSAGE(("Invalid array component signature: %s",
|
||||
componentSignature));
|
||||
EXIT_ERROR(AGENT_ERROR_INVALID_OBJECT,NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
jvmtiDeallocate(signature);
|
||||
|
||||
err:;
|
||||
|
||||
} END_WITH_LOCAL_REFS(env);
|
||||
|
||||
if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
|
||||
@ -592,6 +541,61 @@ setValues(PacketInputStream *in, PacketOutputStream *out)
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
static jdwpError readComponents(JNIEnv *env, PacketInputStream *in, char *signature,
|
||||
jarray array, jint index, jint length) {
|
||||
jdwpError serror = JDWP_ERROR(NONE);
|
||||
|
||||
char *componentSignature = componentTypeSignature(signature);
|
||||
jbyte typeKey = jdwpTag(componentSignature);
|
||||
if (isReferenceTag(typeKey)) {
|
||||
serror = readObjectComponents(env, in, array, index, length);
|
||||
return serror;
|
||||
}
|
||||
switch (typeKey) {
|
||||
case JDWP_TAG(BYTE):
|
||||
serror = readByteComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(CHAR):
|
||||
serror = readCharComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(FLOAT):
|
||||
serror = readFloatComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(DOUBLE):
|
||||
serror = readDoubleComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(INT):
|
||||
serror = readIntComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(LONG):
|
||||
serror = readLongComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(SHORT):
|
||||
serror = readShortComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
case JDWP_TAG(BOOLEAN):
|
||||
serror = readBooleanComponents(env, in, array, index, length);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
ERROR_MESSAGE(("Invalid array component signature: %s",
|
||||
componentSignature));
|
||||
EXIT_ERROR(AGENT_ERROR_INVALID_OBJECT,NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return serror;
|
||||
}
|
||||
|
||||
Command ArrayReference_Commands[] = {
|
||||
{length, "Length"},
|
||||
{getValues, "GetValues"},
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "util.h"
|
||||
#include "inStream.h"
|
||||
#include "outStream.h"
|
||||
#include "signature.h"
|
||||
|
||||
|
||||
/*
|
||||
* Determine the component class by looking thru all classes for
|
||||
@ -148,7 +150,7 @@ writeNewPrimitiveArray(JNIEnv *env, PacketOutputStream *out,
|
||||
|
||||
jarray array = NULL;
|
||||
|
||||
switch (componentSignature[0]) {
|
||||
switch (jdwpTag(componentSignature)) {
|
||||
case JDWP_TAG(BYTE):
|
||||
array = JNI_FUNC_PTR(env,NewByteArray)(env, size);
|
||||
break;
|
||||
@ -227,10 +229,10 @@ newInstance(PacketInputStream *in, PacketOutputStream *out)
|
||||
outStream_setError(out, map2jdwpError(error));
|
||||
return JNI_FALSE;
|
||||
}
|
||||
componentSignature = &signature[1];
|
||||
componentSignature = componentTypeSignature(signature);
|
||||
|
||||
if ((componentSignature[0] == JDWP_TAG(OBJECT)) ||
|
||||
(componentSignature[0] == JDWP_TAG(ARRAY))) {
|
||||
jbyte typeKey = jdwpTag(componentSignature);
|
||||
if (isReferenceTag(typeKey)) {
|
||||
writeNewObjectArray(env, out, arrayClass, size, componentSignature);
|
||||
} else {
|
||||
writeNewPrimitiveArray(env, out, arrayClass, size, componentSignature);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "ClassTypeImpl.h"
|
||||
#include "inStream.h"
|
||||
#include "outStream.h"
|
||||
#include "signature.h"
|
||||
|
||||
static jboolean
|
||||
superclass(PacketInputStream *in, PacketOutputStream *out)
|
||||
@ -58,15 +59,18 @@ readStaticFieldValue(JNIEnv *env, PacketInputStream *in, jclass clazz,
|
||||
jfieldID field, char *signature)
|
||||
{
|
||||
jvalue value;
|
||||
jdwpError serror = JDWP_ERROR(NONE);
|
||||
jbyte typeKey = jdwpTag(signature);
|
||||
|
||||
switch (signature[0]) {
|
||||
case JDWP_TAG(ARRAY):
|
||||
case JDWP_TAG(OBJECT):
|
||||
value.l = inStream_readObjectRef(env, in);
|
||||
JNI_FUNC_PTR(env,SetStaticObjectField)(env, clazz, field, value.l);
|
||||
break;
|
||||
if (isReferenceTag(typeKey)) {
|
||||
value.l = inStream_readObjectRef(env, in);
|
||||
JNI_FUNC_PTR(env,SetStaticObjectField)(env, clazz, field, value.l);
|
||||
if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
|
||||
return JDWP_ERROR(INTERNAL);
|
||||
}
|
||||
return JDWP_ERROR(NONE);
|
||||
}
|
||||
|
||||
switch (typeKey) {
|
||||
case JDWP_TAG(BYTE):
|
||||
value.b = inStream_readByte(in);
|
||||
JNI_FUNC_PTR(env,SetStaticByteField)(env, clazz, field, value.b);
|
||||
@ -109,10 +113,9 @@ readStaticFieldValue(JNIEnv *env, PacketInputStream *in, jclass clazz,
|
||||
}
|
||||
|
||||
if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
|
||||
serror = JDWP_ERROR(INTERNAL);
|
||||
return JDWP_ERROR(INTERNAL);
|
||||
}
|
||||
|
||||
return serror;
|
||||
return JDWP_ERROR(NONE);
|
||||
}
|
||||
|
||||
static jboolean
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "commonRef.h"
|
||||
#include "inStream.h"
|
||||
#include "outStream.h"
|
||||
#include "signature.h"
|
||||
|
||||
static jboolean
|
||||
referenceType(PacketInputStream *in, PacketOutputStream *out)
|
||||
@ -65,21 +66,22 @@ getValues(PacketInputStream *in, PacketOutputStream *out)
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static jvmtiError
|
||||
readFieldValue(JNIEnv *env, PacketInputStream *in, jclass clazz,
|
||||
jobject object, jfieldID field, char *signature)
|
||||
{
|
||||
jvalue value;
|
||||
jvmtiError error;
|
||||
|
||||
switch (signature[0]) {
|
||||
case JDWP_TAG(ARRAY):
|
||||
case JDWP_TAG(OBJECT):
|
||||
value.l = inStream_readObjectRef(env, in);
|
||||
JNI_FUNC_PTR(env,SetObjectField)(env, object, field, value.l);
|
||||
break;
|
||||
|
||||
jbyte typeKey = jdwpTag(signature);
|
||||
if (isReferenceTag(typeKey)) {
|
||||
value.l = inStream_readObjectRef(env, in);
|
||||
JNI_FUNC_PTR(env,SetObjectField)(env, object, field, value.l);
|
||||
if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
|
||||
return AGENT_ERROR_JNI_EXCEPTION;
|
||||
}
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
switch (typeKey) {
|
||||
case JDWP_TAG(BYTE):
|
||||
value.b = inStream_readByte(in);
|
||||
JNI_FUNC_PTR(env,SetByteField)(env, object, field, value.b);
|
||||
@ -121,12 +123,10 @@ readFieldValue(JNIEnv *env, PacketInputStream *in, jclass clazz,
|
||||
break;
|
||||
}
|
||||
|
||||
error = JVMTI_ERROR_NONE;
|
||||
if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
|
||||
error = AGENT_ERROR_JNI_EXCEPTION;
|
||||
return AGENT_ERROR_JNI_EXCEPTION;
|
||||
}
|
||||
|
||||
return error;
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
static jboolean
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
@ -67,6 +67,7 @@
|
||||
#include "classTrack.h"
|
||||
#include "commonRef.h"
|
||||
#include "debugLoop.h"
|
||||
#include "signature.h"
|
||||
|
||||
static HandlerID requestIdCounter;
|
||||
static jbyte currentSessionID;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
@ -28,6 +28,7 @@
|
||||
#include "eventHandler.h"
|
||||
#include "threadControl.h"
|
||||
#include "invoker.h"
|
||||
#include "signature.h"
|
||||
|
||||
|
||||
#define COMMAND_LOOP_THREAD_NAME "JDWP Event Helper Thread"
|
||||
@ -479,7 +480,7 @@ handleFrameEventCommandSingle(JNIEnv* env, PacketOutputStream *out,
|
||||
writeCodeLocation(out, command->clazz, command->method, command->location);
|
||||
if (command->typeKey) {
|
||||
(void)outStream_writeValue(env, out, command->typeKey, command->returnValue);
|
||||
if (isObjectTag(command->typeKey) &&
|
||||
if (isReferenceTag(command->typeKey) &&
|
||||
command->returnValue.l != NULL) {
|
||||
tossGlobalRef(env, &(command->returnValue.l));
|
||||
}
|
||||
@ -851,7 +852,7 @@ saveEventInfoRefs(JNIEnv *env, EventInfo *evinfo)
|
||||
saveGlobalRef(env, clazz, pclazz);
|
||||
}
|
||||
sig = evinfo->u.field_modification.signature_type;
|
||||
if ((sig == JDWP_TAG(ARRAY)) || (sig == JDWP_TAG(OBJECT))) {
|
||||
if (isReferenceTag(sig)) {
|
||||
if ( evinfo->u.field_modification.new_value.l != NULL ) {
|
||||
pobject = &(evinfo->u.field_modification.new_value.l);
|
||||
object = *pobject;
|
||||
@ -904,7 +905,7 @@ tossEventInfoRefs(JNIEnv *env, EventInfo *evinfo)
|
||||
tossGlobalRef(env, &(evinfo->u.field_modification.field_clazz));
|
||||
}
|
||||
sig = evinfo->u.field_modification.signature_type;
|
||||
if ((sig == JDWP_TAG(ARRAY)) || (sig == JDWP_TAG(OBJECT))) {
|
||||
if (isReferenceTag(sig)) {
|
||||
if ( evinfo->u.field_modification.new_value.l != NULL ) {
|
||||
tossGlobalRef(env, &(evinfo->u.field_modification.new_value.l));
|
||||
}
|
||||
@ -1108,7 +1109,7 @@ eventHelper_recordFrameEvent(jint id, jbyte suspendPolicy, EventIndex ei,
|
||||
/*
|
||||
* V or B C D F I J S Z L <classname> ; [ ComponentType
|
||||
*/
|
||||
if (isObjectTag(frameCommand->typeKey) &&
|
||||
if (isReferenceTag(frameCommand->typeKey) &&
|
||||
returnValue.l != NULL) {
|
||||
saveGlobalRef(env, returnValue.l, &(frameCommand->returnValue.l));
|
||||
} else {
|
||||
|
@ -424,7 +424,7 @@ inStream_clearError(PacketInputStream *stream)
|
||||
}
|
||||
|
||||
jvalue
|
||||
inStream_readValue(PacketInputStream *stream, jbyte *typeKeyPtr)
|
||||
inStream_readValue(PacketInputStream *stream)
|
||||
{
|
||||
jvalue value;
|
||||
jbyte typeKey = inStream_readByte(stream);
|
||||
@ -473,9 +473,6 @@ inStream_readValue(PacketInputStream *stream, jbyte *typeKeyPtr)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (typeKeyPtr) {
|
||||
*typeKeyPtr = typeKey;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
@ -70,7 +70,7 @@ jstring inStream_readStringRef(JNIEnv *env, PacketInputStream *stream);
|
||||
jarray inStream_readArrayRef(JNIEnv *env, PacketInputStream *stream);
|
||||
|
||||
char *inStream_readString(PacketInputStream *stream);
|
||||
jvalue inStream_readValue(struct PacketInputStream *in, jbyte *typeKeyPtr);
|
||||
jvalue inStream_readValue(struct PacketInputStream *in);
|
||||
|
||||
jdwpError inStream_skipBytes(PacketInputStream *stream, jint count);
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "eventHandler.h"
|
||||
#include "threadControl.h"
|
||||
#include "outStream.h"
|
||||
#include "signature.h"
|
||||
|
||||
static jrawMonitorID invokerLock;
|
||||
|
||||
@ -52,66 +53,21 @@ void invoker_unlock(void)
|
||||
debugMonitorExit(invokerLock);
|
||||
}
|
||||
|
||||
static jbyte
|
||||
returnTypeTag(char *signature)
|
||||
{
|
||||
char *tagPtr = strchr(signature, SIGNATURE_END_ARGS);
|
||||
JDI_ASSERT(tagPtr);
|
||||
tagPtr++; /* 1st character after the end of args */
|
||||
return (jbyte)*tagPtr;
|
||||
}
|
||||
|
||||
static jbyte
|
||||
nextArgumentTypeTag(void **cursor)
|
||||
{
|
||||
char *tagPtr = *cursor;
|
||||
jbyte argumentTag = (jbyte)*tagPtr;
|
||||
|
||||
if (*tagPtr != SIGNATURE_END_ARGS) {
|
||||
/* Skip any array modifiers */
|
||||
while (*tagPtr == JDWP_TAG(ARRAY)) {
|
||||
tagPtr++;
|
||||
}
|
||||
/* Skip class name */
|
||||
if (*tagPtr == JDWP_TAG(OBJECT)) {
|
||||
tagPtr = strchr(tagPtr, SIGNATURE_END_CLASS) + 1;
|
||||
JDI_ASSERT(tagPtr);
|
||||
} else {
|
||||
/* Skip primitive sig */
|
||||
tagPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
*cursor = tagPtr;
|
||||
return argumentTag;
|
||||
}
|
||||
|
||||
static jbyte
|
||||
firstArgumentTypeTag(char *signature, void **cursor)
|
||||
{
|
||||
JDI_ASSERT(signature[0] == SIGNATURE_BEGIN_ARGS);
|
||||
*cursor = signature + 1; /* skip to the first arg */
|
||||
return nextArgumentTypeTag(cursor);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Note: argument refs may be destroyed on out-of-memory error
|
||||
*/
|
||||
static jvmtiError
|
||||
createGlobalRefs(JNIEnv *env, InvokeRequest *request)
|
||||
{
|
||||
jvmtiError error;
|
||||
jvmtiError error = JVMTI_ERROR_NONE;
|
||||
void *cursor = NULL;
|
||||
jbyte argumentTag = 0;
|
||||
jint argIndex = 0;
|
||||
jvalue *argument = request->arguments;
|
||||
jclass clazz = NULL;
|
||||
jobject instance = NULL;
|
||||
jint argIndex;
|
||||
jbyte argumentTag;
|
||||
jvalue *argument;
|
||||
void *cursor;
|
||||
jobject *argRefs = NULL;
|
||||
|
||||
error = JVMTI_ERROR_NONE;
|
||||
|
||||
if ( request->argumentCount > 0 ) {
|
||||
/*LINTED*/
|
||||
argRefs = jvmtiAllocate((jint)(request->argumentCount*sizeof(jobject)));
|
||||
@ -138,15 +94,12 @@ createGlobalRefs(JNIEnv *env, InvokeRequest *request)
|
||||
}
|
||||
|
||||
if ( error == JVMTI_ERROR_NONE && argRefs!=NULL ) {
|
||||
argIndex = 0;
|
||||
argumentTag = firstArgumentTypeTag(request->methodSignature, &cursor);
|
||||
argument = request->arguments;
|
||||
while (argumentTag != SIGNATURE_END_ARGS) {
|
||||
methodSignature_init(request->methodSignature, &cursor);
|
||||
while (methodSignature_nextArgumentExists(&cursor, &argumentTag)) {
|
||||
if ( argIndex > request->argumentCount ) {
|
||||
break;
|
||||
}
|
||||
if ((argumentTag == JDWP_TAG(OBJECT)) ||
|
||||
(argumentTag == JDWP_TAG(ARRAY))) {
|
||||
if (isReferenceTag(argumentTag)) {
|
||||
/* Create a global ref for any non-null argument */
|
||||
if (argument->l != NULL) {
|
||||
saveGlobalRef(env, argument->l, &argRefs[argIndex]);
|
||||
@ -158,7 +111,6 @@ createGlobalRefs(JNIEnv *env, InvokeRequest *request)
|
||||
}
|
||||
argument++;
|
||||
argIndex++;
|
||||
argumentTag = nextArgumentTypeTag(&cursor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,16 +127,15 @@ createGlobalRefs(JNIEnv *env, InvokeRequest *request)
|
||||
request->instance = instance;
|
||||
if ( argRefs!=NULL ) {
|
||||
argIndex = 0;
|
||||
argumentTag = firstArgumentTypeTag(request->methodSignature, &cursor);
|
||||
methodSignature_init(request->methodSignature, &cursor);
|
||||
argument = request->arguments;
|
||||
while ( argIndex < request->argumentCount ) {
|
||||
if ((argumentTag == JDWP_TAG(OBJECT)) ||
|
||||
(argumentTag == JDWP_TAG(ARRAY))) {
|
||||
while ( methodSignature_nextArgumentExists(&cursor, &argumentTag) &&
|
||||
argIndex < request->argumentCount ) {
|
||||
if ( isReferenceTag(argumentTag) ) {
|
||||
argument->l = argRefs[argIndex];
|
||||
}
|
||||
argument++;
|
||||
argIndex++;
|
||||
argumentTag = nextArgumentTypeTag(&cursor);
|
||||
}
|
||||
jvmtiDeallocate(argRefs);
|
||||
}
|
||||
@ -218,10 +169,11 @@ createGlobalRefs(JNIEnv *env, InvokeRequest *request)
|
||||
static void
|
||||
deleteGlobalArgumentRefs(JNIEnv *env, InvokeRequest *request)
|
||||
{
|
||||
void *cursor;
|
||||
void *cursor = NULL;
|
||||
jint argIndex = 0;
|
||||
jbyte argumentTag = 0;
|
||||
jvalue *argument = request->arguments;
|
||||
jbyte argumentTag = firstArgumentTypeTag(request->methodSignature, &cursor);
|
||||
methodSignature_init(request->methodSignature, &cursor);
|
||||
|
||||
if (request->clazz != NULL) {
|
||||
tossGlobalRef(env, &(request->clazz));
|
||||
@ -230,16 +182,15 @@ deleteGlobalArgumentRefs(JNIEnv *env, InvokeRequest *request)
|
||||
tossGlobalRef(env, &(request->instance));
|
||||
}
|
||||
/* Delete global argument references */
|
||||
while (argIndex < request->argumentCount) {
|
||||
if ((argumentTag == JDWP_TAG(OBJECT)) ||
|
||||
(argumentTag == JDWP_TAG(ARRAY))) {
|
||||
while (methodSignature_nextArgumentExists(&cursor, &argumentTag) &&
|
||||
argIndex < request->argumentCount) {
|
||||
if (isReferenceTag(argumentTag)) {
|
||||
if (argument->l != NULL) {
|
||||
tossGlobalRef(env, &(argument->l));
|
||||
}
|
||||
}
|
||||
argument++;
|
||||
argIndex++;
|
||||
argumentTag = nextArgumentTypeTag(&cursor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -404,23 +355,23 @@ invokeConstructor(JNIEnv *env, InvokeRequest *request)
|
||||
static void
|
||||
invokeStatic(JNIEnv *env, InvokeRequest *request)
|
||||
{
|
||||
switch(returnTypeTag(request->methodSignature)) {
|
||||
case JDWP_TAG(OBJECT):
|
||||
case JDWP_TAG(ARRAY): {
|
||||
jobject object;
|
||||
JDI_ASSERT_MSG(request->clazz, "Request clazz null");
|
||||
object = JNI_FUNC_PTR(env,CallStaticObjectMethodA)(env,
|
||||
request->clazz,
|
||||
request->method,
|
||||
request->arguments);
|
||||
request->returnValue.l = NULL;
|
||||
if (object != NULL) {
|
||||
saveGlobalRef(env, object, &(request->returnValue.l));
|
||||
}
|
||||
break;
|
||||
jbyte returnType = methodSignature_returnTag(request->methodSignature);
|
||||
|
||||
if (isReferenceTag(returnType)) {
|
||||
jobject object;
|
||||
JDI_ASSERT_MSG(request->clazz, "Request clazz null");
|
||||
object = JNI_FUNC_PTR(env,CallStaticObjectMethodA)(env,
|
||||
request->clazz,
|
||||
request->method,
|
||||
request->arguments);
|
||||
request->returnValue.l = NULL;
|
||||
if (object != NULL) {
|
||||
saveGlobalRef(env, object, &(request->returnValue.l));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch (returnType) {
|
||||
case JDWP_TAG(BYTE):
|
||||
request->returnValue.b = JNI_FUNC_PTR(env,CallStaticByteMethodA)(env,
|
||||
request->clazz,
|
||||
@ -493,22 +444,22 @@ invokeStatic(JNIEnv *env, InvokeRequest *request)
|
||||
static void
|
||||
invokeVirtual(JNIEnv *env, InvokeRequest *request)
|
||||
{
|
||||
switch(returnTypeTag(request->methodSignature)) {
|
||||
case JDWP_TAG(OBJECT):
|
||||
case JDWP_TAG(ARRAY): {
|
||||
jobject object;
|
||||
JDI_ASSERT_MSG(request->instance, "Request instance null");
|
||||
object = JNI_FUNC_PTR(env,CallObjectMethodA)(env,
|
||||
request->instance,
|
||||
request->method,
|
||||
request->arguments);
|
||||
request->returnValue.l = NULL;
|
||||
if (object != NULL) {
|
||||
saveGlobalRef(env, object, &(request->returnValue.l));
|
||||
}
|
||||
break;
|
||||
jbyte returnType = methodSignature_returnTag(request->methodSignature);
|
||||
if (isReferenceTag(returnType)) {
|
||||
jobject object;
|
||||
JDI_ASSERT_MSG(request->instance, "Request instance null");
|
||||
object = JNI_FUNC_PTR(env,CallObjectMethodA)(env,
|
||||
request->instance,
|
||||
request->method,
|
||||
request->arguments);
|
||||
request->returnValue.l = NULL;
|
||||
if (object != NULL) {
|
||||
saveGlobalRef(env, object, &(request->returnValue.l));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (returnType) {
|
||||
case JDWP_TAG(BYTE):
|
||||
request->returnValue.b = JNI_FUNC_PTR(env,CallByteMethodA)(env,
|
||||
request->instance,
|
||||
@ -581,24 +532,24 @@ invokeVirtual(JNIEnv *env, InvokeRequest *request)
|
||||
static void
|
||||
invokeNonvirtual(JNIEnv *env, InvokeRequest *request)
|
||||
{
|
||||
switch(returnTypeTag(request->methodSignature)) {
|
||||
case JDWP_TAG(OBJECT):
|
||||
case JDWP_TAG(ARRAY): {
|
||||
jobject object;
|
||||
JDI_ASSERT_MSG(request->clazz, "Request clazz null");
|
||||
JDI_ASSERT_MSG(request->instance, "Request instance null");
|
||||
object = JNI_FUNC_PTR(env,CallNonvirtualObjectMethodA)(env,
|
||||
request->instance,
|
||||
request->clazz,
|
||||
request->method,
|
||||
request->arguments);
|
||||
request->returnValue.l = NULL;
|
||||
if (object != NULL) {
|
||||
saveGlobalRef(env, object, &(request->returnValue.l));
|
||||
}
|
||||
break;
|
||||
jbyte returnType = methodSignature_returnTag(request->methodSignature);
|
||||
if (isReferenceTag(returnType)) {
|
||||
jobject object;
|
||||
JDI_ASSERT_MSG(request->clazz, "Request clazz null");
|
||||
JDI_ASSERT_MSG(request->instance, "Request instance null");
|
||||
object = JNI_FUNC_PTR(env,CallNonvirtualObjectMethodA)(env,
|
||||
request->instance,
|
||||
request->clazz,
|
||||
request->method,
|
||||
request->arguments);
|
||||
request->returnValue.l = NULL;
|
||||
if (object != NULL) {
|
||||
saveGlobalRef(env, object, &(request->returnValue.l));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (returnType) {
|
||||
case JDWP_TAG(BYTE):
|
||||
request->returnValue.b = JNI_FUNC_PTR(env,CallNonvirtualByteMethodA)(env,
|
||||
request->instance,
|
||||
@ -797,7 +748,7 @@ invoker_completeInvokeRequest(jthread thread)
|
||||
*/
|
||||
tag = specificTypeKey(env, request->returnValue.l);
|
||||
} else {
|
||||
tag = returnTypeTag(request->methodSignature);
|
||||
tag = methodSignature_returnTag(request->methodSignature);
|
||||
}
|
||||
id = request->id;
|
||||
exc = request->exception;
|
||||
@ -805,9 +756,9 @@ invoker_completeInvokeRequest(jthread thread)
|
||||
|
||||
/* Release return value and exception references, but delay the release
|
||||
* until after the return packet was sent. */
|
||||
jbyte returnType = methodSignature_returnTag(request->methodSignature);
|
||||
mustReleaseReturnValue = request->invokeType == INVOKE_CONSTRUCTOR ||
|
||||
returnTypeTag(request->methodSignature) == JDWP_TAG(OBJECT) ||
|
||||
returnTypeTag(request->methodSignature) == JDWP_TAG(ARRAY);
|
||||
isReferenceTag(returnType);
|
||||
}
|
||||
|
||||
/*
|
||||
|
112
src/jdk.jdwp.agent/share/native/libjdwp/signature.c
Normal file
112
src/jdk.jdwp.agent/share/native/libjdwp/signature.c
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 "util.h"
|
||||
#include "signature.h"
|
||||
|
||||
|
||||
/*
|
||||
* JNI signature constants, beyond those defined in JVM_TYPE(*)
|
||||
*/
|
||||
#define SIGNATURE_BEGIN_ARGS '('
|
||||
#define SIGNATURE_END_ARGS ')'
|
||||
#define SIGNATURE_END_CLASS ';'
|
||||
|
||||
char* componentTypeSignature(const char *signature) {
|
||||
jbyte typeKey = jdwpTag(signature);
|
||||
JDI_ASSERT(isArrayTag(typeKey));
|
||||
JVM_TYPE_ASSERT(signature[1]);
|
||||
return (char*)&signature[1];
|
||||
}
|
||||
|
||||
jbyte methodSignature_returnTag(char *signature)
|
||||
{
|
||||
char *tagPtr = strchr(signature, SIGNATURE_END_ARGS);
|
||||
JDI_ASSERT(tagPtr);
|
||||
tagPtr++; /* 1st character after the end of args */
|
||||
JVM_TYPE_ASSERT((jbyte)*tagPtr);
|
||||
return (jbyte)*tagPtr;
|
||||
}
|
||||
|
||||
void methodSignature_init(char *signature, void **cursor)
|
||||
{
|
||||
JDI_ASSERT(signature[0] == SIGNATURE_BEGIN_ARGS);
|
||||
*cursor = signature + 1; /* skip to the first arg */
|
||||
}
|
||||
|
||||
|
||||
jboolean methodSignature_nextArgumentExists(void **cursor, jbyte *argumentTag)
|
||||
{
|
||||
char *tagPtr = *cursor;
|
||||
jbyte nextType = (jbyte)*tagPtr;
|
||||
|
||||
if (*tagPtr != SIGNATURE_END_ARGS) {
|
||||
/* Skip any array modifiers */
|
||||
while (*tagPtr == JDWP_TAG(ARRAY)) {
|
||||
tagPtr++;
|
||||
}
|
||||
/* Skip class name */
|
||||
if (*tagPtr == JDWP_TAG(OBJECT)) {
|
||||
tagPtr = strchr(tagPtr, SIGNATURE_END_CLASS) + 1;
|
||||
JDI_ASSERT(tagPtr);
|
||||
} else {
|
||||
/* Skip primitive sig */
|
||||
tagPtr++;
|
||||
}
|
||||
}
|
||||
*cursor = tagPtr;
|
||||
if (nextType != SIGNATURE_END_ARGS) {
|
||||
JVM_TYPE_ASSERT(nextType);
|
||||
*argumentTag = nextType;
|
||||
return JNI_TRUE;
|
||||
}
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the signature "Ljava/lang/Foo;" to a
|
||||
* classname "java.lang.Foo" compatible with the pattern.
|
||||
* Signature is overwritten in-place.
|
||||
*/
|
||||
void convertSignatureToClassname(char *convert)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = convert + 1;
|
||||
while ((*p != ';') && (*p != '\0')) {
|
||||
char c = *p;
|
||||
if (c == '/') {
|
||||
*(p-1) = '.';
|
||||
} else if (c == '.') {
|
||||
// class signature of a hidden class is "Ljava/lang/Foo.1234;"
|
||||
// map to "java.lang.Foo/1234"
|
||||
*(p-1) = '/';
|
||||
} else {
|
||||
*(p-1) = c;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
*(p-1) = '\0';
|
||||
}
|
66
src/jdk.jdwp.agent/share/native/libjdwp/signature.h
Normal file
66
src/jdk.jdwp.agent/share/native/libjdwp/signature.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef JDWP_SIGNATURE_H
|
||||
#define JDWP_SIGNATURE_H
|
||||
|
||||
#define JVM_TYPE_ASSERT(typeKey)\
|
||||
JDI_ASSERT_MSG(JDWP_Tag_OBJECT == typeKey || \
|
||||
JDWP_Tag_ARRAY == typeKey || \
|
||||
JDWP_Tag_BOOLEAN == typeKey || \
|
||||
JDWP_Tag_BYTE == typeKey || \
|
||||
JDWP_Tag_CHAR == typeKey || \
|
||||
JDWP_Tag_DOUBLE == typeKey || \
|
||||
JDWP_Tag_FLOAT == typeKey || \
|
||||
JDWP_Tag_INT == typeKey || \
|
||||
JDWP_Tag_LONG == typeKey || \
|
||||
JDWP_Tag_SHORT == typeKey || \
|
||||
JDWP_Tag_VOID == typeKey, \
|
||||
"Tag is not a JVM basic type")
|
||||
|
||||
static inline jbyte jdwpTag(const char *signature) {
|
||||
JVM_TYPE_ASSERT(signature[0]);
|
||||
return signature[0];
|
||||
}
|
||||
|
||||
static inline jboolean isReferenceTag(jbyte typeKey) {
|
||||
JVM_TYPE_ASSERT(typeKey);
|
||||
return (typeKey == JDWP_TAG(OBJECT)) || (typeKey == JDWP_TAG(ARRAY));
|
||||
}
|
||||
|
||||
static inline jboolean isArrayTag(jbyte typeKey) {
|
||||
JVM_TYPE_ASSERT(typeKey);
|
||||
return (typeKey == JDWP_TAG(ARRAY));
|
||||
}
|
||||
|
||||
char* componentTypeSignature(const char *signature);
|
||||
|
||||
void convertSignatureToClassname(char *convert);
|
||||
|
||||
void methodSignature_init(char *signature, void **cursor);
|
||||
jboolean methodSignature_nextArgumentExists(void **cursor, jbyte *argumentTag);
|
||||
jbyte methodSignature_returnTag(char *signature);
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
@ -32,6 +32,8 @@
|
||||
#include "outStream.h"
|
||||
#include "inStream.h"
|
||||
#include "invoker.h"
|
||||
#include "signature.h"
|
||||
|
||||
|
||||
/* Global data area */
|
||||
BackendGlobalData *gdata = NULL;
|
||||
@ -171,6 +173,8 @@ getStaticMethod(JNIEnv *env, jclass clazz, const char * name, const char *signat
|
||||
return method;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
util_initialize(JNIEnv *env)
|
||||
{
|
||||
@ -343,26 +347,25 @@ writeFieldValue(JNIEnv *env, PacketOutputStream *out, jobject object,
|
||||
outStream_setError(out, map2jdwpError(error));
|
||||
return;
|
||||
}
|
||||
typeKey = signature[0];
|
||||
typeKey = jdwpTag(signature);
|
||||
jvmtiDeallocate(signature);
|
||||
|
||||
/*
|
||||
* For primitive types, the type key is bounced back as is. Objects
|
||||
* are handled in the switch statement below.
|
||||
*/
|
||||
if ((typeKey != JDWP_TAG(OBJECT)) && (typeKey != JDWP_TAG(ARRAY))) {
|
||||
(void)outStream_writeByte(out, typeKey);
|
||||
if (isReferenceTag(typeKey)) {
|
||||
|
||||
jobject value = JNI_FUNC_PTR(env,GetObjectField)(env, object, field);
|
||||
(void)outStream_writeByte(out, specificTypeKey(env, value));
|
||||
(void)outStream_writeObjectRef(env, out, value);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
switch (typeKey) {
|
||||
case JDWP_TAG(OBJECT):
|
||||
case JDWP_TAG(ARRAY): {
|
||||
jobject value = JNI_FUNC_PTR(env,GetObjectField)(env, object, field);
|
||||
(void)outStream_writeByte(out, specificTypeKey(env, value));
|
||||
(void)outStream_writeObjectRef(env, out, value);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* For primitive types, the type key is bounced back as is.
|
||||
*/
|
||||
|
||||
(void)outStream_writeByte(out, typeKey);
|
||||
|
||||
switch (typeKey) {
|
||||
case JDWP_TAG(BYTE):
|
||||
(void)outStream_writeByte(out,
|
||||
JNI_FUNC_PTR(env,GetByteField)(env, object, field));
|
||||
@ -418,26 +421,24 @@ writeStaticFieldValue(JNIEnv *env, PacketOutputStream *out, jclass clazz,
|
||||
outStream_setError(out, map2jdwpError(error));
|
||||
return;
|
||||
}
|
||||
typeKey = signature[0];
|
||||
typeKey = jdwpTag(signature);
|
||||
jvmtiDeallocate(signature);
|
||||
|
||||
/*
|
||||
* For primitive types, the type key is bounced back as is. Objects
|
||||
* are handled in the switch statement below.
|
||||
*/
|
||||
if ((typeKey != JDWP_TAG(OBJECT)) && (typeKey != JDWP_TAG(ARRAY))) {
|
||||
(void)outStream_writeByte(out, typeKey);
|
||||
|
||||
if (isReferenceTag(typeKey)) {
|
||||
|
||||
jobject value = JNI_FUNC_PTR(env,GetStaticObjectField)(env, clazz, field);
|
||||
(void)outStream_writeByte(out, specificTypeKey(env, value));
|
||||
(void)outStream_writeObjectRef(env, out, value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* For primitive types, the type key is bounced back as is.
|
||||
*/
|
||||
(void)outStream_writeByte(out, typeKey);
|
||||
switch (typeKey) {
|
||||
case JDWP_TAG(OBJECT):
|
||||
case JDWP_TAG(ARRAY): {
|
||||
jobject value = JNI_FUNC_PTR(env,GetStaticObjectField)(env, clazz, field);
|
||||
(void)outStream_writeByte(out, specificTypeKey(env, value));
|
||||
(void)outStream_writeObjectRef(env, out, value);
|
||||
break;
|
||||
}
|
||||
|
||||
case JDWP_TAG(BYTE):
|
||||
(void)outStream_writeByte(out,
|
||||
JNI_FUNC_PTR(env,GetStaticByteField)(env, clazz, field));
|
||||
@ -570,7 +571,7 @@ sharedInvoke(PacketInputStream *in, PacketOutputStream *out)
|
||||
return JNI_TRUE;
|
||||
}
|
||||
for (i = 0; (i < argumentCount) && !inStream_error(in); i++) {
|
||||
arguments[i] = inStream_readValue(in, NULL);
|
||||
arguments[i] = inStream_readValue(in);
|
||||
}
|
||||
if (inStream_error(in)) {
|
||||
return JNI_TRUE;
|
||||
@ -977,32 +978,6 @@ getSourceDebugExtension(jclass clazz, char **extensionPtr)
|
||||
(gdata->jvmti, clazz, extensionPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the signature "Ljava/lang/Foo;" to a
|
||||
* classname "java.lang.Foo" compatible with the pattern.
|
||||
* Signature is overwritten in-place.
|
||||
*/
|
||||
void
|
||||
convertSignatureToClassname(char *convert)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = convert + 1;
|
||||
while ((*p != ';') && (*p != '\0')) {
|
||||
char c = *p;
|
||||
if (c == '/') {
|
||||
*(p-1) = '.';
|
||||
} else if (c == '.') {
|
||||
// class signature of a hidden class is "Ljava/lang/Foo.1234;"
|
||||
// map to "java.lang.Foo/1234"
|
||||
*(p-1) = '/';
|
||||
} else {
|
||||
*(p-1) = c;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
*(p-1) = '\0';
|
||||
}
|
||||
|
||||
static void
|
||||
handleInterrupt(void)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, 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
|
||||
@ -251,13 +251,6 @@ typedef struct ObjectBatch {
|
||||
jint count;
|
||||
} ObjectBatch;
|
||||
|
||||
/*
|
||||
* JNI signature constants, beyond those defined in JDWP_TAG(*)
|
||||
*/
|
||||
#define SIGNATURE_BEGIN_ARGS '('
|
||||
#define SIGNATURE_END_ARGS ')'
|
||||
#define SIGNATURE_END_CLASS ';'
|
||||
|
||||
/*
|
||||
* Modifier flags for classes, fields, methods
|
||||
*/
|
||||
@ -291,7 +284,6 @@ jbyte referenceTypeTag(jclass clazz);
|
||||
jbyte specificTypeKey(JNIEnv *env, jobject object);
|
||||
jboolean isObjectTag(jbyte tag);
|
||||
jvmtiError spawnNewThread(jvmtiStartFunction func, void *arg, char *name);
|
||||
void convertSignatureToClassname(char *convert);
|
||||
void writeCodeLocation(struct PacketOutputStream *out, jclass clazz,
|
||||
jmethodID method, jlocation location);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user