Commit 28bf600d authored by Joshua Peraza's avatar Joshua Peraza Committed by Commit Bot

Update Crashpad to edbbc4609d2d0703ed73ba9293971f1346234313

e97cf7b29c16 update gyp_crashpad_android.py
2bfd3c4edcff [POSIX] stop logging on ENOENT
12bc30cdf58a Check if attachment directories exist before open
edbbc4609d2d chromeos: fix typo

Change-Id: Icb1d0ca0eaf1aa854ac9fcdd083b75f8ec8ec59e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1809512Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Commit-Queue: Joshua Peraza <jperaza@chromium.org>
Cr-Commit-Position: refs/heads/master@{#697458}
parent 0cc96a73
...@@ -2,7 +2,7 @@ Name: Crashpad ...@@ -2,7 +2,7 @@ Name: Crashpad
Short Name: crashpad Short Name: crashpad
URL: https://crashpad.chromium.org/ URL: https://crashpad.chromium.org/
Version: unknown Version: unknown
Revision: 06fdbdecdc5d94989543bcec197752fdea2fbd9d Revision: edbbc4609d2d0703ed73ba9293971f1346234313
License: Apache 2.0 License: Apache 2.0
License File: crashpad/LICENSE License File: crashpad/LICENSE
Security Critical: yes Security Critical: yes
......
...@@ -28,82 +28,45 @@ def main(args): ...@@ -28,82 +28,45 @@ def main(args):
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description='Set up an Android cross build', description='Set up an Android cross build',
epilog='Additional arguments will be passed to gyp_crashpad.py.') epilog='Additional arguments will be passed to gyp_crashpad.py.')
parser.add_argument('--arch', required=True, help='Target architecture')
parser.add_argument('--api-level', required=True, help='Target API level')
parser.add_argument('--ndk', required=True, help='Standalone NDK toolchain') parser.add_argument('--ndk', required=True, help='Standalone NDK toolchain')
parser.add_argument('--compiler',
default='clang',
choices=('clang', 'gcc'),
help='The compiler to use, clang by default')
(parsed, extra_command_line_args) = parser.parse_known_args(args) (parsed, extra_command_line_args) = parser.parse_known_args(args)
NDK_ERROR=( ndk_bin_dir = os.path.join(parsed.ndk,
'NDK must be a valid standalone NDK toolchain.\n' + 'toolchains',
'See https://developer.android.com/ndk/guides/standalone_toolchain.html') 'llvm',
arch_dirs = glob.glob(os.path.join(parsed.ndk, '*-linux-android*')) 'prebuilt',
if len(arch_dirs) != 1: 'linux-x86_64',
parser.error(NDK_ERROR) 'bin')
if not os.path.exists(ndk_bin_dir):
parser.error("missing toolchain")
arch_triplet = os.path.basename(arch_dirs[0]) ARCH_TO_ARCH_TRIPLET = {
ARCH_TRIPLET_TO_ARCH = { 'arm': 'armv7a-linux-androideabi',
'arm-linux-androideabi': 'arm', 'arm64': 'aarch64-linux-android',
'aarch64-linux-android': 'arm64', 'ia32': 'i686-linux-android',
'i686-linux-android': 'ia32', 'x64': 'x86_64-linux-android',
'x86_64-linux-android': 'x64',
'mipsel-linux-android': 'mips',
'mips64el-linux-android': 'mips64',
} }
if arch_triplet not in ARCH_TRIPLET_TO_ARCH:
parser.error(NDK_ERROR)
arch = ARCH_TRIPLET_TO_ARCH[arch_triplet]
ndk_bin_dir = os.path.join(parsed.ndk, 'bin') clang_prefix = ARCH_TO_ARCH_TRIPLET[parsed.arch] + parsed.api_level
os.environ['CC_target'] = os.path.join(ndk_bin_dir, clang_prefix + '-clang')
os.environ['CXX_target'] = os.path.join(ndk_bin_dir, clang_prefix + '-clang++')
clang_path = os.path.join(ndk_bin_dir, 'clang') extra_args = ['-D', 'android_api_level=' + parsed.api_level]
extra_args = []
if parsed.compiler == 'clang': # ARM only includes 'v7a' in the tool prefix for clang
os.environ['CC_target'] = clang_path tool_prefix = ('arm-linux-androideabi' if parsed.arch == 'arm'
os.environ['CXX_target'] = os.path.join(ndk_bin_dir, 'clang++') else ARCH_TO_ARCH_TRIPLET[parsed.arch])
elif parsed.compiler == 'gcc':
os.environ['CC_target'] = os.path.join(ndk_bin_dir,
'%s-gcc' % arch_triplet)
os.environ['CXX_target'] = os.path.join(ndk_bin_dir,
'%s-g++' % arch_triplet)
# Unlike the Clang build, when using GCC with unified headers, __ANDROID_API__
# isn’t set automatically and must be pushed in to the build. Fish the correct
# value out of the Clang wrapper script. If deprecated headers are in use, the
# Clang wrapper won’t mention __ANDROID_API__, but the standalone toolchain’s
# <android/api-level.h> will #define it for both Clang and GCC.
#
# android_api_level is extracted in this manner even when compiling with Clang
# so that it’s available for use in GYP conditions that need to test the API
# level, but beware that it’ll only be available when unified headers are in
# use.
#
# Unified headers are the way of the future, according to
# https://android.googlesource.com/platform/ndk/+/ndk-r14/CHANGELOG.md and
# https://android.googlesource.com/platform/ndk/+/master/docs/UnifiedHeaders.md.
# Traditional (deprecated) headers have been removed entirely as of NDK r16.
# https://android.googlesource.com/platform/ndk/+/ndk-release-r16/CHANGELOG.md.
with open(clang_path, 'r') as file:
clang_script_contents = file.read()
matches = re.finditer(r'\s-D__ANDROID_API__=([\d]+)\s',
clang_script_contents)
match = next(matches, None)
if match:
android_api = int(match.group(1))
extra_args.extend(['-D', 'android_api_level=%d' % android_api])
if next(matches, None):
raise AssertionError('__ANDROID_API__ defined too many times')
for tool in ('ar', 'nm', 'readelf'): for tool in ('ar', 'nm', 'readelf'):
os.environ['%s_target' % tool.upper()] = ( os.environ['%s_target' % tool.upper()] = (
os.path.join(ndk_bin_dir, '%s-%s' % (arch_triplet, tool))) os.path.join(ndk_bin_dir, '%s-%s' % (tool_prefix, tool)))
return gyp_crashpad.main( return gyp_crashpad.main(
['-D', 'OS=android', ['-D', 'OS=android',
'-D', 'target_arch=%s' % arch, '-D', 'target_arch=%s' % parsed.arch,
'-D', 'clang=%d' % (1 if parsed.compiler == 'clang' else 0), '-D', 'clang=1',
'-f', 'ninja-android'] + '-f', 'ninja-android'] +
extra_args + extra_args +
extra_command_line_args) extra_command_line_args)
......
...@@ -173,8 +173,7 @@ off_t GetFileSize(const base::FilePath& filepath) { ...@@ -173,8 +173,7 @@ off_t GetFileSize(const base::FilePath& filepath) {
void AddAttachmentSize(const base::FilePath& attachments_dir, uint64_t* size) { void AddAttachmentSize(const base::FilePath& attachments_dir, uint64_t* size) {
// Early return if the attachment directory does not exist. // Early return if the attachment directory does not exist.
struct stat statbuf; if (!IsDirectory(attachments_dir, /*allow_symlinks=*/false)) {
if (stat(attachments_dir.value().c_str(), &statbuf) != 0) {
return; return;
} }
DirectoryReader reader; DirectoryReader reader;
...@@ -334,6 +333,9 @@ void CrashReportDatabase::UploadReport::InitializeAttachments() { ...@@ -334,6 +333,9 @@ void CrashReportDatabase::UploadReport::InitializeAttachments() {
base::FilePath attachments_dir = base::FilePath attachments_dir =
static_cast<CrashReportDatabaseGeneric*>(database_)->AttachmentsPath( static_cast<CrashReportDatabaseGeneric*>(database_)->AttachmentsPath(
uuid); uuid);
if (!IsDirectory(attachments_dir, /*allow_symlinks=*/false)) {
return;
}
DirectoryReader reader; DirectoryReader reader;
if (!reader.Open(attachments_dir)) { if (!reader.Open(attachments_dir)) {
return; return;
...@@ -873,7 +875,6 @@ void CrashReportDatabaseGeneric::CleanOrphanedAttachments() { ...@@ -873,7 +875,6 @@ void CrashReportDatabaseGeneric::CleanOrphanedAttachments() {
base::FilePath root_attachments_dir(base_dir_.Append(kAttachmentsDirectory)); base::FilePath root_attachments_dir(base_dir_.Append(kAttachmentsDirectory));
DirectoryReader reader; DirectoryReader reader;
if (!reader.Open(root_attachments_dir)) { if (!reader.Open(root_attachments_dir)) {
LOG(ERROR) << "no attachments dir";
return; return;
} }
...@@ -914,6 +915,9 @@ void CrashReportDatabaseGeneric::CleanOrphanedAttachments() { ...@@ -914,6 +915,9 @@ void CrashReportDatabaseGeneric::CleanOrphanedAttachments() {
void CrashReportDatabaseGeneric::RemoveAttachmentsByUUID(const UUID& uuid) { void CrashReportDatabaseGeneric::RemoveAttachmentsByUUID(const UUID& uuid) {
base::FilePath attachments_dir = AttachmentsPath(uuid); base::FilePath attachments_dir = AttachmentsPath(uuid);
if (!IsDirectory(attachments_dir, /*allow_symlinks=*/false)) {
return;
}
DirectoryReader reader; DirectoryReader reader;
if (!reader.Open(attachments_dir)) { if (!reader.Open(attachments_dir)) {
return; return;
......
...@@ -135,66 +135,38 @@ target_sysroot = "//third_party/linux/sysroot" ...@@ -135,66 +135,38 @@ target_sysroot = "//third_party/linux/sysroot"
### Android ### Android
Crashpad’s Android port is in its early stages. This build relies on This build relies on cross-compilation. It’s possible to develop Crashpad for
cross-compilation. It’s possible to develop Crashpad for Android on any platform Android on any platform that the [Android NDK (Native Development Kit)]
that the [Android NDK (Native Development (https://developer.android.com/ndk/) runs on.
Kit)](https://developer.android.com/ndk/) runs on.
If it’s not already present on your system, [download the NDK package for your If it’s not already present on your system, [download the NDK package for your
system](https://developer.android.com/ndk/downloads/) and expand it to a system](https://developer.android.com/ndk/downloads/) and expand it to a
suitable location. These instructions assume that it’s been expanded to suitable location. These instructions assume that it’s been expanded to
`~/android-ndk-r16`. `~/android-ndk-r20`.
To build Crashpad, portions of the NDK must be reassembled into a [standalone
toolchain](https://developer.android.com/ndk/guides/standalone_toolchain.html).
This is a repackaged subset of the NDK suitable for cross-compiling for a single
Android architecture (such as `arm`, `arm64`, `x86`, and `x86_64`) targeting a
specific [Android API
level](https://source.android.com/source/build-numbers.html). The standalone
toolchain only needs to be built from the NDK one time for each set of options
desired. To build a standalone toolchain targeting 64-bit ARM and API level 21
(Android 5.0 “Lollipop”), run:
```
$ cd ~
$ python android-ndk-r16/build/tools/make_standalone_toolchain.py \
--arch=arm64 --api=21 --install-dir=android-ndk-r16_arm64_api21
```
Note that Chrome uses Android API level 21 for 64-bit platforms and 16 for Note that Chrome uses Android API level 21 for 64-bit platforms and 16 for
32-bit platforms. See Chrome’s 32-bit platforms. See Chrome’s
[`build/config/android/config.gni`](https://chromium.googlesource.com/chromium/src/+/master/build/config/android/config.gni) [`build/config/android/config.gni`](https://chromium.googlesource.com/chromium/src/+/master/build/config/android/config.gni)
which sets `_android_api_level` and `_android64_api_level`. which sets `_android_api_level` and `_android64_api_level`.
To configure a Crashpad build for Android using the standalone toolchain To configure a Crashpad build for Android use `gyp_crashpad_android.py`. This
assembled above, use `gyp_crashpad_android.py`. This script is a wrapper for script is a wrapper for `gyp_crashpad.py` that sets several environment
`gyp_crashpad.py` that sets several environment variables directing the build to variables directing the build to the toolchain, and several GYP options to
the standalone toolchain, and several GYP options to identify an Android build. identify an Android build. This must be done after any `gclient sync`, or
This must be done after any `gclient sync`, or instead of any `gclient runhooks` instead of any `gclient runhooks` operation.
operation.
``` ```
$ cd ~/crashpad/crashpad $ cd ~/crashpad/crashpad
$ python build/gyp_crashpad_android.py \ python build/gyp_crashpad_android.py \
--ndk ~/android-ndk-r16_arm64_api21 \ --ndk ~/usr/lib/android-ndk-r20 --arch arm64 --api-level 21 \
--generator-output out/android_arm64_api21 --generator-output=out/android_arm64_api21 \
``` ```
`gyp_crashpad_android.py` detects the build type based on the characteristics of To build, direct `ninja` to the specific `out` directory chosen by the
the standalone toolchain given in its `--ndk` argument.
`gyp_crashpad_android.py` sets the build up to use Clang by default. It’s also
possible to use GCC by providing the `--compiler=gcc` argument to
`gyp_crashpad_android.py`.
The Android port is incomplete, but targets known to be working include
`crashpad_test`, `crashpad_util`, and their tests. This list will grow over
time. To build, direct `ninja` to the specific `out` directory chosen by the
`--generator-output` argument to `gyp_crashpad_android.py`. `--generator-output` argument to `gyp_crashpad_android.py`.
``` ```
$ ninja -C out/android_arm64_api21/out/Debug \ $ ninja -C out/android_arm64_api21/out/Debug all
crashpad_test_test crashpad_util_test
``` ```
## Testing ## Testing
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
'crash_report_upload_thread.h', 'crash_report_upload_thread.h',
'handler_main.cc', 'handler_main.cc',
'handler_main.h', 'handler_main.h',
'linux/capture_snapshot.cc',
'linux/capture_snapshot.h',
'linux/crash_report_exception_handler.cc', 'linux/crash_report_exception_handler.cc',
'linux/crash_report_exception_handler.h', 'linux/crash_report_exception_handler.h',
'linux/exception_handler_server.cc', 'linux/exception_handler_server.cc',
......
...@@ -644,7 +644,7 @@ int HandlerMain(int argc, ...@@ -644,7 +644,7 @@ int HandlerMain(int argc,
kOptionTraceParentWithException}, kOptionTraceParentWithException},
#endif // OS_LINUX || OS_ANDROID #endif // OS_LINUX || OS_ANDROID
{"url", required_argument, nullptr, kOptionURL}, {"url", required_argument, nullptr, kOptionURL},
#if defined(OS_CHROEMOS) #if defined(OS_CHROMEOS)
{"use-cros-crash-reporter", {"use-cros-crash-reporter",
no_argument, no_argument,
nullptr, nullptr,
......
...@@ -73,7 +73,8 @@ bool MoveFileOrDirectory(const base::FilePath& source, ...@@ -73,7 +73,8 @@ bool MoveFileOrDirectory(const base::FilePath& source,
//! failure. //! failure.
//! //!
//! On POSIX, this function returns `true` if \a path refers to a file that is //! On POSIX, this function returns `true` if \a path refers to a file that is
//! not a symbolic link, directory, or other kind of special file. //! not a symbolic link, directory, or other kind of special file. If this
//! function fails because \a path does not exist, then no message is logged.
//! //!
//! On Windows, this function returns `true` if \a path refers to a file that //! On Windows, this function returns `true` if \a path refers to a file that
//! is not a symbolic link or directory. //! is not a symbolic link or directory.
...@@ -85,6 +86,9 @@ bool IsRegularFile(const base::FilePath& path); ...@@ -85,6 +86,9 @@ bool IsRegularFile(const base::FilePath& path);
//! \brief Determines if a path refers to a directory, logging a message on //! \brief Determines if a path refers to a directory, logging a message on
//! failure. //! failure.
//! //!
//! On POSIX, if this function fails because \a path does not exist, then no
//! message is logged.
//!
//! \param[in] path The path to check. //! \param[in] path The path to check.
//! \param[in] allow_symlinks Whether to allow the final component in the path //! \param[in] allow_symlinks Whether to allow the final component in the path
//! to be a symbolic link to a directory. //! to be a symbolic link to a directory.
......
...@@ -76,7 +76,7 @@ bool MoveFileOrDirectory(const base::FilePath& source, ...@@ -76,7 +76,7 @@ bool MoveFileOrDirectory(const base::FilePath& source,
bool IsRegularFile(const base::FilePath& path) { bool IsRegularFile(const base::FilePath& path) {
struct stat st; struct stat st;
if (lstat(path.value().c_str(), &st) != 0) { if (lstat(path.value().c_str(), &st) != 0) {
PLOG(ERROR) << "stat " << path.value(); PLOG_IF(ERROR, errno != ENOENT) << "stat " << path.value();
return false; return false;
} }
return S_ISREG(st.st_mode); return S_ISREG(st.st_mode);
...@@ -86,11 +86,11 @@ bool IsDirectory(const base::FilePath& path, bool allow_symlinks) { ...@@ -86,11 +86,11 @@ bool IsDirectory(const base::FilePath& path, bool allow_symlinks) {
struct stat st; struct stat st;
if (allow_symlinks) { if (allow_symlinks) {
if (stat(path.value().c_str(), &st) != 0) { if (stat(path.value().c_str(), &st) != 0) {
PLOG(ERROR) << "stat " << path.value(); PLOG_IF(ERROR, errno != ENOENT) << "stat " << path.value();
return false; return false;
} }
} else if (lstat(path.value().c_str(), &st) != 0) { } else if (lstat(path.value().c_str(), &st) != 0) {
PLOG(ERROR) << "lstat " << path.value(); PLOG_IF(ERROR, errno != ENOENT) << "lstat " << path.value();
return false; return false;
} }
return S_ISDIR(st.st_mode); return S_ISDIR(st.st_mode);
......
...@@ -395,8 +395,8 @@ ...@@ -395,8 +395,8 @@
['OS=="linux" or OS=="android"', { ['OS=="linux" or OS=="android"', {
'sources': [ 'sources': [
'net/http_transport_socket.cc', 'net/http_transport_socket.cc',
'util/process_memory_sanitized.cc', 'process/process_memory_sanitized.cc',
'util/process_memory_sanitized.h', 'process/process_memory_sanitized.h',
], ],
}, { # else: OS!="linux" }, { # else: OS!="linux"
'sources!': [ 'sources!': [
......
...@@ -156,7 +156,7 @@ ...@@ -156,7 +156,7 @@
}], }],
['OS=="linux" or OS=="android"', { ['OS=="linux" or OS=="android"', {
'sources': [ 'sources': [
'util/process_memory_sanitized_test.cc', 'process/process_memory_sanitized_test.cc',
], ],
}], }],
['OS!="linux" and OS!="android"', { ['OS!="linux" and OS!="android"', {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment