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