| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/debugger.h" | 5 #include "vm/debugger.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 | 8 |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 "Show invisible frames in debugger stack traces"); | 35 "Show invisible frames in debugger stack traces"); |
| 36 DEFINE_FLAG(bool, trace_debugger_stacktrace, false, | 36 DEFINE_FLAG(bool, trace_debugger_stacktrace, false, |
| 37 "Trace debugger stacktrace collection"); | 37 "Trace debugger stacktrace collection"); |
| 38 DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages"); | 38 DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages"); |
| 39 DEFINE_FLAG(bool, steal_breakpoints, false, | 39 DEFINE_FLAG(bool, steal_breakpoints, false, |
| 40 "Intercept breakpoints and other pause events before they " | 40 "Intercept breakpoints and other pause events before they " |
| 41 "are sent to the embedder and use a generic VM breakpoint " | 41 "are sent to the embedder and use a generic VM breakpoint " |
| 42 "handler instead. This handler dispatches breakpoints to " | 42 "handler instead. This handler dispatches breakpoints to " |
| 43 "the VM service."); | 43 "the VM service."); |
| 44 | 44 |
| 45 DECLARE_FLAG(bool, trace_isolates); |
| 46 |
| 45 | 47 |
| 46 Debugger::EventHandler* Debugger::event_handler_ = NULL; | 48 Debugger::EventHandler* Debugger::event_handler_ = NULL; |
| 47 | 49 |
| 48 | 50 |
| 49 class RemoteObjectCache : public ZoneAllocated { | 51 class RemoteObjectCache : public ZoneAllocated { |
| 50 public: | 52 public: |
| 51 explicit RemoteObjectCache(intptr_t initial_size); | 53 explicit RemoteObjectCache(intptr_t initial_size); |
| 52 intptr_t AddObject(const Object& obj); | 54 intptr_t AddObject(const Object& obj); |
| 53 RawObject* GetObj(intptr_t obj_id) const; | 55 RawObject* GetObj(intptr_t obj_id) const; |
| 54 bool IsValidId(intptr_t obj_id) const { | 56 bool IsValidId(intptr_t obj_id) const { |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 } | 315 } |
| 314 } | 316 } |
| 315 | 317 |
| 316 | 318 |
| 317 void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) { | 319 void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) { |
| 318 if (HasEventHandler()) { | 320 if (HasEventHandler()) { |
| 319 DebuggerEvent event(isolate_, type); | 321 DebuggerEvent event(isolate_, type); |
| 320 ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID); | 322 ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID); |
| 321 if (type == DebuggerEvent::kIsolateInterrupted) { | 323 if (type == DebuggerEvent::kIsolateInterrupted) { |
| 322 DebuggerStackTrace* trace = CollectStackTrace(); | 324 DebuggerStackTrace* trace = CollectStackTrace(); |
| 323 ASSERT(trace->Length() > 0); | 325 if (trace->Length() > 0) { |
| 324 event.set_top_frame(trace->FrameAt(0)); | 326 event.set_top_frame(trace->FrameAt(0)); |
| 327 } |
| 325 ASSERT(stack_trace_ == NULL); | 328 ASSERT(stack_trace_ == NULL); |
| 326 stack_trace_ = trace; | 329 stack_trace_ = trace; |
| 327 resume_action_ = kContinue; | 330 resume_action_ = kContinue; |
| 328 Pause(&event); | 331 Pause(&event); |
| 329 HandleSteppingRequest(trace); | 332 HandleSteppingRequest(trace); |
| 330 stack_trace_ = NULL; | 333 stack_trace_ = NULL; |
| 331 } else { | 334 } else { |
| 332 InvokeEventHandler(&event); | 335 InvokeEventHandler(&event); |
| 333 } | 336 } |
| 334 } | 337 } |
| 335 } | 338 } |
| 336 | 339 |
| 337 | 340 |
| 338 void Debugger::SignalIsolateInterrupted() { | 341 RawError* Debugger::SignalIsolateInterrupted() { |
| 339 if (HasEventHandler()) { | 342 if (HasEventHandler()) { |
| 340 Debugger* debugger = Isolate::Current()->debugger(); | 343 SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted); |
| 341 debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted); | |
| 342 } | 344 } |
| 345 Dart_IsolateInterruptCallback callback = isolate_->InterruptCallback(); |
| 346 if (callback != NULL) { |
| 347 if (!(*callback)()) { |
| 348 if (FLAG_trace_isolates) { |
| 349 OS::Print("[!] Embedder api: terminating isolate:\n" |
| 350 "\tisolate: %s\n", isolate_->name()); |
| 351 } |
| 352 const String& msg = String::Handle(String::New("isolate terminated")); |
| 353 return UnwindError::New(msg); |
| 354 } |
| 355 } |
| 356 |
| 357 // If any error occurred while in the debug message loop, return it here. |
| 358 const Error& error = |
| 359 Error::Handle(isolate_, isolate_->object_store()->sticky_error()); |
| 360 isolate_->object_store()->clear_sticky_error(); |
| 361 return error.raw(); |
| 343 } | 362 } |
| 344 | 363 |
| 345 | 364 |
| 346 // The vm service handles breakpoint notifications in a different way | 365 // The vm service handles breakpoint notifications in a different way |
| 347 // than the regular debugger breakpoint notifications. | 366 // than the regular debugger breakpoint notifications. |
| 348 static void SendServiceBreakpointEvent(ServiceEvent::EventKind kind, | 367 static void SendServiceBreakpointEvent(ServiceEvent::EventKind kind, |
| 349 Breakpoint* bpt) { | 368 Breakpoint* bpt) { |
| 350 if (Service::debug_stream.enabled()) { | 369 if (Service::debug_stream.enabled()) { |
| 351 ServiceEvent service_event(Isolate::Current(), kind); | 370 ServiceEvent service_event(Isolate::Current(), kind); |
| 352 service_event.set_breakpoint(bpt); | 371 service_event.set_breakpoint(bpt); |
| (...skipping 2193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2546 if ((iter.CurrentTokenKind() == Token::kIDENT) && | 2565 if ((iter.CurrentTokenKind() == Token::kIDENT) && |
| 2547 ((iter.CurrentLiteral() == Symbols::Await().raw()) || | 2566 ((iter.CurrentLiteral() == Symbols::Await().raw()) || |
| 2548 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) { | 2567 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) { |
| 2549 event.set_at_async_jump(true); | 2568 event.set_at_async_jump(true); |
| 2550 } | 2569 } |
| 2551 } | 2570 } |
| 2552 Pause(&event); | 2571 Pause(&event); |
| 2553 } | 2572 } |
| 2554 | 2573 |
| 2555 | 2574 |
| 2556 void Debugger::DebuggerStepCallback() { | 2575 RawError* Debugger::DebuggerStepCallback() { |
| 2557 ASSERT(isolate_->single_step()); | 2576 ASSERT(isolate_->single_step()); |
| 2558 // We can't get here unless the debugger event handler enabled | 2577 // We can't get here unless the debugger event handler enabled |
| 2559 // single stepping. | 2578 // single stepping. |
| 2560 ASSERT(HasEventHandler()); | 2579 ASSERT(HasEventHandler()); |
| 2561 // Don't pause recursively. | 2580 // Don't pause recursively. |
| 2562 if (IsPaused()) return; | 2581 if (IsPaused()) { |
| 2582 return Error::null(); |
| 2583 } |
| 2563 | 2584 |
| 2564 // Check whether we are in a Dart function that the user is | 2585 // Check whether we are in a Dart function that the user is |
| 2565 // interested in. If we saved the frame pointer of a stack frame | 2586 // interested in. If we saved the frame pointer of a stack frame |
| 2566 // the user is interested in, we ignore the single step if we are | 2587 // the user is interested in, we ignore the single step if we are |
| 2567 // in a callee of that frame. Note that we assume that the stack | 2588 // in a callee of that frame. Note that we assume that the stack |
| 2568 // grows towards lower addresses. | 2589 // grows towards lower addresses. |
| 2569 ActivationFrame* frame = TopDartFrame(); | 2590 ActivationFrame* frame = TopDartFrame(); |
| 2570 ASSERT(frame != NULL); | 2591 ASSERT(frame != NULL); |
| 2571 | 2592 |
| 2572 if (stepping_fp_ != 0) { | 2593 if (stepping_fp_ != 0) { |
| 2573 // There is an "interesting frame" set. Only pause at appropriate | 2594 // There is an "interesting frame" set. Only pause at appropriate |
| 2574 // locations in this frame. | 2595 // locations in this frame. |
| 2575 if (stepping_fp_ > frame->fp()) { | 2596 if (stepping_fp_ > frame->fp()) { |
| 2576 // We are in a callee of the frame we're interested in. | 2597 // We are in a callee of the frame we're interested in. |
| 2577 // Ignore this stepping break. | 2598 // Ignore this stepping break. |
| 2578 return; | 2599 return Error::null(); |
| 2579 } else if (frame->fp() > stepping_fp_) { | 2600 } else if (frame->fp() > stepping_fp_) { |
| 2580 // We returned from the "interesting frame", there can be no more | 2601 // We returned from the "interesting frame", there can be no more |
| 2581 // stepping breaks for it. Pause at the next appropriate location | 2602 // stepping breaks for it. Pause at the next appropriate location |
| 2582 // and let the user set the "interesting" frame again. | 2603 // and let the user set the "interesting" frame again. |
| 2583 stepping_fp_ = 0; | 2604 stepping_fp_ = 0; |
| 2584 } | 2605 } |
| 2585 } | 2606 } |
| 2586 | 2607 |
| 2587 if (!frame->IsDebuggable()) { | 2608 if (!frame->IsDebuggable()) { |
| 2588 return; | 2609 return Error::null(); |
| 2589 } | 2610 } |
| 2590 if (frame->TokenPos() == Scanner::kNoSourcePos) { | 2611 if (frame->TokenPos() == Scanner::kNoSourcePos) { |
| 2591 return; | 2612 return Error::null(); |
| 2592 } | 2613 } |
| 2593 | 2614 |
| 2594 // Don't pause for a single step if there is a breakpoint set | 2615 // Don't pause for a single step if there is a breakpoint set |
| 2595 // at this location. | 2616 // at this location. |
| 2596 if (HasActiveBreakpoint(frame->pc())) { | 2617 if (HasActiveBreakpoint(frame->pc())) { |
| 2597 return; | 2618 return Error::null(); |
| 2598 } | 2619 } |
| 2599 | 2620 |
| 2600 if (FLAG_verbose_debug) { | 2621 if (FLAG_verbose_debug) { |
| 2601 OS::Print(">>> single step break at %s:%" Pd " (func %s token %" Pd ")\n", | 2622 OS::Print(">>> single step break at %s:%" Pd " (func %s token %" Pd ")\n", |
| 2602 String::Handle(frame->SourceUrl()).ToCString(), | 2623 String::Handle(frame->SourceUrl()).ToCString(), |
| 2603 frame->LineNumber(), | 2624 frame->LineNumber(), |
| 2604 String::Handle(frame->QualifiedFunctionName()).ToCString(), | 2625 String::Handle(frame->QualifiedFunctionName()).ToCString(), |
| 2605 frame->TokenPos()); | 2626 frame->TokenPos()); |
| 2606 } | 2627 } |
| 2607 | 2628 |
| 2608 ASSERT(stack_trace_ == NULL); | 2629 ASSERT(stack_trace_ == NULL); |
| 2609 stack_trace_ = CollectStackTrace(); | 2630 stack_trace_ = CollectStackTrace(); |
| 2610 SignalPausedEvent(frame, NULL); | 2631 SignalPausedEvent(frame, NULL); |
| 2611 HandleSteppingRequest(stack_trace_); | 2632 HandleSteppingRequest(stack_trace_); |
| 2612 stack_trace_ = NULL; | 2633 stack_trace_ = NULL; |
| 2634 |
| 2635 // If any error occurred while in the debug message loop, return it here. |
| 2636 const Error& error = |
| 2637 Error::Handle(isolate_, isolate_->object_store()->sticky_error()); |
| 2638 isolate_->object_store()->clear_sticky_error(); |
| 2639 return error.raw(); |
| 2613 } | 2640 } |
| 2614 | 2641 |
| 2615 | 2642 |
| 2616 void Debugger::SignalBpReached() { | 2643 RawError* Debugger::SignalBpReached() { |
| 2617 // We ignore this breakpoint when the VM is executing code invoked | 2644 // We ignore this breakpoint when the VM is executing code invoked |
| 2618 // by the debugger to evaluate variables values, or when we see a nested | 2645 // by the debugger to evaluate variables values, or when we see a nested |
| 2619 // breakpoint or exception event. | 2646 // breakpoint or exception event. |
| 2620 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { | 2647 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { |
| 2621 return; | 2648 return Error::null(); |
| 2622 } | 2649 } |
| 2623 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 2650 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
| 2624 ASSERT(stack_trace->Length() > 0); | 2651 ASSERT(stack_trace->Length() > 0); |
| 2625 ActivationFrame* top_frame = stack_trace->FrameAt(0); | 2652 ActivationFrame* top_frame = stack_trace->FrameAt(0); |
| 2626 ASSERT(top_frame != NULL); | 2653 ASSERT(top_frame != NULL); |
| 2627 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc()); | 2654 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc()); |
| 2628 ASSERT(cbpt != NULL); | 2655 ASSERT(cbpt != NULL); |
| 2629 | 2656 |
| 2630 BreakpointLocation* bpt_location = cbpt->bpt_location_; | 2657 BreakpointLocation* bpt_location = cbpt->bpt_location_; |
| 2631 Breakpoint* bpt_hit = NULL; | 2658 Breakpoint* bpt_hit = NULL; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2665 if (bpt->IsRepeated()) { | 2692 if (bpt->IsRepeated()) { |
| 2666 bpt_hit = bpt; | 2693 bpt_hit = bpt; |
| 2667 break; | 2694 break; |
| 2668 } | 2695 } |
| 2669 bpt = bpt->next(); | 2696 bpt = bpt->next(); |
| 2670 } | 2697 } |
| 2671 } | 2698 } |
| 2672 } | 2699 } |
| 2673 | 2700 |
| 2674 if (bpt_hit == NULL) { | 2701 if (bpt_hit == NULL) { |
| 2675 return; | 2702 return Error::null(); |
| 2676 } | 2703 } |
| 2677 | 2704 |
| 2678 if (FLAG_verbose_debug) { | 2705 if (FLAG_verbose_debug) { |
| 2679 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " | 2706 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " |
| 2680 "(token %" Pd ") (address %#" Px ")\n", | 2707 "(token %" Pd ") (address %#" Px ")\n", |
| 2681 cbpt->IsInternal() ? "internal" : "user", | 2708 cbpt->IsInternal() ? "internal" : "user", |
| 2682 String::Handle(cbpt->SourceUrl()).ToCString(), | 2709 String::Handle(cbpt->SourceUrl()).ToCString(), |
| 2683 cbpt->LineNumber(), | 2710 cbpt->LineNumber(), |
| 2684 cbpt->token_pos(), | 2711 cbpt->token_pos(), |
| 2685 top_frame->pc()); | 2712 top_frame->pc()); |
| 2686 } | 2713 } |
| 2687 | 2714 |
| 2688 ASSERT(stack_trace_ == NULL); | 2715 ASSERT(stack_trace_ == NULL); |
| 2689 stack_trace_ = stack_trace; | 2716 stack_trace_ = stack_trace; |
| 2690 SignalPausedEvent(top_frame, bpt_hit); | 2717 SignalPausedEvent(top_frame, bpt_hit); |
| 2691 HandleSteppingRequest(stack_trace_); | 2718 HandleSteppingRequest(stack_trace_); |
| 2692 stack_trace_ = NULL; | 2719 stack_trace_ = NULL; |
| 2693 if (cbpt->IsInternal()) { | 2720 if (cbpt->IsInternal()) { |
| 2694 RemoveInternalBreakpoints(); | 2721 RemoveInternalBreakpoints(); |
| 2695 } | 2722 } |
| 2723 |
| 2724 // If any error occurred while in the debug message loop, return it here. |
| 2725 const Error& error = |
| 2726 Error::Handle(isolate_, isolate_->object_store()->sticky_error()); |
| 2727 isolate_->object_store()->clear_sticky_error(); |
| 2728 return error.raw(); |
| 2696 } | 2729 } |
| 2697 | 2730 |
| 2698 | 2731 |
| 2699 void Debugger::BreakHere(const String& msg) { | 2732 void Debugger::BreakHere(const String& msg) { |
| 2700 // We ignore this breakpoint when the VM is executing code invoked | 2733 // We ignore this breakpoint when the VM is executing code invoked |
| 2701 // by the debugger to evaluate variables values, or when we see a nested | 2734 // by the debugger to evaluate variables values, or when we see a nested |
| 2702 // breakpoint or exception event. | 2735 // breakpoint or exception event. |
| 2703 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { | 2736 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { |
| 2704 return; | 2737 return; |
| 2705 } | 2738 } |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3175 } | 3208 } |
| 3176 | 3209 |
| 3177 | 3210 |
| 3178 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 3211 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 3179 ASSERT(bpt->next() == NULL); | 3212 ASSERT(bpt->next() == NULL); |
| 3180 bpt->set_next(code_breakpoints_); | 3213 bpt->set_next(code_breakpoints_); |
| 3181 code_breakpoints_ = bpt; | 3214 code_breakpoints_ = bpt; |
| 3182 } | 3215 } |
| 3183 | 3216 |
| 3184 } // namespace dart | 3217 } // namespace dart |
| OLD | NEW |