Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Namespaces | Macros | Enumerations | Functions
debugger.h File Reference
#include <memory>
#include "include/dart_tools_api.h"
#include "vm/compiler/api/deopt_id.h"
#include "vm/kernel_isolate.h"
#include "vm/object.h"
#include "vm/port.h"
#include "vm/scopes.h"
#include "vm/service_event.h"
#include "vm/simulator.h"
#include "vm/stack_frame.h"
#include "vm/stack_trace.h"

Go to the source code of this file.

Classes

class  dart::Breakpoint
 
class  dart::BreakpointLocation
 
class  dart::CodeBreakpoint
 
class  dart::ActivationFrame
 
class  dart::DebuggerStackTrace
 
class  dart::DebuggerKeyValueTrait
 
struct  dart::DebuggerKeyValueTrait::Pair
 
class  dart::DebuggerSet
 
class  dart::BoolCallable
 
class  dart::LambdaBoolCallable< T >
 
class  dart::GroupDebugger
 
class  dart::Debugger
 
class  dart::DisableBreakpointsScope
 

Namespaces

namespace  dart
 

Macros

#define TD_Print(format, ...)    if (FLAG_verbose_debug) Log::Current()->Print(format, ##__VA_ARGS__)
 

Enumerations

enum  dart::Dart_ExceptionPauseInfo { dart::kNoPauseOnExceptions = 1 , dart::kPauseOnUnhandledExceptions , dart::kPauseOnAllExceptions , dart::kInvalidExceptionPauseInfo }
 

Functions

 DECLARE_FLAG (bool, verbose_debug)
 

Macro Definition Documentation

◆ TD_Print

#define TD_Print (   format,
  ... 
)     if (FLAG_verbose_debug) Log::Current()->Print(format, ##__VA_ARGS__)

Definition at line 31 of file debugger.h.

35 {
36
37class CodeBreakpoint;
38class Isolate;
39class JSONArray;
40class JSONStream;
41class ObjectPointerVisitor;
42class BreakpointLocation;
43class StackFrame;
44
45// A user-defined breakpoint, which can be set for a particular closure
46// (if |closure| is not |null|) and can fire one (|is_single_shot| is |true|)
47// or many times.
48class Breakpoint {
49 public:
50 Breakpoint(intptr_t id,
51 BreakpointLocation* bpt_location,
52 bool is_single_shot,
53 const Closure& closure)
54 : id_(id),
55 next_(nullptr),
56 closure_(closure.ptr()),
57 bpt_location_(bpt_location),
58 is_single_shot_(is_single_shot) {}
59
60 intptr_t id() const { return id_; }
61 Breakpoint* next() const { return next_; }
62 void set_next(Breakpoint* n) { next_ = n; }
63
64 BreakpointLocation* bpt_location() const { return bpt_location_; }
65 void set_bpt_location(BreakpointLocation* new_bpt_location);
66
67 bool is_single_shot() const { return is_single_shot_; }
68 ClosurePtr closure() const { return closure_; }
69
70 void Enable() {
71 ASSERT(!enabled_);
72 enabled_ = true;
73 }
74
75 void Disable() {
76 ASSERT(enabled_);
77 enabled_ = false;
78 }
79
80 bool is_enabled() const { return enabled_; }
81
82 void PrintJSON(JSONStream* stream);
83
84 private:
85 void VisitObjectPointers(ObjectPointerVisitor* visitor);
86
87 intptr_t id_;
88 Breakpoint* next_;
89 ClosurePtr closure_;
90 BreakpointLocation* bpt_location_;
91 bool is_single_shot_;
92 bool enabled_ = false;
93
94 friend class BreakpointLocation;
95 DISALLOW_COPY_AND_ASSIGN(Breakpoint);
96};
97
98// BreakpointLocation represents a collection of breakpoint conditions at the
99// same token position in Dart source. There may be more than one CodeBreakpoint
100// object per BreakpointLocation.
101// An unresolved breakpoint is one where the underlying code has not
102// been compiled yet. Since the code has not been compiled, we don't know
103// the definitive source location yet. The requested source location may
104// change when the underlying code gets compiled.
105// A latent breakpoint represents a breakpoint location in Dart source
106// that is not loaded in the VM when the breakpoint is requested.
107// When a script with matching url is loaded, a latent breakpoint
108// becomes an unresolved breakpoint.
109class BreakpointLocation {
110 public:
111 // Create a new unresolved breakpoint.
112 BreakpointLocation(Debugger* debugger,
113 const GrowableHandlePtrArray<const Script>& scripts,
114 TokenPosition token_pos,
115 TokenPosition end_token_pos,
116 intptr_t requested_line_number,
117 intptr_t requested_column_number);
118 // Create a new latent breakpoint.
119 BreakpointLocation(Debugger* debugger,
120 const String& url,
121 intptr_t requested_line_number,
122 intptr_t requested_column_number);
123
124 ~BreakpointLocation();
125
126 TokenPosition token_pos() const { return token_pos_.load(); }
127 intptr_t line_number();
128 TokenPosition end_token_pos() const { return end_token_pos_.load(); }
129
130 ScriptPtr script() const {
131 if (scripts_.length() == 0) {
132 return Script::null();
133 }
134 return scripts_.At(0);
135 }
136 StringPtr url() const { return url_; }
137
138 intptr_t requested_line_number() const { return requested_line_number_; }
139 intptr_t requested_column_number() const { return requested_column_number_; }
140
141 void GetCodeLocation(Script* script, TokenPosition* token_pos) const;
142
143 Breakpoint* AddRepeated(Debugger* dbg);
144 Breakpoint* AddSingleShot(Debugger* dbg);
145 Breakpoint* AddBreakpoint(Debugger* dbg,
146 const Closure& closure,
147 bool single_shot);
148
149 bool AnyEnabled() const;
150 bool IsResolved() const { return code_token_pos_.IsReal(); }
151 bool IsLatent() const { return !token_pos().IsReal(); }
152
153 bool EnsureIsResolved(const Function& target_function,
154 TokenPosition exact_token_pos);
155
156 Debugger* debugger() { return debugger_; }
157
158 private:
159 void VisitObjectPointers(ObjectPointerVisitor* visitor);
160
161 void SetResolved(const Function& func, TokenPosition token_pos);
162
163 BreakpointLocation* next() const { return this->next_; }
164 void set_next(BreakpointLocation* value) { next_ = value; }
165
166 void AddBreakpoint(Breakpoint* bpt, Debugger* dbg);
167
168 Breakpoint* breakpoints() const { return this->conditions_; }
169 void set_breakpoints(Breakpoint* head) { this->conditions_ = head; }
170
171 // Finds the breakpoint we hit at |location|.
172 Breakpoint* FindHitBreakpoint(ActivationFrame* top_frame);
173
174 SafepointRwLock* line_number_lock() { return line_number_lock_.get(); }
175
176 Debugger* debugger_;
177 MallocGrowableArray<ScriptPtr> scripts_;
178 StringPtr url_;
179 std::unique_ptr<SafepointRwLock> line_number_lock_;
180 intptr_t line_number_; // lazily computed for token_pos_
181 std::atomic<TokenPosition> token_pos_;
182 std::atomic<TokenPosition> end_token_pos_;
183 BreakpointLocation* next_;
184 Breakpoint* conditions_;
185 intptr_t requested_line_number_;
186 intptr_t requested_column_number_;
187
188 // Valid for resolved breakpoints:
189 TokenPosition code_token_pos_;
190
191 friend class Debugger;
192 friend class GroupDebugger;
193 DISALLOW_COPY_AND_ASSIGN(BreakpointLocation);
194};
195
196// CodeBreakpoint represents a location in compiled code.
197// There may be more than one CodeBreakpoint for one BreakpointLocation,
198// e.g. when a function gets compiled as a regular function and as a closure.
199// There may be more than one BreakpointLocation associated with CodeBreakpoint,
200// one for every isolate in a group that sets a breakpoint at particular
201// code location represented by the CodeBreakpoint.
202// Each BreakpointLocation might be enabled/disabled based on whether it has
203// any actual breakpoints associated with it.
204// The CodeBreakpoint is enabled if it has any such BreakpointLocations
205// associated with it.
206// The class is not thread-safe - users of this class need to ensure the access
207// is synchronized, guarded by mutexes or run inside of a safepoint scope.
208class CodeBreakpoint {
209 public:
210 // Unless CodeBreakpoint is unlinked and is no longer used there should be at
211 // least one BreakpointLocation associated with CodeBreakpoint. If there are
212 // more BreakpointLocation added assumption is is that all of them point to
213 // the same source so have the same token pos.
214 CodeBreakpoint(const Code& code,
215 BreakpointLocation* loc,
216 uword pc,
217 UntaggedPcDescriptors::Kind kind);
218 ~CodeBreakpoint();
219
220 // Used by GroupDebugger to find CodeBreakpoint associated with
221 // particular function.
222 FunctionPtr function() const { return Code::Handle(code_).function(); }
223
224 uword pc() const { return pc_; }
225 bool HasBreakpointLocation(BreakpointLocation* breakpoint_location);
226 bool FindAndDeleteBreakpointLocation(BreakpointLocation* breakpoint_location);
227 bool HasNoBreakpointLocations() {
228 return breakpoint_locations_.length() == 0;
229 }
230
231 void Enable();
232 void Disable();
233 bool IsEnabled() const { return enabled_count_ > 0; }
234
235 CodePtr OrigStubAddress() const;
236
237 const char* ToCString() const;
238
239 private:
240 void VisitObjectPointers(ObjectPointerVisitor* visitor);
241
242 // Finds right BreakpointLocation for a given Isolate's debugger.
243 BreakpointLocation* FindBreakpointForDebugger(Debugger* debugger);
244 // Adds new BreakpointLocation for another isolate that wants to
245 // break at the same function/code location that this CodeBreakpoint
246 // represents.
247 void AddBreakpointLocation(BreakpointLocation* breakpoint_location) {
248 ASSERT(breakpoint_locations_.length() == 0 ||
249 (breakpoint_location->token_pos() ==
250 breakpoint_locations_.At(0)->token_pos() &&
251 breakpoint_location->url() == breakpoint_locations_.At(0)->url()));
252 breakpoint_locations_.Add(breakpoint_location);
253 }
254
255 void set_next(CodeBreakpoint* value) { next_ = value; }
256 CodeBreakpoint* next() const { return this->next_; }
257
258 void PatchCode();
259 void RestoreCode();
260
261 CodePtr code_;
262 uword pc_;
263 int enabled_count_; // incremented for every enabled breakpoint location
264
265 // Breakpoint locations from different debuggers/isolates that
266 // point to this code breakpoint.
267 MallocGrowableArray<BreakpointLocation*> breakpoint_locations_;
268 CodeBreakpoint* next_;
269
270 UntaggedPcDescriptors::Kind breakpoint_kind_;
271 CodePtr saved_value_;
272
273 friend class Debugger;
274 friend class GroupDebugger;
275 DISALLOW_COPY_AND_ASSIGN(CodeBreakpoint);
276};
277
278// ActivationFrame represents one dart function activation frame
279// on the call stack.
280class ActivationFrame : public ZoneAllocated {
281 public:
282 enum Kind {
283 kRegular,
284 kAsyncSuspensionMarker,
285 kAsyncAwaiter,
286 };
287
288 ActivationFrame(uword pc,
289 uword fp,
290 uword sp,
291 const Code& code,
292 const Array& deopt_frame,
293 intptr_t deopt_frame_offset);
294
295 // Create a |kAsyncAwaiter| frame representing asynchronous awaiter
296 // waiting for the completion of a |Future|.
297 //
298 // |closure| is the listener which will be invoked when awaited
299 // computation completes.
300 ActivationFrame(uword pc, const Code& code, const Closure& closure);
301
302 explicit ActivationFrame(Kind kind);
303
304 Kind kind() const { return kind_; }
305
306 uword pc() const { return pc_; }
307 uword fp() const { return fp_; }
308 uword sp() const { return sp_; }
309
310 uword GetCallerSp() const { return fp() + (kCallerSpSlotFromFp * kWordSize); }
311
312 // For |kAsyncAwaiter| frames this is the listener which will be invoked
313 // when the frame below (callee) completes.
314 const Closure& closure() const { return closure_; }
315
316 const Function& function() const { return function_; }
317 const Code& code() const {
318 ASSERT(!code_.IsNull());
319 return code_;
320 }
321
322 enum Relation {
323 kCallee,
324 kSelf,
325 kCaller,
326 };
327
328 Relation CompareTo(uword other_fp) const;
329
330 StringPtr QualifiedFunctionName();
331 StringPtr SourceUrl();
332 ScriptPtr SourceScript();
333 LibraryPtr Library();
334 TokenPosition TokenPos();
335 intptr_t LineNumber();
336 intptr_t ColumnNumber();
337
338 // Returns true if this frame is for a function that is visible
339 // to the user and can be debugged.
340 bool IsDebuggable() const;
341
342 // Returns true if it is possible to rewind the debugger to this frame.
343 bool IsRewindable() const;
344
345 // The context level of a frame is the context level at the
346 // PC/token index of the frame. It determines the depth of the context
347 // chain that belongs to the function of this activation frame.
348 intptr_t ContextLevel();
349
350 const char* ToCString();
351
352 intptr_t NumLocalVariables();
353
354 void VariableAt(intptr_t i,
355 String* name,
356 TokenPosition* declaration_token_pos,
357 TokenPosition* visible_start_token_pos,
358 TokenPosition* visible_end_token_pos,
359 Object* value);
360
361 ArrayPtr GetLocalVariables();
362 ObjectPtr GetParameter(intptr_t index);
363 ClosurePtr GetClosure();
364 ObjectPtr GetReceiver();
365
366 const Context& GetSavedCurrentContext();
367 ObjectPtr GetSuspendStateVar();
368 ObjectPtr GetSuspendableFunctionData();
369
370 TypeArgumentsPtr BuildParameters(
371 const GrowableObjectArray& param_names,
372 const GrowableObjectArray& param_values,
373 const GrowableObjectArray& type_params_names,
374 const GrowableObjectArray& type_params_bounds,
375 const GrowableObjectArray& type_params_defaults);
376
377 ObjectPtr EvaluateCompiledExpression(const ExternalTypedData& kernel_data,
378 const Array& arguments,
379 const Array& type_definitions,
380 const TypeArguments& type_arguments);
381
382 void PrintToJSONObject(JSONObject* jsobj);
383
384 bool HandlesException(const Instance& exc_obj);
385
386 private:
387 void PrintToJSONObjectRegular(JSONObject* jsobj);
388 void PrintToJSONObjectAsyncAwaiter(JSONObject* jsobj);
389 void PrintToJSONObjectAsyncSuspensionMarker(JSONObject* jsobj);
390 void PrintContextMismatchError(intptr_t ctx_slot,
391 intptr_t frame_ctx_level,
392 intptr_t var_ctx_level);
393 void PrintDescriptorsError(const char* message);
394
395 intptr_t TryIndex();
396 intptr_t DeoptId();
397 void GetPcDescriptors();
398 void GetVarDescriptors();
399 void GetDescIndices();
400
401 static const char* KindToCString(Kind kind) {
402 switch (kind) {
403 case kRegular:
404 return "Regular";
405 case kAsyncAwaiter:
406 // Keeping the legacy name in the protocol itself.
407 return "AsyncCausal";
408 case kAsyncSuspensionMarker:
409 return "AsyncSuspensionMarker";
410 default:
411 UNREACHABLE();
412 return "";
413 }
414 }
415
416 ObjectPtr GetStackVar(VariableIndex var_index);
417 ObjectPtr GetRelativeContextVar(intptr_t ctxt_level,
418 intptr_t slot_index,
419 intptr_t frame_ctx_level);
420 ObjectPtr GetContextVar(intptr_t ctxt_level, intptr_t slot_index);
421
422 uword pc_ = 0;
423 uword fp_ = 0;
424 uword sp_ = 0;
425
426 // The anchor of the context chain for this function.
427 Context& ctx_ = Context::ZoneHandle();
428 const Code& code_;
429 const Function& function_;
430 const Closure& closure_;
431
432 bool token_pos_initialized_ = false;
433 TokenPosition token_pos_ = TokenPosition::kNoSource;
434 intptr_t try_index_ = -1;
435 intptr_t deopt_id_ = dart::DeoptId::kNone;
436
437 intptr_t line_number_ = -1;
438 intptr_t column_number_ = -1;
439 intptr_t context_level_ = -1;
440
441 // Some frames are deoptimized into a side array in order to inspect them.
442 const Array& deopt_frame_;
443 const intptr_t deopt_frame_offset_;
444
445 Kind kind_;
446
447 bool vars_initialized_ = false;
448 LocalVarDescriptors& var_descriptors_ = LocalVarDescriptors::ZoneHandle();
449 ZoneGrowableArray<intptr_t> desc_indices_;
450 PcDescriptors& pc_desc_ = PcDescriptors::ZoneHandle();
451
452 friend class Debugger;
453 friend class DebuggerStackTrace;
454 DISALLOW_COPY_AND_ASSIGN(ActivationFrame);
455};
456
457// Array of function activations on the call stack.
458class DebuggerStackTrace : public ZoneAllocated {
459 public:
460 explicit DebuggerStackTrace(int capacity)
461 : thread_(Thread::Current()), zone_(thread_->zone()), trace_(capacity) {}
462
463 intptr_t Length() const { return trace_.length(); }
464
465 ActivationFrame* FrameAt(int i) const { return trace_[i]; }
466
467 ActivationFrame* GetHandlerFrame(const Instance& exc_obj) const;
468
469 static DebuggerStackTrace* Collect();
470 static DebuggerStackTrace* CollectAsyncAwaiters();
471
472 // Returns a debugger stack trace corresponding to a dart.core.StackTrace.
473 // Frames corresponding to invisible functions are omitted. It is not valid
474 // to query local variables in the returned stack.
475 static DebuggerStackTrace* From(const class StackTrace& ex_trace);
476
477 bool has_async_catch_error() const { return has_async_catch_error_; }
478 void set_has_async_catch_error(bool has_async_catch_error) {
479 has_async_catch_error_ = has_async_catch_error;
480 }
481
482 private:
483 void AddActivation(ActivationFrame* frame);
484 void AddAsyncSuspension();
485 void AddAsyncAwaiterFrame(uword pc, const Code& code, const Closure& closure);
486
487 void AppendCodeFrames(StackFrame* frame, const Code& code);
488
489 Thread* thread_;
490 Zone* zone_;
491 Code& inlined_code_ = Code::Handle();
492 Array& deopt_frame_ = Array::Handle();
493 ZoneGrowableArray<ActivationFrame*> trace_;
494 bool has_async_catch_error_ = false;
495
496 friend class Debugger;
497
498 DISALLOW_COPY_AND_ASSIGN(DebuggerStackTrace);
499};
500
501// On which exceptions to pause.
502typedef enum {
508
509class DebuggerKeyValueTrait : public AllStatic {
510 public:
511 typedef const Debugger* Key;
512 typedef bool Value;
513
514 struct Pair {
515 Key key;
516 Value value;
517 Pair() : key(nullptr), value(false) {}
518 Pair(const Key key, const Value& value) : key(key), value(value) {}
519 Pair(const Pair& other) : key(other.key), value(other.value) {}
520 Pair& operator=(const Pair&) = default;
521 };
522
523 static Key KeyOf(Pair kv) { return kv.key; }
524 static Value ValueOf(Pair kv) { return kv.value; }
525 static uword Hash(Key key) {
526 return Utils::WordHash(reinterpret_cast<intptr_t>(key));
527 }
528 static bool IsKeyEqual(Pair kv, Key key) { return kv.key == key; }
529};
530
531class DebuggerSet : public MallocDirectChainedHashMap<DebuggerKeyValueTrait> {
532 public:
533 typedef DebuggerKeyValueTrait::Key Key;
534 typedef DebuggerKeyValueTrait::Value Value;
535 typedef DebuggerKeyValueTrait::Pair Pair;
536
537 virtual ~DebuggerSet() { Clear(); }
538
539 void Insert(const Key& key) {
540 Pair pair(key, /*value=*/true);
541 MallocDirectChainedHashMap<DebuggerKeyValueTrait>::Insert(pair);
542 }
543
544 void Remove(const Key& key) {
545 MallocDirectChainedHashMap<DebuggerKeyValueTrait>::Remove(key);
546 }
547};
548
549class BoolCallable : public ValueObject {
550 public:
551 BoolCallable() {}
552 virtual ~BoolCallable() {}
553
554 virtual bool Call() = 0;
555
556 private:
557 DISALLOW_COPY_AND_ASSIGN(BoolCallable);
558};
559
560template <typename T>
561class LambdaBoolCallable : public BoolCallable {
562 public:
563 explicit LambdaBoolCallable(T& lambda) : lambda_(lambda) {}
564 bool Call() { return lambda_(); }
565
566 private:
567 T& lambda_;
568 DISALLOW_COPY_AND_ASSIGN(LambdaBoolCallable);
569};
570
571class GroupDebugger {
572 public:
573 explicit GroupDebugger(IsolateGroup* isolate_group);
574 ~GroupDebugger();
575
576 void MakeCodeBreakpointAtUnsafe(const Function& func,
577 BreakpointLocation* bpt);
578 void MakeCodeBreakpointAt(const Function& func, BreakpointLocation* bpt);
579
580 // Returns [nullptr] if no breakpoint exists for the given address.
581 CodeBreakpoint* GetCodeBreakpoint(uword breakpoint_address);
582 BreakpointLocation* GetBreakpointLocationFor(Debugger* debugger,
583 uword breakpoint_address,
584 CodeBreakpoint** pcbpt);
585 CodePtr GetPatchedStubAddress(uword breakpoint_address);
586
587 void RegisterBreakpointLocation(BreakpointLocation* location);
588 void UnregisterBreakpointLocation(BreakpointLocation* location);
589
590 void RemoveBreakpointLocation(BreakpointLocation* bpt_location);
591 void UnlinkCodeBreakpoints(BreakpointLocation* bpt_location);
592
593 // Returns true if the call at address pc is patched to point to
594 // a debugger stub.
595 bool HasActiveBreakpoint(uword pc);
596 bool HasCodeBreakpointInFunctionUnsafe(const Function& func);
597 bool HasCodeBreakpointInFunction(const Function& func);
598 bool HasCodeBreakpointInCode(const Code& code);
599
600 bool HasBreakpointInFunction(const Function& func);
601 bool HasBreakpointInCode(const Code& code);
602
603 void SyncBreakpointLocation(BreakpointLocation* loc);
604
605 void Pause();
606
607 bool EnsureLocationIsInFunction(Zone* zone,
608 const Function& function,
609 BreakpointLocation* location);
610 void NotifyCompilation(const Function& func);
611
612 void VisitObjectPointers(ObjectPointerVisitor* visitor);
613
614 SafepointRwLock* code_breakpoints_lock() {
615 return code_breakpoints_lock_.get();
616 }
617
618 SafepointRwLock* breakpoint_locations_lock() {
619 return breakpoint_locations_lock_.get();
620 }
621
622 RwLock* single_stepping_set_lock() { return single_stepping_set_lock_.get(); }
623
624 void RegisterSingleSteppingDebugger(Thread* thread, const Debugger* debugger);
625 void UnregisterSingleSteppingDebugger(Thread* thread,
626 const Debugger* debugger);
627
628 // Returns [true] if there is at least one breakpoint set in function or code.
629 // Checks for both user-defined and internal temporary breakpoints.
630 bool HasBreakpointUnsafe(Thread* thread, const Function& function);
631 bool HasBreakpoint(Thread* thread, const Function& function);
632 bool IsDebugging(Thread* thread, const Function& function);
633
634 IsolateGroup* isolate_group() { return isolate_group_; }
635
636 private:
637 IsolateGroup* isolate_group_;
638
639 std::unique_ptr<SafepointRwLock> code_breakpoints_lock_;
640 CodeBreakpoint* code_breakpoints_;
641
642 // Secondary list of all breakpoint_locations_(primary is in Debugger class).
643 // This list is kept in sync with all the lists in Isolate Debuggers and is
644 // used to quickly scan BreakpointLocations when new Function is compiled.
645 std::unique_ptr<SafepointRwLock> breakpoint_locations_lock_;
646 MallocGrowableArray<BreakpointLocation*> breakpoint_locations_;
647
648 std::unique_ptr<RwLock> single_stepping_set_lock_;
649 DebuggerSet single_stepping_set_;
650
651 void RemoveUnlinkedCodeBreakpoints();
652 void RegisterCodeBreakpoint(CodeBreakpoint* bpt);
653
654 bool needs_breakpoint_cleanup_;
655};
656
657class Debugger {
658 public:
659 enum ResumeAction {
660 kContinue,
661 kStepInto,
662 kStepOver,
663 kStepOut,
664 kStepRewind,
665 kStepOverAsyncSuspension,
666 };
667
668 explicit Debugger(Isolate* isolate);
669 ~Debugger();
670
671 Isolate* isolate() const { return isolate_; }
672
673 void NotifyIsolateCreated();
674 void Shutdown();
675
676 void NotifyDoneLoading();
677
678 // Set breakpoint at closest location to function entry.
679 Breakpoint* SetBreakpointAtEntry(const Function& target_function,
680 bool single_shot);
681 Breakpoint* SetBreakpointAtActivation(const Instance& closure,
682 bool single_shot);
683 Breakpoint* BreakpointAtActivation(const Instance& closure);
684
685 // TODO(turnidge): script_url may no longer be specific enough.
686 Breakpoint* SetBreakpointAtLine(const String& script_url,
687 intptr_t line_number);
688 Breakpoint* SetBreakpointAtLineCol(const String& script_url,
689 intptr_t line_number,
690 intptr_t column_number);
691
692 BreakpointLocation* BreakpointLocationAtLineCol(const String& script_url,
693 intptr_t line_number,
694 intptr_t column_number);
695
696 // Returns true if the breakpoint's state changed.
697 bool SetBreakpointState(Breakpoint* bpt, bool enable);
698
699 void RemoveBreakpoint(intptr_t bp_id);
700 Breakpoint* GetBreakpointById(intptr_t id);
701
702 void AsyncStepInto(const Closure& awaiter);
703
704 void Continue();
705
706 bool SetResumeAction(ResumeAction action,
707 intptr_t frame_index = 1,
708 const char** error = nullptr);
709
710 bool IsStepping() const { return resume_action_ != kContinue; }
711
712 bool IsSingleStepping() const { return resume_action_ == kStepInto; }
713
714 bool IsPaused() const { return pause_event_ != nullptr; }
715
716 bool ignore_breakpoints() const { return ignore_breakpoints_; }
717 void set_ignore_breakpoints(bool ignore_breakpoints) {
718 ignore_breakpoints_ = ignore_breakpoints;
719 }
720
721 // Put the isolate into single stepping mode when Dart code next runs.
722 //
723 // This is used by the vm service to allow the user to step while
724 // paused at isolate start.
725 void EnterSingleStepMode();
726
727 // Indicates why the debugger is currently paused. If the debugger
728 // is not paused, this returns nullptr. Note that the debugger can be
729 // paused for breakpoints, isolate interruption, and (sometimes)
730 // exceptions.
731 const ServiceEvent* PauseEvent() const { return pause_event_; }
732
733 void SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info);
734 Dart_ExceptionPauseInfo GetExceptionPauseInfo() const;
735
736 void VisitObjectPointers(ObjectPointerVisitor* visitor);
737
738 // Returns a stack trace with frames corresponding to invisible functions
739 // omitted. CurrentStackTrace always returns a new trace on the current stack.
740 // The trace returned by StackTrace may have been cached; it is suitable for
741 // use when stepping, but otherwise may be out of sync with the current stack.
742 DebuggerStackTrace* StackTrace();
743
744 DebuggerStackTrace* AsyncAwaiterStackTrace();
745
746 // Pause execution for a breakpoint. Called from generated code.
747 ErrorPtr PauseBreakpoint();
748
749 // Pause execution due to stepping. Called from generated code.
750 ErrorPtr PauseStepping();
751
752 // Pause execution due to isolate interrupt.
753 ErrorPtr PauseInterrupted();
754
755 // Pause after a reload request.
756 ErrorPtr PausePostRequest();
757
758 // Pause execution due to an uncaught exception.
759 void PauseException(const Instance& exc);
760
761 // Pause execution due to a call to the debugger() function from
762 // Dart.
763 void PauseDeveloper(const String& msg);
764
765 void PrintBreakpointsToJSONArray(JSONArray* jsarr) const;
766 void PrintSettingsToJSONObject(JSONObject* jsobj) const;
767
768 static bool IsDebuggable(const Function& func);
769
770 intptr_t limitBreakpointId() { return next_id_; }
771
772 // Callback to the debugger to continue frame rewind, post-deoptimization.
773 void RewindPostDeopt();
774
775 // Sets breakpoint at resumption of a suspendable function
776 // with given function data (such as _Future or _AsyncStarStreamController).
777 void SetBreakpointAtResumption(const Object& function_data);
778
779 // Check breakpoints at frame resumption. Called from generated code.
780 void ResumptionBreakpoint();
781
782 private:
783 ErrorPtr PauseRequest(ServiceEvent::EventKind kind);
784
785 // Will return false if we are not at an await.
786 bool SetupStepOverAsyncSuspension(const char** error);
787
788 bool NeedsIsolateEvents();
789 bool NeedsDebugEvents();
790
791 void SendBreakpointEvent(ServiceEvent::EventKind kind, Breakpoint* bpt);
792
793 void FindCompiledFunctions(
794 const GrowableHandlePtrArray<const Script>& scripts,
795 TokenPosition start_pos,
796 TokenPosition end_pos,
797 GrowableObjectArray* code_function_list);
798 bool FindBestFit(const Script& script,
799 TokenPosition token_pos,
800 TokenPosition last_token_pos,
801 Function* best_fit);
802 void DeoptimizeWorld();
803 void RunWithStoppedDeoptimizedWorld(std::function<void()> fun);
804 void NotifySingleStepping(bool value);
805 BreakpointLocation* SetCodeBreakpoints(
806 const GrowableHandlePtrArray<const Script>& scripts,
807 TokenPosition token_pos,
808 TokenPosition last_token_pos,
809 intptr_t requested_line,
810 intptr_t requested_column,
811 TokenPosition exact_token_pos,
812 const GrowableObjectArray& functions);
813 BreakpointLocation* SetBreakpoint(const Script& script,
814 TokenPosition token_pos,
815 TokenPosition last_token_pos,
816 intptr_t requested_line,
817 intptr_t requested_column,
818 const Function& function);
819 BreakpointLocation* SetBreakpoint(
820 const GrowableHandlePtrArray<const Script>& scripts,
821 TokenPosition token_pos,
822 TokenPosition last_token_pos,
823 intptr_t requested_line,
824 intptr_t requested_column,
825 const Function& function);
826 bool RemoveBreakpointFromTheList(intptr_t bp_id, BreakpointLocation** list);
827 Breakpoint* GetBreakpointByIdInTheList(intptr_t id, BreakpointLocation* list);
828 BreakpointLocation* GetLatentBreakpoint(const String& url,
829 intptr_t line,
830 intptr_t column);
831 void RegisterBreakpointLocationUnsafe(BreakpointLocation* loc);
832 void RegisterBreakpointLocation(BreakpointLocation* bpt);
833 BreakpointLocation* GetResolvedBreakpointLocation(
834 const String& script_url,
835 TokenPosition code_token_pos);
836 BreakpointLocation* GetBreakpointLocation(
837 const String& script_url,
838 TokenPosition token_pos,
839 intptr_t requested_line,
840 intptr_t requested_column,
841 TokenPosition code_token_pos = TokenPosition::kNoSource);
842
843 void PrintBreakpointsListToJSONArray(BreakpointLocation* sbpt,
844 JSONArray* jsarr) const;
845
846 void SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt);
847
848 intptr_t nextId() { return next_id_++; }
849
850 bool ShouldPauseOnException(DebuggerStackTrace* stack_trace,
851 const Instance& exc);
852
853 // Handles any events which pause vm execution. Breakpoints,
854 // interrupts, etc.
855 void Pause(ServiceEvent* event);
856
857 void HandleSteppingRequest(bool skip_next_step = false);
858
859 void CacheStackTraces(DebuggerStackTrace* stack_trace,
860 DebuggerStackTrace* async_awaiter_stack_trace);
861 void ClearCachedStackTraces();
862
863 void RewindToFrame(intptr_t frame_index);
864 void RewindToUnoptimizedFrame(StackFrame* frame, const Code& code);
865 void RewindToOptimizedFrame(StackFrame* frame,
866 const Code& code,
867 intptr_t post_deopt_frame_index);
868
869 void ResetSteppingFramePointer();
870 void SetSyncSteppingFramePointer(DebuggerStackTrace* stack_trace);
871
872 GroupDebugger* group_debugger() { return isolate_->group()->debugger(); }
873
874 Isolate* isolate_;
875
876 // ID number generator.
877 intptr_t next_id_;
878
879 BreakpointLocation* latent_locations_;
880 BreakpointLocation* breakpoint_locations_;
881
882 // Tells debugger what to do when resuming execution after a breakpoint.
883 ResumeAction resume_action_;
884 void set_resume_action(ResumeAction action);
885 intptr_t resume_frame_index_;
886 intptr_t post_deopt_frame_index_;
887
888 // Do not call back to breakpoint handler if this flag is set.
889 // Effectively this means ignoring breakpoints. Set when Dart code may
890 // be run as a side effect of getting values of fields.
891 bool ignore_breakpoints_;
892
893 // Indicates why the debugger is currently paused. If the debugger
894 // is not paused, this is nullptr. Note that the debugger can be
895 // paused for breakpoints, isolate interruption, and (sometimes)
896 // exceptions.
897 ServiceEvent* pause_event_;
898
899 // Current stack trace. Valid only while IsPaused().
900 DebuggerStackTrace* stack_trace_;
901 DebuggerStackTrace* async_awaiter_stack_trace_;
902
903 // When stepping through code, only pause the program if the top
904 // frame corresponds to this fp value, or if the top frame is
905 // lower on the stack.
906 uword stepping_fp_;
907
908 // When stepping through code, do not stop more than once in the same
909 // token position range.
910 uword last_stepping_fp_;
911 TokenPosition last_stepping_pos_;
912
913 // If we step while at a breakpoint, we would hit the same pc twice.
914 // We use this field to let us skip the next single-step after a
915 // breakpoint.
916 bool skip_next_step_;
917
918 Dart_ExceptionPauseInfo exc_pause_info_;
919
920 // Holds function data corresponding to suspendable
921 // function which should be stopped when resumed.
922 MallocGrowableArray<ObjectPtr> breakpoints_at_resumption_;
923
924 friend class Isolate;
925 friend class BreakpointLocation;
926 DISALLOW_COPY_AND_ASSIGN(Debugger);
927};
928
929class DisableBreakpointsScope : public ValueObject {
930 public:
931 DisableBreakpointsScope(Debugger* debugger, bool disable)
932 : debugger_(debugger) {
933 ASSERT(debugger_ != nullptr);
934 initial_state_ = debugger_->ignore_breakpoints();
935 debugger_->set_ignore_breakpoints(disable);
936 }
937
938 ~DisableBreakpointsScope() {
939 debugger_->set_ignore_breakpoints(initial_state_);
940 }
941
942 private:
943 Debugger* debugger_;
944 bool initial_state_;
945
946 DISALLOW_COPY_AND_ASSIGN(DisableBreakpointsScope);
947};
948
949} // namespace dart
950
951#endif // !defined(PRODUCT)
952
953#endif // RUNTIME_VM_DEBUGGER_H_
TArray< uint32_t > Key
static float next(float f)
#define UNREACHABLE()
Definition assert.h:248
static constexpr intptr_t kNone
Definition deopt_id.h:27
#define ASSERT(E)
double frame
Definition examples.cpp:31
FlKeyEvent * event
const uint8_t uint32_t uint32_t GError ** error
uint8_t value
const char * name
Definition fuchsia.cc:50
Win32Message message
void SetBreakpoint(Dart_NativeArguments args)
uintptr_t uword
Definition globals.h:501
const uint32_t fp
constexpr intptr_t kWordSize
Definition globals.h:509
Dart_ExceptionPauseInfo
Definition debugger.h:502
@ kInvalidExceptionPauseInfo
Definition debugger.h:506
@ kPauseOnUnhandledExceptions
Definition debugger.h:504
@ kNoPauseOnExceptions
Definition debugger.h:503
@ kPauseOnAllExceptions
Definition debugger.h:505
std::function< void()> closure
Definition closure.h:14
T * GetReceiver(Dart_NativeArguments args)
static Target * is_enabled(Benchmark *bench, const Config &config)
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581
#define T
const uintptr_t id

Function Documentation

◆ DECLARE_FLAG()

DECLARE_FLAG ( bool  ,
verbose_debug   
)