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 
    195 bool dvmDbgMatchType(RefTypeId instClassId, RefTypeId classId);
    196 
    197 /*
    198  * Method and Field
    199  */
    200 const char* dvmDbgGetMethodName(RefTypeId refTypeId, MethodId id);
    201 void dvmDbgOutputAllFields(RefTypeId refTypeId, bool withGeneric,
    202     ExpandBuf* pReply);
    203 void dvmDbgOutputAllMethods(RefTypeId refTypeId, bool withGeneric,
    204     ExpandBuf* pReply);
    205 void dvmDbgOutputAllInterfaces(RefTypeId refTypeId, ExpandBuf* pReply);
    206 void dvmDbgOutputLineTable(RefTypeId refTypeId, MethodId methodId,
    207     ExpandBuf* pReply);
    208 void dvmDbgOutputVariableTable(RefTypeId refTypeId, MethodId id,
    209     bool withGeneric, ExpandBuf* pReply);
    210 
    211 int dvmDbgGetFieldTag(ObjectId objId, FieldId fieldId);
    212 int dvmDbgGetStaticFieldTag(RefTypeId refTypeId, FieldId fieldId);
    213 void dvmDbgGetFieldValue(ObjectId objId, FieldId fieldId, u1* ptr, int width);
    214 void dvmDbgSetFieldValue(ObjectId objectId, FieldId fieldId, u8 value,
    215     int width);
    216 void dvmDbgGetStaticFieldValue(RefTypeId refTypeId, FieldId fieldId, u1* ptr,
    217     int width);
    218 void dvmDbgSetStaticFieldValue(RefTypeId refTypeId, FieldId fieldId,
    219     u8 rawValue, int width);
    220 
    221 char* dvmDbgStringToUtf8(ObjectId strId);
    222 
    223 /*
    224  * Thread, ThreadGroup, Frame
    225  */
    226 char* dvmDbgGetThreadName(ObjectId threadId);
    227 ObjectId dvmDbgGetThreadGroup(ObjectId threadId);
    228 char* dvmDbgGetThreadGroupName(ObjectId threadGroupId);
    229 ObjectId dvmDbgGetThreadGroupParent(ObjectId threadGroupId);
    230 ObjectId dvmDbgGetSystemThreadGroupId(void);
    231 ObjectId dvmDbgGetMainThreadGroupId(void);
    232 
    233 bool dvmDbgGetThreadStatus(ObjectId threadId, u4* threadStatus,
    234     u4* suspendStatus);
    235 u4 dvmDbgGetThreadSuspendCount(ObjectId threadId);
    236 bool dvmDbgThreadExists(ObjectId threadId);
    237 bool dvmDbgIsSuspended(ObjectId threadId);
    238 //void dvmDbgWaitForSuspend(ObjectId threadId);
    239 void dvmDbgGetThreadGroupThreads(ObjectId threadGroupId,
    240     ObjectId** ppThreadIds, u4* pThreadCount);
    241 void dvmDbgGetAllThreads(ObjectId** ppThreadIds, u4* pThreadCount);
    242 int dvmDbgGetThreadFrameCount(ObjectId threadId);
    243 bool dvmDbgGetThreadFrame(ObjectId threadId, int num, FrameId* pFrameId,
    244     JdwpLocation* pLoc);
    245 
    246 ObjectId dvmDbgGetThreadSelfId(void);
    247 void dvmDbgSuspendVM(bool isEvent);
    248 void dvmDbgResumeVM(void);
    249 void dvmDbgSuspendThread(ObjectId threadId);
    250 void dvmDbgResumeThread(ObjectId threadId);
    251 void dvmDbgSuspendSelf(void);
    252 
    253 bool dvmDbgGetThisObject(ObjectId threadId, FrameId frameId, ObjectId* pThisId);
    254 void dvmDbgGetLocalValue(ObjectId threadId, FrameId frameId, int slot,
    255     u1 tag, u1* buf, int expectedLen);
    256 void dvmDbgSetLocalValue(ObjectId threadId, FrameId frameId, int slot,
    257     u1 tag, u8 value, int width);
    258 
    259 
    260 /*
    261  * Debugger notification
    262  */
    263 void dvmDbgPostLocationEvent(const struct Method* method, int pcOffset,
    264     struct Object* thisPtr, int eventFlags);
    265 void dvmDbgPostException(void* throwFp, int throwRelPc, void* catchFp,
    266     int catchRelPc, struct Object* exception);
    267 void dvmDbgPostThreadStart(struct Thread* thread);
    268 void dvmDbgPostThreadDeath(struct Thread* thread);
    269 void dvmDbgPostClassPrepare(struct ClassObject* clazz);
    270 // FieldAccess, FieldModification
    271 
    272 /* for "eventFlags" */
    273 enum {
    274     DBG_BREAKPOINT      = 0x01,
    275     DBG_SINGLE_STEP     = 0x02,
    276     DBG_METHOD_ENTRY    = 0x04,
    277     DBG_METHOD_EXIT     = 0x08,
    278 };
    279 
    280 bool dvmDbgWatchLocation(const JdwpLocation* pLoc);
    281 void dvmDbgUnwatchLocation(const JdwpLocation* pLoc);
    282 bool dvmDbgConfigureStep(ObjectId threadId, enum JdwpStepSize size,
    283     enum JdwpStepDepth depth);
    284 void dvmDbgUnconfigureStep(ObjectId threadId);
    285 
    286 JdwpError dvmDbgInvokeMethod(ObjectId threadId, ObjectId objectId,
    287     RefTypeId classId, MethodId methodId, u4 numArgs, u8* argArray,
    288     u4 options, u1* pResultTag, u8* pResultValue, ObjectId* pExceptObj);
    289 void dvmDbgExecuteMethod(DebugInvokeReq* pReq);
    290 
    291 /* Make an AddressSet for a line, for single stepping */
    292 const AddressSet *dvmAddressSetForLine(const struct Method* method, int line);
    293 
    294 /* perform "late registration" of an object ID */
    295 void dvmDbgRegisterObjectId(ObjectId id);
    296 
    297 /*
    298  * DDM support.
    299  */
    300 bool dvmDbgDdmHandlePacket(const u1* buf, int dataLen, u1** pReplyBuf,
    301     int* pReplyLen);
    302 void dvmDbgDdmConnected(void);
    303 void dvmDbgDdmDisconnected(void);
    304 void dvmDbgDdmSendChunk(int type, size_t len, const u1* buf);
    305 void dvmDbgDdmSendChunkV(int type, const struct iovec* iov, int iovcnt);
    306 
    307 #define CHUNK_TYPE(_name) \
    308     ((_name)[0] << 24 | (_name)[1] << 16 | (_name)[2] << 8 | (_name)[3])
    309 
    310 #endif /*_DALVIK_DEBUGGER*/
    311