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 */
30struct Object;
31struct ClassObject;
32struct Method;
33struct Thread;
34
35/*
36 * Used by StepControl to track a set of addresses associated with
37 * a single line.
38 */
39typedef struct AddressSet {
40    u4 setSize;
41    u1 set[1];
42} AddressSet;
43
44INLINE void dvmAddressSetSet(AddressSet *pSet, u4 toSet)
45{
46    if (toSet < pSet->setSize) {
47        pSet->set[toSet/8] |= 1 << (toSet % 8);
48    }
49}
50
51INLINE 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 */
63typedef 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 */
80typedef 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 */
108bool dvmDebuggerStartup(void);
109void dvmDebuggerShutdown(void);
110
111void dvmDbgInitMutex(pthread_mutex_t* pMutex);
112void dvmDbgLockMutex(pthread_mutex_t* pMutex);
113void dvmDbgUnlockMutex(pthread_mutex_t* pMutex);
114void dvmDbgInitCond(pthread_cond_t* pCond);
115void dvmDbgCondWait(pthread_cond_t* pCond, pthread_mutex_t* pMutex);
116void dvmDbgCondSignal(pthread_cond_t* pCond);
117void dvmDbgCondBroadcast(pthread_cond_t* pCond);
118
119/*
120 * Return the DebugInvokeReq for the current thread.
121 */
122DebugInvokeReq* dvmDbgGetInvokeReq(void);
123
124/*
125 * Enable/disable breakpoints and step modes.  Used to provide a heads-up
126 * when the debugger attaches.
127 */
128void dvmDbgConnected(void);
129void dvmDbgActive(void);
130void dvmDbgDisconnected(void);
131
132/*
133 * Returns "true" if a debugger is connected.  Returns "false" if it's
134 * just DDM.
135 */
136bool 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 */
143s8 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 */
150int dvmDbgThreadRunning(void);
151int dvmDbgThreadWaiting(void);
152int dvmDbgThreadContinuing(int status);
153
154/*
155 * The debugger wants the VM to exit.
156 */
157void dvmDbgExit(int status);
158
159/*
160 * Class, Object, Array
161 */
162const char* dvmDbgGetClassDescriptor(RefTypeId id);
163ObjectId dvmDbgGetClassObject(RefTypeId id);
164RefTypeId dvmDbgGetSuperclass(RefTypeId id);
165ObjectId dvmDbgGetClassLoader(RefTypeId id);
166u4 dvmDbgGetAccessFlags(RefTypeId id);
167bool dvmDbgIsInterface(RefTypeId id);
168void dvmDbgGetClassList(u4* pNumClasses, RefTypeId** pClassRefBuf);
169void dvmDbgGetVisibleClassList(ObjectId classLoaderId, u4* pNumClasses,
170        RefTypeId** pClassRefBuf);
171void dvmDbgGetClassInfo(RefTypeId classId, u1* pTypeTag, u4* pStatus,
172    char** pSignature);
173bool dvmDbgFindLoadedClassBySignature(const char* classDescriptor,
174        RefTypeId* pRefTypeId);
175void dvmDbgGetObjectType(ObjectId objectId, u1* pRefTypeTag,
176    RefTypeId* pRefTypeId);
177u1 dvmDbgGetClassObjectType(RefTypeId refTypeId);
178char* dvmDbgGetSignature(RefTypeId refTypeId);
179const char* dvmDbgGetSourceFile(RefTypeId refTypeId);
180char* dvmDbgGetObjectTypeName(ObjectId objectId);
181int dvmDbgGetSignatureTag(const char* signature);
182int dvmDbgGetObjectTag(ObjectId objectId, const char* type);
183int dvmDbgGetTagWidth(int tag);
184
185int dvmDbgGetArrayLength(ObjectId arrayId);
186int dvmDbgGetArrayElementTag(ObjectId arrayId);
187bool dvmDbgOutputArray(ObjectId arrayId, int firstIndex, int count,
188    ExpandBuf* pReply);
189bool dvmDbgSetArrayElements(ObjectId arrayId, int firstIndex, int count,
190    const u1* buf);
191
192ObjectId dvmDbgCreateString(const char* str);
193ObjectId dvmDbgCreateObject(RefTypeId classId);
194ObjectId dvmDbgCreateArrayObject(RefTypeId arrayTypeId, u4 length);
195
196bool dvmDbgMatchType(RefTypeId instClassId, RefTypeId classId);
197
198/*
199 * Method and Field
200 */
201const char* dvmDbgGetMethodName(RefTypeId refTypeId, MethodId id);
202void dvmDbgOutputAllFields(RefTypeId refTypeId, bool withGeneric,
203    ExpandBuf* pReply);
204void dvmDbgOutputAllMethods(RefTypeId refTypeId, bool withGeneric,
205    ExpandBuf* pReply);
206void dvmDbgOutputAllInterfaces(RefTypeId refTypeId, ExpandBuf* pReply);
207void dvmDbgOutputLineTable(RefTypeId refTypeId, MethodId methodId,
208    ExpandBuf* pReply);
209void dvmDbgOutputVariableTable(RefTypeId refTypeId, MethodId id,
210    bool withGeneric, ExpandBuf* pReply);
211
212int dvmDbgGetFieldTag(ObjectId objId, FieldId fieldId);
213int dvmDbgGetStaticFieldTag(RefTypeId refTypeId, FieldId fieldId);
214void dvmDbgGetFieldValue(ObjectId objId, FieldId fieldId, u1* ptr, int width);
215void dvmDbgSetFieldValue(ObjectId objectId, FieldId fieldId, u8 value,
216    int width);
217void dvmDbgGetStaticFieldValue(RefTypeId refTypeId, FieldId fieldId, u1* ptr,
218    int width);
219void dvmDbgSetStaticFieldValue(RefTypeId refTypeId, FieldId fieldId,
220    u8 rawValue, int width);
221
222char* dvmDbgStringToUtf8(ObjectId strId);
223
224/*
225 * Thread, ThreadGroup, Frame
226 */
227char* dvmDbgGetThreadName(ObjectId threadId);
228ObjectId dvmDbgGetThreadGroup(ObjectId threadId);
229char* dvmDbgGetThreadGroupName(ObjectId threadGroupId);
230ObjectId dvmDbgGetThreadGroupParent(ObjectId threadGroupId);
231ObjectId dvmDbgGetSystemThreadGroupId(void);
232ObjectId dvmDbgGetMainThreadGroupId(void);
233
234bool dvmDbgGetThreadStatus(ObjectId threadId, u4* threadStatus,
235    u4* suspendStatus);
236u4 dvmDbgGetThreadSuspendCount(ObjectId threadId);
237bool dvmDbgThreadExists(ObjectId threadId);
238bool dvmDbgIsSuspended(ObjectId threadId);
239//void dvmDbgWaitForSuspend(ObjectId threadId);
240void dvmDbgGetThreadGroupThreads(ObjectId threadGroupId,
241    ObjectId** ppThreadIds, u4* pThreadCount);
242void dvmDbgGetAllThreads(ObjectId** ppThreadIds, u4* pThreadCount);
243int dvmDbgGetThreadFrameCount(ObjectId threadId);
244bool dvmDbgGetThreadFrame(ObjectId threadId, int num, FrameId* pFrameId,
245    JdwpLocation* pLoc);
246
247ObjectId dvmDbgGetThreadSelfId(void);
248void dvmDbgSuspendVM(bool isEvent);
249void dvmDbgResumeVM(void);
250void dvmDbgSuspendThread(ObjectId threadId);
251void dvmDbgResumeThread(ObjectId threadId);
252void dvmDbgSuspendSelf(void);
253
254bool dvmDbgGetThisObject(ObjectId threadId, FrameId frameId, ObjectId* pThisId);
255void dvmDbgGetLocalValue(ObjectId threadId, FrameId frameId, int slot,
256    u1 tag, u1* buf, int expectedLen);
257void dvmDbgSetLocalValue(ObjectId threadId, FrameId frameId, int slot,
258    u1 tag, u8 value, int width);
259
260
261/*
262 * Debugger notification
263 */
264void dvmDbgPostLocationEvent(const struct Method* method, int pcOffset,
265    struct Object* thisPtr, int eventFlags);
266void dvmDbgPostException(void* throwFp, int throwRelPc, void* catchFp,
267    int catchRelPc, struct Object* exception);
268void dvmDbgPostThreadStart(struct Thread* thread);
269void dvmDbgPostThreadDeath(struct Thread* thread);
270void dvmDbgPostClassPrepare(struct ClassObject* clazz);
271// FieldAccess, FieldModification
272
273/* for "eventFlags" */
274enum {
275    DBG_BREAKPOINT      = 0x01,
276    DBG_SINGLE_STEP     = 0x02,
277    DBG_METHOD_ENTRY    = 0x04,
278    DBG_METHOD_EXIT     = 0x08,
279};
280
281bool dvmDbgWatchLocation(const JdwpLocation* pLoc);
282void dvmDbgUnwatchLocation(const JdwpLocation* pLoc);
283bool dvmDbgConfigureStep(ObjectId threadId, enum JdwpStepSize size,
284    enum JdwpStepDepth depth);
285void dvmDbgUnconfigureStep(ObjectId threadId);
286
287JdwpError dvmDbgInvokeMethod(ObjectId threadId, ObjectId objectId,
288    RefTypeId classId, MethodId methodId, u4 numArgs, u8* argArray,
289    u4 options, u1* pResultTag, u8* pResultValue, ObjectId* pExceptObj);
290void dvmDbgExecuteMethod(DebugInvokeReq* pReq);
291
292/* Make an AddressSet for a line, for single stepping */
293const AddressSet *dvmAddressSetForLine(const struct Method* method, int line);
294
295/* perform "late registration" of an object ID */
296void dvmDbgRegisterObjectId(ObjectId id);
297
298/*
299 * DDM support.
300 */
301bool dvmDbgDdmHandlePacket(const u1* buf, int dataLen, u1** pReplyBuf,
302    int* pReplyLen);
303void dvmDbgDdmConnected(void);
304void dvmDbgDdmDisconnected(void);
305void dvmDbgDdmSendChunk(int type, size_t len, const u1* buf);
306void 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