1 | // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
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. |
4 | |
5 | #include "lib/stacktrace.h" |
6 | #include "vm/heap/safepoint.h" |
7 | #include "vm/object.h" |
8 | #include "vm/stack_frame.h" |
9 | |
10 | namespace dart { |
11 | |
12 | #if !defined(PRODUCT) |
13 | |
14 | DART_EXPORT |
15 | void _printRawObject(ObjectPtr object) { |
16 | OS::PrintErr("%s\n" , Object::Handle(object).ToCString()); |
17 | } |
18 | |
19 | DART_EXPORT |
20 | Object* _handle(ObjectPtr object) { |
21 | return &Object::Handle(object); |
22 | } |
23 | |
24 | // An utility method for convenient printing of dart stack traces when |
25 | // inside 'gdb'. Note: This function will only work when there is a |
26 | // valid exit frame information. It will not work when a breakpoint is |
27 | // set in dart code and control is got inside 'gdb' without going through |
28 | // the runtime or native transition stub. |
29 | DART_EXPORT |
30 | void _printDartStackTrace() { |
31 | const StackTrace& stacktrace = GetCurrentStackTrace(0); |
32 | OS::PrintErr("=== Current Trace:\n%s===\n" , stacktrace.ToCString()); |
33 | } |
34 | |
35 | // Like _printDartStackTrace, but works in a NoSafepointScope. Use it if you're |
36 | // in the middle of a GC or interested in stub frames. |
37 | DART_EXPORT |
38 | void _printStackTrace() { |
39 | StackFrame::DumpCurrentTrace(); |
40 | } |
41 | |
42 | // Like _printDartStackTrace, but works when stopped in generated code. |
43 | // Must be called with the current fp, sp, and pc. |
44 | DART_EXPORT |
45 | void _printGeneratedStackTrace(uword fp, uword sp, uword pc) { |
46 | StackFrameIterator frames(fp, sp, pc, ValidationPolicy::kDontValidateFrames, |
47 | Thread::Current(), |
48 | StackFrameIterator::kNoCrossThreadIteration); |
49 | StackFrame* frame = frames.NextFrame(); |
50 | while (frame != nullptr) { |
51 | OS::PrintErr("%s\n" , frame->ToCString()); |
52 | frame = frames.NextFrame(); |
53 | } |
54 | } |
55 | |
56 | // Like _printDartStackTrace, but works in the interpreter loop. |
57 | // Must be called with the current interpreter fp, sp, and pc. |
58 | // Note that sp[0] is not modified, but sp[1] will be trashed. |
59 | DART_EXPORT |
60 | void _printInterpreterStackTrace(ObjectPtr* fp, |
61 | ObjectPtr* sp, |
62 | const KBCInstr* pc) { |
63 | Thread* thread = Thread::Current(); |
64 | sp[1] = Function::null(); |
65 | sp[2] = Bytecode::null(); |
66 | sp[3] = static_cast<ObjectPtr>(reinterpret_cast<uword>(pc)); |
67 | sp[4] = static_cast<ObjectPtr>(reinterpret_cast<uword>(fp)); |
68 | ObjectPtr* exit_fp = sp + 1 + kKBCDartFrameFixedSize; |
69 | thread->set_top_exit_frame_info(reinterpret_cast<uword>(exit_fp)); |
70 | thread->set_execution_state(Thread::kThreadInVM); |
71 | _printDartStackTrace(); |
72 | thread->set_execution_state(Thread::kThreadInGenerated); |
73 | thread->set_top_exit_frame_info(0); |
74 | } |
75 | |
76 | class PrintObjectPointersVisitor : public ObjectPointerVisitor { |
77 | public: |
78 | PrintObjectPointersVisitor() |
79 | : ObjectPointerVisitor(IsolateGroup::Current()) {} |
80 | |
81 | void VisitPointers(ObjectPtr* first, ObjectPtr* last) { |
82 | for (ObjectPtr* p = first; p <= last; p++) { |
83 | Object& obj = Object::Handle(*p); |
84 | OS::PrintErr("%p: %s\n" , p, obj.ToCString()); |
85 | } |
86 | } |
87 | }; |
88 | |
89 | DART_EXPORT |
90 | void _printStackTraceWithLocals() { |
91 | PrintObjectPointersVisitor visitor; |
92 | StackFrameIterator frames(ValidationPolicy::kDontValidateFrames, |
93 | Thread::Current(), |
94 | StackFrameIterator::kNoCrossThreadIteration); |
95 | StackFrame* frame = frames.NextFrame(); |
96 | while (frame != nullptr) { |
97 | OS::PrintErr("%s\n" , frame->ToCString()); |
98 | frame->VisitObjectPointers(&visitor); |
99 | frame = frames.NextFrame(); |
100 | } |
101 | } |
102 | |
103 | #endif // !PRODUCT |
104 | |
105 | } // namespace dart |
106 | |