summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/thread.cc3
-rw-r--r--runtime/utils.cc14
-rw-r--r--runtime/utils.h4
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);