diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-04 06:04:46 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-04 06:04:46 +0000 |
commit | 22d95569efd2064e51bf727cee6f44297a4e9013 (patch) | |
tree | 12ae8e62608f576eb97f62210d0648551bfbd8a8 /base | |
parent | 4fe56181ecf3dbe0adb2bfd448040d8b37cb2536 (diff) | |
download | chromium_src-22d95569efd2064e51bf727cee6f44297a4e9013.zip chromium_src-22d95569efd2064e51bf727cee6f44297a4e9013.tar.gz chromium_src-22d95569efd2064e51bf727cee6f44297a4e9013.tar.bz2 |
Implement basic stack traces on Android and reenable unit tests.
Since we install stripped binaries in APKs, print out object file names and relocatable addresses that can be used on the host machine to complete symbolizing and demangling the stack trace using unstripped binaries.
In addition the implementation of StackTrace::PrintBacktrace() was changed to log the stack trace instead of sending SIGSTKFLT.
BUG=248775, 248784
Review URL: https://chromiumcodereview.appspot.com/16770006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@210132 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/base.gyp | 10 | ||||
-rw-r--r-- | base/debug/stack_trace_android.cc | 75 | ||||
-rw-r--r-- | base/logging.cc | 4 |
3 files changed, 46 insertions, 43 deletions
diff --git a/base/base.gyp b/base/base.gyp index 78f1690..3e4f996 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -132,7 +132,6 @@ ], 'dependencies': [ 'base_jni_headers', - 'symbolize', '../third_party/ashmem/ashmem.gyp:ashmem', ], 'include_dirs': [ @@ -143,9 +142,6 @@ '-llog', ], }, - 'defines': [ - 'USE_SYMBOLIZE', - ], 'sources!': [ 'debug/stack_trace_posix.cc', ], @@ -668,7 +664,7 @@ 'module_dir': 'base' }, 'conditions': [ - ['use_glib==1 or (OS == "android" and _toolset == "target")', { + ['use_glib==1', { 'defines': [ 'USE_SYMBOLIZE', ], @@ -684,10 +680,6 @@ ], }], ], - 'sources!': [ - # Broken on Android, and already disabled there. - 'debug/stack_trace_unittest.cc', - ], }], ['OS == "ios" and _toolset != "host"', { 'sources/': [ diff --git a/base/debug/stack_trace_android.cc b/base/debug/stack_trace_android.cc index 050a2d8..4c11a24 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; + + 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); + + 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 diff --git a/base/logging.cc b/base/logging.cc index 3b78387..16cd2f8 100644 --- a/base/logging.cc +++ b/base/logging.cc @@ -556,9 +556,7 @@ LogMessage::LogMessage(const char* file, int line, LogSeverity severity, } LogMessage::~LogMessage() { - // TODO(port): enable stacktrace generation on LOG_FATAL once backtrace are - // working in Android. -#if !defined(NDEBUG) && !defined(OS_ANDROID) && !defined(OS_NACL) +#if !defined(NDEBUG) && !defined(OS_NACL) if (severity_ == LOG_FATAL) { // Include a stack trace on a fatal. base::debug::StackTrace trace; |