android: Launch Crashpad with /system/bin/linker on Q
This adds a small executable, libcrashpad_handler_trampoline.so, to Monochrome, Trichrome, and SystemWebView. The trampoline loads the remaining Crashpad handler code from the main native library, which must export `CrashpadHandlerMain()`. All three packages will continue to use /system/bin/app_process to launch Crashpad on P-. Note on static_initializers.gni: There aren't any real, new static initializers. The increased count is due to the addition of the new object. Static initializers are counted by measuring the size of each object's .init_array and dividing by the object's pointer size. libcrashpad_handler_trampoline.so has two invalid slots which are ignored by the loader: readelf -x .init_array libcrashpad_handler_trampoline.so Hex dump of section '.init_array': 0x00001008 ffffffff 00000000 Bug: 928422 Change-Id: Iba56cd6feda73ebc91f6758724d823e48b5c6e8f Reviewed-on: https://chromium-review.googlesource.com/c/1454078 Reviewed-by: Richard Coles <torne@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org> Reviewed-by: Andrew Grieve <agrieve@chromium.org> Commit-Queue: Joshua Peraza <jperaza@chromium.org> Cr-Commit-Position: refs/heads/master@{#635269}
This commit is contained in:

committed by
Commit Bot

parent
7e453e2b3e
commit
54c5c662fc
android_webview
base/android
build/android/gyp
chrome/android
components/crash/content/app
@ -32,8 +32,18 @@ template("system_webview_apk_tmpl") {
|
||||
|
||||
if (!_use_trichrome_library) {
|
||||
shared_libraries = [ "//android_webview:libwebviewchromium" ]
|
||||
deps += [
|
||||
"//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
|
||||
]
|
||||
loadable_modules = [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
|
||||
|
||||
if (build_apk_secondary_abi && android_64bit_target_cpu) {
|
||||
secondary_abi_shared_libraries = [ "//android_webview:libwebviewchromium($android_secondary_abi_toolchain)" ]
|
||||
_trampoline = "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline($android_secondary_abi_toolchain)"
|
||||
deps += [ _trampoline ]
|
||||
_secondary_out_dir = get_label_info(_trampoline, "root_out_dir")
|
||||
secondary_abi_loadable_modules =
|
||||
[ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ]
|
||||
}
|
||||
} else {
|
||||
uncompress_shared_libraries = true
|
||||
@ -42,6 +52,11 @@ template("system_webview_apk_tmpl") {
|
||||
# architecture.
|
||||
if (android_64bit_target_cpu) {
|
||||
shared_libraries = [ "//android_webview:monochrome" ]
|
||||
deps += [
|
||||
"//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
|
||||
]
|
||||
loadable_modules = [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
|
||||
|
||||
if (build_apk_secondary_abi) {
|
||||
secondary_native_lib_placeholders = [ "libdummy.so" ]
|
||||
}
|
||||
|
@ -75,7 +75,8 @@ BuildInfo::BuildInfo(const std::vector<std::string>& params)
|
||||
firebase_app_id_(StrDupParam(params, 18)),
|
||||
custom_themes_(StrDupParam(params, 19)),
|
||||
resources_version_(StrDupParam(params, 20)),
|
||||
extracted_file_suffix_(params[21]) {}
|
||||
extracted_file_suffix_(params[21]),
|
||||
is_at_least_q_(GetIntParam(params, 22)) {}
|
||||
|
||||
// static
|
||||
BuildInfo* BuildInfo::GetInstance() {
|
||||
|
@ -122,6 +122,8 @@ class BASE_EXPORT BuildInfo {
|
||||
return sdk_int_;
|
||||
}
|
||||
|
||||
bool is_at_least_q() const { return is_at_least_q_; }
|
||||
|
||||
private:
|
||||
friend struct BuildInfoSingletonTraits;
|
||||
|
||||
@ -154,6 +156,7 @@ class BASE_EXPORT BuildInfo {
|
||||
const char* const resources_version_;
|
||||
// Not needed by breakpad.
|
||||
const std::string extracted_file_suffix_;
|
||||
const bool is_at_least_q_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BuildInfo);
|
||||
};
|
||||
|
@ -57,13 +57,29 @@ public class BuildInfo {
|
||||
BuildInfo buildInfo = getInstance();
|
||||
String hostPackageName = ContextUtils.getApplicationContext().getPackageName();
|
||||
return new String[] {
|
||||
Build.BRAND, Build.DEVICE, Build.ID, Build.MANUFACTURER, Build.MODEL,
|
||||
String.valueOf(Build.VERSION.SDK_INT), Build.TYPE, Build.BOARD, hostPackageName,
|
||||
String.valueOf(buildInfo.hostVersionCode), buildInfo.hostPackageLabel,
|
||||
buildInfo.packageName, String.valueOf(buildInfo.versionCode), buildInfo.versionName,
|
||||
buildInfo.androidBuildFingerprint, buildInfo.gmsVersionCode,
|
||||
buildInfo.installerPackageName, buildInfo.abiString, BuildConfig.FIREBASE_APP_ID,
|
||||
buildInfo.customThemes, buildInfo.resourcesVersion, buildInfo.extractedFileSuffix,
|
||||
Build.BRAND,
|
||||
Build.DEVICE,
|
||||
Build.ID,
|
||||
Build.MANUFACTURER,
|
||||
Build.MODEL,
|
||||
String.valueOf(Build.VERSION.SDK_INT),
|
||||
Build.TYPE,
|
||||
Build.BOARD,
|
||||
hostPackageName,
|
||||
String.valueOf(buildInfo.hostVersionCode),
|
||||
buildInfo.hostPackageLabel,
|
||||
buildInfo.packageName,
|
||||
String.valueOf(buildInfo.versionCode),
|
||||
buildInfo.versionName,
|
||||
buildInfo.androidBuildFingerprint,
|
||||
buildInfo.gmsVersionCode,
|
||||
buildInfo.installerPackageName,
|
||||
buildInfo.abiString,
|
||||
BuildConfig.FIREBASE_APP_ID,
|
||||
buildInfo.customThemes,
|
||||
buildInfo.resourcesVersion,
|
||||
buildInfo.extractedFileSuffix,
|
||||
isAtLeastQ() ? "1" : "0",
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ def _AddNativeLibraries(out_apk, native_libs, android_abi, uncompress):
|
||||
if (uncompress and os.path.splitext(basename)[1] == '.so'
|
||||
and 'android_linker' not in basename
|
||||
and (not has_crazy_linker or 'clang_rt' not in basename)
|
||||
and 'crashpad_handler' not in basename):
|
||||
and (not has_crazy_linker or 'crashpad_handler' not in basename)):
|
||||
compress = False
|
||||
# Add prefix to prevent android install from extracting upon install.
|
||||
if has_crazy_linker:
|
||||
|
@ -42,7 +42,9 @@ def main():
|
||||
options = parser.parse_args()
|
||||
|
||||
# JNI_OnLoad is always exported.
|
||||
symbol_list = ['JNI_OnLoad']
|
||||
# CrashpadHandlerMain() is the entry point to the Crashpad handler, required
|
||||
# for libcrashpad_handler_trampoline.so.
|
||||
symbol_list = ['CrashpadHandlerMain', 'JNI_OnLoad']
|
||||
|
||||
if options.export_java_symbols:
|
||||
symbol_list.append('Java_*')
|
||||
|
@ -348,6 +348,30 @@ template("monochrome_public_common_apk_or_module_tmpl") {
|
||||
if (!defined(deps)) {
|
||||
deps = []
|
||||
}
|
||||
if (!defined(loadable_modules)) {
|
||||
loadable_modules = []
|
||||
}
|
||||
if (!defined(secondary_abi_loadable_modules)) {
|
||||
secondary_abi_loadable_modules = []
|
||||
}
|
||||
|
||||
if (!is_trichrome) {
|
||||
deps += [
|
||||
"//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
|
||||
]
|
||||
loadable_modules += [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
|
||||
|
||||
if (android_64bit_target_cpu && build_apk_secondary_abi &&
|
||||
(!defined(invoker.is_64_bit_browser) || !invoker.is_64_bit_browser ||
|
||||
invoker.include_32_bit_webview)) {
|
||||
_trampoline = "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline($android_secondary_abi_toolchain)"
|
||||
deps += [ _trampoline ]
|
||||
_secondary_out_dir = get_label_info(_trampoline, "root_out_dir")
|
||||
secondary_abi_loadable_modules +=
|
||||
[ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ]
|
||||
}
|
||||
}
|
||||
|
||||
deps += [
|
||||
"//chrome/android:chrome_public_non_pak_assets",
|
||||
"//components/crash/android:handler_java",
|
||||
@ -403,11 +427,11 @@ template("monochrome_public_common_apk_or_module_tmpl") {
|
||||
|
||||
# We store this as a separate .so in the APK and only load as needed.
|
||||
if (android_64bit_target_cpu && build_apk_secondary_abi) {
|
||||
secondary_abi_loadable_modules = [ "$root_gen_dir/third_party/android_deps/com_google_ar_core_java/jni/armeabi-v7a/libarcore_sdk_c.so" ]
|
||||
secondary_abi_loadable_modules += [ "$root_gen_dir/third_party/android_deps/com_google_ar_core_java/jni/armeabi-v7a/libarcore_sdk_c.so" ]
|
||||
} else if (android_64bit_target_cpu && !build_apk_secondary_abi) {
|
||||
loadable_modules = [ "$root_gen_dir/third_party/android_deps/com_google_ar_core_java/jni/armeabi-v7a/libarcore_sdk_c.so" ]
|
||||
loadable_modules += [ "$root_gen_dir/third_party/android_deps/com_google_ar_core_java/jni/armeabi-v7a/libarcore_sdk_c.so" ]
|
||||
} else {
|
||||
loadable_modules = [ "$root_gen_dir/third_party/android_deps/com_google_ar_core_java/jni/armeabi-v7a/libarcore_sdk_c.so" ]
|
||||
loadable_modules += [ "$root_gen_dir/third_party/android_deps/com_google_ar_core_java/jni/armeabi-v7a/libarcore_sdk_c.so" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ if (current_toolchain == default_toolchain &&
|
||||
(!is_debug && !using_sanitizer && proprietary_codecs)) {
|
||||
# Define expectations only for target_cpu covered by trybots.
|
||||
if (target_cpu == "arm") {
|
||||
expected_static_initializer_count = 4
|
||||
expected_static_initializer_count = 6
|
||||
} else if (target_cpu == "arm64") {
|
||||
expected_static_initializer_count = 3
|
||||
expected_static_initializer_count = 5
|
||||
}
|
||||
}
|
||||
|
@ -82,9 +82,19 @@ template("trichrome_library_apk_tmpl") {
|
||||
if (build_apk_secondary_abi) {
|
||||
secondary_abi_shared_libraries =
|
||||
[ "//chrome/android:monochrome_secondary_abi_lib" ]
|
||||
|
||||
_trampoline = "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline($android_secondary_abi_toolchain)"
|
||||
deps += [ _trampoline ]
|
||||
_secondary_out_dir = get_label_info(_trampoline, "root_out_dir")
|
||||
secondary_abi_loadable_modules =
|
||||
[ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ]
|
||||
}
|
||||
} else {
|
||||
shared_libraries = [ "//chrome/android:monochrome" ]
|
||||
deps += [
|
||||
"//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
|
||||
]
|
||||
loadable_modules = [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
|
||||
}
|
||||
|
||||
if (!is_java_debug) {
|
||||
|
@ -66,7 +66,10 @@ static_library("app") {
|
||||
}
|
||||
|
||||
if (is_android) {
|
||||
deps += [ "//components/crash/android:jni_headers" ]
|
||||
deps += [
|
||||
"//components/crash/android:jni_headers",
|
||||
"//third_party/crashpad/crashpad/handler",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_android || is_linux) {
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "components/crash/content/app/crashpad.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
@ -246,6 +247,33 @@ void SetBuildInfoAnnotations(std::map<std::string, std::string>* annotations) {
|
||||
}
|
||||
}
|
||||
|
||||
// Constructs paths to a handler trampoline executable and a library exporting
|
||||
// the symbol `CrashpadHandlerMain()`. This requires this function to be built
|
||||
// into the same object exporting this symbol and the handler trampoline is
|
||||
// adjacent to it.
|
||||
bool GetHandlerTrampoline(std::string* handler_trampoline,
|
||||
std::string* handler_library) {
|
||||
Dl_info info;
|
||||
if (dladdr(reinterpret_cast<void*>(&GetHandlerTrampoline), &info) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string local_handler_library(info.dli_fname);
|
||||
|
||||
size_t libdir_end = local_handler_library.rfind('/');
|
||||
if (libdir_end == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string local_handler_trampoline(local_handler_library, 0,
|
||||
libdir_end + 1);
|
||||
local_handler_trampoline += "libcrashpad_handler_trampoline.so";
|
||||
|
||||
handler_trampoline->swap(local_handler_trampoline);
|
||||
handler_library->swap(local_handler_library);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(__arm__) && defined(__ARM_ARCH_7A__)
|
||||
#define CURRENT_ABI "armeabi-v7a"
|
||||
#elif defined(__arm__)
|
||||
@ -281,7 +309,8 @@ void MakePackagePaths(std::string* classpath, std::string* libpath) {
|
||||
|
||||
// Copies and extends the current environment with CLASSPATH and LD_LIBRARY_PATH
|
||||
// set to library paths in the APK.
|
||||
bool BuildEnvironmentWithApk(std::vector<std::string>* result) {
|
||||
bool BuildEnvironmentWithApk(bool use_64_bit,
|
||||
std::vector<std::string>* result) {
|
||||
DCHECK(result->empty());
|
||||
|
||||
std::string classpath;
|
||||
@ -299,6 +328,12 @@ bool BuildEnvironmentWithApk(std::vector<std::string>* result) {
|
||||
env->GetVar(kLdLibraryPathVar, ¤t_library_path);
|
||||
library_path += ":" + current_library_path;
|
||||
|
||||
static constexpr char kRuntimeRootVar[] = "ANDROID_RUNTIME_ROOT";
|
||||
std::string runtime_root;
|
||||
if (env->GetVar(kRuntimeRootVar, &runtime_root)) {
|
||||
library_path += ":" + runtime_root + (use_64_bit ? "/lib64" : "/lib");
|
||||
}
|
||||
|
||||
result->push_back("CLASSPATH=" + classpath);
|
||||
result->push_back("LD_LIBRARY_PATH=" + library_path);
|
||||
for (char** envp = environ; *envp != nullptr; ++envp) {
|
||||
@ -414,6 +449,19 @@ bool SetLdLibraryPath(const base::FilePath& lib_path) {
|
||||
}
|
||||
|
||||
class HandlerStarter {
|
||||
#if defined(OS_ANDROID)
|
||||
// TODO(jperaza): Currently only launching a same-bitness handler is
|
||||
// supported. The logic to build package paths, locate a handler executable,
|
||||
// and the crashpad client interface for launching a Java handler need to be
|
||||
// updated to use a specified bitness before a cross-bitness handler can be
|
||||
// used.
|
||||
#if defined(ARCH_CPU_64_BITS)
|
||||
static constexpr bool kUse64Bit = true;
|
||||
#else
|
||||
static constexpr bool kUse64Bit = false;
|
||||
#endif
|
||||
#endif // OS_ANDROID
|
||||
|
||||
public:
|
||||
static HandlerStarter* Get() {
|
||||
static HandlerStarter* instance = new HandlerStarter();
|
||||
@ -443,25 +491,35 @@ class HandlerStarter {
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
if (!base::PathExists(handler_path)) {
|
||||
use_java_handler_ = true;
|
||||
// The linker doesn't support loading executables passed on its command
|
||||
// line until Q.
|
||||
if (base::android::BuildInfo::GetInstance()->is_at_least_q()) {
|
||||
bool found_library =
|
||||
GetHandlerTrampoline(&handler_trampoline_, &handler_library_);
|
||||
DCHECK(found_library);
|
||||
} else {
|
||||
use_java_handler_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dump_at_crash) {
|
||||
return database_path;
|
||||
}
|
||||
|
||||
if (use_java_handler_) {
|
||||
if (use_java_handler_ || !handler_trampoline_.empty()) {
|
||||
std::vector<std::string> env;
|
||||
if (!BuildEnvironmentWithApk(&env)) {
|
||||
if (!BuildEnvironmentWithApk(kUse64Bit, &env)) {
|
||||
return database_path;
|
||||
}
|
||||
|
||||
// TODO(jperaza): The logic for constructing an appropriate
|
||||
// CLASSPATH/LD_LIBRARY_PATH won't work for Android Q+. The handler will
|
||||
// need to be launched by executing the dynamic linker instead.
|
||||
bool result = GetCrashpadClient().StartJavaHandlerAtCrash(
|
||||
kCrashpadJavaMain, &env, database_path, metrics_path, url,
|
||||
process_annotations, arguments);
|
||||
bool result = use_java_handler_
|
||||
? GetCrashpadClient().StartJavaHandlerAtCrash(
|
||||
kCrashpadJavaMain, &env, database_path,
|
||||
metrics_path, url, process_annotations, arguments)
|
||||
: GetCrashpadClient().StartHandlerWithLinkerAtCrash(
|
||||
handler_trampoline_, handler_library_, kUse64Bit,
|
||||
&env, database_path, metrics_path, url,
|
||||
process_annotations, arguments);
|
||||
DCHECK(result);
|
||||
return database_path;
|
||||
}
|
||||
@ -501,18 +559,21 @@ class HandlerStarter {
|
||||
}
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
if (use_java_handler_) {
|
||||
if (use_java_handler_ || !handler_trampoline_.empty()) {
|
||||
std::vector<std::string> env;
|
||||
if (!BuildEnvironmentWithApk(&env)) {
|
||||
if (!BuildEnvironmentWithApk(kUse64Bit, &env)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(jperaza): The logic for constructing an appropriate
|
||||
// CLASSPATH/LD_LIBRARY_PATH won't work for Android Q+. The handler will
|
||||
// need to be launched by executing the dynamic linker instead.
|
||||
bool result = GetCrashpadClient().StartJavaHandlerForClient(
|
||||
kCrashpadJavaMain, &env, database_path, metrics_path, url,
|
||||
process_annotations, arguments, fd);
|
||||
bool result =
|
||||
use_java_handler_
|
||||
? GetCrashpadClient().StartJavaHandlerForClient(
|
||||
kCrashpadJavaMain, &env, database_path, metrics_path, url,
|
||||
process_annotations, arguments, fd)
|
||||
: GetCrashpadClient().StartHandlerWithLinkerForClient(
|
||||
handler_trampoline_, handler_library_, kUse64Bit, &env,
|
||||
database_path, metrics_path, url, process_annotations,
|
||||
arguments, fd);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
@ -532,6 +593,8 @@ class HandlerStarter {
|
||||
|
||||
crashpad::SanitizationInformation browser_sanitization_info_;
|
||||
#if defined(OS_ANDROID)
|
||||
std::string handler_trampoline_;
|
||||
std::string handler_library_;
|
||||
bool use_java_handler_ = false;
|
||||
#endif
|
||||
|
||||
|
Reference in New Issue
Block a user