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
dvmAddressSetSet(AddressSet * pSet,u4 toSet)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
dvmAddressSetGet(const AddressSet * pSet,u4 toGet)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