debugger.h revision f4cb036808b88fe60d71a705b2744284155cbc01
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_RUNTIME_DEBUGGER_H_ 22#define ART_RUNTIME_DEBUGGER_H_ 23 24#include <pthread.h> 25 26#include <map> 27#include <set> 28#include <string> 29#include <vector> 30 31#include "jdwp/jdwp.h" 32#include "jni.h" 33#include "jvalue.h" 34#include "object_callbacks.h" 35#include "thread_state.h" 36 37namespace art { 38namespace mirror { 39class ArtField; 40class ArtMethod; 41class Class; 42class Object; 43class Throwable; 44} // namespace mirror 45class AllocRecord; 46class Thread; 47class ThrowLocation; 48 49/* 50 * Invoke-during-breakpoint support. 51 */ 52struct DebugInvokeReq { 53 DebugInvokeReq() 54 : ready(false), invoke_needed(false), 55 receiver(NULL), thread(NULL), klass(NULL), method(NULL), 56 arg_count(0), arg_values(NULL), options(0), error(JDWP::ERR_NONE), 57 result_tag(JDWP::JT_VOID), exception(0), 58 lock("a DebugInvokeReq lock", kBreakpointInvokeLock), 59 cond("a DebugInvokeReq condition variable", lock) { 60 } 61 62 /* boolean; only set when we're in the tail end of an event handler */ 63 bool ready; 64 65 /* boolean; set if the JDWP thread wants this thread to do work */ 66 bool invoke_needed; 67 68 /* request */ 69 mirror::Object* receiver; /* not used for ClassType.InvokeMethod */ 70 mirror::Object* thread; 71 mirror::Class* klass; 72 mirror::ArtMethod* method; 73 uint32_t arg_count; 74 uint64_t* arg_values; /* will be NULL if arg_count_ == 0 */ 75 uint32_t options; 76 77 /* result */ 78 JDWP::JdwpError error; 79 JDWP::JdwpTag result_tag; 80 JValue result_value; 81 JDWP::ObjectId exception; 82 83 /* condition variable to wait on while the method executes */ 84 Mutex lock DEFAULT_MUTEX_ACQUIRED_AFTER; 85 ConditionVariable cond GUARDED_BY(lock); 86 87 void VisitRoots(RootCallback* callback, void* arg, uint32_t tid, RootType root_type) 88 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 89 90 void Clear(); 91 92 private: 93 DISALLOW_COPY_AND_ASSIGN(DebugInvokeReq); 94}; 95 96// Thread local data-structure that holds fields for controlling single-stepping. 97struct SingleStepControl { 98 SingleStepControl() 99 : is_active(false), step_size(JDWP::SS_MIN), step_depth(JDWP::SD_INTO), 100 method(nullptr), stack_depth(0) { 101 } 102 103 // Are we single-stepping right now? 104 bool is_active; 105 106 // See JdwpStepSize and JdwpStepDepth for details. 107 JDWP::JdwpStepSize step_size; 108 JDWP::JdwpStepDepth step_depth; 109 110 // The location this single-step was initiated from. 111 // A single-step is initiated in a suspended thread. We save here the current method and the 112 // set of DEX pcs associated to the source line number where the suspension occurred. 113 // This is used to support SD_INTO and SD_OVER single-step depths so we detect when a single-step 114 // causes the execution of an instruction in a different method or at a different line number. 115 mirror::ArtMethod* method; 116 std::set<uint32_t> dex_pcs; 117 118 // The stack depth when this single-step was initiated. This is used to support SD_OVER and SD_OUT 119 // single-step depth. 120 int stack_depth; 121 122 void VisitRoots(RootCallback* callback, void* arg, uint32_t tid, RootType root_type) 123 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 124 125 bool ContainsDexPc(uint32_t dex_pc) const; 126 127 void Clear(); 128 129 private: 130 DISALLOW_COPY_AND_ASSIGN(SingleStepControl); 131}; 132 133// TODO rename to InstrumentationRequest. 134class DeoptimizationRequest { 135 public: 136 enum Kind { 137 kNothing, // no action. 138 kRegisterForEvent, // start listening for instrumentation event. 139 kUnregisterForEvent, // stop listening for instrumentation event. 140 kFullDeoptimization, // deoptimize everything. 141 kFullUndeoptimization, // undeoptimize everything. 142 kSelectiveDeoptimization, // deoptimize one method. 143 kSelectiveUndeoptimization // undeoptimize one method. 144 }; 145 146 DeoptimizationRequest() : kind_(kNothing), instrumentation_event_(0), method_(nullptr) {} 147 148 DeoptimizationRequest(const DeoptimizationRequest& other) 149 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 150 : kind_(other.kind_), instrumentation_event_(other.instrumentation_event_) { 151 // Create a new JNI global reference for the method. 152 SetMethod(other.Method()); 153 } 154 155 mirror::ArtMethod* Method() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 156 157 void SetMethod(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 158 159 // Name 'Kind()' would collide with the above enum name. 160 Kind GetKind() const { 161 return kind_; 162 } 163 164 void SetKind(Kind kind) { 165 kind_ = kind; 166 } 167 168 uint32_t InstrumentationEvent() const { 169 return instrumentation_event_; 170 } 171 172 void SetInstrumentationEvent(uint32_t instrumentation_event) { 173 instrumentation_event_ = instrumentation_event; 174 } 175 176 private: 177 Kind kind_; 178 179 // TODO we could use a union to hold the instrumentation_event and the method since they 180 // respectively have sense only for kRegisterForEvent/kUnregisterForEvent and 181 // kSelectiveDeoptimization/kSelectiveUndeoptimization. 182 183 // Event to start or stop listening to. Only for kRegisterForEvent and kUnregisterForEvent. 184 uint32_t instrumentation_event_; 185 186 // Method for selective deoptimization. 187 jmethodID method_; 188}; 189 190class Dbg { 191 public: 192 class TypeCache { 193 public: 194 // Returns a weak global for the input type. Deduplicates. 195 jobject Add(mirror::Class* t) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, 196 Locks::alloc_tracker_lock_); 197 // Clears the type cache and deletes all the weak global refs. 198 void Clear() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, 199 Locks::alloc_tracker_lock_); 200 201 private: 202 std::multimap<int32_t, jobject> objects_; 203 }; 204 205 static bool ParseJdwpOptions(const std::string& options); 206 static void SetJdwpAllowed(bool allowed); 207 208 static void StartJdwp(); 209 static void StopJdwp(); 210 211 // Invoked by the GC in case we need to keep DDMS informed. 212 static void GcDidFinish() LOCKS_EXCLUDED(Locks::mutator_lock_); 213 214 // Return the DebugInvokeReq for the current thread. 215 static DebugInvokeReq* GetInvokeReq(); 216 217 static Thread* GetDebugThread(); 218 static void ClearWaitForEventThread(); 219 220 /* 221 * Enable/disable breakpoints and step modes. Used to provide a heads-up 222 * when the debugger attaches. 223 */ 224 static void Connected(); 225 static void GoActive() 226 LOCKS_EXCLUDED(Locks::breakpoint_lock_, Locks::deoptimization_lock_, Locks::mutator_lock_); 227 static void Disconnected() LOCKS_EXCLUDED(Locks::deoptimization_lock_, Locks::mutator_lock_); 228 static void Disposed(); 229 230 // Returns true if we're actually debugging with a real debugger, false if it's 231 // just DDMS (or nothing at all). 232 static bool IsDebuggerActive(); 233 234 // Returns true if we had -Xrunjdwp or -agentlib:jdwp= on the command line. 235 static bool IsJdwpConfigured(); 236 237 static bool IsDisposed(); 238 239 /* 240 * Time, in milliseconds, since the last debugger activity. Does not 241 * include DDMS activity. Returns -1 if there has been no activity. 242 * Returns 0 if we're in the middle of handling a debugger request. 243 */ 244 static int64_t LastDebuggerActivity(); 245 246 static void UndoDebuggerSuspensions(); 247 248 /* 249 * Class, Object, Array 250 */ 251 static std::string GetClassName(JDWP::RefTypeId id) 252 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 253 static JDWP::JdwpError GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& class_object_id) 254 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 255 static JDWP::JdwpError GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& superclass_id) 256 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 257 static JDWP::JdwpError GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) 258 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 259 static JDWP::JdwpError GetModifiers(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) 260 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 261 static JDWP::JdwpError GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) 262 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 263 static void GetClassList(std::vector<JDWP::RefTypeId>& classes) 264 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 265 static JDWP::JdwpError GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag, 266 uint32_t* pStatus, std::string* pDescriptor) 267 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 268 static void FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids) 269 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 270 static JDWP::JdwpError GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply) 271 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 272 static JDWP::JdwpError GetSignature(JDWP::RefTypeId ref_type_id, std::string* signature) 273 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 274 static JDWP::JdwpError GetSourceFile(JDWP::RefTypeId ref_type_id, std::string& source_file) 275 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 276 static JDWP::JdwpError GetObjectTag(JDWP::ObjectId object_id, uint8_t& tag) 277 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 278 static size_t GetTagWidth(JDWP::JdwpTag tag); 279 280 static JDWP::JdwpError GetArrayLength(JDWP::ObjectId array_id, int& length) 281 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 282 static JDWP::JdwpError OutputArray(JDWP::ObjectId array_id, int offset, int count, 283 JDWP::ExpandBuf* pReply) 284 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 285 static JDWP::JdwpError SetArrayElements(JDWP::ObjectId array_id, int offset, int count, 286 JDWP::Request& request) 287 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 288 289 static JDWP::ObjectId CreateString(const std::string& str) 290 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 291 static JDWP::JdwpError CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId& new_object) 292 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 293 static JDWP::JdwpError CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t length, 294 JDWP::ObjectId& new_array) 295 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 296 297 static bool MatchType(JDWP::RefTypeId instance_class_id, JDWP::RefTypeId class_id) 298 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 299 300 // 301 // Monitors. 302 // 303 static JDWP::JdwpError GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* reply) 304 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 305 static JDWP::JdwpError GetOwnedMonitors(JDWP::ObjectId thread_id, 306 std::vector<JDWP::ObjectId>& monitors, 307 std::vector<uint32_t>& stack_depths) 308 LOCKS_EXCLUDED(Locks::thread_list_lock_) 309 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 310 static JDWP::JdwpError GetContendedMonitor(JDWP::ObjectId thread_id, 311 JDWP::ObjectId& contended_monitor) 312 LOCKS_EXCLUDED(Locks::thread_list_lock_) 313 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 314 315 // 316 // Heap. 317 // 318 static JDWP::JdwpError GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class_ids, 319 std::vector<uint64_t>& counts) 320 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 321 static JDWP::JdwpError GetInstances(JDWP::RefTypeId class_id, int32_t max_count, 322 std::vector<JDWP::ObjectId>& instances) 323 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 324 static JDWP::JdwpError GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count, 325 std::vector<JDWP::ObjectId>& referring_objects) 326 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 327 static JDWP::JdwpError DisableCollection(JDWP::ObjectId object_id) 328 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 329 static JDWP::JdwpError EnableCollection(JDWP::ObjectId object_id) 330 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 331 static JDWP::JdwpError IsCollected(JDWP::ObjectId object_id, bool& is_collected) 332 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 333 static void DisposeObject(JDWP::ObjectId object_id, uint32_t reference_count) 334 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 335 336 // 337 // Methods and fields. 338 // 339 static std::string GetMethodName(JDWP::MethodId method_id) 340 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 341 static JDWP::JdwpError OutputDeclaredFields(JDWP::RefTypeId ref_type_id, bool with_generic, 342 JDWP::ExpandBuf* pReply) 343 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 344 static JDWP::JdwpError OutputDeclaredMethods(JDWP::RefTypeId ref_type_id, bool with_generic, 345 JDWP::ExpandBuf* pReply) 346 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 347 static JDWP::JdwpError OutputDeclaredInterfaces(JDWP::RefTypeId ref_type_id, 348 JDWP::ExpandBuf* pReply) 349 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 350 static void OutputLineTable(JDWP::RefTypeId ref_type_id, JDWP::MethodId method_id, 351 JDWP::ExpandBuf* pReply) 352 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 353 static void OutputVariableTable(JDWP::RefTypeId ref_type_id, JDWP::MethodId id, bool with_generic, 354 JDWP::ExpandBuf* pReply) 355 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 356 static void OutputMethodReturnValue(JDWP::MethodId method_id, const JValue* return_value, 357 JDWP::ExpandBuf* pReply) 358 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 359 static void OutputFieldValue(JDWP::FieldId field_id, const JValue* field_value, 360 JDWP::ExpandBuf* pReply) 361 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 362 static JDWP::JdwpError GetBytecodes(JDWP::RefTypeId class_id, JDWP::MethodId method_id, 363 std::vector<uint8_t>& bytecodes) 364 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 365 366 static std::string GetFieldName(JDWP::FieldId field_id) 367 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 368 static JDWP::JdwpTag GetFieldBasicTag(JDWP::FieldId field_id) 369 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 370 static JDWP::JdwpTag GetStaticFieldBasicTag(JDWP::FieldId field_id) 371 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 372 static JDWP::JdwpError GetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id, 373 JDWP::ExpandBuf* pReply) 374 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 375 static JDWP::JdwpError SetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id, 376 uint64_t value, int width) 377 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 378 static JDWP::JdwpError GetStaticFieldValue(JDWP::RefTypeId ref_type_id, JDWP::FieldId field_id, 379 JDWP::ExpandBuf* pReply) 380 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 381 static JDWP::JdwpError SetStaticFieldValue(JDWP::FieldId field_id, uint64_t value, int width) 382 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 383 384 static std::string StringToUtf8(JDWP::ObjectId string_id) 385 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 386 static void OutputJValue(JDWP::JdwpTag tag, const JValue* return_value, JDWP::ExpandBuf* pReply) 387 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 388 389 /* 390 * Thread, ThreadGroup, Frame 391 */ 392 static JDWP::JdwpError GetThreadName(JDWP::ObjectId thread_id, std::string& name) 393 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 394 LOCKS_EXCLUDED(Locks::thread_list_lock_); 395 static JDWP::JdwpError GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) 396 LOCKS_EXCLUDED(Locks::thread_list_lock_); 397 static std::string GetThreadGroupName(JDWP::ObjectId thread_group_id); 398 static JDWP::ObjectId GetThreadGroupParent(JDWP::ObjectId thread_group_id) 399 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 400 static JDWP::ObjectId GetSystemThreadGroupId() 401 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 402 static JDWP::ObjectId GetMainThreadGroupId(); 403 404 static JDWP::JdwpThreadStatus ToJdwpThreadStatus(ThreadState state); 405 static JDWP::JdwpError GetThreadStatus(JDWP::ObjectId thread_id, 406 JDWP::JdwpThreadStatus* pThreadStatus, 407 JDWP::JdwpSuspendStatus* pSuspendStatus) 408 LOCKS_EXCLUDED(Locks::thread_list_lock_); 409 static JDWP::JdwpError GetThreadDebugSuspendCount(JDWP::ObjectId thread_id, 410 JDWP::ExpandBuf* pReply) 411 LOCKS_EXCLUDED(Locks::thread_list_lock_, 412 Locks::thread_suspend_count_lock_); 413 // static void WaitForSuspend(JDWP::ObjectId thread_id); 414 415 // Fills 'thread_ids' with the threads in the given thread group. If thread_group_id == 0, 416 // returns all threads. 417 static void GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& thread_ids) 418 LOCKS_EXCLUDED(Locks::thread_list_lock_) 419 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 420 static void GetChildThreadGroups(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& child_thread_group_ids); 421 422 static JDWP::JdwpError GetThreadFrameCount(JDWP::ObjectId thread_id, size_t& result) 423 LOCKS_EXCLUDED(Locks::thread_list_lock_); 424 static JDWP::JdwpError GetThreadFrames(JDWP::ObjectId thread_id, size_t start_frame, 425 size_t frame_count, JDWP::ExpandBuf* buf) 426 LOCKS_EXCLUDED(Locks::thread_list_lock_) 427 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 428 429 static JDWP::ObjectId GetThreadSelfId() 430 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 431 static void SuspendVM() 432 LOCKS_EXCLUDED(Locks::thread_list_lock_, 433 Locks::thread_suspend_count_lock_); 434 static void ResumeVM(); 435 static JDWP::JdwpError SuspendThread(JDWP::ObjectId thread_id, bool request_suspension = true) 436 LOCKS_EXCLUDED(Locks::mutator_lock_, 437 Locks::thread_list_lock_, 438 Locks::thread_suspend_count_lock_); 439 440 static void ResumeThread(JDWP::ObjectId thread_id) 441 LOCKS_EXCLUDED(Locks::thread_list_lock_, 442 Locks::thread_suspend_count_lock_) 443 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 444 static void SuspendSelf(); 445 446 static JDWP::JdwpError GetThisObject(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, 447 JDWP::ObjectId* result) 448 LOCKS_EXCLUDED(Locks::thread_list_lock_, 449 Locks::thread_suspend_count_lock_) 450 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 451 static JDWP::JdwpError GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int slot, 452 JDWP::JdwpTag tag, uint8_t* buf, size_t expectedLen) 453 LOCKS_EXCLUDED(Locks::thread_list_lock_) 454 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 455 static JDWP::JdwpError SetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int slot, 456 JDWP::JdwpTag tag, uint64_t value, size_t width) 457 LOCKS_EXCLUDED(Locks::thread_list_lock_) 458 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 459 460 static JDWP::JdwpError Interrupt(JDWP::ObjectId thread_id) 461 LOCKS_EXCLUDED(Locks::thread_list_lock_); 462 463 /* 464 * Debugger notification 465 */ 466 enum { 467 kBreakpoint = 0x01, 468 kSingleStep = 0x02, 469 kMethodEntry = 0x04, 470 kMethodExit = 0x08, 471 }; 472 static void PostFieldAccessEvent(mirror::ArtMethod* m, int dex_pc, mirror::Object* this_object, 473 mirror::ArtField* f) 474 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 475 static void PostFieldModificationEvent(mirror::ArtMethod* m, int dex_pc, 476 mirror::Object* this_object, mirror::ArtField* f, 477 const JValue* field_value) 478 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 479 static void PostException(const ThrowLocation& throw_location, mirror::ArtMethod* catch_method, 480 uint32_t catch_dex_pc, mirror::Throwable* exception) 481 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 482 static void PostThreadStart(Thread* t) 483 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 484 static void PostThreadDeath(Thread* t) 485 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 486 static void PostClassPrepare(mirror::Class* c) 487 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 488 489 static void UpdateDebugger(Thread* thread, mirror::Object* this_object, 490 mirror::ArtMethod* method, uint32_t new_dex_pc, 491 int event_flags, const JValue* return_value) 492 LOCKS_EXCLUDED(Locks::breakpoint_lock_) 493 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 494 495 // Records deoptimization request in the queue. 496 static void RequestDeoptimization(const DeoptimizationRequest& req) 497 LOCKS_EXCLUDED(Locks::deoptimization_lock_) 498 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 499 500 // Support delayed full undeoptimization requests. This is currently only used for single-step 501 // events. 502 static void DelayFullUndeoptimization() LOCKS_EXCLUDED(Locks::deoptimization_lock_); 503 static void ProcessDelayedFullUndeoptimizations() 504 LOCKS_EXCLUDED(Locks::deoptimization_lock_) 505 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 506 507 // Manage deoptimization after updating JDWP events list. Suspends all threads, processes each 508 // request and finally resumes all threads. 509 static void ManageDeoptimization() 510 LOCKS_EXCLUDED(Locks::deoptimization_lock_) 511 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 512 513 // Breakpoints. 514 static void WatchLocation(const JDWP::JdwpLocation* pLoc, DeoptimizationRequest* req) 515 LOCKS_EXCLUDED(Locks::breakpoint_lock_) 516 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 517 static void UnwatchLocation(const JDWP::JdwpLocation* pLoc, DeoptimizationRequest* req) 518 LOCKS_EXCLUDED(Locks::breakpoint_lock_) 519 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 520 521 // Single-stepping. 522 static JDWP::JdwpError ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize size, 523 JDWP::JdwpStepDepth depth) 524 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 525 static void UnconfigureStep(JDWP::ObjectId thread_id) 526 LOCKS_EXCLUDED(Locks::thread_list_lock_) 527 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 528 529 static JDWP::JdwpError InvokeMethod(JDWP::ObjectId thread_id, JDWP::ObjectId object_id, 530 JDWP::RefTypeId class_id, JDWP::MethodId method_id, 531 uint32_t arg_count, uint64_t* arg_values, 532 JDWP::JdwpTag* arg_types, uint32_t options, 533 JDWP::JdwpTag* pResultTag, uint64_t* pResultValue, 534 JDWP::ObjectId* pExceptObj) 535 LOCKS_EXCLUDED(Locks::thread_list_lock_, 536 Locks::thread_suspend_count_lock_) 537 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 538 static void ExecuteMethod(DebugInvokeReq* pReq); 539 540 /* 541 * DDM support. 542 */ 543 static void DdmSendThreadNotification(Thread* t, uint32_t type) 544 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 545 static void DdmSetThreadNotification(bool enable) 546 LOCKS_EXCLUDED(Locks::thread_list_lock_); 547 static bool DdmHandlePacket(JDWP::Request& request, uint8_t** pReplyBuf, int* pReplyLen); 548 static void DdmConnected() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 549 static void DdmDisconnected() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 550 static void DdmSendChunk(uint32_t type, const std::vector<uint8_t>& bytes) 551 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 552 static void DdmSendChunk(uint32_t type, size_t len, const uint8_t* buf) 553 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 554 static void DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) 555 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 556 557 static void VisitRoots(RootCallback* callback, void* arg) 558 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 559 560 /* 561 * Recent allocation tracking support. 562 */ 563 static void RecordAllocation(mirror::Class* type, size_t byte_count) 564 LOCKS_EXCLUDED(Locks::alloc_tracker_lock_) 565 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 566 static void SetAllocTrackingEnabled(bool enabled) LOCKS_EXCLUDED(Locks::alloc_tracker_lock_); 567 static bool IsAllocTrackingEnabled() { 568 return recent_allocation_records_ != nullptr; 569 } 570 static jbyteArray GetRecentAllocations() 571 LOCKS_EXCLUDED(Locks::alloc_tracker_lock_) 572 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 573 static size_t HeadIndex() EXCLUSIVE_LOCKS_REQUIRED(Locks::alloc_tracker_lock_); 574 static void DumpRecentAllocations() LOCKS_EXCLUDED(Locks::alloc_tracker_lock_); 575 576 enum HpifWhen { 577 HPIF_WHEN_NEVER = 0, 578 HPIF_WHEN_NOW = 1, 579 HPIF_WHEN_NEXT_GC = 2, 580 HPIF_WHEN_EVERY_GC = 3 581 }; 582 static int DdmHandleHpifChunk(HpifWhen when) 583 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 584 585 enum HpsgWhen { 586 HPSG_WHEN_NEVER = 0, 587 HPSG_WHEN_EVERY_GC = 1, 588 }; 589 enum HpsgWhat { 590 HPSG_WHAT_MERGED_OBJECTS = 0, 591 HPSG_WHAT_DISTINCT_OBJECTS = 1, 592 }; 593 static bool DdmHandleHpsgNhsgChunk(HpsgWhen when, HpsgWhat what, bool native); 594 595 static void DdmSendHeapInfo(HpifWhen reason) 596 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 597 static void DdmSendHeapSegments(bool native) 598 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 599 600 private: 601 static void DdmBroadcast(bool connect) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 602 static void PostThreadStartOrStop(Thread*, uint32_t) 603 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 604 605 static void PostLocationEvent(mirror::ArtMethod* method, int pcOffset, 606 mirror::Object* thisPtr, int eventFlags, 607 const JValue* return_value) 608 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 609 610 static JDWP::ObjectId GetThisObjectIdForEvent(mirror::Object* this_object) 611 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 612 613 static void ProcessDeoptimizationRequest(const DeoptimizationRequest& request) 614 EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_); 615 616 static void RequestDeoptimizationLocked(const DeoptimizationRequest& req) 617 EXCLUSIVE_LOCKS_REQUIRED(Locks::deoptimization_lock_) 618 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 619 620 static AllocRecord* recent_allocation_records_ PT_GUARDED_BY(Locks::alloc_tracker_lock_); 621 static size_t alloc_record_max_ GUARDED_BY(Locks::alloc_tracker_lock_); 622 static size_t alloc_record_head_ GUARDED_BY(Locks::alloc_tracker_lock_); 623 static size_t alloc_record_count_ GUARDED_BY(Locks::alloc_tracker_lock_); 624 625 // Deoptimization requests to be processed each time the event list is updated. This is used when 626 // registering and unregistering events so we do not deoptimize while holding the event list 627 // lock. 628 // TODO rename to instrumentation_requests. 629 static std::vector<DeoptimizationRequest> deoptimization_requests_ GUARDED_BY(Locks::deoptimization_lock_); 630 631 // Count the number of events requiring full deoptimization. When the counter is > 0, everything 632 // is deoptimized, otherwise everything is undeoptimized. 633 // Note: we fully deoptimize on the first event only (when the counter is set to 1). We fully 634 // undeoptimize when the last event is unregistered (when the counter is set to 0). 635 static size_t full_deoptimization_event_count_ GUARDED_BY(Locks::deoptimization_lock_); 636 637 // Count the number of full undeoptimization requests delayed to next resume or end of debug 638 // session. 639 static size_t delayed_full_undeoptimization_count_ GUARDED_BY(Locks::deoptimization_lock_); 640 641 static size_t* GetReferenceCounterForEvent(uint32_t instrumentation_event); 642 643 // Weak global type cache, TODO improve this. 644 static TypeCache type_cache_ GUARDED_BY(Locks::alloc_tracker_lock_); 645 646 // Instrumentation event reference counters. 647 // TODO we could use an array instead of having all these dedicated counters. Instrumentation 648 // events are bits of a mask so we could convert them to array index. 649 static size_t dex_pc_change_event_ref_count_ GUARDED_BY(Locks::deoptimization_lock_); 650 static size_t method_enter_event_ref_count_ GUARDED_BY(Locks::deoptimization_lock_); 651 static size_t method_exit_event_ref_count_ GUARDED_BY(Locks::deoptimization_lock_); 652 static size_t field_read_event_ref_count_ GUARDED_BY(Locks::deoptimization_lock_); 653 static size_t field_write_event_ref_count_ GUARDED_BY(Locks::deoptimization_lock_); 654 static size_t exception_catch_event_ref_count_ GUARDED_BY(Locks::deoptimization_lock_); 655 static uint32_t instrumentation_events_ GUARDED_BY(Locks::mutator_lock_); 656 657 friend class AllocRecord; // For type_cache_ with proper annotalysis. 658 DISALLOW_COPY_AND_ASSIGN(Dbg); 659}; 660 661#define CHUNK_TYPE(_name) \ 662 static_cast<uint32_t>((_name)[0] << 24 | (_name)[1] << 16 | (_name)[2] << 8 | (_name)[3]) 663 664} // namespace art 665 666#endif // ART_RUNTIME_DEBUGGER_H_ 667