1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_DEBUG_H_ 29 #define V8_DEBUG_H_ 30 31 #include "arguments.h" 32 #include "assembler.h" 33 #include "debug-agent.h" 34 #include "execution.h" 35 #include "factory.h" 36 #include "flags.h" 37 #include "hashmap.h" 38 #include "platform.h" 39 #include "string-stream.h" 40 #include "v8threads.h" 41 42 #ifdef ENABLE_DEBUGGER_SUPPORT 43 #include "../include/v8-debug.h" 44 45 namespace v8 { 46 namespace internal { 47 48 49 // Forward declarations. 50 class EnterDebugger; 51 52 53 // Step actions. NOTE: These values are in macros.py as well. 54 enum StepAction { 55 StepNone = -1, // Stepping not prepared. 56 StepOut = 0, // Step out of the current function. 57 StepNext = 1, // Step to the next statement in the current function. 58 StepIn = 2, // Step into new functions invoked or the next statement 59 // in the current function. 60 StepMin = 3, // Perform a minimum step in the current function. 61 StepInMin = 4 // Step into new functions invoked or perform a minimum step 62 // in the current function. 63 }; 64 65 66 // Type of exception break. NOTE: These values are in macros.py as well. 67 enum ExceptionBreakType { 68 BreakException = 0, 69 BreakUncaughtException = 1 70 }; 71 72 73 // Type of exception break. NOTE: These values are in macros.py as well. 74 enum BreakLocatorType { 75 ALL_BREAK_LOCATIONS = 0, 76 SOURCE_BREAK_LOCATIONS = 1 77 }; 78 79 80 // Class for iterating through the break points in a function and changing 81 // them. 82 class BreakLocationIterator { 83 public: 84 explicit BreakLocationIterator(Handle<DebugInfo> debug_info, 85 BreakLocatorType type); 86 virtual ~BreakLocationIterator(); 87 88 void Next(); 89 void Next(int count); 90 void FindBreakLocationFromAddress(Address pc); 91 void FindBreakLocationFromPosition(int position); 92 void Reset(); 93 bool Done() const; 94 void SetBreakPoint(Handle<Object> break_point_object); 95 void ClearBreakPoint(Handle<Object> break_point_object); 96 void SetOneShot(); 97 void ClearOneShot(); 98 void PrepareStepIn(); 99 bool IsExit() const; 100 bool HasBreakPoint(); 101 bool IsDebugBreak(); 102 Object* BreakPointObjects(); 103 void ClearAllDebugBreak(); 104 105 code_position()106 inline int code_position() { 107 return static_cast<int>(pc() - debug_info_->code()->entry()); 108 } break_point()109 inline int break_point() { return break_point_; } position()110 inline int position() { return position_; } statement_position()111 inline int statement_position() { return statement_position_; } pc()112 inline Address pc() { return reloc_iterator_->rinfo()->pc(); } code()113 inline Code* code() { return debug_info_->code(); } rinfo()114 inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); } rmode()115 inline RelocInfo::Mode rmode() const { 116 return reloc_iterator_->rinfo()->rmode(); 117 } original_rinfo()118 inline RelocInfo* original_rinfo() { 119 return reloc_iterator_original_->rinfo(); 120 } original_rmode()121 inline RelocInfo::Mode original_rmode() const { 122 return reloc_iterator_original_->rinfo()->rmode(); 123 } 124 125 bool IsDebuggerStatement(); 126 127 protected: 128 bool RinfoDone() const; 129 void RinfoNext(); 130 131 BreakLocatorType type_; 132 int break_point_; 133 int position_; 134 int statement_position_; 135 Handle<DebugInfo> debug_info_; 136 RelocIterator* reloc_iterator_; 137 RelocIterator* reloc_iterator_original_; 138 139 private: 140 void SetDebugBreak(); 141 void ClearDebugBreak(); 142 143 void SetDebugBreakAtIC(); 144 void ClearDebugBreakAtIC(); 145 146 bool IsDebugBreakAtReturn(); 147 void SetDebugBreakAtReturn(); 148 void ClearDebugBreakAtReturn(); 149 150 bool IsDebugBreakSlot(); 151 bool IsDebugBreakAtSlot(); 152 void SetDebugBreakAtSlot(); 153 void ClearDebugBreakAtSlot(); 154 155 DISALLOW_COPY_AND_ASSIGN(BreakLocationIterator); 156 }; 157 158 159 // Cache of all script objects in the heap. When a script is added a weak handle 160 // to it is created and that weak handle is stored in the cache. The weak handle 161 // callback takes care of removing the script from the cache. The key used in 162 // the cache is the script id. 163 class ScriptCache : private HashMap { 164 public: ScriptCache()165 ScriptCache() : HashMap(ScriptMatch), collected_scripts_(10) {} ~ScriptCache()166 virtual ~ScriptCache() { Clear(); } 167 168 // Add script to the cache. 169 void Add(Handle<Script> script); 170 171 // Return the scripts in the cache. 172 Handle<FixedArray> GetScripts(); 173 174 // Generate debugger events for collected scripts. 175 void ProcessCollectedScripts(); 176 177 private: 178 // Calculate the hash value from the key (script id). Hash(int key)179 static uint32_t Hash(int key) { return ComputeIntegerHash(key); } 180 181 // Scripts match if their keys (script id) match. ScriptMatch(void * key1,void * key2)182 static bool ScriptMatch(void* key1, void* key2) { return key1 == key2; } 183 184 // Clear the cache releasing all the weak handles. 185 void Clear(); 186 187 // Weak handle callback for scripts in the cache. 188 static void HandleWeakScript(v8::Persistent<v8::Value> obj, void* data); 189 190 // List used during GC to temporarily store id's of collected scripts. 191 List<int> collected_scripts_; 192 }; 193 194 195 // Linked list holding debug info objects. The debug info objects are kept as 196 // weak handles to avoid a debug info object to keep a function alive. 197 class DebugInfoListNode { 198 public: 199 explicit DebugInfoListNode(DebugInfo* debug_info); 200 virtual ~DebugInfoListNode(); 201 next()202 DebugInfoListNode* next() { return next_; } set_next(DebugInfoListNode * next)203 void set_next(DebugInfoListNode* next) { next_ = next; } debug_info()204 Handle<DebugInfo> debug_info() { return debug_info_; } 205 206 private: 207 // Global (weak) handle to the debug info object. 208 Handle<DebugInfo> debug_info_; 209 210 // Next pointer for linked list. 211 DebugInfoListNode* next_; 212 }; 213 214 // This class contains the debugger support. The main purpose is to handle 215 // setting break points in the code. 216 // 217 // This class controls the debug info for all functions which currently have 218 // active breakpoints in them. This debug info is held in the heap root object 219 // debug_info which is a FixedArray. Each entry in this list is of class 220 // DebugInfo. 221 class Debug { 222 public: 223 void Setup(bool create_heap_objects); 224 bool Load(); 225 void Unload(); IsLoaded()226 bool IsLoaded() { return !debug_context_.is_null(); } InDebugger()227 bool InDebugger() { return thread_local_.debugger_entry_ != NULL; } 228 void PreemptionWhileInDebugger(); 229 void Iterate(ObjectVisitor* v); 230 231 Object* Break(Arguments args); 232 void SetBreakPoint(Handle<SharedFunctionInfo> shared, 233 Handle<Object> break_point_object, 234 int* source_position); 235 void ClearBreakPoint(Handle<Object> break_point_object); 236 void ClearAllBreakPoints(); 237 void FloodWithOneShot(Handle<SharedFunctionInfo> shared); 238 void FloodHandlerWithOneShot(); 239 void ChangeBreakOnException(ExceptionBreakType type, bool enable); 240 bool IsBreakOnException(ExceptionBreakType type); 241 void PrepareStep(StepAction step_action, int step_count); 242 void ClearStepping(); 243 bool StepNextContinue(BreakLocationIterator* break_location_iterator, 244 JavaScriptFrame* frame); 245 static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared); 246 static bool HasDebugInfo(Handle<SharedFunctionInfo> shared); 247 248 // Returns whether the operation succeeded. 249 bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared); 250 251 // Returns true if the current stub call is patched to call the debugger. 252 static bool IsDebugBreak(Address addr); 253 // Returns true if the current return statement has been patched to be 254 // a debugger breakpoint. 255 static bool IsDebugBreakAtReturn(RelocInfo* rinfo); 256 257 // Check whether a code stub with the specified major key is a possible break 258 // point location. 259 static bool IsSourceBreakStub(Code* code); 260 static bool IsBreakStub(Code* code); 261 262 // Find the builtin to use for invoking the debug break 263 static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode); 264 265 static Handle<Object> GetSourceBreakLocations( 266 Handle<SharedFunctionInfo> shared); 267 268 // Getter for the debug_context. debug_context()269 inline Handle<Context> debug_context() { return debug_context_; } 270 271 // Check whether a global object is the debug global object. 272 bool IsDebugGlobal(GlobalObject* global); 273 274 // Check whether this frame is just about to return. 275 bool IsBreakAtReturn(JavaScriptFrame* frame); 276 277 // Fast check to see if any break points are active. has_break_points()278 inline bool has_break_points() { return has_break_points_; } 279 280 void NewBreak(StackFrame::Id break_frame_id); 281 void SetBreak(StackFrame::Id break_frame_id, int break_id); break_frame_id()282 StackFrame::Id break_frame_id() { 283 return thread_local_.break_frame_id_; 284 } break_id()285 int break_id() { return thread_local_.break_id_; } 286 StepInActive()287 bool StepInActive() { return thread_local_.step_into_fp_ != 0; } 288 void HandleStepIn(Handle<JSFunction> function, 289 Handle<Object> holder, 290 Address fp, 291 bool is_constructor); step_in_fp()292 Address step_in_fp() { return thread_local_.step_into_fp_; } step_in_fp_addr()293 Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; } 294 StepOutActive()295 bool StepOutActive() { return thread_local_.step_out_fp_ != 0; } step_out_fp()296 Address step_out_fp() { return thread_local_.step_out_fp_; } 297 debugger_entry()298 EnterDebugger* debugger_entry() { 299 return thread_local_.debugger_entry_; 300 } set_debugger_entry(EnterDebugger * entry)301 void set_debugger_entry(EnterDebugger* entry) { 302 thread_local_.debugger_entry_ = entry; 303 } 304 305 // Check whether any of the specified interrupts are pending. is_interrupt_pending(InterruptFlag what)306 bool is_interrupt_pending(InterruptFlag what) { 307 return (thread_local_.pending_interrupts_ & what) != 0; 308 } 309 310 // Set specified interrupts as pending. set_interrupts_pending(InterruptFlag what)311 void set_interrupts_pending(InterruptFlag what) { 312 thread_local_.pending_interrupts_ |= what; 313 } 314 315 // Clear specified interrupts from pending. clear_interrupt_pending(InterruptFlag what)316 void clear_interrupt_pending(InterruptFlag what) { 317 thread_local_.pending_interrupts_ &= ~static_cast<int>(what); 318 } 319 320 // Getter and setter for the disable break state. disable_break()321 bool disable_break() { return disable_break_; } set_disable_break(bool disable_break)322 void set_disable_break(bool disable_break) { 323 disable_break_ = disable_break; 324 } 325 326 // Getters for the current exception break state. break_on_exception()327 bool break_on_exception() { return break_on_exception_; } break_on_uncaught_exception()328 bool break_on_uncaught_exception() { 329 return break_on_uncaught_exception_; 330 } 331 332 enum AddressId { 333 k_after_break_target_address, 334 k_debug_break_return_address, 335 k_debug_break_slot_address, 336 k_restarter_frame_function_pointer 337 }; 338 339 // Support for setting the address to jump to when returning from break point. after_break_target_address()340 Address* after_break_target_address() { 341 return reinterpret_cast<Address*>(&thread_local_.after_break_target_); 342 } restarter_frame_function_pointer_address()343 Address* restarter_frame_function_pointer_address() { 344 Object*** address = &thread_local_.restarter_frame_function_pointer_; 345 return reinterpret_cast<Address*>(address); 346 } 347 348 // Support for saving/restoring registers when handling debug break calls. register_address(int r)349 Object** register_address(int r) { 350 return ®isters_[r]; 351 } 352 353 // Access to the debug break on return code. debug_break_return()354 Code* debug_break_return() { return debug_break_return_; } debug_break_return_address()355 Code** debug_break_return_address() { 356 return &debug_break_return_; 357 } 358 359 // Access to the debug break in debug break slot code. debug_break_slot()360 Code* debug_break_slot() { return debug_break_slot_; } debug_break_slot_address()361 Code** debug_break_slot_address() { 362 return &debug_break_slot_; 363 } 364 365 static const int kEstimatedNofDebugInfoEntries = 16; 366 static const int kEstimatedNofBreakPointsInFunction = 16; 367 368 // Passed to MakeWeak. 369 static void HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data); 370 371 friend class Debugger; 372 friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc 373 friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc 374 375 // Threading support. 376 char* ArchiveDebug(char* to); 377 char* RestoreDebug(char* from); 378 static int ArchiveSpacePerThread(); FreeThreadResources()379 void FreeThreadResources() { } 380 381 // Mirror cache handling. 382 void ClearMirrorCache(); 383 384 // Script cache handling. 385 void CreateScriptCache(); 386 void DestroyScriptCache(); 387 void AddScriptToScriptCache(Handle<Script> script); 388 Handle<FixedArray> GetLoadedScripts(); 389 390 // Garbage collection notifications. 391 void AfterGarbageCollection(); 392 393 // Code generator routines. 394 static void GenerateSlot(MacroAssembler* masm); 395 static void GenerateLoadICDebugBreak(MacroAssembler* masm); 396 static void GenerateStoreICDebugBreak(MacroAssembler* masm); 397 static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm); 398 static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm); 399 static void GenerateConstructCallDebugBreak(MacroAssembler* masm); 400 static void GenerateReturnDebugBreak(MacroAssembler* masm); 401 static void GenerateStubNoRegistersDebugBreak(MacroAssembler* masm); 402 static void GenerateSlotDebugBreak(MacroAssembler* masm); 403 static void GeneratePlainReturnLiveEdit(MacroAssembler* masm); 404 405 // FrameDropper is a code replacement for a JavaScript frame with possibly 406 // several frames above. 407 // There is no calling conventions here, because it never actually gets 408 // called, it only gets returned to. 409 static void GenerateFrameDropperLiveEdit(MacroAssembler* masm); 410 411 // Called from stub-cache.cc. 412 static void GenerateCallICDebugBreak(MacroAssembler* masm); 413 414 // Describes how exactly a frame has been dropped from stack. 415 enum FrameDropMode { 416 // No frame has been dropped. 417 FRAMES_UNTOUCHED, 418 // The top JS frame had been calling IC stub. IC stub mustn't be called now. 419 FRAME_DROPPED_IN_IC_CALL, 420 // The top JS frame had been calling debug break slot stub. Patch the 421 // address this stub jumps to in the end. 422 FRAME_DROPPED_IN_DEBUG_SLOT_CALL, 423 // The top JS frame had been calling some C++ function. The return address 424 // gets patched automatically. 425 FRAME_DROPPED_IN_DIRECT_CALL 426 }; 427 428 void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, 429 FrameDropMode mode, 430 Object** restarter_frame_function_pointer); 431 432 // Initializes an artificial stack frame. The data it contains is used for: 433 // a. successful work of frame dropper code which eventually gets control, 434 // b. being compatible with regular stack structure for various stack 435 // iterators. 436 // Returns address of stack allocated pointer to restarted function, 437 // the value that is called 'restarter_frame_function_pointer'. The value 438 // at this address (possibly updated by GC) may be used later when preparing 439 // 'step in' operation. 440 static Object** SetUpFrameDropperFrame(StackFrame* bottom_js_frame, 441 Handle<Code> code); 442 443 static const int kFrameDropperFrameSize; 444 445 // Architecture-specific constant. 446 static const bool kFrameDropperSupported; 447 448 private: 449 explicit Debug(Isolate* isolate); 450 ~Debug(); 451 452 static bool CompileDebuggerScript(int index); 453 void ClearOneShot(); 454 void ActivateStepIn(StackFrame* frame); 455 void ClearStepIn(); 456 void ActivateStepOut(StackFrame* frame); 457 void ClearStepOut(); 458 void ClearStepNext(); 459 // Returns whether the compile succeeded. 460 void RemoveDebugInfo(Handle<DebugInfo> debug_info); 461 void SetAfterBreakTarget(JavaScriptFrame* frame); 462 Handle<Object> CheckBreakPoints(Handle<Object> break_point); 463 bool CheckBreakPoint(Handle<Object> break_point_object); 464 465 // Global handle to debug context where all the debugger JavaScript code is 466 // loaded. 467 Handle<Context> debug_context_; 468 469 // Boolean state indicating whether any break points are set. 470 bool has_break_points_; 471 472 // Cache of all scripts in the heap. 473 ScriptCache* script_cache_; 474 475 // List of active debug info objects. 476 DebugInfoListNode* debug_info_list_; 477 478 bool disable_break_; 479 bool break_on_exception_; 480 bool break_on_uncaught_exception_; 481 482 // Per-thread data. 483 class ThreadLocal { 484 public: 485 // Counter for generating next break id. 486 int break_count_; 487 488 // Current break id. 489 int break_id_; 490 491 // Frame id for the frame of the current break. 492 StackFrame::Id break_frame_id_; 493 494 // Step action for last step performed. 495 StepAction last_step_action_; 496 497 // Source statement position from last step next action. 498 int last_statement_position_; 499 500 // Number of steps left to perform before debug event. 501 int step_count_; 502 503 // Frame pointer from last step next action. 504 Address last_fp_; 505 506 // Frame pointer for frame from which step in was performed. 507 Address step_into_fp_; 508 509 // Frame pointer for the frame where debugger should be called when current 510 // step out action is completed. 511 Address step_out_fp_; 512 513 // Storage location for jump when exiting debug break calls. 514 Address after_break_target_; 515 516 // Stores the way how LiveEdit has patched the stack. It is used when 517 // debugger returns control back to user script. 518 FrameDropMode frame_drop_mode_; 519 520 // Top debugger entry. 521 EnterDebugger* debugger_entry_; 522 523 // Pending interrupts scheduled while debugging. 524 int pending_interrupts_; 525 526 // When restarter frame is on stack, stores the address 527 // of the pointer to function being restarted. Otherwise (most of the time) 528 // stores NULL. This pointer is used with 'step in' implementation. 529 Object** restarter_frame_function_pointer_; 530 }; 531 532 // Storage location for registers when handling debug break calls 533 JSCallerSavedBuffer registers_; 534 ThreadLocal thread_local_; 535 void ThreadInit(); 536 537 // Code to call for handling debug break on return. 538 Code* debug_break_return_; 539 540 // Code to call for handling debug break in debug break slots. 541 Code* debug_break_slot_; 542 543 Isolate* isolate_; 544 545 friend class Isolate; 546 547 DISALLOW_COPY_AND_ASSIGN(Debug); 548 }; 549 550 551 DECLARE_RUNTIME_FUNCTION(Object*, Debug_Break); 552 553 554 // Message delivered to the message handler callback. This is either a debugger 555 // event or the response to a command. 556 class MessageImpl: public v8::Debug::Message { 557 public: 558 // Create a message object for a debug event. 559 static MessageImpl NewEvent(DebugEvent event, 560 bool running, 561 Handle<JSObject> exec_state, 562 Handle<JSObject> event_data); 563 564 // Create a message object for the response to a debug command. 565 static MessageImpl NewResponse(DebugEvent event, 566 bool running, 567 Handle<JSObject> exec_state, 568 Handle<JSObject> event_data, 569 Handle<String> response_json, 570 v8::Debug::ClientData* client_data); 571 572 // Implementation of interface v8::Debug::Message. 573 virtual bool IsEvent() const; 574 virtual bool IsResponse() const; 575 virtual DebugEvent GetEvent() const; 576 virtual bool WillStartRunning() const; 577 virtual v8::Handle<v8::Object> GetExecutionState() const; 578 virtual v8::Handle<v8::Object> GetEventData() const; 579 virtual v8::Handle<v8::String> GetJSON() const; 580 virtual v8::Handle<v8::Context> GetEventContext() const; 581 virtual v8::Debug::ClientData* GetClientData() const; 582 583 private: 584 MessageImpl(bool is_event, 585 DebugEvent event, 586 bool running, 587 Handle<JSObject> exec_state, 588 Handle<JSObject> event_data, 589 Handle<String> response_json, 590 v8::Debug::ClientData* client_data); 591 592 bool is_event_; // Does this message represent a debug event? 593 DebugEvent event_; // Debug event causing the break. 594 bool running_; // Will the VM start running after this event? 595 Handle<JSObject> exec_state_; // Current execution state. 596 Handle<JSObject> event_data_; // Data associated with the event. 597 Handle<String> response_json_; // Response JSON if message holds a response. 598 v8::Debug::ClientData* client_data_; // Client data passed with the request. 599 }; 600 601 602 // Details of the debug event delivered to the debug event listener. 603 class EventDetailsImpl : public v8::Debug::EventDetails { 604 public: 605 EventDetailsImpl(DebugEvent event, 606 Handle<JSObject> exec_state, 607 Handle<JSObject> event_data, 608 Handle<Object> callback_data, 609 v8::Debug::ClientData* client_data); 610 virtual DebugEvent GetEvent() const; 611 virtual v8::Handle<v8::Object> GetExecutionState() const; 612 virtual v8::Handle<v8::Object> GetEventData() const; 613 virtual v8::Handle<v8::Context> GetEventContext() const; 614 virtual v8::Handle<v8::Value> GetCallbackData() const; 615 virtual v8::Debug::ClientData* GetClientData() const; 616 private: 617 DebugEvent event_; // Debug event causing the break. 618 Handle<JSObject> exec_state_; // Current execution state. 619 Handle<JSObject> event_data_; // Data associated with the event. 620 Handle<Object> callback_data_; // User data passed with the callback 621 // when it was registered. 622 v8::Debug::ClientData* client_data_; // Data passed to DebugBreakForCommand. 623 }; 624 625 626 // Message send by user to v8 debugger or debugger output message. 627 // In addition to command text it may contain a pointer to some user data 628 // which are expected to be passed along with the command reponse to message 629 // handler. 630 class CommandMessage { 631 public: 632 static CommandMessage New(const Vector<uint16_t>& command, 633 v8::Debug::ClientData* data); 634 CommandMessage(); 635 ~CommandMessage(); 636 637 // Deletes user data and disposes of the text. 638 void Dispose(); text()639 Vector<uint16_t> text() const { return text_; } client_data()640 v8::Debug::ClientData* client_data() const { return client_data_; } 641 private: 642 CommandMessage(const Vector<uint16_t>& text, 643 v8::Debug::ClientData* data); 644 645 Vector<uint16_t> text_; 646 v8::Debug::ClientData* client_data_; 647 }; 648 649 // A Queue of CommandMessage objects. A thread-safe version is 650 // LockingCommandMessageQueue, based on this class. 651 class CommandMessageQueue BASE_EMBEDDED { 652 public: 653 explicit CommandMessageQueue(int size); 654 ~CommandMessageQueue(); IsEmpty()655 bool IsEmpty() const { return start_ == end_; } 656 CommandMessage Get(); 657 void Put(const CommandMessage& message); Clear()658 void Clear() { start_ = end_ = 0; } // Queue is empty after Clear(). 659 private: 660 // Doubles the size of the message queue, and copies the messages. 661 void Expand(); 662 663 CommandMessage* messages_; 664 int start_; 665 int end_; 666 int size_; // The size of the queue buffer. Queue can hold size-1 messages. 667 }; 668 669 670 class MessageDispatchHelperThread; 671 672 673 // LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage 674 // messages. The message data is not managed by LockingCommandMessageQueue. 675 // Pointers to the data are passed in and out. Implemented by adding a 676 // Mutex to CommandMessageQueue. Includes logging of all puts and gets. 677 class LockingCommandMessageQueue BASE_EMBEDDED { 678 public: 679 explicit LockingCommandMessageQueue(int size); 680 ~LockingCommandMessageQueue(); 681 bool IsEmpty() const; 682 CommandMessage Get(); 683 void Put(const CommandMessage& message); 684 void Clear(); 685 private: 686 CommandMessageQueue queue_; 687 Mutex* lock_; 688 DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue); 689 }; 690 691 692 class Debugger { 693 public: 694 ~Debugger(); 695 696 void DebugRequest(const uint16_t* json_request, int length); 697 698 Handle<Object> MakeJSObject(Vector<const char> constructor_name, 699 int argc, Object*** argv, 700 bool* caught_exception); 701 Handle<Object> MakeExecutionState(bool* caught_exception); 702 Handle<Object> MakeBreakEvent(Handle<Object> exec_state, 703 Handle<Object> break_points_hit, 704 bool* caught_exception); 705 Handle<Object> MakeExceptionEvent(Handle<Object> exec_state, 706 Handle<Object> exception, 707 bool uncaught, 708 bool* caught_exception); 709 Handle<Object> MakeNewFunctionEvent(Handle<Object> func, 710 bool* caught_exception); 711 Handle<Object> MakeCompileEvent(Handle<Script> script, 712 bool before, 713 bool* caught_exception); 714 Handle<Object> MakeScriptCollectedEvent(int id, 715 bool* caught_exception); 716 void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); 717 void OnException(Handle<Object> exception, bool uncaught); 718 void OnBeforeCompile(Handle<Script> script); 719 720 enum AfterCompileFlags { 721 NO_AFTER_COMPILE_FLAGS, 722 SEND_WHEN_DEBUGGING 723 }; 724 void OnAfterCompile(Handle<Script> script, 725 AfterCompileFlags after_compile_flags); 726 void OnNewFunction(Handle<JSFunction> fun); 727 void OnScriptCollected(int id); 728 void ProcessDebugEvent(v8::DebugEvent event, 729 Handle<JSObject> event_data, 730 bool auto_continue); 731 void NotifyMessageHandler(v8::DebugEvent event, 732 Handle<JSObject> exec_state, 733 Handle<JSObject> event_data, 734 bool auto_continue); 735 void SetEventListener(Handle<Object> callback, Handle<Object> data); 736 void SetMessageHandler(v8::Debug::MessageHandler2 handler); 737 void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, 738 int period); 739 void SetDebugMessageDispatchHandler( 740 v8::Debug::DebugMessageDispatchHandler handler, 741 bool provide_locker); 742 743 // Invoke the message handler function. 744 void InvokeMessageHandler(MessageImpl message); 745 746 // Add a debugger command to the command queue. 747 void ProcessCommand(Vector<const uint16_t> command, 748 v8::Debug::ClientData* client_data = NULL); 749 750 // Check whether there are commands in the command queue. 751 bool HasCommands(); 752 753 // Enqueue a debugger command to the command queue for event listeners. 754 void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL); 755 756 Handle<Object> Call(Handle<JSFunction> fun, 757 Handle<Object> data, 758 bool* pending_exception); 759 760 // Start the debugger agent listening on the provided port. 761 bool StartAgent(const char* name, int port, 762 bool wait_for_connection = false); 763 764 // Stop the debugger agent. 765 void StopAgent(); 766 767 // Blocks until the agent has started listening for connections 768 void WaitForAgent(); 769 770 void CallMessageDispatchHandler(); 771 772 Handle<Context> GetDebugContext(); 773 774 // Unload the debugger if possible. Only called when no debugger is currently 775 // active. 776 void UnloadDebugger(); 777 friend void ForceUnloadDebugger(); // In test-debug.cc 778 EventActive(v8::DebugEvent event)779 inline bool EventActive(v8::DebugEvent event) { 780 ScopedLock with(debugger_access_); 781 782 // Check whether the message handler was been cleared. 783 if (debugger_unload_pending_) { 784 if (isolate_->debug()->debugger_entry() == NULL) { 785 UnloadDebugger(); 786 } 787 } 788 789 if (((event == v8::BeforeCompile) || (event == v8::AfterCompile)) && 790 !FLAG_debug_compile_events) { 791 return false; 792 793 } else if ((event == v8::ScriptCollected) && 794 !FLAG_debug_script_collected_events) { 795 return false; 796 } 797 798 // Currently argument event is not used. 799 return !compiling_natives_ && Debugger::IsDebuggerActive(); 800 } 801 set_compiling_natives(bool compiling_natives)802 void set_compiling_natives(bool compiling_natives) { 803 Debugger::compiling_natives_ = compiling_natives; 804 } compiling_natives()805 bool compiling_natives() const { return compiling_natives_; } set_loading_debugger(bool v)806 void set_loading_debugger(bool v) { is_loading_debugger_ = v; } is_loading_debugger()807 bool is_loading_debugger() const { return is_loading_debugger_; } 808 809 bool IsDebuggerActive(); 810 811 private: 812 explicit Debugger(Isolate* isolate); 813 814 void CallEventCallback(v8::DebugEvent event, 815 Handle<Object> exec_state, 816 Handle<Object> event_data, 817 v8::Debug::ClientData* client_data); 818 void CallCEventCallback(v8::DebugEvent event, 819 Handle<Object> exec_state, 820 Handle<Object> event_data, 821 v8::Debug::ClientData* client_data); 822 void CallJSEventCallback(v8::DebugEvent event, 823 Handle<Object> exec_state, 824 Handle<Object> event_data); 825 void ListenersChanged(); 826 827 Mutex* debugger_access_; // Mutex guarding debugger variables. 828 Handle<Object> event_listener_; // Global handle to listener. 829 Handle<Object> event_listener_data_; 830 bool compiling_natives_; // Are we compiling natives? 831 bool is_loading_debugger_; // Are we loading the debugger? 832 bool never_unload_debugger_; // Can we unload the debugger? 833 v8::Debug::MessageHandler2 message_handler_; 834 bool debugger_unload_pending_; // Was message handler cleared? 835 v8::Debug::HostDispatchHandler host_dispatch_handler_; 836 Mutex* dispatch_handler_access_; // Mutex guarding dispatch handler. 837 v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_; 838 MessageDispatchHelperThread* message_dispatch_helper_thread_; 839 int host_dispatch_micros_; 840 841 DebuggerAgent* agent_; 842 843 static const int kQueueInitialSize = 4; 844 LockingCommandMessageQueue command_queue_; 845 Semaphore* command_received_; // Signaled for each command received. 846 LockingCommandMessageQueue event_command_queue_; 847 848 Isolate* isolate_; 849 850 friend class EnterDebugger; 851 friend class Isolate; 852 853 DISALLOW_COPY_AND_ASSIGN(Debugger); 854 }; 855 856 857 // This class is used for entering the debugger. Create an instance in the stack 858 // to enter the debugger. This will set the current break state, make sure the 859 // debugger is loaded and switch to the debugger context. If the debugger for 860 // some reason could not be entered FailedToEnter will return true. 861 class EnterDebugger BASE_EMBEDDED { 862 public: EnterDebugger()863 EnterDebugger() 864 : isolate_(Isolate::Current()), 865 prev_(isolate_->debug()->debugger_entry()), 866 it_(isolate_), 867 has_js_frames_(!it_.done()), 868 save_(isolate_) { 869 Debug* debug = isolate_->debug(); 870 ASSERT(prev_ != NULL || !debug->is_interrupt_pending(PREEMPT)); 871 ASSERT(prev_ != NULL || !debug->is_interrupt_pending(DEBUGBREAK)); 872 873 // Link recursive debugger entry. 874 debug->set_debugger_entry(this); 875 876 // Store the previous break id and frame id. 877 break_id_ = debug->break_id(); 878 break_frame_id_ = debug->break_frame_id(); 879 880 // Create the new break info. If there is no JavaScript frames there is no 881 // break frame id. 882 if (has_js_frames_) { 883 debug->NewBreak(it_.frame()->id()); 884 } else { 885 debug->NewBreak(StackFrame::NO_ID); 886 } 887 888 // Make sure that debugger is loaded and enter the debugger context. 889 load_failed_ = !debug->Load(); 890 if (!load_failed_) { 891 // NOTE the member variable save which saves the previous context before 892 // this change. 893 isolate_->set_context(*debug->debug_context()); 894 } 895 } 896 ~EnterDebugger()897 ~EnterDebugger() { 898 ASSERT(Isolate::Current() == isolate_); 899 Debug* debug = isolate_->debug(); 900 901 // Restore to the previous break state. 902 debug->SetBreak(break_frame_id_, break_id_); 903 904 // Check for leaving the debugger. 905 if (prev_ == NULL) { 906 // Clear mirror cache when leaving the debugger. Skip this if there is a 907 // pending exception as clearing the mirror cache calls back into 908 // JavaScript. This can happen if the v8::Debug::Call is used in which 909 // case the exception should end up in the calling code. 910 if (!isolate_->has_pending_exception()) { 911 // Try to avoid any pending debug break breaking in the clear mirror 912 // cache JavaScript code. 913 if (isolate_->stack_guard()->IsDebugBreak()) { 914 debug->set_interrupts_pending(DEBUGBREAK); 915 isolate_->stack_guard()->Continue(DEBUGBREAK); 916 } 917 debug->ClearMirrorCache(); 918 } 919 920 // Request preemption and debug break when leaving the last debugger entry 921 // if any of these where recorded while debugging. 922 if (debug->is_interrupt_pending(PREEMPT)) { 923 // This re-scheduling of preemption is to avoid starvation in some 924 // debugging scenarios. 925 debug->clear_interrupt_pending(PREEMPT); 926 isolate_->stack_guard()->Preempt(); 927 } 928 if (debug->is_interrupt_pending(DEBUGBREAK)) { 929 debug->clear_interrupt_pending(DEBUGBREAK); 930 isolate_->stack_guard()->DebugBreak(); 931 } 932 933 // If there are commands in the queue when leaving the debugger request 934 // that these commands are processed. 935 if (isolate_->debugger()->HasCommands()) { 936 isolate_->stack_guard()->DebugCommand(); 937 } 938 939 // If leaving the debugger with the debugger no longer active unload it. 940 if (!isolate_->debugger()->IsDebuggerActive()) { 941 isolate_->debugger()->UnloadDebugger(); 942 } 943 } 944 945 // Leaving this debugger entry. 946 debug->set_debugger_entry(prev_); 947 } 948 949 // Check whether the debugger could be entered. FailedToEnter()950 inline bool FailedToEnter() { return load_failed_; } 951 952 // Check whether there are any JavaScript frames on the stack. HasJavaScriptFrames()953 inline bool HasJavaScriptFrames() { return has_js_frames_; } 954 955 // Get the active context from before entering the debugger. GetContext()956 inline Handle<Context> GetContext() { return save_.context(); } 957 958 private: 959 Isolate* isolate_; 960 EnterDebugger* prev_; // Previous debugger entry if entered recursively. 961 JavaScriptFrameIterator it_; 962 const bool has_js_frames_; // Were there any JavaScript frames? 963 StackFrame::Id break_frame_id_; // Previous break frame id. 964 int break_id_; // Previous break id. 965 bool load_failed_; // Did the debugger fail to load? 966 SaveContext save_; // Saves previous context. 967 }; 968 969 970 // Stack allocated class for disabling break. 971 class DisableBreak BASE_EMBEDDED { 972 public: DisableBreak(bool disable_break)973 explicit DisableBreak(bool disable_break) : isolate_(Isolate::Current()) { 974 prev_disable_break_ = isolate_->debug()->disable_break(); 975 isolate_->debug()->set_disable_break(disable_break); 976 } ~DisableBreak()977 ~DisableBreak() { 978 ASSERT(Isolate::Current() == isolate_); 979 isolate_->debug()->set_disable_break(prev_disable_break_); 980 } 981 982 private: 983 Isolate* isolate_; 984 // The previous state of the disable break used to restore the value when this 985 // object is destructed. 986 bool prev_disable_break_; 987 }; 988 989 990 // Debug_Address encapsulates the Address pointers used in generating debug 991 // code. 992 class Debug_Address { 993 public: Debug_Address(Debug::AddressId id)994 explicit Debug_Address(Debug::AddressId id) : id_(id) { } 995 AfterBreakTarget()996 static Debug_Address AfterBreakTarget() { 997 return Debug_Address(Debug::k_after_break_target_address); 998 } 999 DebugBreakReturn()1000 static Debug_Address DebugBreakReturn() { 1001 return Debug_Address(Debug::k_debug_break_return_address); 1002 } 1003 RestarterFrameFunctionPointer()1004 static Debug_Address RestarterFrameFunctionPointer() { 1005 return Debug_Address(Debug::k_restarter_frame_function_pointer); 1006 } 1007 address(Isolate * isolate)1008 Address address(Isolate* isolate) const { 1009 Debug* debug = isolate->debug(); 1010 switch (id_) { 1011 case Debug::k_after_break_target_address: 1012 return reinterpret_cast<Address>(debug->after_break_target_address()); 1013 case Debug::k_debug_break_return_address: 1014 return reinterpret_cast<Address>(debug->debug_break_return_address()); 1015 case Debug::k_debug_break_slot_address: 1016 return reinterpret_cast<Address>(debug->debug_break_slot_address()); 1017 case Debug::k_restarter_frame_function_pointer: 1018 return reinterpret_cast<Address>( 1019 debug->restarter_frame_function_pointer_address()); 1020 default: 1021 UNREACHABLE(); 1022 return NULL; 1023 } 1024 } 1025 private: 1026 Debug::AddressId id_; 1027 }; 1028 1029 // The optional thread that Debug Agent may use to temporary call V8 to process 1030 // pending debug requests if debuggee is not running V8 at the moment. 1031 // Techincally it does not call V8 itself, rather it asks embedding program 1032 // to do this via v8::Debug::HostDispatchHandler 1033 class MessageDispatchHelperThread: public Thread { 1034 public: 1035 explicit MessageDispatchHelperThread(Isolate* isolate); 1036 ~MessageDispatchHelperThread(); 1037 1038 void Schedule(); 1039 1040 private: 1041 void Run(); 1042 1043 Semaphore* const sem_; 1044 Mutex* const mutex_; 1045 bool already_signalled_; 1046 1047 DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread); 1048 }; 1049 1050 1051 } } // namespace v8::internal 1052 1053 #endif // ENABLE_DEBUGGER_SUPPORT 1054 1055 #endif // V8_DEBUG_H_ 1056