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. |