1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* 18 * Dalvik-specific side of debugger support. (The JDWP code is intended to 19 * be relatively generic.) 20 */ 21 #ifndef _DALVIK_DEBUGGER 22 #define _DALVIK_DEBUGGER 23 24 #include "Common.h" 25 #include "Misc.h" 26 #include "jdwp/Jdwp.h" 27 #include <pthread.h> 28 29 /* fwd decl */ 30 struct Object; 31 struct ClassObject; 32 struct Method; 33 struct Thread; 34 35 /* 36 * Used by StepControl to track a set of addresses associated with 37 * a single line. 38 */ 39 typedef struct AddressSet { 40 u4 setSize; 41 u1 set[1]; 42 } AddressSet; 43 44 INLINE void dvmAddressSetSet(AddressSet *pSet, u4 toSet) 45 { 46 if (toSet < pSet->setSize) { 47 pSet->set[toSet/8] |= 1 << (toSet % 8); 48 } 49 } 50 51 INLINE bool dvmAddressSetGet(const AddressSet *pSet, u4 toGet) 52 { 53 if (toGet < pSet->setSize) { 54 return (pSet->set[toGet/8] & (1 << (toGet % 8))) != 0; 55 } else { 56 return false; 57 } 58 } 59 60 /* 61 * Single-step management. 62 */ 63 typedef struct StepControl { 64 /* request */ 65 enum JdwpStepSize size; 66 enum JdwpStepDepth depth; 67 struct Thread* thread; /* don't deref; for comparison only */ 68 69 /* current state */ 70 bool active; 71 const struct Method* method; 72 int line; /* line #; could be -1 */ 73 const AddressSet* pAddressSet; /* if non-null, address set for line */ 74 int frameDepth; 75 } StepControl; 76 77 /* 78 * Invoke-during-breakpoint support. 79 */ 80 typedef struct DebugInvokeReq { 81 /* boolean; only set when we're in the tail end of an event handler */ 82 bool ready; 83 84 /* boolean; set if the JDWP thread wants this thread to do work */ 85 bool invokeNeeded; 86 87 /* request */ 88 struct Object* obj; /* not used for ClassType.InvokeMethod */ 89 struct Object* thread; 90 struct ClassObject* clazz; 91 struct Method* method; 92 u4 numArgs; 93 u8* argArray; /* will be NULL if numArgs==0 */ 94 u4 options; 95 96 /* result */ 97 JdwpError err; 98 u1 resultTag; 99 JValue resultValue; 100 ObjectId exceptObj; 101 102 /* condition variable to wait on while the method executes */ 103 pthread_mutex_t lock; 104 pthread_cond_t cv; 105 } DebugInvokeReq; 106 107 /* system init/shutdown */ 108 bool dvmDebuggerStartup(void); 109 void dvmDebuggerShutdown(void); 110 111 void dvmDbgInitMutex(pthread_mutex_t* pMutex); 112 void dvmDbgLockMutex(pthread_mutex_t* pMutex); 113 void dvmDbgUnlockMutex(pthread_mutex_t* pMutex); 114 void dvmDbgInitCond(pthread_cond_t* pCond); 115 void dvmDbgCondWait(pthread_cond_t* pCond, pthread_mutex_t* pMutex); 116 void dvmDbgCondSignal(pthread_cond_t* pCond); 117 void dvmDbgCondBroadcast(pthread_cond_t* pCond); 118 119 /* 120 * Return the DebugInvokeReq for the current thread. 121 */ 122 DebugInvokeReq* dvmDbgGetInvokeReq(void); 123 124 /* 125 * Enable/disable breakpoints and step modes. Used to provide a heads-up 126 * when the debugger attaches. 127 */ 128 void dvmDbgConnected(void); 129 void dvmDbgActive(void); 130 void dvmDbgDisconnected(void); 131 132 /* 133 * Returns "true" if a debugger is connected. Returns "false" if it's 134 * just DDM. 135 */ 136 bool dvmDbgIsDebuggerConnected(void); 137 138 /* 139 * Time, in milliseconds, since the last debugger activity. Does not 140 * include DDMS activity. Returns -1 if there has been no activity. 141 * Returns 0 if we're in the middle of handling a debugger request. 142 */ 143 s8 dvmDbgLastDebuggerActivity(void); 144 145 /* 146 * Block/allow GC depending on what we're doing. These return the old 147 * status, which can be fed to dvmDbgThreadGoing() to restore the previous 148 * mode. 149 */ 150 int dvmDbgThreadRunning(void); 151 int dvmDbgThreadWaiting(void); 152 int dvmDbgThreadContinuing(int status); 153 154 /* 155 * The debugger wants the VM to exit. 156 */ 157 void dvmDbgExit(int status); 158 159 /* 160 * Class, Object, Array 161 */ 162 const char* dvmDbgGetClassDescriptor(RefTypeId id); 163 ObjectId dvmDbgGetClassObject(RefTypeId id); 164 RefTypeId dvmDbgGetSuperclass(RefTypeId id); 165 ObjectId dvmDbgGetClassLoader(RefTypeId id); 166 u4 dvmDbgGetAccessFlags(RefTypeId id); 167 bool dvmDbgIsInterface(RefTypeId id); 168 void dvmDbgGetClassList(u4* pNumClasses, RefTypeId** pClassRefBuf); 169 void dvmDbgGetVisibleClassList(ObjectId classLoaderId, u4* pNumClasses, 170 RefTypeId** pClassRefBuf); 171 void dvmDbgGetClassInfo(RefTypeId classId, u1* pTypeTag, u4* pStatus, 172 char** pSignature); 173 bool dvmDbgFindLoadedClassBySignature(const char* classDescriptor, 174 RefTypeId* pRefTypeId); 175 void dvmDbgGetObjectType(ObjectId objectId, u1* pRefTypeTag, 176 RefTypeId* pRefTypeId); 177 u1 dvmDbgGetClassObjectType(RefTypeId refTypeId); 178 char* dvmDbgGetSignature(RefTypeId refTypeId); 179 const char* dvmDbgGetSourceFile(RefTypeId refTypeId); 180 char* dvmDbgGetObjectTypeName(ObjectId objectId); 181 int dvmDbgGetSignatureTag(const char* signature); 182 int dvmDbgGetObjectTag(ObjectId objectId, const char* type); 183 int dvmDbgGetTagWidth(int tag); 184 185 int dvmDbgGetArrayLength(ObjectId arrayId); 186 int dvmDbgGetArrayElementTag(ObjectId arrayId); 187 bool dvmDbgOutputArray(ObjectId arrayId, int firstIndex, int count, 188 ExpandBuf* pReply); 189 bool dvmDbgSetArrayElements(ObjectId arrayId, int firstIndex, int count, 190 const u1* buf); 191 192 ObjectId dvmDbgCreateString(const char* str); 193 ObjectId dvmDbgCreateObject(RefTypeId classId); 194 ObjectId dvmDbgCreateArrayObject(RefTypeId arrayTypeId, u4 length); 195 196 bool dvmDbgMatchType(RefTypeId instClassId, RefTypeId classId); 197 198 /* 199 * Method and Field 200 */ 201 const char* dvmDbgGetMethodName(RefTypeId refTypeId, MethodId id); 202 void dvmDbgOutputAllFields(RefTypeId refTypeId, bool withGeneric, 203 ExpandBuf* pReply); 204 void dvmDbgOutputAllMethods(RefTypeId refTypeId, bool withGeneric, 205 ExpandBuf* pReply); 206 void dvmDbgOutputAllInterfaces(RefTypeId refTypeId, ExpandBuf* pReply); 207 void dvmDbgOutputLineTable(RefTypeId refTypeId, MethodId methodId, 208 ExpandBuf* pReply); 209 void dvmDbgOutputVariableTable(RefTypeId refTypeId, MethodId id, 210 bool withGeneric, ExpandBuf* pReply); 211 212 int dvmDbgGetFieldTag(ObjectId objId, FieldId fieldId); 213 int dvmDbgGetStaticFieldTag(RefTypeId refTypeId, FieldId fieldId); 214 void dvmDbgGetFieldValue(ObjectId objId, FieldId fieldId, u1* ptr, int width); 215 void dvmDbgSetFieldValue(ObjectId objectId, FieldId fieldId, u8 value, 216 int width); 217 void dvmDbgGetStaticFieldValue(RefTypeId refTypeId, FieldId fieldId, u1* ptr, 218 int width); 219 void dvmDbgSetStaticFieldValue(RefTypeId refTypeId, FieldId fieldId, 220 u8 rawValue, int width); 221 222 char* dvmDbgStringToUtf8(ObjectId strId); 223 224 /* 225 * Thread, ThreadGroup, Frame 226 */ 227 char* dvmDbgGetThreadName(ObjectId threadId); 228 ObjectId dvmDbgGetThreadGroup(ObjectId threadId); 229 char* dvmDbgGetThreadGroupName(ObjectId threadGroupId); 230 ObjectId dvmDbgGetThreadGroupParent(ObjectId threadGroupId); 231 ObjectId dvmDbgGetSystemThreadGroupId(void); 232 ObjectId dvmDbgGetMainThreadGroupId(void); 233 234 bool dvmDbgGetThreadStatus(ObjectId threadId, u4* threadStatus, 235 u4* suspendStatus); 236 u4 dvmDbgGetThreadSuspendCount(ObjectId threadId); 237 bool dvmDbgThreadExists(ObjectId threadId); 238 bool dvmDbgIsSuspended(ObjectId threadId); 239 //void dvmDbgWaitForSuspend(ObjectId threadId); 240 void dvmDbgGetThreadGroupThreads(ObjectId threadGroupId, 241 ObjectId** ppThreadIds, u4* pThreadCount); 242 void dvmDbgGetAllThreads(ObjectId** ppThreadIds, u4* pThreadCount); 243 int dvmDbgGetThreadFrameCount(ObjectId threadId); 244 bool dvmDbgGetThreadFrame(ObjectId threadId, int num, FrameId* pFrameId, 245 JdwpLocation* pLoc); 246 247 ObjectId dvmDbgGetThreadSelfId(void); 248 void dvmDbgSuspendVM(bool isEvent); 249 void dvmDbgResumeVM(void); 250 void dvmDbgSuspendThread(ObjectId threadId); 251 void dvmDbgResumeThread(ObjectId threadId); 252 void dvmDbgSuspendSelf(void); 253 254 bool dvmDbgGetThisObject(ObjectId threadId, FrameId frameId, ObjectId* pThisId); 255 void dvmDbgGetLocalValue(ObjectId threadId, FrameId frameId, int slot, 256 u1 tag, u1* buf, int expectedLen); 257 void dvmDbgSetLocalValue(ObjectId threadId, FrameId frameId, int slot, 258 u1 tag, u8 value, int width); 259 260 261 /* 262 * Debugger notification 263 */ 264 void dvmDbgPostLocationEvent(const struct Method* method, int pcOffset, 265 struct Object* thisPtr, int eventFlags); 266 void dvmDbgPostException(void* throwFp, int throwRelPc, void* catchFp, 267 int catchRelPc, struct Object* exception); 268 void dvmDbgPostThreadStart(struct Thread* thread); 269 void dvmDbgPostThreadDeath(struct Thread* thread); 270 void dvmDbgPostClassPrepare(struct ClassObject* clazz); 271 // FieldAccess, FieldModification 272 273 /* for "eventFlags" */ 274 enum { 275 DBG_BREAKPOINT = 0x01, 276 DBG_SINGLE_STEP = 0x02, 277 DBG_METHOD_ENTRY = 0x04, 278 DBG_METHOD_EXIT = 0x08, 279 }; 280 281 bool dvmDbgWatchLocation(const JdwpLocation* pLoc); 282 void dvmDbgUnwatchLocation(const JdwpLocation* pLoc); 283 bool dvmDbgConfigureStep(ObjectId threadId, enum JdwpStepSize size, 284 enum JdwpStepDepth depth); 285 void dvmDbgUnconfigureStep(ObjectId threadId); 286 287 JdwpError dvmDbgInvokeMethod(ObjectId threadId, ObjectId objectId, 288 RefTypeId classId, MethodId methodId, u4 numArgs, u8* argArray, 289 u4 options, u1* pResultTag, u8* pResultValue, ObjectId* pExceptObj); 290 void dvmDbgExecuteMethod(DebugInvokeReq* pReq); 291 292 /* Make an AddressSet for a line, for single stepping */ 293 const AddressSet *dvmAddressSetForLine(const struct Method* method, int line); 294 295 /* perform "late registration" of an object ID */ 296 void dvmDbgRegisterObjectId(ObjectId id); 297 298 /* 299 * DDM support. 300 */ 301 bool dvmDbgDdmHandlePacket(const u1* buf, int dataLen, u1** pReplyBuf, 302 int* pReplyLen); 303 void dvmDbgDdmConnected(void); 304 void dvmDbgDdmDisconnected(void); 305 void dvmDbgDdmSendChunk(int type, size_t len, const u1* buf); 306 void dvmDbgDdmSendChunkV(int type, const struct iovec* iov, int iovcnt); 307 308 #define CHUNK_TYPE(_name) \ 309 ((_name)[0] << 24 | (_name)[1] << 16 | (_name)[2] << 8 | (_name)[3]) 310 311 #endif /*_DALVIK_DEBUGGER*/ 312