Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(821)

Unified Diff: base/debug/stack_trace_android.cc

Issue 16770006: Implement basic stack traces on Android and reenable unit tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/base.gyp ('k') | base/logging.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..c5f6de50fffa8a753d3eae999c3681c690eaecc2 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,52 @@ 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, &regions)) {
+ __android_log_write(
+ ANDROID_LOG_ERROR, "chromium", "Failed to parse /proc/self/maps");
+ }
+
+ for (size_t i = 0; i < count_; ++i) {
+ *os << base::StringPrintf("#%02d ", i);
+
+ // Subtract by one as return address of function may be in the next
Mark Mentovai 2013/07/03 14:03:30 Nit: “subtract one,” not “subtract by one.”
scherkus (not reviewing) 2013/07/03 19:43:01 Done.
+ // function when a function is annotated as noreturn.
Mark Mentovai 2013/07/03 14:03:30 This comment only tells half the story. If someone
scherkus (not reviewing) 2013/07/03 19:43:01 I fully admit that this is vestigial code from whe
+ uintptr_t address = reinterpret_cast<uintptr_t>(trace_[i]) - 1;
+
+ std::vector<MappedMemoryRegion>::iterator iter = regions.begin();
+ while (iter != regions.end()) {
+ if (address >= iter->start && address < iter->end &&
+ (iter->permissions & MappedMemoryRegion::READ) &&
Mark Mentovai 2013/07/03 14:03:30 Why check the protection bits? If the address is i
scherkus (not reviewing) 2013/07/03 19:43:01 do you mean non-zero inode/device? considering we
Mark Mentovai 2013/07/04 01:25:49 scherkus wrote:
+ (iter->permissions & MappedMemoryRegion::EXECUTE)) {
+ break;
+ }
+ ++iter;
+ }
+
+ if (iter != regions.end()) {
+ uintptr_t rel_pc = address - iter->start + iter->offset;
+ const char* path = iter->path.c_str();
+ *os << base::StringPrintf("pc %08x %s", rel_pc, path);
Mark Mentovai 2013/07/03 14:03:30 Maybe it’s just me, but this format seems kind of
scherkus (not reviewing) 2013/07/03 19:43:01 Was attempting to emulate the Android stack dump s
+ } else {
+ *os << base::StringPrintf("<unknown> 0x%08x", address);
Mark Mentovai 2013/07/03 14:03:30 kinda like the format you used here. But why’d yo
scherkus (not reviewing) 2013/07/03 19:43:01 Done.
+ }
+
+ *os << "\n";
+ }
}
} // namespace debug
« no previous file with comments | « base/base.gyp ('k') | base/logging.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698