mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 23:49:45 +00:00
[vm] Update gdb helpers.
- 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>
This commit is contained in:
parent
d82385e372
commit
5187dbfffe
|
@ -3,22 +3,54 @@
|
|||
// 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)
|
||||
|
||||
DART_EXPORT
|
||||
void _printObjectPtr(ObjectPtr object) {
|
||||
OS::PrintErr("%s\n", Object::Handle(object).ToCString());
|
||||
#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();
|
||||
}
|
||||
|
||||
DART_EXPORT
|
||||
Object* _handle(ObjectPtr object) {
|
||||
return &Object::Handle(object);
|
||||
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
|
||||
|
@ -26,7 +58,7 @@ Object* _handle(ObjectPtr object) {
|
|||
// 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.
|
||||
DART_EXPORT
|
||||
GDB_HELPER
|
||||
void _printDartStackTrace() {
|
||||
const StackTrace& stacktrace = GetCurrentStackTrace(0);
|
||||
OS::PrintErr("=== Current Trace:\n%s===\n", stacktrace.ToCString());
|
||||
|
@ -34,14 +66,16 @@ void _printDartStackTrace() {
|
|||
|
||||
// Like _printDartStackTrace, but works in a NoSafepointScope. Use it if you're
|
||||
// in the middle of a GC or interested in stub frames.
|
||||
DART_EXPORT
|
||||
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.
|
||||
DART_EXPORT
|
||||
// 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(),
|
||||
|
@ -77,7 +111,7 @@ class PrintObjectPointersVisitor : public ObjectPointerVisitor {
|
|||
#endif
|
||||
};
|
||||
|
||||
DART_EXPORT
|
||||
GDB_HELPER
|
||||
void _printStackTraceWithLocals() {
|
||||
PrintObjectPointersVisitor visitor;
|
||||
StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
|
||||
|
|
|
@ -497,7 +497,7 @@ class PageSpace {
|
|||
friend class ConcurrentSweeperTask;
|
||||
friend class GCCompactor;
|
||||
friend class CompactorTask;
|
||||
friend void DumpStackFrame(intptr_t frame_index, uword pc, uword fp);
|
||||
friend class Code;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(PageSpace);
|
||||
};
|
||||
|
|
|
@ -18263,6 +18263,36 @@ CodePtr Code::FindCode(uword pc, int64_t timestamp) {
|
|||
return visitor.result();
|
||||
}
|
||||
|
||||
CodePtr Code::FindCodeUnsafe(uword pc) {
|
||||
class FindCodeUnsafeVisitor : public ObjectVisitor {
|
||||
public:
|
||||
explicit FindCodeUnsafeVisitor(uword pc) : pc_(pc), result_(Code::null()) {}
|
||||
|
||||
void VisitObject(ObjectPtr obj) {
|
||||
if (obj->IsCode()) {
|
||||
CodePtr code = static_cast<CodePtr>(obj);
|
||||
if (Code::ContainsInstructionAt(code, pc_)) {
|
||||
result_ = code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CodePtr result() { return result_; }
|
||||
|
||||
private:
|
||||
uword pc_;
|
||||
CodePtr result_;
|
||||
};
|
||||
|
||||
IsolateGroup* group = IsolateGroup::Current();
|
||||
PageSpace* old_space = group->heap()->old_space();
|
||||
old_space->MakeIterable();
|
||||
FindCodeUnsafeVisitor visitor(pc);
|
||||
old_space->VisitObjectsUnsafe(&visitor);
|
||||
Dart::vm_isolate_group()->heap()->old_space()->VisitObjectsUnsafe(&visitor);
|
||||
return visitor.result();
|
||||
}
|
||||
|
||||
TokenPosition Code::GetTokenIndexOfPC(uword pc) const {
|
||||
uword pc_offset = pc - PayloadStart();
|
||||
const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
|
||||
|
|
|
@ -7156,6 +7156,7 @@ class Code : public Object {
|
|||
|
||||
#endif
|
||||
static CodePtr FindCode(uword pc, int64_t timestamp);
|
||||
static CodePtr FindCodeUnsafe(uword pc);
|
||||
|
||||
int32_t GetPointerOffsetAt(int index) const {
|
||||
NoSafepointScope no_safepoint;
|
||||
|
|
|
@ -106,31 +106,8 @@ void DumpStackFrame(intptr_t frame_index, uword pc, uword fp) {
|
|||
(thread->execution_state() != Thread::kThreadInNative) &&
|
||||
(thread->execution_state() != Thread::kThreadInVM);
|
||||
if (symbolize_jit_code) {
|
||||
IsolateGroup* group = thread->isolate_group();
|
||||
class FindCodeVisitor : public ObjectVisitor {
|
||||
public:
|
||||
explicit FindCodeVisitor(uword pc, Code& result)
|
||||
: pc_(pc), result_(result) {}
|
||||
void VisitObject(ObjectPtr obj) {
|
||||
if (obj->IsCode()) {
|
||||
CodePtr code = static_cast<CodePtr>(obj);
|
||||
if (Code::ContainsInstructionAt(code, pc_)) {
|
||||
result_ = code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uword pc_;
|
||||
Code& result_;
|
||||
};
|
||||
PageSpace* old_space = group->heap()->old_space();
|
||||
old_space->MakeIterable();
|
||||
Code result;
|
||||
result = Code::null();
|
||||
FindCodeVisitor visitor(lookup_pc, result);
|
||||
old_space->VisitObjectsUnsafe(&visitor);
|
||||
Dart::vm_isolate_group()->heap()->old_space()->VisitObjectsUnsafe(&visitor);
|
||||
result = Code::FindCodeUnsafe(lookup_pc);
|
||||
if (!result.IsNull()) {
|
||||
DumpStackFrame(
|
||||
pc, fp,
|
||||
|
|
Loading…
Reference in a new issue