diff options
| -rw-r--r-- | runtime/thread.cc | 3 | ||||
| -rw-r--r-- | runtime/utils.cc | 14 | ||||
| -rw-r--r-- | runtime/utils.h | 4 |
3 files changed, 17 insertions, 4 deletions
diff --git a/runtime/thread.cc b/runtime/thread.cc index a50fa00c19..6fc8c0f1a8 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -864,7 +864,8 @@ void Thread::DumpStack(std::ostream& os) const { // If we're currently in native code, dump that stack before dumping the managed stack. if (dump_for_abort || ShouldShowNativeStack(this)) { DumpKernelStack(os, GetTid(), " kernel: ", false); - DumpNativeStack(os, GetTid(), " native: ", false); + SirtRef<mirror::ArtMethod> method_ref(Thread::Current(), GetCurrentMethod(nullptr)); + DumpNativeStack(os, GetTid(), " native: ", false, method_ref.get()); } UniquePtr<Context> context(Context::Create()); StackDumpVisitor dumper(os, const_cast<Thread*>(this), context.get(), !throwing_OutOfMemoryError_); diff --git a/runtime/utils.cc b/runtime/utils.cc index 237d217f0b..d2d23e8de6 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -38,6 +38,7 @@ #include "mirror/string.h" #include "object_utils.h" #include "os.h" +#include "scoped_thread_state_change.h" #include "utf-inl.h" #if !defined(HAVE_POSIX_CLOCKS) @@ -1052,7 +1053,12 @@ static std::string CleanMapName(const backtrace_map_t* map) { return map->name.substr(last_slash + 1); } -void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix, bool include_count) { +void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix, bool include_count, + mirror::ArtMethod* current_method) { + // We may be called from contexts where current_method is not null, so we must assert this. + if (current_method != nullptr) { + Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); + } UniquePtr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, tid)); if (!backtrace->Unwind(0)) { os << prefix << "(backtrace::Unwind failed for thread " << tid << ")\n"; @@ -1073,7 +1079,11 @@ void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix, bool inclu if (!it->func_name.empty()) { os << it->func_name; } else { - os << "???"; + if (current_method != nullptr && current_method->IsWithinQuickCode(it->pc)) { + os << JniLongName(current_method) << "+" << (it->pc - current_method->GetQuickOatCodeOffset()); + } else { + os << "???"; + } } if (it->func_offset != 0) { os << "+" << it->func_offset; diff --git a/runtime/utils.h b/runtime/utils.h index bcbeb0ea63..dbc3ab7634 100644 --- a/runtime/utils.h +++ b/runtime/utils.h @@ -373,7 +373,9 @@ std::string GetSchedulerGroupName(pid_t tid); void SetThreadName(const char* thread_name); // Dumps the native stack for thread 'tid' to 'os'. -void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix = "", bool include_count = true); +void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix = "", + bool include_count = true, mirror::ArtMethod* current_method = nullptr) + NO_THREAD_SAFETY_ANALYSIS; // Dumps the kernel stack for thread 'tid' to 'os'. Note that this is only available on linux-x86. void DumpKernelStack(std::ostream& os, pid_t tid, const char* prefix = "", bool include_count = true); |