| 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 | |