mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:59:47 +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
|
@ -10,7 +10,7 @@
|
|||
|
||||
namespace dart {
|
||||
|
||||
const intptr_t kSkipCount = 5;
|
||||
const intptr_t kSkipCount = 4;
|
||||
|
||||
} // namespace dart
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
namespace dart {
|
||||
|
||||
const intptr_t kSkipCount = 5;
|
||||
const intptr_t kSkipCount = 4;
|
||||
|
||||
} // namespace dart
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
namespace dart {
|
||||
|
||||
#if defined(DEBUG)
|
||||
const intptr_t kSkipCount = 6;
|
||||
#elif !(defined(PRODUCT) || defined(DEBUG))
|
||||
const intptr_t kSkipCount = 5;
|
||||
#elif !(defined(PRODUCT) || defined(DEBUG))
|
||||
const intptr_t kSkipCount = 4;
|
||||
#endif
|
||||
|
||||
} // namespace dart
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
namespace dart {
|
||||
|
||||
#if defined(DEBUG)
|
||||
const intptr_t kSkipCount = 6;
|
||||
#elif !(defined(PRODUCT) || defined(DEBUG))
|
||||
const intptr_t kSkipCount = 5;
|
||||
#elif !(defined(PRODUCT) || defined(DEBUG))
|
||||
const intptr_t kSkipCount = 4;
|
||||
#endif
|
||||
|
||||
} // namespace dart
|
||||
|
|
|
@ -417,6 +417,7 @@ void ClearProfileVisitor::VisitSample(Sample* sample) {
|
|||
|
||||
static void DumpStackFrame(intptr_t frame_index,
|
||||
uword pc,
|
||||
uword fp,
|
||||
bool try_symbolize_dart_frames) {
|
||||
Thread* thread = Thread::Current();
|
||||
if ((thread != NULL) && !thread->IsAtSafepoint() &&
|
||||
|
@ -430,7 +431,8 @@ static void DumpStackFrame(intptr_t frame_index,
|
|||
code = Code::LookupCode(pc); // In current isolate.
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -438,12 +440,24 @@ static void DumpStackFrame(intptr_t frame_index,
|
|||
|
||||
uintptr_t start = 0;
|
||||
char* native_symbol_name = NativeSymbolResolver::LookupSymbolName(pc, &start);
|
||||
if (native_symbol_name == NULL) {
|
||||
OS::PrintErr(" [0x%" Pp "] Unknown symbol\n", pc);
|
||||
} else {
|
||||
OS::PrintErr(" [0x%" Pp "] %s\n", pc, native_symbol_name);
|
||||
if (native_symbol_name != NULL) {
|
||||
OS::PrintErr(" pc 0x%" Pp " fp 0x%" Pp " %s\n", pc, fp,
|
||||
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 {
|
||||
|
@ -469,14 +483,14 @@ class ProfilerStackWalker : public ValueObject {
|
|||
}
|
||||
}
|
||||
|
||||
bool Append(uword pc) {
|
||||
bool Append(uword pc, uword fp) {
|
||||
if (frames_skipped_ < skip_count_) {
|
||||
frames_skipped_++;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sample_ == NULL) {
|
||||
DumpStackFrame(frame_index_, pc, try_symbolize_dart_frames_);
|
||||
DumpStackFrame(frame_index_, pc, fp, try_symbolize_dart_frames_);
|
||||
frame_index_++;
|
||||
total_frames_++;
|
||||
return true;
|
||||
|
@ -632,7 +646,7 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
|
|||
in_interpreted_frame));
|
||||
}
|
||||
|
||||
if (!Append(reinterpret_cast<uword>(pc_))) {
|
||||
if (!Append(reinterpret_cast<uword>(pc_), reinterpret_cast<uword>(fp_))) {
|
||||
break; // Sample is full.
|
||||
}
|
||||
|
||||
|
@ -725,7 +739,7 @@ class ProfilerNativeStackWalker : public ProfilerStackWalker {
|
|||
void walk() {
|
||||
const uword kMaxStep = VirtualMemory::PageSize();
|
||||
|
||||
Append(original_pc_);
|
||||
Append(original_pc_, original_fp_);
|
||||
|
||||
uword* pc = reinterpret_cast<uword*>(original_pc_);
|
||||
uword* fp = reinterpret_cast<uword*>(original_fp_);
|
||||
|
@ -747,10 +761,6 @@ class ProfilerNativeStackWalker : public ProfilerStackWalker {
|
|||
}
|
||||
|
||||
while (true) {
|
||||
if (!Append(reinterpret_cast<uword>(pc))) {
|
||||
return;
|
||||
}
|
||||
|
||||
pc = CallerPC(fp);
|
||||
previous_fp = fp;
|
||||
fp = CallerFP(fp);
|
||||
|
@ -794,6 +804,10 @@ class ProfilerNativeStackWalker : public ProfilerStackWalker {
|
|||
|
||||
// Move the lower bound up.
|
||||
lower_bound_ = reinterpret_cast<uword>(fp);
|
||||
|
||||
if (!Append(reinterpret_cast<uword>(pc), reinterpret_cast<uword>(fp))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue