8241080: Consolidate signature parsing code in serviceability tools
Reviewed-by: sspitsyn, cjplummer
This commit is contained in:
parent
fa36d28aff
commit
9d4872f612
src
jdk.jdi/share/classes/com/sun/tools/jdi
ArrayTypeImpl.javaEventSetImpl.javaJNITypeParser.javaObjectReferenceImpl.javaPrimitiveValueImpl.javaReferenceTypeImpl.javaValueImpl.javaVoidValueImpl.java
jdk.jdwp.agent/share/native/libjdwp
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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() {
|
public String componentSignature() {
|
||||||
return signature().substring(1); // Just skip the leading '['
|
JNITypeParser sig = new JNITypeParser(signature());
|
||||||
|
return sig.componentSignature();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String componentTypeName() {
|
public String componentTypeName() {
|
||||||
@ -90,8 +91,9 @@ public class ArrayTypeImpl extends ReferenceTypeImpl
|
|||||||
* this method is sometimes needed for proper type checking.
|
* this method is sometimes needed for proper type checking.
|
||||||
*/
|
*/
|
||||||
Type findComponentType(String signature) throws ClassNotLoadedException {
|
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
|
// It's a reference type
|
||||||
JNITypeParser parser = new JNITypeParser(componentSignature());
|
JNITypeParser parser = new JNITypeParser(componentSignature());
|
||||||
List<ReferenceType> list = vm.classesByName(parser.typeName());
|
List<ReferenceType> list = vm.classesByName(parser.typeName());
|
||||||
@ -109,7 +111,7 @@ public class ArrayTypeImpl extends ReferenceTypeImpl
|
|||||||
throw new ClassNotLoadedException(componentTypeName());
|
throw new ClassNotLoadedException(componentTypeName());
|
||||||
} else {
|
} else {
|
||||||
// It's a primitive type
|
// 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() {
|
public String className() {
|
||||||
assert classSignature.startsWith("L") && classSignature.endsWith(";");
|
return JNITypeParser.convertSignatureToClassname(classSignature);
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String classSignature() {
|
public String classSignature() {
|
||||||
|
@ -113,10 +113,69 @@ public class JNITypeParser {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte jdwpTag() {
|
||||||
|
return (byte) signature().charAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
String componentSignature(int level) {
|
String componentSignature(int level) {
|
||||||
|
assert level <= dimensionCount();
|
||||||
return signature().substring(level);
|
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() {
|
private synchronized List<String> signatureList() {
|
||||||
if (signatureList == null) {
|
if (signatureList == null) {
|
||||||
signatureList = new ArrayList<>(10);
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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
|
* type which might cause a confusing ClassNotLoadedException if
|
||||||
* the destination is primitive or an array.
|
* the destination is primitive or an array.
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
* TO DO: Centralize JNI signature knowledge
|
JNITypeParser destSig = new JNITypeParser(destination.signature());
|
||||||
*/
|
JNITypeParser sourceSig = new JNITypeParser(type().signature());
|
||||||
if (destination.signature().length() == 1) {
|
if (destSig.isPrimitive()) {
|
||||||
throw new InvalidTypeException("Can't assign object value to primitive");
|
throw new InvalidTypeException("Can't assign object value to primitive");
|
||||||
}
|
}
|
||||||
if ((destination.signature().charAt(0) == '[') &&
|
if (destSig.isArray() && !sourceSig.isArray()) {
|
||||||
(type().signature().charAt(0) != '[')) {
|
|
||||||
throw new InvalidTypeException("Can't assign non-array value to an array");
|
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");
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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)
|
ValueImpl convertForAssignmentTo(ValueContainer destination)
|
||||||
throws InvalidTypeException
|
throws InvalidTypeException
|
||||||
{
|
{
|
||||||
/*
|
JNITypeParser destSig = new JNITypeParser(destination.signature());
|
||||||
* TO DO: Centralize JNI signature knowledge
|
JNITypeParser sourceSig = new JNITypeParser(type().signature());
|
||||||
*/
|
|
||||||
if (destination.signature().length() > 1) {
|
if (destSig.isReference()) {
|
||||||
throw new InvalidTypeException("Can't assign primitive value to object");
|
throw new InvalidTypeException("Can't assign primitive value to object");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((destination.signature().charAt(0) == 'Z') &&
|
if (destSig.isBoolean() && !sourceSig.isBoolean()) {
|
||||||
(type().signature().charAt(0) != 'Z')) {
|
|
||||||
throw new InvalidTypeException("Can't assign non-boolean value to a boolean");
|
throw new InvalidTypeException("Can't assign non-boolean value to a boolean");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((destination.signature().charAt(0) != 'Z') &&
|
if (!destSig.isBoolean() && sourceSig.isBoolean()) {
|
||||||
(type().signature().charAt(0) == 'Z')) {
|
|
||||||
throw new InvalidTypeException("Can't assign boolean value to an non-boolean");
|
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");
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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) {
|
private static boolean isOneDimensionalPrimitiveArray(String signature) {
|
||||||
int i = signature.lastIndexOf('[');
|
JNITypeParser sig = new JNITypeParser(signature);
|
||||||
/*
|
if (sig.isArray()) {
|
||||||
* TO DO: Centralize JNI signature knowledge.
|
JNITypeParser componentSig = new JNITypeParser(sig.componentSignature());
|
||||||
*
|
return componentSig.isPrimitive();
|
||||||
* 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');
|
|
||||||
}
|
}
|
||||||
return isPA;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type findType(String signature) throws ClassNotLoadedException {
|
Type findType(String signature) throws ClassNotLoadedException {
|
||||||
Type type;
|
Type type;
|
||||||
if (signature.length() == 1) {
|
JNITypeParser sig = new JNITypeParser(signature);
|
||||||
/* OTI FIX: Must be a primitive type or the void type */
|
if (sig.isVoid()) {
|
||||||
char sig = signature.charAt(0);
|
type = vm.theVoidType();
|
||||||
if (sig == 'V') {
|
} else if (sig.isPrimitive()) {
|
||||||
type = vm.theVoidType();
|
type = vm.primitiveTypeMirror(sig.jdwpTag());
|
||||||
} else {
|
|
||||||
type = vm.primitiveTypeMirror((byte)sig);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Must be a reference type.
|
// Must be a reference type.
|
||||||
ClassLoaderReferenceImpl loader =
|
ClassLoaderReferenceImpl loader =
|
||||||
(ClassLoaderReferenceImpl)classLoader();
|
(ClassLoaderReferenceImpl) classLoader();
|
||||||
if ((loader == null) ||
|
if ((loader == null) ||
|
||||||
(isOneDimensionalPrimitiveArray(signature)) //Work around 4450091
|
(isOneDimensionalPrimitiveArray(signature)) //Work around 4450091
|
||||||
) {
|
) {
|
||||||
// Caller wants type of boot class field
|
// Caller wants type of boot class field
|
||||||
type = vm.findBootType(signature);
|
type = vm.findBootType(signature);
|
||||||
} else {
|
} 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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)
|
ValueContainer destination)
|
||||||
throws InvalidTypeException, ClassNotLoadedException {
|
throws InvalidTypeException, ClassNotLoadedException {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
/*
|
JNITypeParser sig = new JNITypeParser(destination.signature());
|
||||||
* TO DO: Centralize JNI signature knowledge
|
if (sig.isPrimitive()) {
|
||||||
*/
|
|
||||||
if (destination.signature().length() == 1) {
|
|
||||||
throw new InvalidTypeException("Can't set a primitive type to null");
|
throw new InvalidTypeException("Can't set a primitive type to null");
|
||||||
}
|
}
|
||||||
return null; // no further checking or conversion necessary
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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)
|
ValueImpl prepareForAssignmentTo(ValueContainer destination)
|
||||||
throws InvalidTypeException
|
throws InvalidTypeException
|
||||||
{
|
{
|
||||||
if ("void".equals(destination.typeName())) {
|
JNITypeParser sig = new JNITypeParser(destination.signature());
|
||||||
|
if (sig.isVoid()) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
throw new InvalidTypeException();
|
throw new InvalidTypeException();
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "ArrayReferenceImpl.h"
|
#include "ArrayReferenceImpl.h"
|
||||||
#include "inStream.h"
|
#include "inStream.h"
|
||||||
#include "outStream.h"
|
#include "outStream.h"
|
||||||
|
#include "signature.h"
|
||||||
|
|
||||||
static jboolean
|
static jboolean
|
||||||
length(PacketInputStream *in, PacketOutputStream *out)
|
length(PacketInputStream *in, PacketOutputStream *out)
|
||||||
@ -204,7 +205,7 @@ writeDoubleComponents(JNIEnv *env, PacketOutputStream *out,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
writeObjectComponents(JNIEnv *env, PacketOutputStream *out,
|
writeObjectComponents(JNIEnv *env, PacketOutputStream *out,
|
||||||
jarray array, jint index, jint length)
|
jarray array, jint index, jint length)
|
||||||
{
|
{
|
||||||
|
|
||||||
WITH_LOCAL_REFS(env, length) {
|
WITH_LOCAL_REFS(env, length) {
|
||||||
@ -225,6 +226,9 @@ writeObjectComponents(JNIEnv *env, PacketOutputStream *out,
|
|||||||
} END_WITH_LOCAL_REFS(env);
|
} END_WITH_LOCAL_REFS(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void writeComponents(JNIEnv *env, PacketOutputStream *out, char *signature,
|
||||||
|
jarray array, jint index, jint length);
|
||||||
|
|
||||||
static jboolean
|
static jboolean
|
||||||
getValues(PacketInputStream *in, PacketOutputStream *out)
|
getValues(PacketInputStream *in, PacketOutputStream *out)
|
||||||
{
|
{
|
||||||
@ -265,68 +269,14 @@ getValues(PacketInputStream *in, PacketOutputStream *out)
|
|||||||
|
|
||||||
WITH_LOCAL_REFS(env, 1) {
|
WITH_LOCAL_REFS(env, 1) {
|
||||||
|
|
||||||
jclass arrayClass;
|
|
||||||
char *signature = NULL;
|
char *signature = NULL;
|
||||||
char *componentSignature;
|
|
||||||
jbyte typeKey;
|
|
||||||
jvmtiError error;
|
|
||||||
|
|
||||||
arrayClass = JNI_FUNC_PTR(env,GetObjectClass)(env, array);
|
jclass arrayClass = JNI_FUNC_PTR(env,GetObjectClass)(env, array);
|
||||||
error = classSignature(arrayClass, &signature, NULL);
|
jvmtiError error = classSignature(arrayClass, &signature, NULL);
|
||||||
if (error != JVMTI_ERROR_NONE) {
|
if (error == JVMTI_ERROR_NONE) {
|
||||||
goto err;
|
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);
|
} END_WITH_LOCAL_REFS(env);
|
||||||
|
|
||||||
@ -338,6 +288,58 @@ getValues(PacketInputStream *in, PacketOutputStream *out)
|
|||||||
return JNI_TRUE;
|
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
|
static jdwpError
|
||||||
readBooleanComponents(JNIEnv *env, PacketInputStream *in,
|
readBooleanComponents(JNIEnv *env, PacketInputStream *in,
|
||||||
jarray array, int index, int length)
|
jarray array, int index, int length)
|
||||||
@ -477,6 +479,8 @@ readObjectComponents(JNIEnv *env, PacketInputStream *in,
|
|||||||
return JDWP_ERROR(NONE);
|
return JDWP_ERROR(NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static jdwpError readComponents(JNIEnv *env, PacketInputStream *in, char *signature,
|
||||||
|
jarray array, jint index, jint length);
|
||||||
|
|
||||||
static jboolean
|
static jboolean
|
||||||
setValues(PacketInputStream *in, PacketOutputStream *out)
|
setValues(PacketInputStream *in, PacketOutputStream *out)
|
||||||
@ -515,69 +519,14 @@ setValues(PacketInputStream *in, PacketOutputStream *out)
|
|||||||
|
|
||||||
WITH_LOCAL_REFS(env, 1) {
|
WITH_LOCAL_REFS(env, 1) {
|
||||||
|
|
||||||
jclass arrayClass;
|
|
||||||
char *signature = NULL;
|
char *signature = NULL;
|
||||||
char *componentSignature;
|
|
||||||
jvmtiError error;
|
|
||||||
|
|
||||||
arrayClass = JNI_FUNC_PTR(env,GetObjectClass)(env, array);
|
jclass arrayClass = JNI_FUNC_PTR(env,GetObjectClass)(env, array);
|
||||||
error = classSignature(arrayClass, &signature, NULL);
|
jvmtiError error = classSignature(arrayClass, &signature, NULL);
|
||||||
if (error != JVMTI_ERROR_NONE) {
|
if (error == JVMTI_ERROR_NONE) {
|
||||||
goto err;
|
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);
|
} END_WITH_LOCAL_REFS(env);
|
||||||
|
|
||||||
if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
|
if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
|
||||||
@ -592,6 +541,61 @@ setValues(PacketInputStream *in, PacketOutputStream *out)
|
|||||||
return JNI_TRUE;
|
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[] = {
|
Command ArrayReference_Commands[] = {
|
||||||
{length, "Length"},
|
{length, "Length"},
|
||||||
{getValues, "GetValues"},
|
{getValues, "GetValues"},
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "inStream.h"
|
#include "inStream.h"
|
||||||
#include "outStream.h"
|
#include "outStream.h"
|
||||||
|
#include "signature.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine the component class by looking thru all classes for
|
* Determine the component class by looking thru all classes for
|
||||||
@ -148,7 +150,7 @@ writeNewPrimitiveArray(JNIEnv *env, PacketOutputStream *out,
|
|||||||
|
|
||||||
jarray array = NULL;
|
jarray array = NULL;
|
||||||
|
|
||||||
switch (componentSignature[0]) {
|
switch (jdwpTag(componentSignature)) {
|
||||||
case JDWP_TAG(BYTE):
|
case JDWP_TAG(BYTE):
|
||||||
array = JNI_FUNC_PTR(env,NewByteArray)(env, size);
|
array = JNI_FUNC_PTR(env,NewByteArray)(env, size);
|
||||||
break;
|
break;
|
||||||
@ -227,10 +229,10 @@ newInstance(PacketInputStream *in, PacketOutputStream *out)
|
|||||||
outStream_setError(out, map2jdwpError(error));
|
outStream_setError(out, map2jdwpError(error));
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
componentSignature = &signature[1];
|
componentSignature = componentTypeSignature(signature);
|
||||||
|
|
||||||
if ((componentSignature[0] == JDWP_TAG(OBJECT)) ||
|
jbyte typeKey = jdwpTag(componentSignature);
|
||||||
(componentSignature[0] == JDWP_TAG(ARRAY))) {
|
if (isReferenceTag(typeKey)) {
|
||||||
writeNewObjectArray(env, out, arrayClass, size, componentSignature);
|
writeNewObjectArray(env, out, arrayClass, size, componentSignature);
|
||||||
} else {
|
} else {
|
||||||
writeNewPrimitiveArray(env, out, arrayClass, size, componentSignature);
|
writeNewPrimitiveArray(env, out, arrayClass, size, componentSignature);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "ClassTypeImpl.h"
|
#include "ClassTypeImpl.h"
|
||||||
#include "inStream.h"
|
#include "inStream.h"
|
||||||
#include "outStream.h"
|
#include "outStream.h"
|
||||||
|
#include "signature.h"
|
||||||
|
|
||||||
static jboolean
|
static jboolean
|
||||||
superclass(PacketInputStream *in, PacketOutputStream *out)
|
superclass(PacketInputStream *in, PacketOutputStream *out)
|
||||||
@ -58,15 +59,18 @@ readStaticFieldValue(JNIEnv *env, PacketInputStream *in, jclass clazz,
|
|||||||
jfieldID field, char *signature)
|
jfieldID field, char *signature)
|
||||||
{
|
{
|
||||||
jvalue value;
|
jvalue value;
|
||||||
jdwpError serror = JDWP_ERROR(NONE);
|
jbyte typeKey = jdwpTag(signature);
|
||||||
|
|
||||||
switch (signature[0]) {
|
if (isReferenceTag(typeKey)) {
|
||||||
case JDWP_TAG(ARRAY):
|
value.l = inStream_readObjectRef(env, in);
|
||||||
case JDWP_TAG(OBJECT):
|
JNI_FUNC_PTR(env,SetStaticObjectField)(env, clazz, field, value.l);
|
||||||
value.l = inStream_readObjectRef(env, in);
|
if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
|
||||||
JNI_FUNC_PTR(env,SetStaticObjectField)(env, clazz, field, value.l);
|
return JDWP_ERROR(INTERNAL);
|
||||||
break;
|
}
|
||||||
|
return JDWP_ERROR(NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (typeKey) {
|
||||||
case JDWP_TAG(BYTE):
|
case JDWP_TAG(BYTE):
|
||||||
value.b = inStream_readByte(in);
|
value.b = inStream_readByte(in);
|
||||||
JNI_FUNC_PTR(env,SetStaticByteField)(env, clazz, field, value.b);
|
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)) {
|
if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
|
||||||
serror = JDWP_ERROR(INTERNAL);
|
return JDWP_ERROR(INTERNAL);
|
||||||
}
|
}
|
||||||
|
return JDWP_ERROR(NONE);
|
||||||
return serror;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static jboolean
|
static jboolean
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "commonRef.h"
|
#include "commonRef.h"
|
||||||
#include "inStream.h"
|
#include "inStream.h"
|
||||||
#include "outStream.h"
|
#include "outStream.h"
|
||||||
|
#include "signature.h"
|
||||||
|
|
||||||
static jboolean
|
static jboolean
|
||||||
referenceType(PacketInputStream *in, PacketOutputStream *out)
|
referenceType(PacketInputStream *in, PacketOutputStream *out)
|
||||||
@ -65,21 +66,22 @@ getValues(PacketInputStream *in, PacketOutputStream *out)
|
|||||||
return JNI_TRUE;
|
return JNI_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static jvmtiError
|
static jvmtiError
|
||||||
readFieldValue(JNIEnv *env, PacketInputStream *in, jclass clazz,
|
readFieldValue(JNIEnv *env, PacketInputStream *in, jclass clazz,
|
||||||
jobject object, jfieldID field, char *signature)
|
jobject object, jfieldID field, char *signature)
|
||||||
{
|
{
|
||||||
jvalue value;
|
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):
|
case JDWP_TAG(BYTE):
|
||||||
value.b = inStream_readByte(in);
|
value.b = inStream_readByte(in);
|
||||||
JNI_FUNC_PTR(env,SetByteField)(env, object, field, value.b);
|
JNI_FUNC_PTR(env,SetByteField)(env, object, field, value.b);
|
||||||
@ -121,12 +123,10 @@ readFieldValue(JNIEnv *env, PacketInputStream *in, jclass clazz,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = JVMTI_ERROR_NONE;
|
|
||||||
if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
|
if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
|
||||||
error = AGENT_ERROR_JNI_EXCEPTION;
|
return AGENT_ERROR_JNI_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
return JVMTI_ERROR_NONE;
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static jboolean
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -67,6 +67,7 @@
|
|||||||
#include "classTrack.h"
|
#include "classTrack.h"
|
||||||
#include "commonRef.h"
|
#include "commonRef.h"
|
||||||
#include "debugLoop.h"
|
#include "debugLoop.h"
|
||||||
|
#include "signature.h"
|
||||||
|
|
||||||
static HandlerID requestIdCounter;
|
static HandlerID requestIdCounter;
|
||||||
static jbyte currentSessionID;
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -28,6 +28,7 @@
|
|||||||
#include "eventHandler.h"
|
#include "eventHandler.h"
|
||||||
#include "threadControl.h"
|
#include "threadControl.h"
|
||||||
#include "invoker.h"
|
#include "invoker.h"
|
||||||
|
#include "signature.h"
|
||||||
|
|
||||||
|
|
||||||
#define COMMAND_LOOP_THREAD_NAME "JDWP Event Helper Thread"
|
#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);
|
writeCodeLocation(out, command->clazz, command->method, command->location);
|
||||||
if (command->typeKey) {
|
if (command->typeKey) {
|
||||||
(void)outStream_writeValue(env, out, command->typeKey, command->returnValue);
|
(void)outStream_writeValue(env, out, command->typeKey, command->returnValue);
|
||||||
if (isObjectTag(command->typeKey) &&
|
if (isReferenceTag(command->typeKey) &&
|
||||||
command->returnValue.l != NULL) {
|
command->returnValue.l != NULL) {
|
||||||
tossGlobalRef(env, &(command->returnValue.l));
|
tossGlobalRef(env, &(command->returnValue.l));
|
||||||
}
|
}
|
||||||
@ -851,7 +852,7 @@ saveEventInfoRefs(JNIEnv *env, EventInfo *evinfo)
|
|||||||
saveGlobalRef(env, clazz, pclazz);
|
saveGlobalRef(env, clazz, pclazz);
|
||||||
}
|
}
|
||||||
sig = evinfo->u.field_modification.signature_type;
|
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 ) {
|
if ( evinfo->u.field_modification.new_value.l != NULL ) {
|
||||||
pobject = &(evinfo->u.field_modification.new_value.l);
|
pobject = &(evinfo->u.field_modification.new_value.l);
|
||||||
object = *pobject;
|
object = *pobject;
|
||||||
@ -904,7 +905,7 @@ tossEventInfoRefs(JNIEnv *env, EventInfo *evinfo)
|
|||||||
tossGlobalRef(env, &(evinfo->u.field_modification.field_clazz));
|
tossGlobalRef(env, &(evinfo->u.field_modification.field_clazz));
|
||||||
}
|
}
|
||||||
sig = evinfo->u.field_modification.signature_type;
|
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 ) {
|
if ( evinfo->u.field_modification.new_value.l != NULL ) {
|
||||||
tossGlobalRef(env, &(evinfo->u.field_modification.new_value.l));
|
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
|
* V or B C D F I J S Z L <classname> ; [ ComponentType
|
||||||
*/
|
*/
|
||||||
if (isObjectTag(frameCommand->typeKey) &&
|
if (isReferenceTag(frameCommand->typeKey) &&
|
||||||
returnValue.l != NULL) {
|
returnValue.l != NULL) {
|
||||||
saveGlobalRef(env, returnValue.l, &(frameCommand->returnValue.l));
|
saveGlobalRef(env, returnValue.l, &(frameCommand->returnValue.l));
|
||||||
} else {
|
} else {
|
||||||
|
@ -424,7 +424,7 @@ inStream_clearError(PacketInputStream *stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
jvalue
|
jvalue
|
||||||
inStream_readValue(PacketInputStream *stream, jbyte *typeKeyPtr)
|
inStream_readValue(PacketInputStream *stream)
|
||||||
{
|
{
|
||||||
jvalue value;
|
jvalue value;
|
||||||
jbyte typeKey = inStream_readByte(stream);
|
jbyte typeKey = inStream_readByte(stream);
|
||||||
@ -473,9 +473,6 @@ inStream_readValue(PacketInputStream *stream, jbyte *typeKeyPtr)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeKeyPtr) {
|
|
||||||
*typeKeyPtr = typeKey;
|
|
||||||
}
|
|
||||||
return value;
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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);
|
jarray inStream_readArrayRef(JNIEnv *env, PacketInputStream *stream);
|
||||||
|
|
||||||
char *inStream_readString(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);
|
jdwpError inStream_skipBytes(PacketInputStream *stream, jint count);
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "eventHandler.h"
|
#include "eventHandler.h"
|
||||||
#include "threadControl.h"
|
#include "threadControl.h"
|
||||||
#include "outStream.h"
|
#include "outStream.h"
|
||||||
|
#include "signature.h"
|
||||||
|
|
||||||
static jrawMonitorID invokerLock;
|
static jrawMonitorID invokerLock;
|
||||||
|
|
||||||
@ -52,66 +53,21 @@ void invoker_unlock(void)
|
|||||||
debugMonitorExit(invokerLock);
|
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
|
* Note: argument refs may be destroyed on out-of-memory error
|
||||||
*/
|
*/
|
||||||
static jvmtiError
|
static jvmtiError
|
||||||
createGlobalRefs(JNIEnv *env, InvokeRequest *request)
|
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;
|
jclass clazz = NULL;
|
||||||
jobject instance = NULL;
|
jobject instance = NULL;
|
||||||
jint argIndex;
|
|
||||||
jbyte argumentTag;
|
|
||||||
jvalue *argument;
|
|
||||||
void *cursor;
|
|
||||||
jobject *argRefs = NULL;
|
jobject *argRefs = NULL;
|
||||||
|
|
||||||
error = JVMTI_ERROR_NONE;
|
|
||||||
|
|
||||||
if ( request->argumentCount > 0 ) {
|
if ( request->argumentCount > 0 ) {
|
||||||
/*LINTED*/
|
/*LINTED*/
|
||||||
argRefs = jvmtiAllocate((jint)(request->argumentCount*sizeof(jobject)));
|
argRefs = jvmtiAllocate((jint)(request->argumentCount*sizeof(jobject)));
|
||||||
@ -138,15 +94,12 @@ createGlobalRefs(JNIEnv *env, InvokeRequest *request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( error == JVMTI_ERROR_NONE && argRefs!=NULL ) {
|
if ( error == JVMTI_ERROR_NONE && argRefs!=NULL ) {
|
||||||
argIndex = 0;
|
methodSignature_init(request->methodSignature, &cursor);
|
||||||
argumentTag = firstArgumentTypeTag(request->methodSignature, &cursor);
|
while (methodSignature_nextArgumentExists(&cursor, &argumentTag)) {
|
||||||
argument = request->arguments;
|
|
||||||
while (argumentTag != SIGNATURE_END_ARGS) {
|
|
||||||
if ( argIndex > request->argumentCount ) {
|
if ( argIndex > request->argumentCount ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((argumentTag == JDWP_TAG(OBJECT)) ||
|
if (isReferenceTag(argumentTag)) {
|
||||||
(argumentTag == JDWP_TAG(ARRAY))) {
|
|
||||||
/* Create a global ref for any non-null argument */
|
/* Create a global ref for any non-null argument */
|
||||||
if (argument->l != NULL) {
|
if (argument->l != NULL) {
|
||||||
saveGlobalRef(env, argument->l, &argRefs[argIndex]);
|
saveGlobalRef(env, argument->l, &argRefs[argIndex]);
|
||||||
@ -158,7 +111,6 @@ createGlobalRefs(JNIEnv *env, InvokeRequest *request)
|
|||||||
}
|
}
|
||||||
argument++;
|
argument++;
|
||||||
argIndex++;
|
argIndex++;
|
||||||
argumentTag = nextArgumentTypeTag(&cursor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,16 +127,15 @@ createGlobalRefs(JNIEnv *env, InvokeRequest *request)
|
|||||||
request->instance = instance;
|
request->instance = instance;
|
||||||
if ( argRefs!=NULL ) {
|
if ( argRefs!=NULL ) {
|
||||||
argIndex = 0;
|
argIndex = 0;
|
||||||
argumentTag = firstArgumentTypeTag(request->methodSignature, &cursor);
|
methodSignature_init(request->methodSignature, &cursor);
|
||||||
argument = request->arguments;
|
argument = request->arguments;
|
||||||
while ( argIndex < request->argumentCount ) {
|
while ( methodSignature_nextArgumentExists(&cursor, &argumentTag) &&
|
||||||
if ((argumentTag == JDWP_TAG(OBJECT)) ||
|
argIndex < request->argumentCount ) {
|
||||||
(argumentTag == JDWP_TAG(ARRAY))) {
|
if ( isReferenceTag(argumentTag) ) {
|
||||||
argument->l = argRefs[argIndex];
|
argument->l = argRefs[argIndex];
|
||||||
}
|
}
|
||||||
argument++;
|
argument++;
|
||||||
argIndex++;
|
argIndex++;
|
||||||
argumentTag = nextArgumentTypeTag(&cursor);
|
|
||||||
}
|
}
|
||||||
jvmtiDeallocate(argRefs);
|
jvmtiDeallocate(argRefs);
|
||||||
}
|
}
|
||||||
@ -218,10 +169,11 @@ createGlobalRefs(JNIEnv *env, InvokeRequest *request)
|
|||||||
static void
|
static void
|
||||||
deleteGlobalArgumentRefs(JNIEnv *env, InvokeRequest *request)
|
deleteGlobalArgumentRefs(JNIEnv *env, InvokeRequest *request)
|
||||||
{
|
{
|
||||||
void *cursor;
|
void *cursor = NULL;
|
||||||
jint argIndex = 0;
|
jint argIndex = 0;
|
||||||
|
jbyte argumentTag = 0;
|
||||||
jvalue *argument = request->arguments;
|
jvalue *argument = request->arguments;
|
||||||
jbyte argumentTag = firstArgumentTypeTag(request->methodSignature, &cursor);
|
methodSignature_init(request->methodSignature, &cursor);
|
||||||
|
|
||||||
if (request->clazz != NULL) {
|
if (request->clazz != NULL) {
|
||||||
tossGlobalRef(env, &(request->clazz));
|
tossGlobalRef(env, &(request->clazz));
|
||||||
@ -230,16 +182,15 @@ deleteGlobalArgumentRefs(JNIEnv *env, InvokeRequest *request)
|
|||||||
tossGlobalRef(env, &(request->instance));
|
tossGlobalRef(env, &(request->instance));
|
||||||
}
|
}
|
||||||
/* Delete global argument references */
|
/* Delete global argument references */
|
||||||
while (argIndex < request->argumentCount) {
|
while (methodSignature_nextArgumentExists(&cursor, &argumentTag) &&
|
||||||
if ((argumentTag == JDWP_TAG(OBJECT)) ||
|
argIndex < request->argumentCount) {
|
||||||
(argumentTag == JDWP_TAG(ARRAY))) {
|
if (isReferenceTag(argumentTag)) {
|
||||||
if (argument->l != NULL) {
|
if (argument->l != NULL) {
|
||||||
tossGlobalRef(env, &(argument->l));
|
tossGlobalRef(env, &(argument->l));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
argument++;
|
argument++;
|
||||||
argIndex++;
|
argIndex++;
|
||||||
argumentTag = nextArgumentTypeTag(&cursor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,23 +355,23 @@ invokeConstructor(JNIEnv *env, InvokeRequest *request)
|
|||||||
static void
|
static void
|
||||||
invokeStatic(JNIEnv *env, InvokeRequest *request)
|
invokeStatic(JNIEnv *env, InvokeRequest *request)
|
||||||
{
|
{
|
||||||
switch(returnTypeTag(request->methodSignature)) {
|
jbyte returnType = methodSignature_returnTag(request->methodSignature);
|
||||||
case JDWP_TAG(OBJECT):
|
|
||||||
case JDWP_TAG(ARRAY): {
|
if (isReferenceTag(returnType)) {
|
||||||
jobject object;
|
jobject object;
|
||||||
JDI_ASSERT_MSG(request->clazz, "Request clazz null");
|
JDI_ASSERT_MSG(request->clazz, "Request clazz null");
|
||||||
object = JNI_FUNC_PTR(env,CallStaticObjectMethodA)(env,
|
object = JNI_FUNC_PTR(env,CallStaticObjectMethodA)(env,
|
||||||
request->clazz,
|
request->clazz,
|
||||||
request->method,
|
request->method,
|
||||||
request->arguments);
|
request->arguments);
|
||||||
request->returnValue.l = NULL;
|
request->returnValue.l = NULL;
|
||||||
if (object != NULL) {
|
if (object != NULL) {
|
||||||
saveGlobalRef(env, object, &(request->returnValue.l));
|
saveGlobalRef(env, object, &(request->returnValue.l));
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (returnType) {
|
||||||
case JDWP_TAG(BYTE):
|
case JDWP_TAG(BYTE):
|
||||||
request->returnValue.b = JNI_FUNC_PTR(env,CallStaticByteMethodA)(env,
|
request->returnValue.b = JNI_FUNC_PTR(env,CallStaticByteMethodA)(env,
|
||||||
request->clazz,
|
request->clazz,
|
||||||
@ -493,22 +444,22 @@ invokeStatic(JNIEnv *env, InvokeRequest *request)
|
|||||||
static void
|
static void
|
||||||
invokeVirtual(JNIEnv *env, InvokeRequest *request)
|
invokeVirtual(JNIEnv *env, InvokeRequest *request)
|
||||||
{
|
{
|
||||||
switch(returnTypeTag(request->methodSignature)) {
|
jbyte returnType = methodSignature_returnTag(request->methodSignature);
|
||||||
case JDWP_TAG(OBJECT):
|
if (isReferenceTag(returnType)) {
|
||||||
case JDWP_TAG(ARRAY): {
|
jobject object;
|
||||||
jobject object;
|
JDI_ASSERT_MSG(request->instance, "Request instance null");
|
||||||
JDI_ASSERT_MSG(request->instance, "Request instance null");
|
object = JNI_FUNC_PTR(env,CallObjectMethodA)(env,
|
||||||
object = JNI_FUNC_PTR(env,CallObjectMethodA)(env,
|
request->instance,
|
||||||
request->instance,
|
request->method,
|
||||||
request->method,
|
request->arguments);
|
||||||
request->arguments);
|
request->returnValue.l = NULL;
|
||||||
request->returnValue.l = NULL;
|
if (object != NULL) {
|
||||||
if (object != NULL) {
|
saveGlobalRef(env, object, &(request->returnValue.l));
|
||||||
saveGlobalRef(env, object, &(request->returnValue.l));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (returnType) {
|
||||||
case JDWP_TAG(BYTE):
|
case JDWP_TAG(BYTE):
|
||||||
request->returnValue.b = JNI_FUNC_PTR(env,CallByteMethodA)(env,
|
request->returnValue.b = JNI_FUNC_PTR(env,CallByteMethodA)(env,
|
||||||
request->instance,
|
request->instance,
|
||||||
@ -581,24 +532,24 @@ invokeVirtual(JNIEnv *env, InvokeRequest *request)
|
|||||||
static void
|
static void
|
||||||
invokeNonvirtual(JNIEnv *env, InvokeRequest *request)
|
invokeNonvirtual(JNIEnv *env, InvokeRequest *request)
|
||||||
{
|
{
|
||||||
switch(returnTypeTag(request->methodSignature)) {
|
jbyte returnType = methodSignature_returnTag(request->methodSignature);
|
||||||
case JDWP_TAG(OBJECT):
|
if (isReferenceTag(returnType)) {
|
||||||
case JDWP_TAG(ARRAY): {
|
jobject object;
|
||||||
jobject object;
|
JDI_ASSERT_MSG(request->clazz, "Request clazz null");
|
||||||
JDI_ASSERT_MSG(request->clazz, "Request clazz null");
|
JDI_ASSERT_MSG(request->instance, "Request instance null");
|
||||||
JDI_ASSERT_MSG(request->instance, "Request instance null");
|
object = JNI_FUNC_PTR(env,CallNonvirtualObjectMethodA)(env,
|
||||||
object = JNI_FUNC_PTR(env,CallNonvirtualObjectMethodA)(env,
|
request->instance,
|
||||||
request->instance,
|
request->clazz,
|
||||||
request->clazz,
|
request->method,
|
||||||
request->method,
|
request->arguments);
|
||||||
request->arguments);
|
request->returnValue.l = NULL;
|
||||||
request->returnValue.l = NULL;
|
if (object != NULL) {
|
||||||
if (object != NULL) {
|
saveGlobalRef(env, object, &(request->returnValue.l));
|
||||||
saveGlobalRef(env, object, &(request->returnValue.l));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (returnType) {
|
||||||
case JDWP_TAG(BYTE):
|
case JDWP_TAG(BYTE):
|
||||||
request->returnValue.b = JNI_FUNC_PTR(env,CallNonvirtualByteMethodA)(env,
|
request->returnValue.b = JNI_FUNC_PTR(env,CallNonvirtualByteMethodA)(env,
|
||||||
request->instance,
|
request->instance,
|
||||||
@ -797,7 +748,7 @@ invoker_completeInvokeRequest(jthread thread)
|
|||||||
*/
|
*/
|
||||||
tag = specificTypeKey(env, request->returnValue.l);
|
tag = specificTypeKey(env, request->returnValue.l);
|
||||||
} else {
|
} else {
|
||||||
tag = returnTypeTag(request->methodSignature);
|
tag = methodSignature_returnTag(request->methodSignature);
|
||||||
}
|
}
|
||||||
id = request->id;
|
id = request->id;
|
||||||
exc = request->exception;
|
exc = request->exception;
|
||||||
@ -805,9 +756,9 @@ invoker_completeInvokeRequest(jthread thread)
|
|||||||
|
|
||||||
/* Release return value and exception references, but delay the release
|
/* Release return value and exception references, but delay the release
|
||||||
* until after the return packet was sent. */
|
* until after the return packet was sent. */
|
||||||
|
jbyte returnType = methodSignature_returnTag(request->methodSignature);
|
||||||
mustReleaseReturnValue = request->invokeType == INVOKE_CONSTRUCTOR ||
|
mustReleaseReturnValue = request->invokeType == INVOKE_CONSTRUCTOR ||
|
||||||
returnTypeTag(request->methodSignature) == JDWP_TAG(OBJECT) ||
|
isReferenceTag(returnType);
|
||||||
returnTypeTag(request->methodSignature) == JDWP_TAG(ARRAY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -32,6 +32,8 @@
|
|||||||
#include "outStream.h"
|
#include "outStream.h"
|
||||||
#include "inStream.h"
|
#include "inStream.h"
|
||||||
#include "invoker.h"
|
#include "invoker.h"
|
||||||
|
#include "signature.h"
|
||||||
|
|
||||||
|
|
||||||
/* Global data area */
|
/* Global data area */
|
||||||
BackendGlobalData *gdata = NULL;
|
BackendGlobalData *gdata = NULL;
|
||||||
@ -171,6 +173,8 @@ getStaticMethod(JNIEnv *env, jclass clazz, const char * name, const char *signat
|
|||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
util_initialize(JNIEnv *env)
|
util_initialize(JNIEnv *env)
|
||||||
{
|
{
|
||||||
@ -343,26 +347,25 @@ writeFieldValue(JNIEnv *env, PacketOutputStream *out, jobject object,
|
|||||||
outStream_setError(out, map2jdwpError(error));
|
outStream_setError(out, map2jdwpError(error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
typeKey = signature[0];
|
typeKey = jdwpTag(signature);
|
||||||
jvmtiDeallocate(signature);
|
jvmtiDeallocate(signature);
|
||||||
|
|
||||||
/*
|
if (isReferenceTag(typeKey)) {
|
||||||
* For primitive types, the type key is bounced back as is. Objects
|
|
||||||
* are handled in the switch statement below.
|
jobject value = JNI_FUNC_PTR(env,GetObjectField)(env, object, field);
|
||||||
*/
|
(void)outStream_writeByte(out, specificTypeKey(env, value));
|
||||||
if ((typeKey != JDWP_TAG(OBJECT)) && (typeKey != JDWP_TAG(ARRAY))) {
|
(void)outStream_writeObjectRef(env, out, value);
|
||||||
(void)outStream_writeByte(out, typeKey);
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (typeKey) {
|
/*
|
||||||
case JDWP_TAG(OBJECT):
|
* For primitive types, the type key is bounced back as is.
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
(void)outStream_writeByte(out, typeKey);
|
||||||
|
|
||||||
|
switch (typeKey) {
|
||||||
case JDWP_TAG(BYTE):
|
case JDWP_TAG(BYTE):
|
||||||
(void)outStream_writeByte(out,
|
(void)outStream_writeByte(out,
|
||||||
JNI_FUNC_PTR(env,GetByteField)(env, object, field));
|
JNI_FUNC_PTR(env,GetByteField)(env, object, field));
|
||||||
@ -418,26 +421,24 @@ writeStaticFieldValue(JNIEnv *env, PacketOutputStream *out, jclass clazz,
|
|||||||
outStream_setError(out, map2jdwpError(error));
|
outStream_setError(out, map2jdwpError(error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
typeKey = signature[0];
|
typeKey = jdwpTag(signature);
|
||||||
jvmtiDeallocate(signature);
|
jvmtiDeallocate(signature);
|
||||||
|
|
||||||
/*
|
|
||||||
* For primitive types, the type key is bounced back as is. Objects
|
if (isReferenceTag(typeKey)) {
|
||||||
* are handled in the switch statement below.
|
|
||||||
*/
|
jobject value = JNI_FUNC_PTR(env,GetStaticObjectField)(env, clazz, field);
|
||||||
if ((typeKey != JDWP_TAG(OBJECT)) && (typeKey != JDWP_TAG(ARRAY))) {
|
(void)outStream_writeByte(out, specificTypeKey(env, value));
|
||||||
(void)outStream_writeByte(out, typeKey);
|
(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) {
|
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):
|
case JDWP_TAG(BYTE):
|
||||||
(void)outStream_writeByte(out,
|
(void)outStream_writeByte(out,
|
||||||
JNI_FUNC_PTR(env,GetStaticByteField)(env, clazz, field));
|
JNI_FUNC_PTR(env,GetStaticByteField)(env, clazz, field));
|
||||||
@ -570,7 +571,7 @@ sharedInvoke(PacketInputStream *in, PacketOutputStream *out)
|
|||||||
return JNI_TRUE;
|
return JNI_TRUE;
|
||||||
}
|
}
|
||||||
for (i = 0; (i < argumentCount) && !inStream_error(in); i++) {
|
for (i = 0; (i < argumentCount) && !inStream_error(in); i++) {
|
||||||
arguments[i] = inStream_readValue(in, NULL);
|
arguments[i] = inStream_readValue(in);
|
||||||
}
|
}
|
||||||
if (inStream_error(in)) {
|
if (inStream_error(in)) {
|
||||||
return JNI_TRUE;
|
return JNI_TRUE;
|
||||||
@ -977,32 +978,6 @@ getSourceDebugExtension(jclass clazz, char **extensionPtr)
|
|||||||
(gdata->jvmti, clazz, 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
|
static void
|
||||||
handleInterrupt(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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -251,13 +251,6 @@ typedef struct ObjectBatch {
|
|||||||
jint count;
|
jint count;
|
||||||
} ObjectBatch;
|
} 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
|
* Modifier flags for classes, fields, methods
|
||||||
*/
|
*/
|
||||||
@ -291,7 +284,6 @@ jbyte referenceTypeTag(jclass clazz);
|
|||||||
jbyte specificTypeKey(JNIEnv *env, jobject object);
|
jbyte specificTypeKey(JNIEnv *env, jobject object);
|
||||||
jboolean isObjectTag(jbyte tag);
|
jboolean isObjectTag(jbyte tag);
|
||||||
jvmtiError spawnNewThread(jvmtiStartFunction func, void *arg, char *name);
|
jvmtiError spawnNewThread(jvmtiStartFunction func, void *arg, char *name);
|
||||||
void convertSignatureToClassname(char *convert);
|
|
||||||
void writeCodeLocation(struct PacketOutputStream *out, jclass clazz,
|
void writeCodeLocation(struct PacketOutputStream *out, jclass clazz,
|
||||||
jmethodID method, jlocation location);
|
jmethodID method, jlocation location);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user