Chromium Code Reviews| 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 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 } | 314 } |
| 313 } | 315 } |
| 314 | 316 |
| 315 | 317 |
| 316 void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) { | 318 void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) { |
| 317 if (HasEventHandler()) { | 319 if (HasEventHandler()) { |
| 318 DebuggerEvent event(isolate_, type); | 320 DebuggerEvent event(isolate_, type); |
| 319 ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID); | 321 ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID); |
| 320 if (type == DebuggerEvent::kIsolateInterrupted) { | 322 if (type == DebuggerEvent::kIsolateInterrupted) { |
| 321 DebuggerStackTrace* trace = CollectStackTrace(); | 323 DebuggerStackTrace* trace = CollectStackTrace(); |
| 322 ASSERT(trace->Length() > 0); | 324 if (trace->Length() > 0) { |
| 323 event.set_top_frame(trace->FrameAt(0)); | 325 event.set_top_frame(trace->FrameAt(0)); |
| 326 } | |
| 324 ASSERT(stack_trace_ == NULL); | 327 ASSERT(stack_trace_ == NULL); |
| 325 stack_trace_ = trace; | 328 stack_trace_ = trace; |
| 326 resume_action_ = kContinue; | 329 resume_action_ = kContinue; |
| 327 Pause(&event); | 330 Pause(&event); |
| 328 HandleSteppingRequest(trace); | 331 HandleSteppingRequest(trace); |
| 329 stack_trace_ = NULL; | 332 stack_trace_ = NULL; |
| 330 } else { | 333 } else { |
| 331 InvokeEventHandler(&event); | 334 InvokeEventHandler(&event); |
| 332 } | 335 } |
| 333 } | 336 } |
| 334 } | 337 } |
| 335 | 338 |
| 336 | 339 |
| 337 void Debugger::SignalIsolateInterrupted() { | 340 RawError* Debugger::SignalIsolateInterrupted() { |
| 338 if (HasEventHandler()) { | 341 if (HasEventHandler()) { |
| 339 Debugger* debugger = Isolate::Current()->debugger(); | 342 SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted); |
| 340 debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted); | |
| 341 } | 343 } |
| 344 Dart_IsolateInterruptCallback callback = isolate_->InterruptCallback(); | |
| 345 if (callback) { | |
| 346 if (!(*callback)()) { | |
| 347 if (FLAG_trace_isolates) { | |
| 348 OS::Print("[!] Embedder api: terminating isolate:\n" | |
| 349 "\tisolate: %s\n", isolate_->name()); | |
| 350 } | |
| 351 const String& msg = String::Handle(String::New("isolate terminated")); | |
| 352 return UnwindError::New(msg); | |
| 353 } | |
| 354 } | |
| 355 | |
| 356 // If any error occurred while in the debug message loop, return it here. | |
|
turnidge
2015/09/15 22:14:10
This could happen, for example, if the isolate rec
| |
| 357 const Error& error = | |
| 358 Error::Handle(isolate_, isolate_->object_store()->sticky_error()); | |
| 359 isolate_->object_store()->clear_sticky_error(); | |
| 360 return error.raw(); | |
| 342 } | 361 } |
| 343 | 362 |
| 344 | 363 |
| 345 // The vm service handles breakpoint notifications in a different way | 364 // The vm service handles breakpoint notifications in a different way |
| 346 // than the regular debugger breakpoint notifications. | 365 // than the regular debugger breakpoint notifications. |
| 347 static void SendServiceBreakpointEvent(ServiceEvent::EventKind kind, | 366 static void SendServiceBreakpointEvent(ServiceEvent::EventKind kind, |
| 348 Breakpoint* bpt) { | 367 Breakpoint* bpt) { |
| 349 if (Service::debug_stream.enabled()) { | 368 if (Service::debug_stream.enabled()) { |
| 350 ServiceEvent service_event(Isolate::Current(), kind); | 369 ServiceEvent service_event(Isolate::Current(), kind); |
| 351 service_event.set_breakpoint(bpt); | 370 service_event.set_breakpoint(bpt); |
| (...skipping 2191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2543 if ((iter.CurrentTokenKind() == Token::kIDENT) && | 2562 if ((iter.CurrentTokenKind() == Token::kIDENT) && |
| 2544 ((iter.CurrentLiteral() == Symbols::Await().raw()) || | 2563 ((iter.CurrentLiteral() == Symbols::Await().raw()) || |
| 2545 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) { | 2564 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) { |
| 2546 event.set_at_async_jump(true); | 2565 event.set_at_async_jump(true); |
| 2547 } | 2566 } |
| 2548 } | 2567 } |
| 2549 Pause(&event); | 2568 Pause(&event); |
| 2550 } | 2569 } |
| 2551 | 2570 |
| 2552 | 2571 |
| 2553 void Debugger::DebuggerStepCallback() { | 2572 RawError* Debugger::DebuggerStepCallback() { |
| 2554 ASSERT(isolate_->single_step()); | 2573 ASSERT(isolate_->single_step()); |
| 2555 // We can't get here unless the debugger event handler enabled | 2574 // We can't get here unless the debugger event handler enabled |
| 2556 // single stepping. | 2575 // single stepping. |
| 2557 ASSERT(HasEventHandler()); | 2576 ASSERT(HasEventHandler()); |
| 2558 // Don't pause recursively. | 2577 // Don't pause recursively. |
| 2559 if (IsPaused()) return; | 2578 if (IsPaused()) { |
| 2579 return Error::null(); | |
| 2580 } | |
| 2560 | 2581 |
| 2561 // Check whether we are in a Dart function that the user is | 2582 // Check whether we are in a Dart function that the user is |
| 2562 // interested in. If we saved the frame pointer of a stack frame | 2583 // interested in. If we saved the frame pointer of a stack frame |
| 2563 // the user is interested in, we ignore the single step if we are | 2584 // the user is interested in, we ignore the single step if we are |
| 2564 // in a callee of that frame. Note that we assume that the stack | 2585 // in a callee of that frame. Note that we assume that the stack |
| 2565 // grows towards lower addresses. | 2586 // grows towards lower addresses. |
| 2566 ActivationFrame* frame = TopDartFrame(); | 2587 ActivationFrame* frame = TopDartFrame(); |
| 2567 ASSERT(frame != NULL); | 2588 ASSERT(frame != NULL); |
| 2568 | 2589 |
| 2569 if (stepping_fp_ != 0) { | 2590 if (stepping_fp_ != 0) { |
| 2570 // There is an "interesting frame" set. Only pause at appropriate | 2591 // There is an "interesting frame" set. Only pause at appropriate |
| 2571 // locations in this frame. | 2592 // locations in this frame. |
| 2572 if (stepping_fp_ > frame->fp()) { | 2593 if (stepping_fp_ > frame->fp()) { |
| 2573 // We are in a callee of the frame we're interested in. | 2594 // We are in a callee of the frame we're interested in. |
| 2574 // Ignore this stepping break. | 2595 // Ignore this stepping break. |
| 2575 return; | 2596 return Error::null(); |
| 2576 } else if (frame->fp() > stepping_fp_) { | 2597 } else if (frame->fp() > stepping_fp_) { |
| 2577 // We returned from the "interesting frame", there can be no more | 2598 // We returned from the "interesting frame", there can be no more |
| 2578 // stepping breaks for it. Pause at the next appropriate location | 2599 // stepping breaks for it. Pause at the next appropriate location |
| 2579 // and let the user set the "interesting" frame again. | 2600 // and let the user set the "interesting" frame again. |
| 2580 stepping_fp_ = 0; | 2601 stepping_fp_ = 0; |
| 2581 } | 2602 } |
| 2582 } | 2603 } |
| 2583 | 2604 |
| 2584 if (!frame->IsDebuggable()) { | 2605 if (!frame->IsDebuggable()) { |
| 2585 return; | 2606 return Error::null(); |
| 2586 } | 2607 } |
| 2587 if (frame->TokenPos() == Scanner::kNoSourcePos) { | 2608 if (frame->TokenPos() == Scanner::kNoSourcePos) { |
| 2588 return; | 2609 return Error::null(); |
| 2589 } | 2610 } |
| 2590 | 2611 |
| 2591 // Don't pause for a single step if there is a breakpoint set | 2612 // Don't pause for a single step if there is a breakpoint set |
| 2592 // at this location. | 2613 // at this location. |
| 2593 if (HasActiveBreakpoint(frame->pc())) { | 2614 if (HasActiveBreakpoint(frame->pc())) { |
| 2594 return; | 2615 return Error::null(); |
| 2595 } | 2616 } |
| 2596 | 2617 |
| 2597 if (FLAG_verbose_debug) { | 2618 if (FLAG_verbose_debug) { |
| 2598 OS::Print(">>> single step break at %s:%" Pd " (func %s token %" Pd ")\n", | 2619 OS::Print(">>> single step break at %s:%" Pd " (func %s token %" Pd ")\n", |
| 2599 String::Handle(frame->SourceUrl()).ToCString(), | 2620 String::Handle(frame->SourceUrl()).ToCString(), |
| 2600 frame->LineNumber(), | 2621 frame->LineNumber(), |
| 2601 String::Handle(frame->QualifiedFunctionName()).ToCString(), | 2622 String::Handle(frame->QualifiedFunctionName()).ToCString(), |
| 2602 frame->TokenPos()); | 2623 frame->TokenPos()); |
| 2603 } | 2624 } |
| 2604 | 2625 |
| 2605 ASSERT(stack_trace_ == NULL); | 2626 ASSERT(stack_trace_ == NULL); |
| 2606 stack_trace_ = CollectStackTrace(); | 2627 stack_trace_ = CollectStackTrace(); |
| 2607 SignalPausedEvent(frame, NULL); | 2628 SignalPausedEvent(frame, NULL); |
| 2608 HandleSteppingRequest(stack_trace_); | 2629 HandleSteppingRequest(stack_trace_); |
| 2609 stack_trace_ = NULL; | 2630 stack_trace_ = NULL; |
| 2631 | |
| 2632 // If any error occurred while in the debug message loop, return it here. | |
| 2633 const Error& error = | |
| 2634 Error::Handle(isolate_, isolate_->object_store()->sticky_error()); | |
| 2635 isolate_->object_store()->clear_sticky_error(); | |
| 2636 return error.raw(); | |
| 2610 } | 2637 } |
| 2611 | 2638 |
| 2612 | 2639 |
| 2613 void Debugger::SignalBpReached() { | 2640 RawError* Debugger::SignalBpReached() { |
| 2614 // We ignore this breakpoint when the VM is executing code invoked | 2641 // We ignore this breakpoint when the VM is executing code invoked |
| 2615 // by the debugger to evaluate variables values, or when we see a nested | 2642 // by the debugger to evaluate variables values, or when we see a nested |
| 2616 // breakpoint or exception event. | 2643 // breakpoint or exception event. |
| 2617 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { | 2644 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { |
| 2618 return; | 2645 return Error::null(); |
| 2619 } | 2646 } |
| 2620 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 2647 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
| 2621 ASSERT(stack_trace->Length() > 0); | 2648 ASSERT(stack_trace->Length() > 0); |
| 2622 ActivationFrame* top_frame = stack_trace->FrameAt(0); | 2649 ActivationFrame* top_frame = stack_trace->FrameAt(0); |
| 2623 ASSERT(top_frame != NULL); | 2650 ASSERT(top_frame != NULL); |
| 2624 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc()); | 2651 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc()); |
| 2625 ASSERT(cbpt != NULL); | 2652 ASSERT(cbpt != NULL); |
| 2626 | 2653 |
| 2627 BreakpointLocation* bpt_location = cbpt->bpt_location_; | 2654 BreakpointLocation* bpt_location = cbpt->bpt_location_; |
| 2628 Breakpoint* bpt_hit = NULL; | 2655 Breakpoint* bpt_hit = NULL; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2662 if (bpt->IsRepeated()) { | 2689 if (bpt->IsRepeated()) { |
| 2663 bpt_hit = bpt; | 2690 bpt_hit = bpt; |
| 2664 break; | 2691 break; |
| 2665 } | 2692 } |
| 2666 bpt = bpt->next(); | 2693 bpt = bpt->next(); |
| 2667 } | 2694 } |
| 2668 } | 2695 } |
| 2669 } | 2696 } |
| 2670 | 2697 |
| 2671 if (bpt_hit == NULL) { | 2698 if (bpt_hit == NULL) { |
| 2672 return; | 2699 return Error::null(); |
| 2673 } | 2700 } |
| 2674 | 2701 |
| 2675 if (FLAG_verbose_debug) { | 2702 if (FLAG_verbose_debug) { |
| 2676 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " | 2703 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " |
| 2677 "(token %" Pd ") (address %#" Px ")\n", | 2704 "(token %" Pd ") (address %#" Px ")\n", |
| 2678 cbpt->IsInternal() ? "internal" : "user", | 2705 cbpt->IsInternal() ? "internal" : "user", |
| 2679 String::Handle(cbpt->SourceUrl()).ToCString(), | 2706 String::Handle(cbpt->SourceUrl()).ToCString(), |
| 2680 cbpt->LineNumber(), | 2707 cbpt->LineNumber(), |
| 2681 cbpt->token_pos(), | 2708 cbpt->token_pos(), |
| 2682 top_frame->pc()); | 2709 top_frame->pc()); |
| 2683 } | 2710 } |
| 2684 | 2711 |
| 2685 ASSERT(stack_trace_ == NULL); | 2712 ASSERT(stack_trace_ == NULL); |
| 2686 stack_trace_ = stack_trace; | 2713 stack_trace_ = stack_trace; |
| 2687 SignalPausedEvent(top_frame, bpt_hit); | 2714 SignalPausedEvent(top_frame, bpt_hit); |
| 2688 HandleSteppingRequest(stack_trace_); | 2715 HandleSteppingRequest(stack_trace_); |
| 2689 stack_trace_ = NULL; | 2716 stack_trace_ = NULL; |
| 2690 if (cbpt->IsInternal()) { | 2717 if (cbpt->IsInternal()) { |
| 2691 RemoveInternalBreakpoints(); | 2718 RemoveInternalBreakpoints(); |
| 2692 } | 2719 } |
| 2720 | |
| 2721 // If any error occurred while in the debug message loop, return it here. | |
| 2722 const Error& error = | |
| 2723 Error::Handle(isolate_, isolate_->object_store()->sticky_error()); | |
| 2724 isolate_->object_store()->clear_sticky_error(); | |
| 2725 return error.raw(); | |
| 2693 } | 2726 } |
| 2694 | 2727 |
| 2695 | 2728 |
| 2696 void Debugger::BreakHere(const String& msg) { | 2729 void Debugger::BreakHere(const String& msg) { |
| 2697 // We ignore this breakpoint when the VM is executing code invoked | 2730 // We ignore this breakpoint when the VM is executing code invoked |
| 2698 // by the debugger to evaluate variables values, or when we see a nested | 2731 // by the debugger to evaluate variables values, or when we see a nested |
| 2699 // breakpoint or exception event. | 2732 // breakpoint or exception event. |
| 2700 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { | 2733 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { |
| 2701 return; | 2734 return; |
| 2702 } | 2735 } |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3172 } | 3205 } |
| 3173 | 3206 |
| 3174 | 3207 |
| 3175 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 3208 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 3176 ASSERT(bpt->next() == NULL); | 3209 ASSERT(bpt->next() == NULL); |
| 3177 bpt->set_next(code_breakpoints_); | 3210 bpt->set_next(code_breakpoints_); |
| 3178 code_breakpoints_ = bpt; | 3211 code_breakpoints_ = bpt; |
| 3179 } | 3212 } |
| 3180 | 3213 |
| 3181 } // namespace dart | 3214 } // namespace dart |
| OLD | NEW |