mirror of
https://github.com/dart-lang/sdk
synced 2024-10-15 00:04:55 +00:00
5187dbfffe
- Take raw addresses instead of ObjectPtr. gdb seems to sometimes not understand how to do the cast. - Use newer "retain" attribute to disable linker GC instead of exporting a dynamic symbol. - Add helper to get the current thread. Directly accessing dart::OSThread::current_vm_thread_ doesn't work. - Add helper to find the function or stub for a PC and disassemble. TEST=gdb Change-Id: I3825a820194673a9a9d5153cd0e0cf175acab5f4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/363403 Reviewed-by: Alexander Aprelev <aam@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
131 lines
4 KiB
C++
131 lines
4 KiB
C++
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include "lib/stacktrace.h"
|
|
#include "vm/compiler/assembler/disassembler.h"
|
|
#include "vm/heap/safepoint.h"
|
|
#include "vm/object.h"
|
|
#include "vm/os_thread.h"
|
|
#include "vm/stack_frame.h"
|
|
|
|
namespace dart {
|
|
|
|
#if !defined(PRODUCT)
|
|
|
|
#if defined(__GNUC__)
|
|
// Older toolchains don't know about "retain"
|
|
#pragma GCC diagnostic ignored "-Wattributes"
|
|
#define GDB_HELPER extern "C" __attribute__((used, retain))
|
|
#else
|
|
#define GDB_HELPER extern "C"
|
|
#endif
|
|
|
|
GDB_HELPER
|
|
void* _currentThread() {
|
|
return OSThread::CurrentVMThread();
|
|
}
|
|
|
|
GDB_HELPER
|
|
void _printObjectPtr(uword object) {
|
|
OS::PrintErr("%s\n",
|
|
Object::Handle(static_cast<ObjectPtr>(object)).ToCString());
|
|
}
|
|
|
|
GDB_HELPER
|
|
Object* _handle(uword object) {
|
|
return &Object::Handle(static_cast<ObjectPtr>(object));
|
|
}
|
|
|
|
GDB_HELPER
|
|
void _disassemble(uword pc) {
|
|
Code& code = Code::Handle(Code::FindCodeUnsafe(pc));
|
|
if (code.IsNull()) {
|
|
OS::PrintErr("No code found\n");
|
|
} else {
|
|
Object& owner = Object::Handle(code.owner());
|
|
if (owner.IsFunction()) {
|
|
Disassembler::DisassembleCode(Function::Cast(owner), code,
|
|
code.is_optimized());
|
|
} else {
|
|
Disassembler::DisassembleStub(code.Name(), code);
|
|
}
|
|
}
|
|
}
|
|
|
|
// An utility method for convenient printing of dart stack traces when
|
|
// inside 'gdb'. Note: This function will only work when there is a
|
|
// valid exit frame information. It will not work when a breakpoint is
|
|
// set in dart code and control is got inside 'gdb' without going through
|
|
// the runtime or native transition stub.
|
|
GDB_HELPER
|
|
void _printDartStackTrace() {
|
|
const StackTrace& stacktrace = GetCurrentStackTrace(0);
|
|
OS::PrintErr("=== Current Trace:\n%s===\n", stacktrace.ToCString());
|
|
}
|
|
|
|
// Like _printDartStackTrace, but works in a NoSafepointScope. Use it if you're
|
|
// in the middle of a GC or interested in stub frames.
|
|
GDB_HELPER
|
|
void _printStackTrace() {
|
|
StackFrame::DumpCurrentTrace();
|
|
}
|
|
|
|
// Like _printDartStackTrace, but works when stopped in generated code.
|
|
// Must be called with the current fp, sp, and pc. I.e.,
|
|
//
|
|
// (gdb) print _printGeneratedStackTrace($rbp, $rsp, $rip)
|
|
GDB_HELPER
|
|
void _printGeneratedStackTrace(uword fp, uword sp, uword pc) {
|
|
StackFrameIterator frames(fp, sp, pc, ValidationPolicy::kDontValidateFrames,
|
|
Thread::Current(),
|
|
StackFrameIterator::kNoCrossThreadIteration);
|
|
StackFrame* frame = frames.NextFrame();
|
|
while (frame != nullptr) {
|
|
OS::PrintErr("%s\n", frame->ToCString());
|
|
frame = frames.NextFrame();
|
|
}
|
|
}
|
|
|
|
class PrintObjectPointersVisitor : public ObjectPointerVisitor {
|
|
public:
|
|
PrintObjectPointersVisitor()
|
|
: ObjectPointerVisitor(IsolateGroup::Current()) {}
|
|
|
|
void VisitPointers(ObjectPtr* first, ObjectPtr* last) override {
|
|
for (ObjectPtr* p = first; p <= last; p++) {
|
|
Object& obj = Object::Handle(*p);
|
|
OS::PrintErr("%p: %s\n", p, obj.ToCString());
|
|
}
|
|
}
|
|
|
|
#if defined(DART_COMPRESSED_POINTERS)
|
|
void VisitCompressedPointers(uword heap_base,
|
|
CompressedObjectPtr* first,
|
|
CompressedObjectPtr* last) override {
|
|
for (CompressedObjectPtr* p = first; p <= last; p++) {
|
|
Object& obj = Object::Handle(p->Decompress(heap_base));
|
|
OS::PrintErr("%p: %s\n", p, obj.ToCString());
|
|
}
|
|
}
|
|
#endif
|
|
};
|
|
|
|
GDB_HELPER
|
|
void _printStackTraceWithLocals() {
|
|
PrintObjectPointersVisitor visitor;
|
|
StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
|
|
Thread::Current(),
|
|
StackFrameIterator::kNoCrossThreadIteration);
|
|
StackFrame* frame = frames.NextFrame();
|
|
while (frame != nullptr) {
|
|
OS::PrintErr("%s\n", frame->ToCString());
|
|
frame->VisitObjectPointers(&visitor);
|
|
frame = frames.NextFrame();
|
|
}
|
|
}
|
|
|
|
#endif // !PRODUCT
|
|
|
|
} // namespace dart
|