| Index: chrome/app/breakpad_linuxish.cc
|
| diff --git a/chrome/app/breakpad_linux.cc b/chrome/app/breakpad_linuxish.cc
|
| similarity index 87%
|
| rename from chrome/app/breakpad_linux.cc
|
| rename to chrome/app/breakpad_linuxish.cc
|
| index 17b4e8ae989ac8900d55838a67be2717d5f18d23..e5c257043621d8bd38072c772dbd422149047267 100644
|
| --- a/chrome/app/breakpad_linux.cc
|
| +++ b/chrome/app/breakpad_linuxish.cc
|
| @@ -6,7 +6,7 @@
|
| // calls when in seccomp mode.
|
| #define SYS_SYSCALL_ENTRYPOINT "playground$syscallEntryPoint"
|
|
|
| -#include "chrome/app/breakpad_linux.h"
|
| +#include "chrome/app/breakpad_linuxish.h"
|
|
|
| #include <fcntl.h>
|
| #include <poll.h>
|
| @@ -42,7 +42,16 @@
|
| #include "chrome/common/env_vars.h"
|
| #include "chrome/common/logging_chrome.h"
|
| #include "content/common/chrome_descriptors.h"
|
| +
|
| +#if defined(OS_ANDROID)
|
| +#include <android/log.h>
|
| +#include <sys/stat.h>
|
| +#include "base/android/path_utils.h"
|
| +#include "base/android/build_info.h"
|
| +#include "third_party/lss/linux_syscall_support.h"
|
| +#else
|
| #include "seccompsandbox/linux_syscall_support.h"
|
| +#endif
|
|
|
| #ifndef PR_SET_PTRACER
|
| #define PR_SET_PTRACER 0x59616d61
|
| @@ -118,6 +127,35 @@ static void my_uint64tos(char* output, uint64_t i, unsigned i_len) {
|
| output[index - 1] = '0' + (i % 10);
|
| }
|
|
|
| +#if defind(OS_ANDROID)
|
| +static char* my_strncpy(char* dst, const char* src, size_t len) {
|
| + int i = len;
|
| + char* p = dst;
|
| + if (!dst || !src)
|
| + return dst;
|
| + while (i != 0 && *src != '\0') {
|
| + *p++ = *src++;
|
| + i--;
|
| + }
|
| + while (i != 0) {
|
| + *p++ = '\0';
|
| + i--;
|
| + }
|
| + return dst;
|
| +}
|
| +
|
| +static char* my_strncat(char *dest, const char *src, size_t len) {
|
| + char *ret = dest;
|
| + while (*dest)
|
| + dest++;
|
| + while (len--)
|
| + if (!(*dest++ = *src++))
|
| + return ret;
|
| + *dest = 0;
|
| + return ret;
|
| +}
|
| +#endif
|
| +
|
| namespace {
|
|
|
| // MIME substrings.
|
| @@ -305,6 +343,14 @@ void DumpProcess() {
|
| g_breakpad->WriteMinidump();
|
| }
|
|
|
| +size_t log(const char* buf, size_t nbytes) {
|
| +#if defined(OS_ANDROID)
|
| + return __android_log_write(ANDROID_LOG_WARN, "google-breakpad", buf);
|
| +#else
|
| + return sys_write(2, buf, nbytes)
|
| +#endif
|
| +}
|
| +
|
| } // namespace
|
|
|
| void HandleCrashDump(const BreakpadInfo& info) {
|
| @@ -314,13 +360,18 @@ void HandleCrashDump(const BreakpadInfo& info) {
|
| const int dumpfd = sys_open(info.filename, O_RDONLY, 0);
|
| if (dumpfd < 0) {
|
| static const char msg[] = "Cannot upload crash dump: failed to open\n";
|
| - sys_write(2, msg, sizeof(msg));
|
| + log(msg, sizeof(msg));
|
| return;
|
| }
|
| +#if defined(OS_ANDROID)
|
| + struct stat st;
|
| + if (fstat(dumpfd, &st) != 0) {
|
| +#else
|
| struct kernel_stat st;
|
| if (sys_fstat(dumpfd, &st) != 0) {
|
| +#endif
|
| static const char msg[] = "Cannot upload crash dump: stat failed\n";
|
| - sys_write(2, msg, sizeof(msg));
|
| + log(msg, sizeof(msg));
|
| IGNORE_RET(sys_close(dumpfd));
|
| return;
|
| }
|
| @@ -330,7 +381,7 @@ void HandleCrashDump(const BreakpadInfo& info) {
|
| uint8_t* dump_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size));
|
| if (!dump_data) {
|
| static const char msg[] = "Cannot upload crash dump: cannot alloc\n";
|
| - sys_write(2, msg, sizeof(msg));
|
| + log(msg, sizeof(msg));
|
| IGNORE_RET(sys_close(dumpfd));
|
| return;
|
| }
|
| @@ -345,7 +396,7 @@ void HandleCrashDump(const BreakpadInfo& info) {
|
| if (ufd < 0) {
|
| static const char msg[] = "Cannot upload crash dump because /dev/urandom"
|
| " is missing\n";
|
| - sys_write(2, msg, sizeof(msg) - 1);
|
| + log(msg, sizeof(msg) - 1);
|
| return;
|
| }
|
|
|
| @@ -369,7 +420,7 @@ void HandleCrashDump(const BreakpadInfo& info) {
|
| if (temp_file_fd < 0) {
|
| static const char msg[] = "Failed to create temporary file in /tmp: "
|
| "cannot upload crash dump\n";
|
| - sys_write(2, msg, sizeof(msg) - 1);
|
| + log(msg, sizeof(msg) - 1);
|
| IGNORE_RET(sys_close(ufd));
|
| return;
|
| }
|
| @@ -377,7 +428,7 @@ void HandleCrashDump(const BreakpadInfo& info) {
|
| temp_file_fd = sys_open(info.filename, O_WRONLY, 0600);
|
| if (temp_file_fd < 0) {
|
| static const char msg[] = "Failed to save crash dump: failed to open\n";
|
| - sys_write(2, msg, sizeof(msg) - 1);
|
| + log(msg, sizeof(msg) - 1);
|
| IGNORE_RET(sys_close(ufd));
|
| return;
|
| }
|
| @@ -476,12 +527,27 @@ void HandleCrashDump(const BreakpadInfo& info) {
|
|
|
| MimeWriter writer(temp_file_fd, mime_boundary);
|
| {
|
| -#if defined(OS_CHROMEOS)
|
| +#if defined(OS_ANDROID)
|
| + static const char chrome_product_msg[] = "Chrome_Android";
|
| +#elif defined(OS_CHROMEOS)
|
| static const char chrome_product_msg[] = "Chrome_ChromeOS";
|
| #else // OS_LINUX
|
| static const char chrome_product_msg[] = "Chrome_Linux";
|
| #endif
|
| +
|
| +#if defined (OS_ANDROID)
|
| + base::android::BuildInfo* android_build_info =
|
| + base::android::BuildInfo::GetInstance();
|
| + static const char* version_msg =
|
| + android_build_info->package_version_code();
|
| + static const char android_build_id[] = "android_build_id";
|
| + static const char android_build_fp[] = "android_build_fp";
|
| + static const char device[] = "device";
|
| + static const char model[] = "model";
|
| + static const char brand[] = "brand";
|
| +#else
|
| static const char version_msg[] = PRODUCT_VERSION;
|
| +#endif
|
|
|
| writer.AddBoundary();
|
| writer.AddPairString("prod", chrome_product_msg);
|
| @@ -490,6 +556,28 @@ void HandleCrashDump(const BreakpadInfo& info) {
|
| writer.AddBoundary();
|
| writer.AddPairString("guid", info.guid);
|
| writer.AddBoundary();
|
| + if (info.pid > 0) {
|
| + uint64_t pid_str_len = my_uint64_len(info.pid);
|
| + char* pid_buf = reinterpret_cast<char*>(allocator.Alloc(pid_str_len));
|
| + my_uint64tos(pid_buf, info.pid, pid_str_len);
|
| + writer.AddPairString("pid", pid_buf);
|
| + writer.AddBoundary();
|
| + }
|
| +#if defined(OS_ANDROID)
|
| + // Addtional MIME blocks are added for logging on Android devices.
|
| + writer.AddPairString(
|
| + android_build_id, android_build_info->android_build_id());
|
| + writer.AddBoundary();
|
| + writer.AddPairString(
|
| + android_build_fp, android_build_info->android_build_fp());
|
| + writer.AddBoundary();
|
| + writer.AddPairString(device, android_build_info->device());
|
| + writer.AddBoundary();
|
| + writer.AddPairString(model, android_build_info->model());
|
| + writer.AddBoundary();
|
| + writer.AddPairString(brand, android_build_info->brand());
|
| + writer.AddBoundary();
|
| +#endif
|
| writer.Flush();
|
| }
|
|
|
| @@ -637,6 +725,36 @@ void HandleCrashDump(const BreakpadInfo& info) {
|
| writer.Flush();
|
|
|
| IGNORE_RET(sys_close(temp_file_fd));
|
| +#if defined(OS_ANDROID)
|
| + uint64_t pid_str_len = my_uint64_len(info.pid);
|
| + char* pid_buf = reinterpret_cast<char*>(allocator.Alloc(pid_str_len));
|
| + my_uint64tos(pid_buf, info.pid, pid_str_len);
|
| +
|
| + static const char* output_msg = "Output crash dump file:";
|
| + log(output_msg, my_strlen(output_msg));
|
| + int initial_filename_len = my_strln(info.filename);
|
| + log(info.filename, info.filename);
|
| + // -1 because we won't need the null terminator on the original filename.
|
| + size_t done_filename_len = initial_filename_len -1 + pid_str_len;
|
| + char* done_filename = reinterpret_cast<char*>(
|
| + allocator.Alloc(done_filename_len));
|
| + // Rename the file such that the pid is the suffix in order signal to other
|
| + // processes that the minidump is complete. The advantage of using the pid as
|
| + // the suffix is that it is trivial to associate the minidump with the
|
| + // crashed process.
|
| + // Finally, note strncpy prevents null terminators from
|
| + // being copied. Pad the rest with 0's.
|
| + my_strncpy(done_filename, info.filename, done_filename_len);
|
| + // Append the suffix a null terminator should be added.
|
| + my_strncat(done_filename, pid_buf, pid_str_len);
|
| + // Rename the minidump file to signal that it is complete.
|
| + if (rename(info.filename, done_filename)) {
|
| + __android_log_write(ANDROID_LOG_WARN, "chromium", "Failed to rename:");
|
| + __android_log_write(ANDROID_LOG_WARN, "chromium", info.filename);
|
| + __android_log_write(ANDROID_LOG_WARN, "chromium", "to");
|
| + __android_log_write(ANDROID_LOG_WARN, "chromium", done_filename);
|
| + }
|
| +#endif
|
|
|
| if (!info.upload)
|
| return;
|
| @@ -718,7 +836,7 @@ void HandleCrashDump(const BreakpadInfo& info) {
|
| execve(kWgetBinary, const_cast<char**>(args), environ);
|
| static const char msg[] = "Cannot upload crash dump: cannot exec "
|
| "/usr/bin/wget\n";
|
| - sys_write(2, msg, sizeof(msg) - 1);
|
| + log(msg, sizeof(msg) - 1);
|
| sys__exit(1);
|
| }
|
|
|
| @@ -748,9 +866,9 @@ void HandleCrashDump(const BreakpadInfo& info) {
|
| // Write crash dump id to stderr.
|
| id_buf[len] = 0;
|
| static const char msg[] = "\nCrash dump id: ";
|
| - sys_write(2, msg, sizeof(msg) - 1);
|
| - sys_write(2, id_buf, my_strlen(id_buf));
|
| - sys_write(2, "\n", 1);
|
| + log(msg, sizeof(msg) - 1);
|
| + log(id_buf, my_strlen(id_buf));
|
| + log("\n", 1);
|
|
|
| // Write crash dump id to crash log as: seconds_since_epoch,crash_id
|
| struct kernel_timeval tv;
|
| @@ -825,6 +943,7 @@ static bool CrashDone(const char* dump_path,
|
| info.upload = upload;
|
| info.process_start_time = g_process_start_time;
|
| info.oom_size = base::g_oom_size;
|
| + info.pid = 0;
|
| HandleCrashDump(info);
|
| return true;
|
| }
|
| @@ -837,6 +956,7 @@ static bool CrashDoneNoUpload(const char* dump_path,
|
| return CrashDone(dump_path, minidump_id, false, succeeded);
|
| }
|
|
|
| +#if !defined(OS_ANDROID)
|
| // Wrapper function, do not add more code here.
|
| static bool CrashDoneUpload(const char* dump_path,
|
| const char* minidump_id,
|
| @@ -844,6 +964,7 @@ static bool CrashDoneUpload(const char* dump_path,
|
| bool succeeded) {
|
| return CrashDone(dump_path, minidump_id, true, succeeded);
|
| }
|
| +#endif
|
|
|
| void EnableCrashDumping(const bool unattended) {
|
| g_is_crash_reporter_enabled = true;
|
| @@ -860,8 +981,16 @@ void EnableCrashDumping(const bool unattended) {
|
| g_crash_log_path = new char[crash_log_path_len];
|
| strncpy(g_crash_log_path, logfile_str.c_str(), crash_log_path_len);
|
| }
|
| -
|
| DCHECK(!g_breakpad);
|
| +#if defined(OS_ANDROID)
|
| + // In Android we never upload from native code.
|
| + g_breakpad = new google_breakpad::ExceptionHandler(
|
| + dumps_path.value().c_str(),
|
| + NULL,
|
| + CrashDoneNoUpload,
|
| + NULL,
|
| + true /* install handlers */);
|
| +#else
|
| if (unattended) {
|
| g_breakpad = new google_breakpad::ExceptionHandler(
|
| dumps_path.value().c_str(),
|
| @@ -877,6 +1006,7 @@ void EnableCrashDumping(const bool unattended) {
|
| NULL,
|
| true /* install handlers */);
|
| }
|
| +#endif
|
| }
|
|
|
| // Non-Browser = Extension, Gpu, Plugins, Ppapi and Renderer
|
| @@ -887,7 +1017,7 @@ static bool NonBrowserCrashHandler(const void* crash_context,
|
| int fds[2] = { -1, -1 };
|
| if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
|
| static const char msg[] = "Failed to create socket for crash dumping.\n";
|
| - sys_write(2, msg, sizeof(msg)-1);
|
| + log(msg, sizeof(msg)-1);
|
| return false;
|
| }
|
|
|
| @@ -964,7 +1094,7 @@ static bool NonBrowserCrashHandler(const void* crash_context,
|
|
|
| if (HANDLE_EINTR(sys_sendmsg(fd, &msg, 0)) < 0) {
|
| static const char errmsg[] = "Failed to tell parent about crash.\n";
|
| - sys_write(2, errmsg, sizeof(errmsg)-1);
|
| + log(errmsg, sizeof(errmsg)-1);
|
| IGNORE_RET(sys_close(fds[1]));
|
| return false;
|
| }
|
| @@ -972,7 +1102,7 @@ static bool NonBrowserCrashHandler(const void* crash_context,
|
|
|
| if (HANDLE_EINTR(sys_read(fds[0], &b, 1)) != 1) {
|
| static const char errmsg[] = "Parent failed to complete crash dump.\n";
|
| - sys_write(2, errmsg, sizeof(errmsg)-1);
|
| + log(errmsg, sizeof(errmsg)-1);
|
| }
|
|
|
| return true;
|
| @@ -989,6 +1119,11 @@ void EnableNonBrowserCrashDumping() {
|
| }
|
|
|
| void InitCrashReporter() {
|
| +#if defined(OS_ANDROID)
|
| + // This will guarantee that the BuildInfo has been initialized and subsequent
|
| + // calls will not require memory allocation.
|
| + base::android::BuildInfo::GetInstance();
|
| +#endif
|
| // Determine the process type and take appropriate action.
|
| const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
|
| if (parsed_command_line.HasSwitch(switches::kDisableBreakpad))
|
| @@ -1003,6 +1138,9 @@ void InitCrashReporter() {
|
| process_type == switches::kPpapiPluginProcess ||
|
| process_type == switches::kZygoteProcess ||
|
| process_type == switches::kGpuProcess) {
|
| +#if defined(OS_ANDROID)
|
| + child_process_logging::SetClientId("Android");
|
| +#endif
|
| // We might be chrooted in a zygote or renderer process so we cannot call
|
| // GetCollectStatsConsent because that needs access the the user's home
|
| // dir. Instead, we set a command line flag for these processes.
|
|
|