debugger.h revision 4b9702c6912c6f8745a77f5b5af56e7fe196e7c2
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 ART_DEBUGGER_H_
22#define ART_DEBUGGER_H_
23
24#include <pthread.h>
25
26#include <string>
27
28#include "jdwp/jdwp.h"
29#include "jni.h"
30#include "jvalue.h"
31#include "root_visitor.h"
32
33namespace art {
34namespace mirror {
35class AbstractMethod;
36class Class;
37class Object;
38class Throwable;
39}  // namespace mirror
40struct AllocRecord;
41class Thread;
42
43/*
44 * Invoke-during-breakpoint support.
45 */
46struct DebugInvokeReq {
47  DebugInvokeReq()
48      : ready(false), invoke_needed_(false),
49        receiver_(NULL), thread_(NULL), class_(NULL), method_(NULL),
50        arg_count_(0), arg_values_(NULL), options_(0), error(JDWP::ERR_NONE),
51        result_tag(JDWP::JT_VOID), exception(0),
52        lock_("a DebugInvokeReq lock", kBreakpointInvokeLock),
53        cond_("a DebugInvokeReq condition variable", lock_) {
54  }
55
56  /* boolean; only set when we're in the tail end of an event handler */
57  bool ready;
58
59  /* boolean; set if the JDWP thread wants this thread to do work */
60  bool invoke_needed_;
61
62  /* request */
63  mirror::Object* receiver_;      /* not used for ClassType.InvokeMethod */
64  mirror::Object* thread_;
65  mirror::Class* class_;
66  mirror::AbstractMethod* method_;
67  uint32_t arg_count_;
68  uint64_t* arg_values_;   /* will be NULL if arg_count_ == 0 */
69  uint32_t options_;
70
71  /* result */
72  JDWP::JdwpError error;
73  JDWP::JdwpTag result_tag;
74  JValue result_value;
75  JDWP::ObjectId exception;
76
77  /* condition variable to wait on while the method executes */
78  Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
79  ConditionVariable cond_ GUARDED_BY(lock_);
80};
81
82class Dbg {
83 public:
84  static bool ParseJdwpOptions(const std::string& options);
85  static void SetJdwpAllowed(bool allowed);
86
87  static void StartJdwp();
88  static void StopJdwp();
89
90  // Invoked by the GC in case we need to keep DDMS informed.
91  static void GcDidFinish() LOCKS_EXCLUDED(Locks::mutator_lock_);
92
93  // Return the DebugInvokeReq for the current thread.
94  static DebugInvokeReq* GetInvokeReq();
95
96  static Thread* GetDebugThread();
97  static void ClearWaitForEventThread();
98
99  /*
100   * Enable/disable breakpoints and step modes.  Used to provide a heads-up
101   * when the debugger attaches.
102   */
103  static void Connected();
104  static void GoActive() LOCKS_EXCLUDED(Locks::breakpoint_lock_);
105  static void Disconnected();
106  static void Disposed();
107
108  // Returns true if we're actually debugging with a real debugger, false if it's
109  // just DDMS (or nothing at all).
110  static bool IsDebuggerActive();
111
112  // Returns true if we had -Xrunjdwp or -agentlib:jdwp= on the command line.
113  static bool IsJdwpConfigured();
114
115  static bool IsDisposed();
116
117  /*
118   * Time, in milliseconds, since the last debugger activity.  Does not
119   * include DDMS activity.  Returns -1 if there has been no activity.
120   * Returns 0 if we're in the middle of handling a debugger request.
121   */
122  static int64_t LastDebuggerActivity();
123
124  static void UndoDebuggerSuspensions();
125
126  /*
127   * Class, Object, Array
128   */
129  static std::string GetClassName(JDWP::RefTypeId id)
130      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
131  static JDWP::JdwpError GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& class_object_id)
132      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
133  static JDWP::JdwpError GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& superclass_id)
134      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
135  static JDWP::JdwpError GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply)
136      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
137  static JDWP::JdwpError GetModifiers(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply)
138      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
139  static JDWP::JdwpError GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply)
140      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
141  static void GetClassList(std::vector<JDWP::RefTypeId>& classes)
142      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
143  static JDWP::JdwpError GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag,
144                                      uint32_t* pStatus, std::string* pDescriptor)
145      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
146  static void FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids)
147      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
148  static JDWP::JdwpError GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply)
149      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
150  static JDWP::JdwpError GetSignature(JDWP::RefTypeId ref_type_id, std::string& signature)
151      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
152  static JDWP::JdwpError GetSourceFile(JDWP::RefTypeId ref_type_id, std::string& source_file)
153      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
154  static JDWP::JdwpError GetObjectTag(JDWP::ObjectId object_id, uint8_t& tag)
155      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
156  static size_t GetTagWidth(JDWP::JdwpTag tag);
157
158  static JDWP::JdwpError GetArrayLength(JDWP::ObjectId array_id, int& length)
159      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
160  static JDWP::JdwpError OutputArray(JDWP::ObjectId array_id, int offset, int count,
161                                     JDWP::ExpandBuf* pReply)
162      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
163  static JDWP::JdwpError SetArrayElements(JDWP::ObjectId array_id, int offset, int count,
164                                          JDWP::Request& request)
165      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
166
167  static JDWP::ObjectId CreateString(const std::string& str)
168      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
169  static JDWP::JdwpError CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId& new_object)
170      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
171  static JDWP::JdwpError CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t length,
172                                           JDWP::ObjectId& new_array)
173      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
174
175  static bool MatchType(JDWP::RefTypeId instance_class_id, JDWP::RefTypeId class_id)
176      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
177
178  //
179  // Monitors.
180  //
181  static JDWP::JdwpError GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* reply)
182      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
183  static JDWP::JdwpError GetOwnedMonitors(JDWP::ObjectId thread_id,
184                                          std::vector<JDWP::ObjectId>& monitors,
185                                          std::vector<uint32_t>& stack_depths)
186      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
187  static JDWP::JdwpError GetContendedMonitor(JDWP::ObjectId thread_id, JDWP::ObjectId& contended_monitor)
188      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
189
190  //
191  // Heap.
192  //
193  static JDWP::JdwpError GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class_ids,
194                                           std::vector<uint64_t>& counts)
195      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
196  static JDWP::JdwpError GetInstances(JDWP::RefTypeId class_id, int32_t max_count,
197                                      std::vector<JDWP::ObjectId>& instances)
198      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
199  static JDWP::JdwpError GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count,
200                                             std::vector<JDWP::ObjectId>& referring_objects)
201      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
202  static JDWP::JdwpError DisableCollection(JDWP::ObjectId object_id)
203      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
204  static JDWP::JdwpError EnableCollection(JDWP::ObjectId object_id)
205      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
206  static JDWP::JdwpError IsCollected(JDWP::ObjectId object_id, bool& is_collected)
207      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
208  static void DisposeObject(JDWP::ObjectId object_id, uint32_t reference_count)
209      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
210
211  //
212  // Methods and fields.
213  //
214  static std::string GetMethodName(JDWP::MethodId method_id)
215      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
216  static JDWP::JdwpError OutputDeclaredFields(JDWP::RefTypeId ref_type_id, bool with_generic,
217                                              JDWP::ExpandBuf* pReply)
218      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
219  static JDWP::JdwpError OutputDeclaredMethods(JDWP::RefTypeId ref_type_id, bool with_generic,
220                                               JDWP::ExpandBuf* pReply)
221      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
222  static JDWP::JdwpError OutputDeclaredInterfaces(JDWP::RefTypeId ref_type_id,
223                                                  JDWP::ExpandBuf* pReply)
224      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
225  static void OutputLineTable(JDWP::RefTypeId ref_type_id, JDWP::MethodId method_id,
226                              JDWP::ExpandBuf* pReply)
227      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
228  static void OutputVariableTable(JDWP::RefTypeId ref_type_id, JDWP::MethodId id, bool with_generic,
229                                  JDWP::ExpandBuf* pReply)
230      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
231  static JDWP::JdwpError GetBytecodes(JDWP::RefTypeId class_id, JDWP::MethodId method_id,
232                                      std::vector<uint8_t>& bytecodes)
233      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
234
235  static std::string GetFieldName(JDWP::FieldId field_id)
236      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
237  static JDWP::JdwpTag GetFieldBasicTag(JDWP::FieldId field_id)
238      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
239  static JDWP::JdwpTag GetStaticFieldBasicTag(JDWP::FieldId field_id)
240      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);;
241  static JDWP::JdwpError GetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id,
242                                       JDWP::ExpandBuf* pReply)
243      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
244  static JDWP::JdwpError SetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id,
245                                       uint64_t value, int width)
246      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
247  static JDWP::JdwpError GetStaticFieldValue(JDWP::RefTypeId ref_type_id, JDWP::FieldId field_id,
248                                             JDWP::ExpandBuf* pReply)
249      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
250  static JDWP::JdwpError SetStaticFieldValue(JDWP::FieldId field_id, uint64_t value, int width)
251      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
252
253  static std::string StringToUtf8(JDWP::ObjectId string_id)
254      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
255
256  /*
257   * Thread, ThreadGroup, Frame
258   */
259  static JDWP::JdwpError GetThreadName(JDWP::ObjectId thread_id, std::string& name)
260      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
261      LOCKS_EXCLUDED(Locks::thread_list_lock_);
262  static JDWP::JdwpError GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply);
263  static std::string GetThreadGroupName(JDWP::ObjectId thread_group_id);
264  static JDWP::ObjectId GetThreadGroupParent(JDWP::ObjectId thread_group_id)
265      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
266  static JDWP::ObjectId GetSystemThreadGroupId()
267      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
268  static JDWP::ObjectId GetMainThreadGroupId();
269
270  static JDWP::JdwpError GetThreadStatus(JDWP::ObjectId thread_id, JDWP::JdwpThreadStatus* pThreadStatus, JDWP::JdwpSuspendStatus* pSuspendStatus);
271  static JDWP::JdwpError GetThreadDebugSuspendCount(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply);
272  //static void WaitForSuspend(JDWP::ObjectId thread_id);
273
274  // Fills 'thread_ids' with the threads in the given thread group. If thread_group_id == 0,
275  // returns all threads.
276  static void GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& thread_ids)
277      LOCKS_EXCLUDED(Locks::thread_list_lock_)
278      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
279  static void GetChildThreadGroups(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& child_thread_group_ids);
280
281  static JDWP::JdwpError GetThreadFrameCount(JDWP::ObjectId thread_id, size_t& result);
282  static JDWP::JdwpError GetThreadFrames(JDWP::ObjectId thread_id, size_t start_frame,
283                                         size_t frame_count, JDWP::ExpandBuf* buf)
284      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
285
286  static JDWP::ObjectId GetThreadSelfId()
287      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
288  static void SuspendVM()
289      LOCKS_EXCLUDED(Locks::thread_list_lock_,
290                     Locks::thread_suspend_count_lock_);
291  static void ResumeVM();
292  static JDWP::JdwpError SuspendThread(JDWP::ObjectId thread_id, bool request_suspension = true)
293      LOCKS_EXCLUDED(Locks::mutator_lock_,
294                     Locks::thread_list_lock_,
295                     Locks::thread_suspend_count_lock_);
296
297  static void ResumeThread(JDWP::ObjectId thread_id)
298      LOCKS_EXCLUDED(Locks::thread_list_lock_,
299                     Locks::thread_suspend_count_lock_)
300      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
301  static void SuspendSelf();
302
303  static JDWP::JdwpError GetThisObject(JDWP::ObjectId thread_id, JDWP::FrameId frame_id,
304                                       JDWP::ObjectId* result)
305      LOCKS_EXCLUDED(Locks::thread_list_lock_,
306                     Locks::thread_suspend_count_lock_)
307      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
308  static void GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int slot,
309                            JDWP::JdwpTag tag, uint8_t* buf, size_t expectedLen)
310      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
311  static void SetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int slot,
312                            JDWP::JdwpTag tag, uint64_t value, size_t width)
313      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
314
315  static JDWP::JdwpError Interrupt(JDWP::ObjectId thread_id);
316
317  /*
318   * Debugger notification
319   */
320  enum {
321    kBreakpoint     = 0x01,
322    kSingleStep     = 0x02,
323    kMethodEntry    = 0x04,
324    kMethodExit     = 0x08,
325  };
326  static void PostLocationEvent(const mirror::AbstractMethod* method, int pcOffset,
327                                mirror::Object* thisPtr, int eventFlags)
328      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
329  static void PostException(Thread* thread, JDWP::FrameId throw_frame_id,
330                            mirror::AbstractMethod* throw_method,
331                            uint32_t throw_dex_pc, mirror::AbstractMethod* catch_method,
332                            uint32_t catch_dex_pc, mirror::Throwable* exception)
333      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
334  static void PostThreadStart(Thread* t)
335      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
336  static void PostThreadDeath(Thread* t)
337      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
338  static void PostClassPrepare(mirror::Class* c)
339      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
340
341  static void UpdateDebugger(int32_t dex_pc, Thread* self)
342      LOCKS_EXCLUDED(Locks::breakpoint_lock_)
343      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
344
345  static void WatchLocation(const JDWP::JdwpLocation* pLoc)
346      LOCKS_EXCLUDED(Locks::breakpoint_lock_)
347      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
348  static void UnwatchLocation(const JDWP::JdwpLocation* pLoc)
349      LOCKS_EXCLUDED(Locks::breakpoint_lock_)
350      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
351  static JDWP::JdwpError ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize size,
352                                       JDWP::JdwpStepDepth depth)
353      LOCKS_EXCLUDED(Locks::breakpoint_lock_)
354      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
355  static void UnconfigureStep(JDWP::ObjectId thread_id) LOCKS_EXCLUDED(Locks::breakpoint_lock_);
356
357  static JDWP::JdwpError InvokeMethod(JDWP::ObjectId thread_id, JDWP::ObjectId object_id,
358                                      JDWP::RefTypeId class_id, JDWP::MethodId method_id,
359                                      uint32_t arg_count, uint64_t* arg_values,
360                                      JDWP::JdwpTag* arg_types, uint32_t options,
361                                      JDWP::JdwpTag* pResultTag, uint64_t* pResultValue,
362                                      JDWP::ObjectId* pExceptObj)
363      LOCKS_EXCLUDED(Locks::thread_list_lock_,
364                     Locks::thread_suspend_count_lock_)
365      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
366  static void ExecuteMethod(DebugInvokeReq* pReq);
367
368  /*
369   * DDM support.
370   */
371  static void DdmSendThreadNotification(Thread* t, uint32_t type)
372      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
373  static void DdmSetThreadNotification(bool enable);
374  static bool DdmHandlePacket(JDWP::Request& request, uint8_t** pReplyBuf, int* pReplyLen);
375  static void DdmConnected() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
376  static void DdmDisconnected() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
377  static void DdmSendChunk(uint32_t type, const std::vector<uint8_t>& bytes)
378      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
379  static void DdmSendChunk(uint32_t type, size_t len, const uint8_t* buf)
380      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
381  static void DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count)
382      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
383
384  /*
385   * Recent allocation tracking support.
386   */
387  static void RecordAllocation(mirror::Class* type, size_t byte_count)
388      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
389  static void SetAllocTrackingEnabled(bool enabled);
390  static inline bool IsAllocTrackingEnabled() { return recent_allocation_records_ != NULL; }
391  static jbyteArray GetRecentAllocations() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
392  static void DumpRecentAllocations();
393
394  enum HpifWhen {
395    HPIF_WHEN_NEVER = 0,
396    HPIF_WHEN_NOW = 1,
397    HPIF_WHEN_NEXT_GC = 2,
398    HPIF_WHEN_EVERY_GC = 3
399  };
400  static int DdmHandleHpifChunk(HpifWhen when)
401      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
402
403  enum HpsgWhen {
404    HPSG_WHEN_NEVER = 0,
405    HPSG_WHEN_EVERY_GC = 1,
406  };
407  enum HpsgWhat {
408    HPSG_WHAT_MERGED_OBJECTS = 0,
409    HPSG_WHAT_DISTINCT_OBJECTS = 1,
410  };
411  static bool DdmHandleHpsgNhsgChunk(HpsgWhen when, HpsgWhat what, bool native);
412
413  static void DdmSendHeapInfo(HpifWhen reason)
414      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
415  static void DdmSendHeapSegments(bool native)
416      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
417
418 private:
419  static void DdmBroadcast(bool) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
420  static void PostThreadStartOrStop(Thread*, uint32_t)
421      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
422
423  static AllocRecord* recent_allocation_records_;
424};
425
426#define CHUNK_TYPE(_name) \
427    static_cast<uint32_t>((_name)[0] << 24 | (_name)[1] << 16 | (_name)[2] << 8 | (_name)[3])
428
429}  // namespace art
430
431#endif  // ART_DEBUGGER_H_
432