0N/A/*
2362N/A * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A#include "util.h"
0N/A#include "ReferenceTypeImpl.h"
0N/A#include "inStream.h"
0N/A#include "outStream.h"
0N/A
0N/A
0N/Astatic jboolean
0N/Asignature(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A char *signature = NULL;
0N/A jclass clazz;
0N/A jvmtiError error;
0N/A
0N/A clazz = inStream_readClassRef(getEnv(), in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A error = classSignature(clazz, &signature, NULL);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A (void)outStream_writeString(out, signature);
0N/A jvmtiDeallocate(signature);
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic jboolean
0N/AsignatureWithGeneric(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A /* Returns both the signature and the generic signature */
0N/A char *signature = NULL;
0N/A char *genericSignature = NULL;
0N/A jclass clazz;
0N/A jvmtiError error;
0N/A
0N/A clazz = inStream_readClassRef(getEnv(), in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A error = classSignature(clazz, &signature, &genericSignature);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A (void)outStream_writeString(out, signature);
0N/A writeGenericSignature(out, genericSignature);
0N/A jvmtiDeallocate(signature);
0N/A if (genericSignature != NULL) {
0N/A jvmtiDeallocate(genericSignature);
0N/A }
0N/A
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic jboolean
0N/AgetClassLoader(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A jclass clazz;
0N/A jobject loader;
0N/A jvmtiError error;
0N/A JNIEnv *env;
0N/A
0N/A env = getEnv();
0N/A
0N/A clazz = inStream_readClassRef(env, in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A error = classLoader(clazz, &loader);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A (void)outStream_writeObjectRef(env, out, loader);
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic jboolean
0N/Amodifiers(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A jint modifiers;
0N/A jclass clazz;
0N/A jvmtiError error;
0N/A
0N/A clazz = inStream_readClassRef(getEnv(), in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassModifiers)
0N/A (gdata->jvmti, clazz, &modifiers);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A (void)outStream_writeInt(out, modifiers);
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic void
0N/AwriteMethodInfo(PacketOutputStream *out, jclass clazz, jmethodID method,
0N/A int outputGenerics)
0N/A{
0N/A char *name = NULL;
0N/A char *signature = NULL;
0N/A char *genericSignature = NULL;
0N/A jint modifiers;
0N/A jvmtiError error;
0N/A jboolean isSynthetic;
0N/A
0N/A error = isMethodSynthetic(method, &isSynthetic);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return;
0N/A }
0N/A
0N/A error = methodModifiers(method, &modifiers);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return;
0N/A }
0N/A
0N/A error = methodSignature(method, &name, &signature, &genericSignature);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return;
0N/A }
0N/A
0N/A if (isSynthetic) {
0N/A modifiers |= MOD_SYNTHETIC;
0N/A }
0N/A (void)outStream_writeMethodID(out, method);
0N/A (void)outStream_writeString(out, name);
0N/A (void)outStream_writeString(out, signature);
0N/A if (outputGenerics == 1) {
0N/A writeGenericSignature(out, genericSignature);
0N/A }
0N/A (void)outStream_writeInt(out, modifiers);
0N/A jvmtiDeallocate(name);
0N/A jvmtiDeallocate(signature);
0N/A if (genericSignature != NULL) {
0N/A jvmtiDeallocate(genericSignature);
0N/A }
0N/A}
0N/A
0N/Astatic jboolean
0N/Amethods1(PacketInputStream *in, PacketOutputStream *out,
0N/A int outputGenerics)
0N/A{
0N/A int i;
0N/A jclass clazz;
0N/A jint methodCount = 0;
0N/A jmethodID *methods = NULL;
0N/A jvmtiError error;
0N/A
0N/A clazz = inStream_readClassRef(getEnv(), in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassMethods)
0N/A (gdata->jvmti, clazz, &methodCount, &methods);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A (void)outStream_writeInt(out, methodCount);
0N/A for (i = 0; (i < methodCount) && !outStream_error(out); i++) {
0N/A writeMethodInfo(out, clazz, methods[i], outputGenerics);
0N/A }
0N/A
0N/A /* Free methods array */
0N/A if ( methods != NULL ) {
0N/A jvmtiDeallocate(methods);
0N/A }
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic jboolean
0N/Amethods(PacketInputStream *in, PacketOutputStream *out,
0N/A int outputGenerics)
0N/A{
0N/A return methods1(in, out, 0);
0N/A}
0N/A
0N/Astatic jboolean
0N/AmethodsWithGeneric(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A return methods1(in, out, 1);
0N/A}
0N/A
0N/A
0N/A
0N/Astatic jboolean
0N/Ainstances(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A jint maxInstances;
0N/A jclass clazz;
0N/A JNIEnv *env;
0N/A
0N/A if (gdata->vmDead) {
0N/A outStream_setError(out, JDWP_ERROR(VM_DEAD));
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A env = getEnv();
0N/A clazz = inStream_readClassRef(env, in);
0N/A maxInstances = inStream_readInt(in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A WITH_LOCAL_REFS(env, 1) {
0N/A jvmtiError error;
0N/A ObjectBatch batch;
0N/A
0N/A error = classInstances(clazz, &batch, maxInstances);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A } else {
0N/A int kk;
0N/A jbyte typeKey;
0N/A
0N/A (void)outStream_writeInt(out, batch.count);
0N/A if (batch.count > 0) {
0N/A /*
0N/A * They are all instances of this class and will all have
0N/A * the same typeKey, so just compute it once.
0N/A */
0N/A typeKey = specificTypeKey(env, batch.objects[0]);
0N/A
0N/A for (kk = 0; kk < batch.count; kk++) {
0N/A jobject inst;
0N/A
0N/A inst = batch.objects[kk];
0N/A (void)outStream_writeByte(out, typeKey);
0N/A (void)outStream_writeObjectRef(env, out, inst);
0N/A }
0N/A }
0N/A jvmtiDeallocate(batch.objects);
0N/A }
0N/A } END_WITH_LOCAL_REFS(env);
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic jboolean
0N/AgetClassVersion(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A jclass clazz;
0N/A jvmtiError error;
0N/A jint majorVersion;
0N/A jint minorVersion;
0N/A
0N/A clazz = inStream_readClassRef(getEnv(), in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti, GetClassVersionNumbers)
0N/A (gdata->jvmti, clazz, &minorVersion, &majorVersion);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A (void)outStream_writeInt(out, majorVersion);
0N/A (void)outStream_writeInt(out, minorVersion);
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic jboolean
0N/AgetConstantPool(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A
0N/A jclass clazz;
0N/A jvmtiError error;
0N/A jint cpCount;
0N/A jint cpByteCount;
0N/A unsigned char* cpBytesPtr;
0N/A
0N/A
0N/A clazz = inStream_readClassRef(getEnv(), in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A /* Initialize assuming no bytecodes and no error */
0N/A error = JVMTI_ERROR_NONE;
0N/A cpCount = 0;
0N/A cpByteCount = 0;
0N/A cpBytesPtr = NULL;
0N/A
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetConstantPool)
0N/A (gdata->jvmti, clazz, &cpCount, &cpByteCount, &cpBytesPtr);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A } else {
0N/A (void)outStream_writeInt(out, cpCount);
0N/A (void)outStream_writeByteArray(out, cpByteCount, (jbyte *)cpBytesPtr);
0N/A jvmtiDeallocate(cpBytesPtr);
0N/A }
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic void
0N/AwriteFieldInfo(PacketOutputStream *out, jclass clazz, jfieldID fieldID,
0N/A int outputGenerics)
0N/A{
0N/A char *name;
0N/A char *signature = NULL;
0N/A char *genericSignature = NULL;
0N/A jint modifiers;
0N/A jboolean isSynthetic;
0N/A jvmtiError error;
0N/A
0N/A error = isFieldSynthetic(clazz, fieldID, &isSynthetic);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return;
0N/A }
0N/A
0N/A error = fieldModifiers(clazz, fieldID, &modifiers);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return;
0N/A }
0N/A
0N/A error = fieldSignature(clazz, fieldID, &name, &signature, &genericSignature);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return;
0N/A }
0N/A if (isSynthetic) {
0N/A modifiers |= MOD_SYNTHETIC;
0N/A }
0N/A (void)outStream_writeFieldID(out, fieldID);
0N/A (void)outStream_writeString(out, name);
0N/A (void)outStream_writeString(out, signature);
0N/A if (outputGenerics == 1) {
0N/A writeGenericSignature(out, genericSignature);
0N/A }
0N/A (void)outStream_writeInt(out, modifiers);
0N/A jvmtiDeallocate(name);
0N/A jvmtiDeallocate(signature);
0N/A if (genericSignature != NULL) {
0N/A jvmtiDeallocate(genericSignature);
0N/A }
0N/A}
0N/A
0N/Astatic jboolean
0N/Afields1(PacketInputStream *in, PacketOutputStream *out, int outputGenerics)
0N/A{
0N/A int i;
0N/A jclass clazz;
0N/A jint fieldCount = 0;
0N/A jfieldID *fields = NULL;
0N/A jvmtiError error;
0N/A
0N/A clazz = inStream_readClassRef(getEnv(), in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassFields)
0N/A (gdata->jvmti, clazz, &fieldCount, &fields);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A (void)outStream_writeInt(out, fieldCount);
0N/A for (i = 0; (i < fieldCount) && !outStream_error(out); i++) {
0N/A writeFieldInfo(out, clazz, fields[i], outputGenerics);
0N/A }
0N/A
0N/A /* Free fields array */
0N/A if ( fields != NULL ) {
0N/A jvmtiDeallocate(fields);
0N/A }
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/A
0N/Astatic jboolean
0N/Afields(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A return fields1(in, out, 0);
0N/A}
0N/A
0N/Astatic jboolean
0N/AfieldsWithGeneric(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A return fields1(in, out, 1);
0N/A
0N/A}
0N/A
0N/Astatic jboolean
0N/AgetValues(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A sharedGetFieldValues(in, out, JNI_TRUE);
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic jboolean
0N/AsourceFile(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A char *fileName;
0N/A jvmtiError error;
0N/A jclass clazz;
0N/A
0N/A clazz = inStream_readClassRef(getEnv(), in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName)
0N/A (gdata->jvmti, clazz, &fileName);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A (void)outStream_writeString(out, fileName);
0N/A jvmtiDeallocate(fileName);
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic jboolean
0N/AsourceDebugExtension(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A char *extension;
0N/A jvmtiError error;
0N/A jclass clazz;
0N/A
0N/A clazz = inStream_readClassRef(getEnv(), in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A error = getSourceDebugExtension(clazz, &extension);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A (void)outStream_writeString(out, extension);
0N/A jvmtiDeallocate(extension);
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic jboolean
0N/AnestedTypes(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A JNIEnv *env;
0N/A jclass clazz;
0N/A
0N/A env = getEnv();
0N/A
0N/A clazz = inStream_readClassRef(env, in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A WITH_LOCAL_REFS(env, 1) {
0N/A
0N/A jvmtiError error;
0N/A jint count;
0N/A jclass *nested;
0N/A
0N/A error = allNestedClasses(clazz, &nested, &count);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A } else {
0N/A int i;
0N/A (void)outStream_writeInt(out, count);
0N/A for (i = 0; i < count; i++) {
0N/A (void)outStream_writeByte(out, referenceTypeTag(nested[i]));
0N/A (void)outStream_writeObjectRef(env, out, nested[i]);
0N/A }
0N/A if ( nested != NULL ) {
0N/A jvmtiDeallocate(nested);
0N/A }
0N/A }
0N/A
0N/A } END_WITH_LOCAL_REFS(env);
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic jboolean
0N/AgetClassStatus(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A jint status;
0N/A jclass clazz;
0N/A
0N/A clazz = inStream_readClassRef(getEnv(), in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A status = classStatus(clazz);
0N/A (void)outStream_writeInt(out, map2jdwpClassStatus(status));
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic jboolean
0N/Ainterfaces(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A JNIEnv *env;
0N/A jclass clazz;
0N/A
0N/A env = getEnv();
0N/A
0N/A clazz = inStream_readClassRef(env, in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A WITH_LOCAL_REFS(env, 1) {
0N/A
0N/A jvmtiError error;
0N/A jint interfaceCount;
0N/A jclass *interfaces;
0N/A
0N/A error = allInterfaces(clazz, &interfaces, &interfaceCount);
0N/A if (error != JVMTI_ERROR_NONE) {
0N/A outStream_setError(out, map2jdwpError(error));
0N/A } else {
0N/A int i;
0N/A
0N/A (void)outStream_writeInt(out, interfaceCount);
0N/A for (i = 0; i < interfaceCount; i++) {
0N/A (void)outStream_writeObjectRef(env, out, interfaces[i]);
0N/A }
0N/A if ( interfaces != NULL ) {
0N/A jvmtiDeallocate(interfaces);
0N/A }
0N/A }
0N/A
0N/A } END_WITH_LOCAL_REFS(env);
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Astatic jboolean
0N/AclassObject(PacketInputStream *in, PacketOutputStream *out)
0N/A{
0N/A jclass clazz;
0N/A JNIEnv *env;
0N/A
0N/A env = getEnv();
0N/A clazz = inStream_readClassRef(env, in);
0N/A if (inStream_error(in)) {
0N/A return JNI_TRUE;
0N/A }
0N/A
0N/A /*
0N/A * In our implementation, the reference type id is the same as the
0N/A * class object id, so we bounce it right back.
0N/A *
0N/A */
0N/A
0N/A (void)outStream_writeObjectRef(env, out, clazz);
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Avoid *ReferenceType_Cmds[] = { (void *)18
0N/A ,(void *)signature
0N/A ,(void *)getClassLoader
0N/A ,(void *)modifiers
0N/A ,(void *)fields
0N/A ,(void *)methods
0N/A ,(void *)getValues
0N/A ,(void *)sourceFile
0N/A ,(void *)nestedTypes
0N/A ,(void *)getClassStatus
0N/A ,(void *)interfaces
0N/A ,(void *)classObject
0N/A ,(void *)sourceDebugExtension
0N/A ,(void *)signatureWithGeneric
0N/A ,(void *)fieldsWithGeneric
0N/A ,(void *)methodsWithGeneric
0N/A ,(void *)instances
0N/A ,(void *)getClassVersion
0N/A ,(void *)getConstantPool
0N/A};