summaryrefslogtreecommitdiffstats
path: root/runtime/utils.cc
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-01-08 20:11:09 -0800
committerAndreas Gampe <agampe@google.com>2015-01-09 09:49:46 -0800
commit8e1cb91d2de6cacf388ca8550325fd8c21b1e58c (patch)
tree927cef6c60ab2943b4f1692b71160a80dbfcc213 /runtime/utils.cc
parent46af48acf4221a7f819d58dfffb576d0523ae285 (diff)
downloadart-8e1cb91d2de6cacf388ca8550325fd8c21b1e58c.tar.gz
art-8e1cb91d2de6cacf388ca8550325fd8c21b1e58c.tar.bz2
art-8e1cb91d2de6cacf388ca8550325fd8c21b1e58c.zip
ART: Use addr2line on the host for DumpNativeStack
Use addr2line to attempt some better debug output for unexpected signals in tests. This prints the demangled function name, source file and line number (including inlined frames) when possible. Bug: 18933933 Change-Id: I4b98d0cc7bef5cdc63c7ee0882629b363778afe2
Diffstat (limited to 'runtime/utils.cc')
-rw-r--r--runtime/utils.cc79
1 files changed, 79 insertions, 0 deletions
diff --git a/runtime/utils.cc b/runtime/utils.cc
index dd0bdbbe7..ef12d6e12 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -60,6 +60,10 @@
namespace art {
+#if defined(__linux__)
+static constexpr bool kUseAddr2line = !kIsTargetBuild;
+#endif
+
pid_t GetTid() {
#if defined(__APPLE__)
uint64_t owner;
@@ -1117,6 +1121,66 @@ std::string GetSchedulerGroupName(pid_t tid) {
return "";
}
+#if defined(__linux__)
+static bool RunCommand(std::string cmd, std::ostream* os, const char* prefix) {
+ FILE* stream = popen(cmd.c_str(), "r");
+ if (stream) {
+ if (os != nullptr) {
+ bool odd_line = true; // We indent them differently.
+ constexpr size_t kMaxBuffer = 128; // Relatively small buffer. Should be OK as we're on an
+ // alt stack, but just to be sure...
+ char buffer[kMaxBuffer];
+ while (!feof(stream)) {
+ if (fgets(buffer, kMaxBuffer, stream) != nullptr) {
+ // Split on newlines.
+ char* tmp = buffer;
+ for (;;) {
+ char* new_line = strchr(tmp, '\n');
+ if (new_line == nullptr) {
+ // Print the rest.
+ if (*tmp != 0) {
+ if (prefix != nullptr) {
+ *os << prefix;
+ }
+ if (!odd_line) {
+ *os << " ";
+ }
+ *os << tmp;
+ }
+ break;
+ }
+ if (prefix != nullptr) {
+ *os << prefix;
+ }
+ *os << " ";
+ if (!odd_line) {
+ *os << " ";
+ }
+ char saved = *(new_line + 1);
+ *(new_line + 1) = 0;
+ *os << tmp;
+ *(new_line + 1) = saved;
+ tmp = new_line + 1;
+ odd_line = !odd_line;
+ }
+ }
+ }
+ }
+ pclose(stream);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static void Addr2line(const std::string& map_src, uintptr_t offset, std::ostream& os,
+ const char* prefix) {
+ std::string cmdline(StringPrintf("addr2line --functions --inlines --demangle -e %s %zx",
+ map_src.c_str(), offset));
+ RunCommand(cmdline.c_str(), &os, prefix);
+}
+#endif
+
void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix,
mirror::ArtMethod* current_method, void* ucontext_ptr) {
#if __linux__
@@ -1142,6 +1206,16 @@ void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix,
return;
}
+ // Check whether we have and should use addr2line.
+ bool use_addr2line;
+ if (kUseAddr2line) {
+ // Try to run it to see whether we have it. Push an argument so that it doesn't assume a.out
+ // and print to stderr.
+ use_addr2line = RunCommand("addr2line -h", nullptr, nullptr);
+ } else {
+ use_addr2line = false;
+ }
+
for (Backtrace::const_iterator it = backtrace->begin();
it != backtrace->end(); ++it) {
// We produce output like this:
@@ -1153,6 +1227,7 @@ void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix,
// after the <RELATIVE_ADDR>. There can be any prefix data before the
// #XX. <RELATIVE_ADDR> has to be a hex number but with no 0x prefix.
os << prefix << StringPrintf("#%02zu pc ", it->num);
+ bool try_addr2line = false;
if (!it->map) {
os << StringPrintf("%08" PRIxPTR " ???", it->pc);
} else {
@@ -1163,6 +1238,7 @@ void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix,
if (it->func_offset != 0) {
os << "+" << it->func_offset;
}
+ try_addr2line = true;
} else if (current_method != nullptr &&
Locks::mutator_lock_->IsSharedHeld(Thread::Current()) &&
current_method->PcIsWithinQuickCode(it->pc)) {
@@ -1175,6 +1251,9 @@ void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix,
os << ")";
}
os << "\n";
+ if (try_addr2line && use_addr2line) {
+ Addr2line(it->map->name, it->pc - it->map->start, os, prefix);
+ }
}
#else
UNUSED(os, tid, prefix, current_method, ucontext_ptr);