Chromium Code Reviews| Index: chrome/app/breakpad_posix.cc |
| diff --git a/chrome/app/breakpad_linux.cc b/chrome/app/breakpad_posix.cc |
| similarity index 87% |
| rename from chrome/app/breakpad_linux.cc |
| rename to chrome/app/breakpad_posix.cc |
| index eff3a12bea23760acdad75459bb69b2abd0f891a..0761f11242d8986e3e52af6e7829fc8b4370ae52 100644 |
| --- a/chrome/app/breakpad_linux.cc |
| +++ b/chrome/app/breakpad_posix.cc |
| @@ -43,6 +43,16 @@ |
| #include "content/common/chrome_descriptors.h" |
| #include "seccompsandbox/linux_syscall_support.h" |
|
Yaron
2012/03/26 18:51:15
Remove this include if it shouldn't be in the andr
carlosvaldivia
2012/04/03 06:24:47
Done.
|
| +#ifdef OS_ANDROID |
|
Yaron
2012/03/26 18:51:15
Nit: preferred style is #if defined(OS_ANDROID)
carlosvaldivia
2012/04/03 06:24:47
Done.
|
| +#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 |
| #endif |
| @@ -114,6 +124,35 @@ static void my_uint64tos(char* output, uint64_t i, unsigned i_len) { |
| output[index - 1] = '0' + (i % 10); |
| } |
| +static inline 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 inline 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; |
| +} |
| + |
| namespace { |
| // MIME substrings. |
| @@ -303,6 +342,14 @@ void DumpProcess() { |
| } // namespace |
| +void log(const char* buf, size_t nbytes) { |
| +#if defined(__ANDROID__) |
| + return __android_log_write(ANDROID_LOG_WARN, "google-breakpad", buf); |
| +#else |
| + return sys_write(2, buf, nbytes) |
| +#endif |
| +} |
| + |
| void HandleCrashDump(const BreakpadInfo& info) { |
| // WARNING: this code runs in a compromised context. It may not call into |
| // libc nor allocate memory normally. |
| @@ -310,13 +357,13 @@ 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; |
| } |
| struct kernel_stat st; |
| if (sys_fstat(dumpfd, &st) != 0) { |
| 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; |
| } |
| @@ -326,7 +373,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; |
| } |
| @@ -341,7 +388,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; |
| } |
| @@ -365,7 +412,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; |
| } |
| @@ -373,7 +420,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; |
| } |
| @@ -462,12 +509,26 @@ 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) |
| + const 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); |
| @@ -476,6 +537,28 @@ void HandleCrashDump(const BreakpadInfo& info) { |
| writer.AddBoundary(); |
| writer.AddPairString("guid", info.guid); |
| writer.AddBoundary(); |
| + if (info.pid > -1) { |
| + uint64_t pid_str_len = my_uint64_len(info.pid); |
| + char* pid_buf = reinterpret_cast<char*>(alllocator.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(); |
| } |
| @@ -612,6 +695,31 @@ void HandleCrashDump(const BreakpadInfo& info) { |
| writer.Flush(); |
| IGNORE_RET(sys_close(temp_file_fd)); |
| +#if defined(OS_ANDROID) |
| + const char* output_msg = "Output crash dump file:"; |
| + __android_log_write(ANDROID_LOG_WARN, "chromium", output_msg); |
|
Yaron
2012/03/26 18:51:15
Why are these printed with "chromium" whereas the
carlosvaldivia
2012/04/03 06:24:47
breakpad_posix is chromium code. The other cl is g
|
| + __android_log_write(ANDROID_LOG_WARN, "chromium", info.filename); |
| + // -1 because we won't need the null terminator on the original filename. |
| + unsigned done_filename_len = info.filename_length -1 + info.pid_str_length; |
| + 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, info.pid_str, info.pid_str_length); |
| + // 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; |
| @@ -693,7 +801,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); |
| } |
| @@ -723,9 +831,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; |
| @@ -811,6 +919,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, |
| @@ -818,6 +927,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; |
| @@ -834,7 +944,12 @@ 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); |
| } |
| - |
| +#if defined(OS_ANDROID) |
| + // In Android we never upload from native code. |
| + new google_breakpad::ExceptionHandler(dumps_path.value().c_str(), NULL, |
| + CrashDoneNoUpload, NULL, |
| + true /* install handlers */); |
| +#else |
| DCHECK(!g_breakpad); |
| if (unattended) { |
| g_breakpad = new google_breakpad::ExceptionHandler( |
| @@ -851,6 +966,7 @@ void EnableCrashDumping(const bool unattended) { |
| NULL, |
| true /* install handlers */); |
| } |
| +#endif |
| } |
| // Non-Browser = Extension, Gpu, Plugins, Ppapi and Renderer |
| @@ -861,7 +977,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; |
| } |
| @@ -936,7 +1052,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; |
| } |
| @@ -944,7 +1060,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; |
| @@ -961,6 +1077,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)) |
| @@ -975,6 +1096,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. |