diff --git a/src/client/linux/handler/exception_handler.cc b/src/client/linux/handler/exception_handler.cc index dca7e7f0..9b20fe25 100644 --- a/src/client/linux/handler/exception_handler.cc +++ b/src/client/linux/handler/exception_handler.cc @@ -233,6 +233,11 @@ ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor, !minidump_descriptor_.IsMicrodumpOnConsole()) minidump_descriptor_.UpdatePath(); +#if defined(__ANDROID__) + if (minidump_descriptor_.IsMicrodumpOnConsole()) + logger::initializeCrashLogWriter(); +#endif + pthread_mutex_lock(&g_handler_stack_mutex_); if (!g_handler_stack_) g_handler_stack_ = new std::vector; diff --git a/src/client/linux/log/log.cc b/src/client/linux/log/log.cc index 18635913..fc23aa6d 100644 --- a/src/client/linux/log/log.cc +++ b/src/client/linux/log/log.cc @@ -31,15 +31,51 @@ #if defined(__ANDROID__) #include +#include #else #include "third_party/lss/linux_syscall_support.h" #endif namespace logger { +#if defined(__ANDROID__) +namespace { + +// __android_log_buf_write() is not exported in the NDK and is being used by +// dynamic runtime linking. Its declaration is taken from Android's +// system/core/include/log/log.h. +using AndroidLogBufferWriteFunc = int (*)(int bufID, int prio, const char *tag, + const char *text); +const int kAndroidCrashLogId = 4; // From LOG_ID_CRASH in log.h. +const char kAndroidLogTag[] = "google-breakpad"; + +bool g_crash_log_initialized = false; +AndroidLogBufferWriteFunc g_android_log_buf_write = nullptr; + +} // namespace + +void initializeCrashLogWriter() { + if (g_crash_log_initialized) + return; + g_android_log_buf_write = reinterpret_cast( + dlsym(RTLD_DEFAULT, "__android_log_buf_write")); + g_crash_log_initialized = true; +} + +int writeToCrashLog(const char* buf) { + // Try writing to the crash log ring buffer. If not available, fall back to + // the standard log buffer. + if (g_android_log_buf_write) { + return g_android_log_buf_write(kAndroidCrashLogId, ANDROID_LOG_FATAL, + kAndroidLogTag, buf); + } + return __android_log_write(ANDROID_LOG_FATAL, kAndroidLogTag, buf); +} +#endif + int write(const char* buf, size_t nbytes) { #if defined(__ANDROID__) - return __android_log_write(ANDROID_LOG_WARN, "google-breakpad", buf); + return __android_log_write(ANDROID_LOG_WARN, kAndroidLogTag, buf); #else return sys_write(2, buf, nbytes); #endif diff --git a/src/client/linux/log/log.h b/src/client/linux/log/log.h index a50e30dc..f94bbd5f 100644 --- a/src/client/linux/log/log.h +++ b/src/client/linux/log/log.h @@ -36,6 +36,20 @@ namespace logger { int write(const char* buf, size_t nbytes); +// In the case of Android the log can be written to the default system log +// (default behavior of write() above, or to the crash log (see +// writeToCrashLog() below). +#if defined(__ANDROID__) + +// The logger must be initialized in a non-compromised context. +void initializeCrashLogWriter(); + +// Once initialized, writeToCrashLog is safe to use in a compromised context, +// even if the initialization failed, in which case this will silently fall +// back on write(). +int writeToCrashLog(const char* buf); +#endif + } // namespace logger #endif // CLIENT_LINUX_LOG_LOG_H_ diff --git a/src/client/linux/microdump_writer/microdump_writer.cc b/src/client/linux/microdump_writer/microdump_writer.cc index d54d4909..c2dba35b 100644 --- a/src/client/linux/microdump_writer/microdump_writer.cc +++ b/src/client/linux/microdump_writer/microdump_writer.cc @@ -105,9 +105,11 @@ class MicrodumpWriter { private: // Writes one line to the system log. void LogLine(const char* msg) { +#if defined(__ANDROID__) + logger::writeToCrashLog(msg); +#else logger::write(msg, my_strlen(msg)); -#if !defined(__ANDROID__) - logger::write("\n", 1); // Android logger appends the \n. Linux's doesn't. + logger::write("\n", 1); #endif }