Index: base/debug/stack_trace_android.cc |
diff --git a/base/debug/stack_trace_android.cc b/base/debug/stack_trace_android.cc |
index 050a2d8c501904b17e3bee5cf13993fafd639026..4c11a244d6ee2f5513c560f67702de21ab924c5c 100644 |
--- a/base/debug/stack_trace_android.cc |
+++ b/base/debug/stack_trace_android.cc |
@@ -4,17 +4,11 @@ |
#include "base/debug/stack_trace.h" |
-#include <signal.h> |
-#include <sys/types.h> |
-#include <unistd.h> |
+#include <android/log.h> |
#include <unwind.h> // TODO(dmikurube): Remove. See http://crbug.com/236855. |
-#include "base/logging.h" |
- |
-#ifdef __MIPSEL__ |
-// SIGSTKFLT is not defined for MIPS. |
-#define SIGSTKFLT SIGSEGV |
-#endif |
+#include "base/debug/proc_maps_linux.h" |
+#include "base/strings/stringprintf.h" |
// TODO(dmikurube): Remove when Bionic's get_backtrace() gets popular. |
// See http://crbug.com/236855. |
@@ -93,32 +87,51 @@ StackTrace::StackTrace() { |
// TODO(dmikurube): Symbolize in Chrome. |
} |
-// Sends fake SIGSTKFLT signals to let the Android linker and debuggerd dump |
-// stack. See inlined comments and Android bionic/linker/debugger.c and |
-// system/core/debuggerd/debuggerd.c for details. |
void StackTrace::PrintBacktrace() const { |
- // Get the current handler of SIGSTKFLT for later use. |
- sighandler_t sig_handler = signal(SIGSTKFLT, SIG_DFL); |
- signal(SIGSTKFLT, sig_handler); |
- |
- // The Android linker will handle this signal and send a stack dumping request |
- // to debuggerd which will ptrace_attach this process. Before returning from |
- // the signal handler, the linker sets the signal handler to SIG_IGN. |
- kill(gettid(), SIGSTKFLT); |
- |
- // Because debuggerd will wait for the process to be stopped by the actual |
- // signal in crashing scenarios, signal is sent again to met the expectation. |
- // Debuggerd will dump stack into the system log and /data/tombstones/ files. |
- // NOTE: If this process runs in the interactive shell, it will be put |
- // in the background. To resume it in the foreground, use 'fg' command. |
- kill(gettid(), SIGSTKFLT); |
- |
- // Restore the signal handler so that this method can work the next time. |
- signal(SIGSTKFLT, sig_handler); |
+ std::string backtrace = ToString(); |
+ __android_log_write(ANDROID_LOG_ERROR, "chromium", backtrace.c_str()); |
} |
+// NOTE: Native libraries in APKs are stripped before installing. Print out the |
+// relocatable address and library names so host computers can use tools to |
+// symbolize and demangle (e.g., addr2line, c++filt). |
void StackTrace::OutputToStream(std::ostream* os) const { |
- NOTIMPLEMENTED(); |
+ std::string proc_maps; |
+ std::vector<MappedMemoryRegion> regions; |
+ if (!ReadProcMaps(&proc_maps)) { |
+ __android_log_write( |
+ ANDROID_LOG_ERROR, "chromium", "Failed to read /proc/self/maps"); |
+ } else if (!ParseProcMaps(proc_maps, ®ions)) { |
+ __android_log_write( |
+ ANDROID_LOG_ERROR, "chromium", "Failed to parse /proc/self/maps"); |
+ } |
+ |
+ for (size_t i = 0; i < count_; ++i) { |
+ // Subtract one as return address of function may be in the next |
+ // function when a function is annotated as noreturn. |
+ uintptr_t address = reinterpret_cast<uintptr_t>(trace_[i]) - 1; |
Mark Mentovai
2013/07/04 01:25:49
OK, I guess the safe thing to do is leave this as
|
+ |
+ std::vector<MappedMemoryRegion>::iterator iter = regions.begin(); |
+ while (iter != regions.end()) { |
+ if (address >= iter->start && address < iter->end && |
+ !iter->path.empty()) { |
+ break; |
+ } |
+ ++iter; |
+ } |
+ |
+ *os << base::StringPrintf("#%02d 0x%08x ", i, address); |
Mark Mentovai
2013/07/04 01:25:49
This format is awesome.
|
+ |
+ if (iter != regions.end()) { |
+ uintptr_t rel_pc = address - iter->start + iter->offset; |
+ const char* path = iter->path.c_str(); |
+ *os << base::StringPrintf("%s+0x%08x", path, rel_pc); |
+ } else { |
+ *os << "<unknown>"; |
+ } |
+ |
+ *os << "\n"; |
+ } |
} |
} // namespace debug |