diff options
author | carlosvaldivia@google.com <carlosvaldivia@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-10 22:52:44 +0000 |
---|---|---|
committer | carlosvaldivia@google.com <carlosvaldivia@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-10 22:52:44 +0000 |
commit | 6653c19c044e724ad9a93248611abd2135d16a1a (patch) | |
tree | 1e036d686937704495302c125d7f3f200a521470 | |
parent | b168ddfb28b4d83213dcfd5974ba64d2dc964030 (diff) | |
download | chromium_src-6653c19c044e724ad9a93248611abd2135d16a1a.zip chromium_src-6653c19c044e724ad9a93248611abd2135d16a1a.tar.gz chromium_src-6653c19c044e724ad9a93248611abd2135d16a1a.tar.bz2 |
Upstream crash changes for android.
Third time is a charm.
Original Reviews:
https://chromiumcodereview.appspot.com/9838033/
http://codereview.chromium.org/9967017
Revert "Revert 131593"
This reverts commit e306ea7f630d4264075913ea3a1a728d98ca9605.
BUG=
TEST=
Review URL: http://codereview.chromium.org/9960072
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131662 0039d316-1c4b-4281-b951-d872f2087c98
21 files changed, 610 insertions, 56 deletions
diff --git a/base/android/build_info.cc b/base/android/build_info.cc new file mode 100644 index 0000000..157ce42 --- /dev/null +++ b/base/android/build_info.cc @@ -0,0 +1,66 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/android/build_info.h" + +#include <string> + +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "base/android/scoped_java_ref.h" +#include "base/logging.h" +#include "base/memory/singleton.h" +#include "jni/build_info_jni.h" + +namespace base { +namespace android { + +BuildInfo::BuildInfo() { + JNIEnv* env = AttachCurrentThread(); + + // The const char* pointers initialized below will be owned by the + // resultant BuildInfo. + std::string device_str = + ConvertJavaStringToUTF8(Java_BuildInfo_getDevice(env)); + device_ = strdup(device_str.c_str()); + + std::string model_str = + ConvertJavaStringToUTF8(Java_BuildInfo_getDeviceModel(env)); + model_ = strdup(model_str.c_str()); + + std::string brand_str = + ConvertJavaStringToUTF8(Java_BuildInfo_getBrand(env)); + brand_ = strdup(brand_str.c_str()); + + std::string android_build_id_str = + ConvertJavaStringToUTF8(Java_BuildInfo_getAndroidBuildId(env)); + android_build_id_ = strdup(android_build_id_str.c_str()); + + std::string android_build_fp_str = + ConvertJavaStringToUTF8(Java_BuildInfo_getAndroidBuildFingerprint(env)); + android_build_fp_ = strdup(android_build_fp_str.c_str()); + + jobject app_context = GetApplicationContext(); + std::string package_version_code_str = + ConvertJavaStringToUTF8(Java_BuildInfo_getPackageVersionCode( + env, app_context)); + package_version_code_ = strdup(package_version_code_str.c_str()); + + std::string package_version_name_str = + ConvertJavaStringToUTF8( + Java_BuildInfo_getPackageVersionName(env, app_context)); + package_version_name_ = strdup(package_version_name_str.c_str()); +} + +// static +BuildInfo* BuildInfo::GetInstance() { + return Singleton<BuildInfo, LeakySingletonTraits<BuildInfo> >::get(); +} + +bool RegisterBuildInfo(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace android +} // namespace base diff --git a/base/android/build_info.h b/base/android/build_info.h new file mode 100644 index 0000000..95a0cf5 --- /dev/null +++ b/base/android/build_info.h @@ -0,0 +1,88 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ANDROID_BUILD_INFO_H_ +#define BASE_ANDROID_BUILD_INFO_H_ + +#include <jni.h> + +#include <string> + +#include "base/memory/singleton.h" + +namespace base { +namespace android { + +// BuildInfo is a singleton class that stores android build and device +// information. It will be called from Android specific java code and gets used +// primarily in crash reporting. +class BuildInfo { + public: + + ~BuildInfo() {} + + // Static factory method for getting the singleton BuildInfo instance. + // Note that ownership is not conferred on the caller and the BuildInfo in + // question isn't actually freed until shutdown. This is ok because there + // should only be one instance of BuildInfo ever created. + static BuildInfo* GetInstance(); + + // Const char* is used instead of std::strings because these values must be + // available even if the process is in a crash state. Sadly + // std::string.c_str() doesn't guarantee that memory won't be allocated when + // it is called. + const char* device() const { + return device_; + } + + const char* model() const { + return model_; + } + + const char* brand() const { + return brand_; + } + + const char* android_build_id() const { + return android_build_id_; + } + + const char* android_build_fp() const { + return android_build_fp_; + } + + const char* package_version_code() const { + return package_version_code_; + } + + const char* package_version_name() const { + return package_version_name_; + } + + private: + BuildInfo(); + + friend struct DefaultSingletonTraits<BuildInfo>; + + // Const char* is used instead of std::strings because these values must be + // available even if the process is in a crash state. Sadly + // std::string.c_str() doesn't guarantee that memory won't be allocated when + // it is called. + char* device_; + char* model_; + char* brand_; + char* android_build_id_; + char* android_build_fp_; + char* package_version_code_; + char* package_version_name_; + + DISALLOW_COPY_AND_ASSIGN(BuildInfo); +}; + +bool RegisterBuildInfo(JNIEnv* env); + +} // namespace android +} // namespace base + +#endif // BASE_ANDROID_BUILD_INFO_H_ diff --git a/base/android/java/org/chromium/base/BuildInfo.java b/base/android/java/org/chromium/base/BuildInfo.java new file mode 100644 index 0000000..75748ac --- /dev/null +++ b/base/android/java/org/chromium/base/BuildInfo.java @@ -0,0 +1,88 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Build; +import android.util.Log; + +/** + * BuildInfo is a utility class providing easy access to {@link PackageInfo} + * information. This is primarly of use for accessesing package information + * from native code. + */ +public class BuildInfo { + private static final String TAG = "BuildInfo"; + private static final int MAX_FINGERPRINT_LENGTH = 128; + + /** + * BuildInfo is a static utility class and therefore should'nt be + * instantiated. + */ + private BuildInfo() { + } + + @CalledByNative + public static String getDevice() { + return Build.DEVICE; + } + + @CalledByNative + public static String getBrand() { + return Build.BRAND; + } + + @CalledByNative + public static String getAndroidBuildId() { + return Build.ID; + } + + /** + * @return The build fingerprint for the current Android install. The value is truncated to a + * 128 characters as this is used for crash and UMA reporting, which should avoid huge + * strings. + */ + @CalledByNative + public static String getAndroidBuildFingerprint() { + return Build.FINGERPRINT.substring( + 0, Math.min(Build.FINGERPRINT.length(), MAX_FINGERPRINT_LENGTH)); + } + + @CalledByNative + public static String getDeviceModel() { + return Build.MODEL; + } + + @CalledByNative + public static String getPackageVersionCode(Context context) { + String msg = "versionCode not available."; + try { + PackageManager pm = context.getPackageManager(); + PackageInfo pi = pm.getPackageInfo("com.android.chrome", 0); + msg = "" + pi.versionCode; + } catch (NameNotFoundException e) { + Log.d(TAG, msg); + } + return msg; + + } + + @CalledByNative + public static String getPackageVersionName(Context context) { + String msg = "versionName not available"; + try { + PackageManager pm = context.getPackageManager(); + PackageInfo pi = pm.getPackageInfo("com.android.chrome", 0); + msg = pi.versionName; + } catch (NameNotFoundException e) { + Log.d(TAG, msg); + } + return msg; + } + +} diff --git a/base/base.gyp b/base/base.gyp index 4225f7e..c6058873 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -122,10 +122,12 @@ 'action_name': 'generate_jni_headers', 'inputs': [ 'android/jni_generator/jni_generator.py', + 'android/java/org/chromium/base/BuildInfo.java', 'android/java/org/chromium/base/PathUtils.java', 'android/java/org/chromium/base/SystemMessageHandler.java', ], 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/base/jni/build_info_jni.h', '<(SHARED_INTERMEDIATE_DIR)/base/jni/path_utils_jni.h', '<(SHARED_INTERMEDIATE_DIR)/base/jni/system_message_handler_jni.h', ], diff --git a/base/base.gypi b/base/base.gypi index facb472..48812a0 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -21,6 +21,8 @@ 'third_party/nspr/prtime.h', 'third_party/nspr/prcpucfg_linux.h', 'third_party/xdg_mime/xdgmime.h', + 'android/build_info.cc', + 'android/build_info.h', 'android/scoped_java_ref.cc', 'android/scoped_java_ref.h', 'android/jni_android.cc', diff --git a/breakpad/breakpad.gyp b/breakpad/breakpad.gyp index ca561d8..6ecab03 100644 --- a/breakpad/breakpad.gyp +++ b/breakpad/breakpad.gyp @@ -217,12 +217,159 @@ }, ], }], - [ 'OS=="linux"', { + [ 'OS=="linux" or OS=="android"', { 'conditions': [ + ['OS=="android"', { + 'defines': [ + '__ANDROID__', + ], + }], # Tools needed for archiving build symbols. ['linux_breakpad==1', { 'targets': [ { + 'target_name': 'minidump_stackwalk', + 'type': 'executable', + + # This uses the system libcurl, so don't use the default 32-bit + # compile flags when building on a 64-bit machine. + 'variables': { + 'host_arch': '<!(uname -m)', + }, + 'conditions': [ + ['host_arch=="x86_64"', { + 'cflags!': ['-m32', '-march=pentium4', '-msse2', + '-mfpmath=sse'], + 'ldflags!': ['-m32'], + 'cflags': ['-O2'], + 'include_dirs!': ['/usr/include32'], + }], + ['OS=="android"', { + 'toolsets': [ 'host' ], + }], + ], + 'include_dirs': [ + 'src', + 'src/third_party', + '..', + ], + 'sources': [ + 'src/google_breakpad/procesor/call_stack.h', + 'src/processor/minidump_stackwalk.cc', + 'src/processor/stackwalker.cc', + 'src/processor/stackwalker.h', + 'src/processor/basic_code_module.h', + 'src/processor/basic_code_modules.cc', + 'src/processor/basic_code_modules.h', + 'src/processor/basic_source_line_resolver.cc', + 'src/processor/basic_source_line_resolver.h', + 'src/processor/binarystream.cc', + 'src/processor/binarystream.h', + 'src/processor/call_stack.cc', + 'src/processor/cfi_frame_info.cc', + 'src/processor/cfi_frame_info.h', + 'src/processor/disassembler_x86.cc', + 'src/processor/disassembler_x86.h', + 'src/processor/exploitability.cc', + 'src/processor/exploitability.h', + 'src/processor/exploitability_win.cc', + 'src/processor/exploitability_win.h', + 'src/processor/logging.cc', + 'src/processor/logging.h', + 'src/processor/minidump.cc', + 'src/processor/minidump.h', + 'src/processor/minidump_processor.cc', + 'src/processor/minidump_processor.h', + 'src/processor/pathname_stripper.cc', + 'src/processor/pathname_stripper.h', + 'src/processor/process_state.cc', + 'src/processor/process_state.h', + 'src/processor/simple_symbol_supplier.cc', + 'src/processor/simple_symbol_supplier.h', + 'src/processor/source_line_resolver_base.cc', + 'src/processor/source_line_resolver_base.h', + 'src/processor/stackwalker.cc', + 'src/processor/stackwalker.h', + 'src/processor/stackwalker_amd64.cc', + 'src/processor/stackwalker_amd64.h', + 'src/processor/stackwalker_arm.cc', + 'src/processor/stackwalker_arm.h', + 'src/processor/stackwalker_ppc.cc', + 'src/processor/stackwalker_ppc.h', + 'src/processor/stackwalker_sparc.cc', + 'src/processor/stackwalker_sparc.h', + 'src/processor/stackwalker_x86.cc', + 'src/processor/stackwalker_x86.h', + 'src/processor/tokenize.cc', + 'src/processor/tokenize.h', + # libdisasm + 'src/third_party/libdisasm/ia32_implicit.c', + 'src/third_party/libdisasm/ia32_implicit.h', + 'src/third_party/libdisasm/ia32_insn.c', + 'src/third_party/libdisasm/ia32_insn.h', + 'src/third_party/libdisasm/ia32_invariant.c', + 'src/third_party/libdisasm/ia32_invariant.h', + 'src/third_party/libdisasm/ia32_modrm.c', + 'src/third_party/libdisasm/ia32_modrm.h', + 'src/third_party/libdisasm/ia32_opcode_tables.c', + 'src/third_party/libdisasm/ia32_opcode_tables.h', + 'src/third_party/libdisasm/ia32_operand.c', + 'src/third_party/libdisasm/ia32_operand.h', + 'src/third_party/libdisasm/ia32_reg.c', + 'src/third_party/libdisasm/ia32_reg.h', + 'src/third_party/libdisasm/ia32_settings.c', + 'src/third_party/libdisasm/ia32_settings.h', + 'src/third_party/libdisasm/libdis.h', + 'src/third_party/libdisasm/qword.h', + 'src/third_party/libdisasm/x86_disasm.c', + 'src/third_party/libdisasm/x86_format.c', + 'src/third_party/libdisasm/x86_imm.c', + 'src/third_party/libdisasm/x86_imm.h', + 'src/third_party/libdisasm/x86_insn.c', + 'src/third_party/libdisasm/x86_misc.c', + 'src/third_party/libdisasm/x86_operand_list.c', + 'src/third_party/libdisasm/x86_operand_list.h', + ], + }, + { + 'target_name': 'minidump_dump', + 'type': 'executable', + # This uses the system libcurl, so don't use the default 32-bit + # compile flags when building on a 64-bit machine. + 'variables': { + 'host_arch': '<!(uname -m)', + }, + 'conditions': [ + ['host_arch=="x86_64"', { + 'cflags!': ['-m32', '-march=pentium4', '-msse2', + '-mfpmath=sse'], + 'ldflags!': ['-m32'], + 'cflags': ['-O2'], + 'include_dirs!': ['/usr/include32'], + }], + ['OS=="android"', { + 'toolsets': [ 'host' ], + }], + ], + 'sources': [ + 'src/processor/minidump_dump.cc', + 'src/processor/basic_code_module.h', + 'src/processor/basic_code_modules.h', + 'src/processor/basic_code_modules.cc', + 'src/processor/logging.h', + 'src/processor/logging.cc', + 'src/processor/minidump.h', + 'src/processor/minidump.cc', + 'src/processor/pathname_stripper.h', + 'src/processor/pathname_stripper.cc', + ], + 'include_dirs': [ + 'src', + 'src/third_party', + '..', + ], + }, + { 'target_name': 'symupload', 'type': 'executable', @@ -239,6 +386,9 @@ 'cflags': ['-O2'], 'include_dirs!': ['/usr/include32'], }], + ['OS=="android"', { + 'toolsets': [ 'host' ], + }], ], 'sources': [ @@ -258,6 +408,11 @@ { 'target_name': 'dump_syms', 'type': 'executable', + 'conditions': [ + ['OS=="android"', { + 'toolsets': [ 'host' ], + }], + ], # dwarf2reader.cc uses dynamic_cast. Because we don't typically # don't support RTTI, we enable it for this single target. Since @@ -358,6 +513,12 @@ ['target_arch=="arm"', { 'cflags': ['-Wa,-mimplicit-it=always'], }], + ['OS=="android"', { + 'sources!':[ + 'src/common/linux/elf_core_dump.cc', + 'src/common/linux/elf_core_dump.h', + ], + }], ], 'link_settings': { diff --git a/build/filename_rules.gypi b/build/filename_rules.gypi index d5a5a65..162e9b2 100644 --- a/build/filename_rules.gypi +++ b/build/filename_rules.gypi @@ -29,6 +29,12 @@ ['exclude', '(^|/)linux/'], ], }], + ['OS!="android" and OS!="linux" and OS!="openbsd" and OS!="freebsd"', { + 'sources/': [ + ['exclude', '_linuxish(_unittest)?\\.(h|cc)$'], + ['exclude', '(^|/)linuxish/'], + ], + }], ['OS!="android"', { 'sources/': [ ['exclude', '_android(_unittest)?\\.cc$'], diff --git a/chrome/app/DEPS b/chrome/app/DEPS index 414df54..680eaa9 100644 --- a/chrome/app/DEPS +++ b/chrome/app/DEPS @@ -13,4 +13,5 @@ include_rules = [ "+policy", # For generated headers and source "+sandbox", "+tools/memory_watcher", + "+third_party/lss/linux_syscall_support.h", ] diff --git a/chrome/app/breakpad_linux.cc b/chrome/app/breakpad_linuxish.cc index 17b4e8ae..f058ee1 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 defined(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 WriteLog(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)); + WriteLog(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)); + WriteLog(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)); + WriteLog(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); + WriteLog(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); + WriteLog(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); + WriteLog(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:"; + WriteLog(output_msg, my_strlen(output_msg)); + unsigned filename_len = my_strlen(info.filename); + WriteLog(info.filename, filename_len); + // -1 because we won't need the null terminator on the original filename. + size_t done_filename_len = 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 to signal 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); + WriteLog(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); + WriteLog(msg, sizeof(msg) - 1); + WriteLog(id_buf, my_strlen(id_buf)); + WriteLog("\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,8 +964,9 @@ static bool CrashDoneUpload(const char* dump_path, bool succeeded) { return CrashDone(dump_path, minidump_id, true, succeeded); } +#endif -void EnableCrashDumping(const bool unattended) { +void EnableCrashDumping(bool unattended) { g_is_crash_reporter_enabled = true; FilePath tmp_path("/tmp"); @@ -860,8 +981,10 @@ 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) + unattended = true; +#endif if (unattended) { g_breakpad = new google_breakpad::ExceptionHandler( dumps_path.value().c_str(), @@ -887,7 +1010,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); + WriteLog(msg, sizeof(msg)-1); return false; } @@ -964,7 +1087,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); + WriteLog(errmsg, sizeof(errmsg)-1); IGNORE_RET(sys_close(fds[1])); return false; } @@ -972,7 +1095,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); + WriteLog(errmsg, sizeof(errmsg)-1); } return true; @@ -989,6 +1112,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 +1131,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. diff --git a/chrome/app/breakpad_linux.h b/chrome/app/breakpad_linuxish.h index 7c20514..9a7e2fd 100644 --- a/chrome/app/breakpad_linux.h +++ b/chrome/app/breakpad_linuxish.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_APP_BREAKPAD_LINUX_H_ -#define CHROME_APP_BREAKPAD_LINUX_H_ +#ifndef CHROME_APP_BREAKPAD_LINUXISH_H_ +#define CHROME_APP_BREAKPAD_LINUXISH_H_ #pragma once #include "base/basictypes.h" @@ -28,8 +28,9 @@ struct BreakpadInfo { bool upload; // Whether to upload or save crash dump. uint64_t process_start_time; // Uptime of the crashing process. size_t oom_size; // Amount of memory requested if OOM. + uint64_t pid; // PID where applicable. }; extern void HandleCrashDump(const BreakpadInfo& info); -#endif // CHROME_APP_BREAKPAD_LINUX_H_ +#endif // CHROME_APP_BREAKPAD_LINUXISH_H_ diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index 5a492d9..c03b310 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc @@ -89,7 +89,7 @@ #endif #if defined(USE_LINUX_BREAKPAD) -#include "chrome/app/breakpad_linux.h" +#include "chrome/app/breakpad_linuxish.h" #endif base::LazyInstance<chrome::ChromeContentBrowserClient> diff --git a/chrome/browser/chrome_browser_main_linux.cc b/chrome/browser/chrome_browser_main_linux.cc index 2ba1b41..1354ffb 100644 --- a/chrome/browser/chrome_browser_main_linux.cc +++ b/chrome/browser/chrome_browser_main_linux.cc @@ -8,7 +8,7 @@ #include <stdlib.h> #include "base/linux_util.h" -#include "chrome/app/breakpad_linux.h" +#include "chrome/app/breakpad_linuxish.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/common/env_vars.h" #include "chrome/common/pref_names.h" diff --git a/chrome/browser/chrome_browser_main_x11.cc b/chrome/browser/chrome_browser_main_x11.cc index 55968ca..fbd832f 100644 --- a/chrome/browser/chrome_browser_main_x11.cc +++ b/chrome/browser/chrome_browser_main_x11.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -15,7 +15,7 @@ #include "ui/base/x/x11_util_internal.h" #if defined(USE_LINUX_BREAKPAD) -#include "chrome/app/breakpad_linux.h" +#include "chrome/app/breakpad_linuxish.h" #endif using content::BrowserThread; diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index d6c8557..b11823e 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc @@ -135,9 +135,9 @@ #include "chrome/browser/chrome_browser_main_extra_parts_ash.h" #endif -#if defined(OS_LINUX) || defined(OS_OPENBSD) +#if defined(OS_LINUX) || defined(OS_OPENBSD) || defined(OS_ANDROID) #include "base/linux_util.h" -#include "chrome/browser/crash_handler_host_linux.h" +#include "chrome/browser/crash_handler_host_linuxish.h" #endif #if defined(TOOLKIT_GTK) @@ -1611,11 +1611,6 @@ bool ChromeContentBrowserClient::AllowSocketAPI( #if defined(OS_POSIX) && !defined(OS_MACOSX) int ChromeContentBrowserClient::GetCrashSignalFD( const CommandLine& command_line) { -#if defined(OS_ANDROID) - // TODO(carlosvaldivia): Upstream breakpad code for Android and remove this - // fork. http://crbug.com/113560 - NOTIMPLEMENTED(); -#else if (command_line.HasSwitch(switches::kExtensionProcess)) { ExtensionCrashHandlerHostLinux* crash_handler = ExtensionCrashHandlerHostLinux::GetInstance(); @@ -1636,7 +1631,6 @@ int ChromeContentBrowserClient::GetCrashSignalFD( if (process_type == switches::kGpuProcess) return GpuCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket(); -#endif // defined(OS_ANDROID) return -1; } diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index d308b30..075e016 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc @@ -50,7 +50,7 @@ #include "ui/base/l10n/l10n_util.h" #if defined(USE_LINUX_BREAKPAD) -#include "chrome/app/breakpad_linux.h" +#include "chrome/app/breakpad_linuxish.h" #endif using content::BrowserThread; diff --git a/chrome/browser/crash_handler_host_linux.cc b/chrome/browser/crash_handler_host_linuxish.cc index c385406..8b393fe 100644 --- a/chrome/browser/crash_handler_host_linux.cc +++ b/chrome/browser/crash_handler_host_linuxish.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/crash_handler_host_linux.h" +#include "chrome/browser/crash_handler_host_linuxish.h" #include <stdint.h> #include <stdlib.h> @@ -27,11 +27,17 @@ #include "breakpad/src/client/linux/handler/exception_handler.h" #include "breakpad/src/client/linux/minidump_writer/linux_dumper.h" #include "breakpad/src/client/linux/minidump_writer/minidump_writer.h" -#include "chrome/app/breakpad_linux.h" +#include "chrome/app/breakpad_linuxish.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/env_vars.h" #include "content/public/browser/browser_thread.h" +#if defined(OS_ANDROID) +#include <sys/linux-syscalls.h> + +#define SYS_read __NR_read +#endif + using content::BrowserThread; using google_breakpad::ExceptionHandler; @@ -318,8 +324,12 @@ void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) { info->distro_length = strlen(distro); info->distro = distro; - +#if defined(OS_ANDROID) + // Nothing gets uploaded in android. + info->upload = false; +#else info->upload = (getenv(env_vars::kHeadless) == NULL); +#endif info->process_start_time = uptime; info->oom_size = oom_size; @@ -361,6 +371,7 @@ void CrashHandlerHostLinux::WriteDumpFile(BreakpadInfo* info, minidump_filename.copy(minidump_filename_str, minidump_filename.length()); minidump_filename_str[minidump_filename.length()] = '\0'; info->filename = minidump_filename_str; + info->pid = crashing_pid; BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, diff --git a/chrome/browser/crash_handler_host_linux.h b/chrome/browser/crash_handler_host_linuxish.h index 55ef624..80c06d9 100644 --- a/chrome/browser/crash_handler_host_linux.h +++ b/chrome/browser/crash_handler_host_linuxish.h @@ -1,9 +1,9 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CRASH_HANDLER_HOST_LINUX_H_ -#define CHROME_BROWSER_CRASH_HANDLER_HOST_LINUX_H_ +#ifndef CHROME_BROWSER_CRASH_HANDLER_HOST_LINUXISH_H_ +#define CHROME_BROWSER_CRASH_HANDLER_HOST_LINUXISH_H_ #pragma once #include "base/compiler_specific.h" @@ -26,11 +26,11 @@ class Thread; template <typename T> struct DefaultSingletonTraits; // This is the base class for singleton objects which crash dump renderers and -// plugins on Linux. We perform the crash dump from the browser because it -// allows us to be outside the sandbox. +// plugins on Linux or Android. We perform the crash dump from the browser +// because it allows us to be outside the sandbox. // -// PluginCrashHandlerHostLinux and RendererCrashHandlerHostLinux are singletons -// that handle plugin and renderer crashes, respectively. +// PluginCrashHandlerHostLinux and RendererCrashHandlerHostLinux are +// singletons that handle plugin and renderer crashes, respectively. // // Processes signal that they need to be dumped by sending a datagram over a // UNIX domain socket. All processes of the same type share the client end of @@ -181,4 +181,4 @@ class RendererCrashHandlerHostLinux : public CrashHandlerHostLinux { DISALLOW_COPY_AND_ASSIGN(RendererCrashHandlerHostLinux); }; -#endif // CHROME_BROWSER_CRASH_HANDLER_HOST_LINUX_H_ +#endif // CHROME_BROWSER_CRASH_HANDLER_HOST_LINUXISH_H_ diff --git a/chrome/browser/crash_handler_host_linux_stub.cc b/chrome/browser/crash_handler_host_linuxish_stub.cc index 8685846..8101c8f 100644 --- a/chrome/browser/crash_handler_host_linux_stub.cc +++ b/chrome/browser/crash_handler_host_linuxish_stub.cc @@ -1,11 +1,11 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This is a stub file which is compiled in when we are building without // breakpad support. -#include "chrome/browser/crash_handler_host_linux.h" +#include "chrome/browser/crash_handler_host_linuxish.h" #include "base/memory/singleton.h" diff --git a/chrome/browser/ui/gtk/first_run_dialog.cc b/chrome/browser/ui/gtk/first_run_dialog.cc index f91b3d9..ddbbeff 100644 --- a/chrome/browser/ui/gtk/first_run_dialog.cc +++ b/chrome/browser/ui/gtk/first_run_dialog.cc @@ -29,7 +29,7 @@ #include "ui/base/resource/resource_bundle.h" #if defined(USE_LINUX_BREAKPAD) -#include "chrome/app/breakpad_linux.h" +#include "chrome/app/breakpad_linuxish.h" #endif #if defined(GOOGLE_CHROME_BUILD) diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index ea3fd8f..be4472b 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -932,7 +932,6 @@ 'browser/content_settings/tab_specific_content_settings.h', 'browser/cookies_tree_model.cc', 'browser/cookies_tree_model.h', - 'browser/crash_handler_host_linux.h', 'browser/crash_upload_list.cc', 'browser/crash_upload_list.h', 'browser/crash_upload_list_win.cc', @@ -4339,12 +4338,15 @@ '-lXss', ], }, + }], + ['os_posix == 1 and OS != "mac"', { + 'sources': [ 'browser/crash_handler_host_linuxish.h', ], 'conditions': [ ['linux_breakpad==1', { 'sources': [ - 'app/breakpad_linux.cc', - 'app/breakpad_linux.h', - 'browser/crash_handler_host_linux.cc', + 'app/breakpad_linuxish.cc', + 'app/breakpad_linuxish.h', + 'browser/crash_handler_host_linuxish.cc', ], 'dependencies': [ '../breakpad/breakpad.gyp:breakpad_client', @@ -4352,13 +4354,13 @@ 'common', ], 'include_dirs': [ - # breakpad_linux.cc uses generated file_version_info_linux.h. + # breakpad_linuxish.cc uses generated file_version_info_linux.h. '<(SHARED_INTERMEDIATE_DIR)', '../breakpad/src', ], }, { # linux_breakpad==0 'sources': [ - 'browser/crash_handler_host_linux_stub.cc', + 'browser/crash_handler_host_linuxish_stub.cc', ], }], ], diff --git a/chrome/common/logging_chrome_uitest.cc b/chrome/common/logging_chrome_uitest.cc index 8c87ff4..551fbd9 100644 --- a/chrome/common/logging_chrome_uitest.cc +++ b/chrome/common/logging_chrome_uitest.cc @@ -66,7 +66,8 @@ TEST_F(ChromeLoggingTest, EnvironmentLogFileName) { RestoreEnvironmentVariable(); } -#if defined(OS_LINUX) && (!defined(NDEBUG) || !defined(USE_LINUX_BREAKPAD)) +#if (defined(OS_LINUX) || defined(OS_ANDROID)) \ + && (!defined(NDEBUG) || !defined(USE_LINUX_BREAKPAD)) // On Linux in Debug mode, Chrome generates a SIGTRAP. // we do not catch SIGTRAPs, thus no crash dump. // This also does not work if Breakpad is disabled. @@ -149,7 +150,7 @@ class RendererCrashTest : public UITest { } }; -#if defined(OS_LINUX) && !defined(USE_LINUX_BREAKPAD) +#if (defined(OS_LINUX) || defined(OS_ANDROID)) && !defined(USE_LINUX_BREAKPAD) // On Linux, do not expect a crash dump if Breakpad is disabled. #define EXPECTED_CRASH_CRASHES 0 #else |