Home | History | Annotate | Download | only in vm
      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