/* * Copyright (c) 1998, 2005, 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_UTIL_H #define JDWP_UTIL_H #include #include #include #include #include #ifdef DEBUG /* Just to make sure these interfaces are not used here. */ #undef free #define free(p) Do not use this interface. #undef malloc #define malloc(p) Do not use this interface. #undef calloc #define calloc(p) Do not use this interface. #undef realloc #define realloc(p) Do not use this interface. #undef strdup #define strdup(p) Do not use this interface. #endif #include "log_messages.h" #include "vm_interface.h" #include "JDWP.h" #include "util_md.h" #include "error_messages.h" #include "debugInit.h" /* Get access to Native Platform Toolkit functions */ #include "npt.h" /* Definition of a CommonRef tracked by the backend for the frontend */ typedef struct RefNode { jlong seqNum; /* ID of reference, also key for hash table */ jobject ref; /* could be strong or weak */ struct RefNode *next; /* next RefNode* in bucket chain */ jint count; /* count of references */ unsigned isStrong : 1; /* 1 means this is a string reference */ } RefNode; /* Value of a NULL ID */ #define NULL_OBJECT_ID ((jlong)0) /* * Globals used throughout the back end */ typedef jint FrameNumber; // ANDROID-CHANGED: support for DDMS extension apis. typedef jvmtiError (*DdmProcessChunk)(jvmtiEnv* jvmti, jint type_in, jint length_in, const jbyte* data_in, jint* type_out, jint* length_out, jbyte** data_out); typedef struct { jvmtiEnv *jvmti; JavaVM *jvm; volatile jboolean vmDead; /* Once VM is dead it stays that way - don't put in init */ jboolean assertOn; jboolean assertFatal; jboolean doerrorexit; jboolean modifiedUtf8; jboolean quiet; /* Debug flags (bit mask) */ int debugflags; /* Possible debug flags */ #define USE_ITERATE_THROUGH_HEAP 0X001 char * options; jclass classClass; jclass threadClass; jclass threadGroupClass; jclass classLoaderClass; jclass stringClass; jclass systemClass; jmethodID threadConstructor; jmethodID threadSetDaemon; jmethodID threadResume; jmethodID systemGetProperty; jmethodID setProperty; jthreadGroup systemThreadGroup; jobject agent_properties; jint cachedJvmtiVersion; jvmtiCapabilities cachedJvmtiCapabilities; jboolean haveCachedJvmtiCapabilities; jvmtiEventCallbacks callbacks; /* Various property values we should grab on initialization */ char* property_java_version; /* UTF8 java.version */ char* property_java_vm_name; /* UTF8 java.vm.name */ char* property_java_vm_info; /* UTF8 java.vm.info */ char* property_java_class_path; /* UTF8 java.class.path */ char* property_sun_boot_class_path; /* UTF8 sun.boot.class.path */ char* property_sun_boot_library_path; /* UTF8 sun.boot.library.path */ char* property_path_separator; /* UTF8 path.separator */ char* property_user_dir; /* UTF8 user.dir */ unsigned log_flags; /* The Native Platform Toolkit access */ NptEnv *npt; /* Common References static data */ jrawMonitorID refLock; jlong nextSeqNum; RefNode **objectsByID; int objectsByIDsize; int objectsByIDcount; /* Indication that the agent has been loaded */ jboolean isLoaded; /* ANDROID-CHANGED: com.android.art.internal.ddm.process_chunk extension function */ DdmProcessChunk ddm_process_chunk; /* ANDROID-CHANGED: Need to keep track of if ddm is initially active. */ jboolean ddmInitiallyActive; } BackendGlobalData; extern BackendGlobalData * gdata; /* * Event Index for handlers */ typedef enum { EI_min = 1, EI_SINGLE_STEP = 1, EI_BREAKPOINT = 2, EI_FRAME_POP = 3, EI_EXCEPTION = 4, EI_THREAD_START = 5, EI_THREAD_END = 6, EI_CLASS_PREPARE = 7, EI_GC_FINISH = 8, EI_CLASS_LOAD = 9, EI_FIELD_ACCESS = 10, EI_FIELD_MODIFICATION = 11, EI_EXCEPTION_CATCH = 12, EI_METHOD_ENTRY = 13, EI_METHOD_EXIT = 14, EI_MONITOR_CONTENDED_ENTER = 15, EI_MONITOR_CONTENDED_ENTERED = 16, EI_MONITOR_WAIT = 17, EI_MONITOR_WAITED = 18, EI_VM_INIT = 19, EI_VM_DEATH = 20, EI_max = 20 } EventIndex; /* Agent errors that might be in a jvmtiError for JDWP or internal. * (Done this way so that compiler allows it's use as a jvmtiError) */ #define _AGENT_ERROR(x) ((jvmtiError)(JVMTI_ERROR_MAX+64+x)) #define AGENT_ERROR_INTERNAL _AGENT_ERROR(1) #define AGENT_ERROR_VM_DEAD _AGENT_ERROR(2) #define AGENT_ERROR_NO_JNI_ENV _AGENT_ERROR(3) #define AGENT_ERROR_JNI_EXCEPTION _AGENT_ERROR(4) #define AGENT_ERROR_JVMTI_INTERNAL _AGENT_ERROR(5) #define AGENT_ERROR_JDWP_INTERNAL _AGENT_ERROR(6) #define AGENT_ERROR_NOT_CURRENT_FRAME _AGENT_ERROR(7) #define AGENT_ERROR_OUT_OF_MEMORY _AGENT_ERROR(8) #define AGENT_ERROR_INVALID_TAG _AGENT_ERROR(9) #define AGENT_ERROR_ALREADY_INVOKING _AGENT_ERROR(10) #define AGENT_ERROR_INVALID_INDEX _AGENT_ERROR(11) #define AGENT_ERROR_INVALID_LENGTH _AGENT_ERROR(12) #define AGENT_ERROR_INVALID_STRING _AGENT_ERROR(13) #define AGENT_ERROR_INVALID_CLASS_LOADER _AGENT_ERROR(14) #define AGENT_ERROR_INVALID_ARRAY _AGENT_ERROR(15) #define AGENT_ERROR_TRANSPORT_LOAD _AGENT_ERROR(16) #define AGENT_ERROR_TRANSPORT_INIT _AGENT_ERROR(17) #define AGENT_ERROR_NATIVE_METHOD _AGENT_ERROR(18) #define AGENT_ERROR_INVALID_COUNT _AGENT_ERROR(19) #define AGENT_ERROR_INVALID_FRAMEID _AGENT_ERROR(20) #define AGENT_ERROR_NULL_POINTER _AGENT_ERROR(21) #define AGENT_ERROR_ILLEGAL_ARGUMENT _AGENT_ERROR(22) #define AGENT_ERROR_INVALID_THREAD _AGENT_ERROR(23) #define AGENT_ERROR_INVALID_EVENT_TYPE _AGENT_ERROR(24) #define AGENT_ERROR_INVALID_OBJECT _AGENT_ERROR(25) #define AGENT_ERROR_NO_MORE_FRAMES _AGENT_ERROR(26) /* Combined event information */ typedef struct { EventIndex ei; jthread thread; jclass clazz; jmethodID method; jlocation location; jobject object; /* possibly an exception or user object */ union { /* ei = EI_FIELD_ACCESS */ struct { jclass field_clazz; jfieldID field; } field_access; /* ei = EI_FIELD_MODIFICATION */ struct { jclass field_clazz; jfieldID field; char signature_type; jvalue new_value; } field_modification; /* ei = EI_EXCEPTION */ struct { jclass catch_clazz; jmethodID catch_method; jlocation catch_location; } exception; /* ei = EI_METHOD_EXIT */ struct { jvalue return_value; } method_exit; /* For monitor wait events */ union { /* ei = EI_MONITOR_WAIT */ jlong timeout; /* ei = EI_MONITOR_WAITED */ jboolean timed_out; } monitor; } u; } EventInfo; /* Structure to hold dynamic array of objects */ typedef struct ObjectBatch { jobject *objects; 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 */ #define MOD_PUBLIC 0x0001 /* visible to everyone */ #define MOD_PRIVATE 0x0002 /* visible only to the defining class */ #define MOD_PROTECTED 0x0004 /* visible to subclasses */ #define MOD_STATIC 0x0008 /* instance variable is static */ #define MOD_FINAL 0x0010 /* no further subclassing, overriding */ #define MOD_SYNCHRONIZED 0x0020 /* wrap method call in monitor lock */ #define MOD_VOLATILE 0x0040 /* can cache in registers */ #define MOD_TRANSIENT 0x0080 /* not persistant */ #define MOD_NATIVE 0x0100 /* implemented in C */ #define MOD_INTERFACE 0x0200 /* class is an interface */ #define MOD_ABSTRACT 0x0400 /* no definition provided */ /* * Additional modifiers not defined as such in the JVM spec */ #define MOD_SYNTHETIC 0xf0000000 /* not in source code */ /* * jlong conversion macros */ #define jlong_zero ((jlong) 0) #define jlong_one ((jlong) 1) #define jlong_to_ptr(a) ((void*)(intptr_t)(a)) #define ptr_to_jlong(a) ((jlong)(intptr_t)(a)) #define jint_to_jlong(a) ((jlong)(a)) #define jlong_to_jint(a) ((jint)(a)) /* * util funcs */ void util_initialize(JNIEnv *env); void util_reset(void); struct PacketInputStream; struct PacketOutputStream; jint uniqueID(void); 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); jvmtiError classInstances(jclass klass, ObjectBatch *instances, int maxInstances); jvmtiError classInstanceCounts(jint classCount, jclass *classes, jlong *counts); jvmtiError objectReferrers(jobject obj, ObjectBatch *referrers, int maxObjects); // ANDROID-CHANGED: Helper function to get current time in milliseconds on CLOCK_MONOTONIC jlong milliTime(void); /* * Command handling helpers shared among multiple command sets */ int filterDebugThreads(jthread *threads, int count); void sharedGetFieldValues(struct PacketInputStream *in, struct PacketOutputStream *out, jboolean isStatic); jboolean sharedInvoke(struct PacketInputStream *in, struct PacketOutputStream *out); jvmtiError fieldSignature(jclass, jfieldID, char **, char **, char **); jvmtiError fieldModifiers(jclass, jfieldID, jint *); jvmtiError methodSignature(jmethodID, char **, char **, char **); jvmtiError methodReturnType(jmethodID, char *); jvmtiError methodModifiers(jmethodID, jint *); jvmtiError methodClass(jmethodID, jclass *); jvmtiError methodLocation(jmethodID, jlocation*, jlocation*); jvmtiError classLoader(jclass, jobject *); /* * Thin wrappers on top of JNI */ JNIEnv *getEnv(void); jboolean isClass(jobject object); jboolean isThread(jobject object); jboolean isThreadGroup(jobject object); jboolean isString(jobject object); jboolean isClassLoader(jobject object); jboolean isArray(jobject object); /* * Thin wrappers on top of JVMTI */ jvmtiError jvmtiGetCapabilities(jvmtiCapabilities *caps); jint jvmtiMajorVersion(void); jint jvmtiMinorVersion(void); jint jvmtiMicroVersion(void); jvmtiError getSourceDebugExtension(jclass clazz, char **extensionPtr); jboolean canSuspendResumeThreadLists(void); jrawMonitorID debugMonitorCreate(char *name); void debugMonitorEnter(jrawMonitorID theLock); void debugMonitorExit(jrawMonitorID theLock); void debugMonitorWait(jrawMonitorID theLock); void debugMonitorTimedWait(jrawMonitorID theLock, jlong millis); void debugMonitorNotify(jrawMonitorID theLock); void debugMonitorNotifyAll(jrawMonitorID theLock); void debugMonitorDestroy(jrawMonitorID theLock); jthread *allThreads(jint *count); void threadGroupInfo(jthreadGroup, jvmtiThreadGroupInfo *info); char *getClassname(jclass); jvmtiError classSignature(jclass, char**, char**); jint classStatus(jclass); void writeGenericSignature(struct PacketOutputStream *, char *); jboolean isMethodNative(jmethodID); jboolean isMethodObsolete(jmethodID); jvmtiError isMethodSynthetic(jmethodID, jboolean*); jvmtiError isFieldSynthetic(jclass, jfieldID, jboolean*); jboolean isSameObject(JNIEnv *env, jobject o1, jobject o2); jint objectHashCode(jobject); jvmtiError allInterfaces(jclass clazz, jclass **ppinterfaces, jint *count); jvmtiError allLoadedClasses(jclass **ppclasses, jint *count); jvmtiError allClassLoaderClasses(jobject loader, jclass **ppclasses, jint *count); jvmtiError allNestedClasses(jclass clazz, jclass **ppnested, jint *pcount); void setAgentPropertyValue(JNIEnv *env, char *propertyName, char* propertyValue); void *jvmtiAllocate(jint numBytes); void jvmtiDeallocate(void *buffer); void eventIndexInit(void); jdwpEvent eventIndex2jdwp(EventIndex i); jvmtiEvent eventIndex2jvmti(EventIndex i); EventIndex jdwp2EventIndex(jdwpEvent eventType); EventIndex jvmti2EventIndex(jvmtiEvent kind); jvmtiError map2jvmtiError(jdwpError); jdwpError map2jdwpError(jvmtiError); jdwpThreadStatus map2jdwpThreadStatus(jint state); jint map2jdwpSuspendStatus(jint state); jint map2jdwpClassStatus(jint); void log_debugee_location(const char *func, jthread thread, jmethodID method, jlocation location); /* * Local Reference management. The two macros below are used * throughout the back end whenever space for JNI local references * is needed in the current frame. */ void createLocalRefSpace(JNIEnv *env, jint capacity); #define WITH_LOCAL_REFS(env, number) \ createLocalRefSpace(env, number); \ { /* BEGINNING OF WITH SCOPE */ #define END_WITH_LOCAL_REFS(env) \ JNI_FUNC_PTR(env,PopLocalFrame)(env, NULL); \ } /* END OF WITH SCOPE */ void saveGlobalRef(JNIEnv *env, jobject obj, jobject *pobj); void tossGlobalRef(JNIEnv *env, jobject *pobj); /* ANDROID_CHANGED: Expose this method publicly. * This returns a newly allocated jvmtiEnv* with the can_tag_objects capability. */ jvmtiEnv *getSpecialJvmti(void); #endif