mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 08:20:31 +00:00
[vm, profiler] Improve profiler stacks and VM backtraces.
- Fix duplication of top frame from the native stack walker - Include frame pointer, useful for debugging stack overflows - Print dso name and offset when no symbol is available at runtime to allow offline symbolification Change-Id: I150d508e7c370c26ddd836b9dd50c2a465c19ebf Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/98432 Reviewed-by: Zach Anderson <zra@google.com>
This commit is contained in:
parent
335a854696
commit
d77a6064a9
5 changed files with 33 additions and 19 deletions
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
namespace dart {
|
namespace dart {
|
||||||
|
|
||||||
const intptr_t kSkipCount = 5;
|
const intptr_t kSkipCount = 4;
|
||||||
|
|
||||||
} // namespace dart
|
} // namespace dart
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
namespace dart {
|
namespace dart {
|
||||||
|
|
||||||
const intptr_t kSkipCount = 5;
|
const intptr_t kSkipCount = 4;
|
||||||
|
|
||||||
} // namespace dart
|
} // namespace dart
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
namespace dart {
|
namespace dart {
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
const intptr_t kSkipCount = 6;
|
|
||||||
#elif !(defined(PRODUCT) || defined(DEBUG))
|
|
||||||
const intptr_t kSkipCount = 5;
|
const intptr_t kSkipCount = 5;
|
||||||
|
#elif !(defined(PRODUCT) || defined(DEBUG))
|
||||||
|
const intptr_t kSkipCount = 4;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace dart
|
} // namespace dart
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
namespace dart {
|
namespace dart {
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
const intptr_t kSkipCount = 6;
|
|
||||||
#elif !(defined(PRODUCT) || defined(DEBUG))
|
|
||||||
const intptr_t kSkipCount = 5;
|
const intptr_t kSkipCount = 5;
|
||||||
|
#elif !(defined(PRODUCT) || defined(DEBUG))
|
||||||
|
const intptr_t kSkipCount = 4;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace dart
|
} // namespace dart
|
||||||
|
|
|
@ -417,6 +417,7 @@ void ClearProfileVisitor::VisitSample(Sample* sample) {
|
||||||
|
|
||||||
static void DumpStackFrame(intptr_t frame_index,
|
static void DumpStackFrame(intptr_t frame_index,
|
||||||
uword pc,
|
uword pc,
|
||||||
|
uword fp,
|
||||||
bool try_symbolize_dart_frames) {
|
bool try_symbolize_dart_frames) {
|
||||||
Thread* thread = Thread::Current();
|
Thread* thread = Thread::Current();
|
||||||
if ((thread != NULL) && !thread->IsAtSafepoint() &&
|
if ((thread != NULL) && !thread->IsAtSafepoint() &&
|
||||||
|
@ -430,7 +431,8 @@ static void DumpStackFrame(intptr_t frame_index,
|
||||||
code = Code::LookupCode(pc); // In current isolate.
|
code = Code::LookupCode(pc); // In current isolate.
|
||||||
}
|
}
|
||||||
if (!code.IsNull()) {
|
if (!code.IsNull()) {
|
||||||
OS::PrintErr(" [0x%" Pp "] %s\n", pc, code.QualifiedName());
|
OS::PrintErr(" pc 0x%" Pp " fp 0x%" Pp " %s\n", pc, fp,
|
||||||
|
code.QualifiedName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -438,12 +440,24 @@ static void DumpStackFrame(intptr_t frame_index,
|
||||||
|
|
||||||
uintptr_t start = 0;
|
uintptr_t start = 0;
|
||||||
char* native_symbol_name = NativeSymbolResolver::LookupSymbolName(pc, &start);
|
char* native_symbol_name = NativeSymbolResolver::LookupSymbolName(pc, &start);
|
||||||
if (native_symbol_name == NULL) {
|
if (native_symbol_name != NULL) {
|
||||||
OS::PrintErr(" [0x%" Pp "] Unknown symbol\n", pc);
|
OS::PrintErr(" pc 0x%" Pp " fp 0x%" Pp " %s\n", pc, fp,
|
||||||
} else {
|
native_symbol_name);
|
||||||
OS::PrintErr(" [0x%" Pp "] %s\n", pc, native_symbol_name);
|
|
||||||
NativeSymbolResolver::FreeSymbolName(native_symbol_name);
|
NativeSymbolResolver::FreeSymbolName(native_symbol_name);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* dso_name;
|
||||||
|
uword dso_base;
|
||||||
|
if (NativeSymbolResolver::LookupSharedObject(pc, &dso_base, &dso_name)) {
|
||||||
|
uword dso_offset = pc - dso_base;
|
||||||
|
OS::PrintErr(" pc 0x%" Pp " fp 0x%" Pp " %s+0x%" Px "\n", pc, fp, dso_name,
|
||||||
|
dso_offset);
|
||||||
|
NativeSymbolResolver::FreeSymbolName(dso_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OS::PrintErr(" pc 0x%" Pp " fp 0x%" Pp " Uknown symbol\n", pc, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProfilerStackWalker : public ValueObject {
|
class ProfilerStackWalker : public ValueObject {
|
||||||
|
@ -469,14 +483,14 @@ class ProfilerStackWalker : public ValueObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Append(uword pc) {
|
bool Append(uword pc, uword fp) {
|
||||||
if (frames_skipped_ < skip_count_) {
|
if (frames_skipped_ < skip_count_) {
|
||||||
frames_skipped_++;
|
frames_skipped_++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sample_ == NULL) {
|
if (sample_ == NULL) {
|
||||||
DumpStackFrame(frame_index_, pc, try_symbolize_dart_frames_);
|
DumpStackFrame(frame_index_, pc, fp, try_symbolize_dart_frames_);
|
||||||
frame_index_++;
|
frame_index_++;
|
||||||
total_frames_++;
|
total_frames_++;
|
||||||
return true;
|
return true;
|
||||||
|
@ -632,7 +646,7 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
|
||||||
in_interpreted_frame));
|
in_interpreted_frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Append(reinterpret_cast<uword>(pc_))) {
|
if (!Append(reinterpret_cast<uword>(pc_), reinterpret_cast<uword>(fp_))) {
|
||||||
break; // Sample is full.
|
break; // Sample is full.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,7 +739,7 @@ class ProfilerNativeStackWalker : public ProfilerStackWalker {
|
||||||
void walk() {
|
void walk() {
|
||||||
const uword kMaxStep = VirtualMemory::PageSize();
|
const uword kMaxStep = VirtualMemory::PageSize();
|
||||||
|
|
||||||
Append(original_pc_);
|
Append(original_pc_, original_fp_);
|
||||||
|
|
||||||
uword* pc = reinterpret_cast<uword*>(original_pc_);
|
uword* pc = reinterpret_cast<uword*>(original_pc_);
|
||||||
uword* fp = reinterpret_cast<uword*>(original_fp_);
|
uword* fp = reinterpret_cast<uword*>(original_fp_);
|
||||||
|
@ -747,10 +761,6 @@ class ProfilerNativeStackWalker : public ProfilerStackWalker {
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!Append(reinterpret_cast<uword>(pc))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pc = CallerPC(fp);
|
pc = CallerPC(fp);
|
||||||
previous_fp = fp;
|
previous_fp = fp;
|
||||||
fp = CallerFP(fp);
|
fp = CallerFP(fp);
|
||||||
|
@ -794,6 +804,10 @@ class ProfilerNativeStackWalker : public ProfilerStackWalker {
|
||||||
|
|
||||||
// Move the lower bound up.
|
// Move the lower bound up.
|
||||||
lower_bound_ = reinterpret_cast<uword>(fp);
|
lower_bound_ = reinterpret_cast<uword>(fp);
|
||||||
|
|
||||||
|
if (!Append(reinterpret_cast<uword>(pc), reinterpret_cast<uword>(fp))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue