diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn index 13bfd0a724b..b74447f9d48 100644 --- a/runtime/BUILD.gn +++ b/runtime/BUILD.gn @@ -83,6 +83,9 @@ config("add_empty_macho_section_config") { config("dart_precompiler_config") { defines = [] defines += [ "DART_PRECOMPILER" ] + if (is_clang) { + cflags = [ "-fno-omit-frame-pointer" ] + } } config("dart_os_config") { diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc index 4ad80c5e5a9..966cb847e19 100644 --- a/runtime/vm/profiler.cc +++ b/runtime/vm/profiler.cc @@ -377,9 +377,9 @@ static bool GetAndValidateThreadStackBounds(OSThread* os_thread, return ValidateThreadStackBounds(fp, sp, *stack_lower, *stack_upper); } -// Some simple sanity checking of |pc|, |fp|, and |sp|. -static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) { - if ((sp == 0) || (fp == 0) || (pc == 0)) { +// Some simple sanity checking of |fp|, and |sp|. +static bool InitialStackRegistersCheck(uintptr_t fp, uintptr_t sp) { + if ((sp == 0) || (fp == 0)) { // None of these registers should be zero. return false; } @@ -393,6 +393,17 @@ static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) { return true; } +#if !defined(PRODUCT) +// Some simple sanity checking of |pc|, |fp|, and |sp|. +static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) { + if (pc == 0) { + return false; + } + + return InitialStackRegistersCheck(fp, sp); +} +#endif // !defined(PRODUCT) + void Profiler::DumpStackTrace(void* context) { if (context == NULL) { DumpStackTrace(/*for_crash=*/true); @@ -444,6 +455,15 @@ void Profiler::DumpStackTrace(bool for_crash) { DumpStackTrace(sp, fp, pc, for_crash); } +static void DumpCompilerState(Thread* thread) { +#if !defined(DART_PRECOMPILED_RUNTIME) + if (thread != nullptr && thread->execution_state() == Thread::kThreadInVM && + thread->HasCompilerState()) { + thread->compiler_state().ReportCrash(); + } +#endif +} + void Profiler::DumpStackTrace(uword sp, uword fp, uword pc, bool for_crash) { if (for_crash) { // Allow only one stack trace to prevent recursively printing stack traces @@ -496,9 +516,15 @@ void Profiler::DumpStackTrace(uword sp, uword fp, uword pc, bool for_crash) { vm_source == nullptr ? 0 : reinterpret_cast(vm_source->snapshot_instructions)); + OS::PrintErr("fp=%" Px ", sp=%" Px ", pc=%" Px "\n", fp, sp, pc); - if (!InitialRegisterCheck(pc, fp, sp)) { - OS::PrintErr("Stack dump aborted because InitialRegisterCheck failed.\n"); + if (!InitialStackRegistersCheck(fp, sp)) { + OS::PrintErr( + "Stack dump aborted because InitialStackRegistersCheck failed.\n"); + if (pc != 0) { // At the very least dump the top frame. + DumpStackFrame(0, pc, fp); + } + DumpCompilerState(thread); return; } @@ -508,6 +534,10 @@ void Profiler::DumpStackTrace(uword sp, uword fp, uword pc, bool for_crash) { &stack_upper)) { OS::PrintErr( "Stack dump aborted because GetAndValidateThreadStackBounds failed.\n"); + if (pc != 0) { // At the very least dump the top frame. + DumpStackFrame(0, pc, fp); + } + DumpCompilerState(thread); return; } @@ -524,13 +554,10 @@ void Profiler::DumpStackTrace(uword sp, uword fp, uword pc, bool for_crash) { StackFrame::DumpCurrentTrace(); } else if (thread->execution_state() == Thread::kThreadInVM) { StackFrame::DumpCurrentTrace(); -#if !defined(DART_PRECOMPILED_RUNTIME) - if (thread->HasCompilerState()) { - thread->compiler_state().ReportCrash(); - } -#endif } } + + DumpCompilerState(thread); } #endif // !defined(PRODUCT) || defined(DART_PRECOMPILER)