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_H_
     22 #define DALVIK_DEBUGGER_H_
     23 
     24 #include <pthread.h>
     25 #include "Common.h"
     26 #include "Misc.h"
     27 #include "jdwp/Jdwp.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 struct AddressSet {
     40     u4 setSize;
     41     u1 set[1];
     42 };
     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 struct StepControl {
     64     /* request */
     65     JdwpStepSize size;
     66     JdwpStepDepth depth;
     67     Thread* thread;         /* don't deref; for comparison only */
     68 
     69     /* current state */
     70     bool active;
     71     const Method* method;
     72     int line;           /* line #; could be -1 */
     73     const AddressSet* pAddressSet;    /* if non-null, address set for line */
     74     int frameDepth;
     75 };
     76 
     77 /*
     78  * Invoke-during-breakpoint support.
     79  */
     80 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     Object* obj;        /* not used for ClassType.InvokeMethod */
     89     Object* thread;
     90     ClassObject* clazz;
     91     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 };
    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     const 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 const char* dvmDbgGetSignature(RefTypeId refTypeId);
    179 const char* dvmDbgGetSourceFile(RefTypeId refTypeId);
    180 const char* dvmDbgGetObjectTypeName(ObjectId objectId);
    181 u1 dvmDbgGetObjectTag(ObjectId objectId);
    182 int dvmDbgGetTagWidth(int tag);
    183 
    184 int dvmDbgGetArrayLength(ObjectId arrayId);
    185 u1 dvmDbgGetArrayElementTag(ObjectId arrayId);
    186 bool dvmDbgOutputArray(ObjectId arrayId, int firstIndex, int count,
    187     ExpandBuf* pReply);
    188 bool dvmDbgSetArrayElements(ObjectId arrayId, int firstIndex, int count,
    189     const u1* buf);
    190 
    191 ObjectId dvmDbgCreateString(const char* str);
    192 ObjectId dvmDbgCreateObject(RefTypeId classId);
    193 ObjectId dvmDbgCreateArrayObject(RefTypeId arrayTypeId, u4 length);
    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 u1 dvmDbgGetFieldBasicTag(ObjectId objId, FieldId fieldId);
    212 u1 dvmDbgGetStaticFieldBasicTag(RefTypeId refTypeId, FieldId fieldId);
    213 void dvmDbgGetFieldValue(ObjectId objectId, FieldId fieldId, ExpandBuf* pReply);
    214 void dvmDbgSetFieldValue(ObjectId objectId, FieldId fieldId, u8 value,
    215     int width);
    216 void dvmDbgGetStaticFieldValue(RefTypeId refTypeId, FieldId fieldId,
    217     ExpandBuf* pReply);
    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 Method* method, int pcOffset,
    264     Object* thisPtr, int eventFlags);
    265 void dvmDbgPostException(void* throwFp, int throwRelPc, void* catchFp,
    266     int catchRelPc, Object* exception);
    267 void dvmDbgPostThreadStart(Thread* thread);
    268 void dvmDbgPostThreadDeath(Thread* thread);
    269 void dvmDbgPostClassPrepare(ClassObject* clazz);
    270 
    271 /* for "eventFlags" */
    272 enum {
    273     DBG_BREAKPOINT      = 0x01,
    274     DBG_SINGLE_STEP     = 0x02,
    275     DBG_METHOD_ENTRY    = 0x04,
    276     DBG_METHOD_EXIT     = 0x08,
    277 };
    278 
    279 bool dvmDbgWatchLocation(const JdwpLocation* pLoc);
    280 void dvmDbgUnwatchLocation(const JdwpLocation* pLoc);
    281 bool dvmDbgConfigureStep(ObjectId threadId, JdwpStepSize size,
    282     JdwpStepDepth depth);
    283 void dvmDbgUnconfigureStep(ObjectId threadId);
    284 
    285 JdwpError dvmDbgInvokeMethod(ObjectId threadId, ObjectId objectId,
    286     RefTypeId classId, MethodId methodId, u4 numArgs, u8* argArray,
    287     u4 options, u1* pResultTag, u8* pResultValue, ObjectId* pExceptObj);
    288 void dvmDbgExecuteMethod(DebugInvokeReq* pReq);
    289 
    290 /* Make an AddressSet for a line, for single stepping */
    291 const AddressSet *dvmAddressSetForLine(const Method* method, int line);
    292 
    293 /* perform "late registration" of an object ID */
    294 void dvmDbgRegisterObjectId(ObjectId id);
    295 
    296 /*
    297  * DDM support.
    298  */
    299 bool dvmDbgDdmHandlePacket(const u1* buf, int dataLen, u1** pReplyBuf,
    300     int* pReplyLen);
    301 void dvmDbgDdmConnected(void);
    302 void dvmDbgDdmDisconnected(void);
    303 void dvmDbgDdmSendChunk(int type, size_t len, const u1* buf);
    304 void dvmDbgDdmSendChunkV(int type, const struct iovec* iov, int iovcnt);
    305 
    306 #define CHUNK_TYPE(_name) \
    307     ((_name)[0] << 24 | (_name)[1] << 16 | (_name)[2] << 8 | (_name)[3])
    308 
    309 #endif  // DALVIK_DEBUGGER_H_
    310