mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-17 16:43:53 +00:00
android: Add methods to start handler with /system/bin/linker
Starting with Android Q, Bionic's linker will support loading executables from an APK, replacing the /system/bin/app_process workaround. libhandler_trampoline.so is a small executable, which `dlopen()`s the handler code from another native library allowing de-duplicating shared code with that library without having that library available for a more direct link time dependency. Bug: 928422 Change-Id: Ib126b8fca6005a34b9e4ef103eb1383dc0c554ea Reviewed-on: https://chromium-review.googlesource.com/c/1477336 Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
dc17650336
commit
99bf283e54
@ -188,6 +188,97 @@ class CrashpadClient {
|
|||||||
const std::map<std::string, std::string>& annotations,
|
const std::map<std::string, std::string>& annotations,
|
||||||
const std::vector<std::string>& arguments,
|
const std::vector<std::string>& arguments,
|
||||||
int socket);
|
int socket);
|
||||||
|
|
||||||
|
//! \brief Installs a signal handler to start a Crashpad handler process by
|
||||||
|
//! loading it with `/system/bin/linker`.
|
||||||
|
//!
|
||||||
|
//! This method is only supported by Android Q+.
|
||||||
|
//!
|
||||||
|
//! \param[in] handler_trampoline The path to a Crashpad handler trampoline
|
||||||
|
//! executable, possibly located within an apk, e.g.
|
||||||
|
//! "/data/app/myapk.apk!/myabi/libcrashpad_handler_trampoline.so".
|
||||||
|
//! \param[in] handler_library The name of a library exporting the symbol
|
||||||
|
//! `CrashpadHandlerMain()`. The path to this library must be present in
|
||||||
|
//! `LD_LIBRARY_PATH`.
|
||||||
|
//! \param[in] is_64_bit `true` if \a handler_trampoline and \a
|
||||||
|
//! handler_library are 64-bit objects. They must have the same bitness.
|
||||||
|
//! \param[in] env A vector of environment variables of the form `var=value`
|
||||||
|
//! defining the environment in which to execute `app_process`. If this
|
||||||
|
//! value is `nullptr`, the application's environment at the time of the
|
||||||
|
//! crash will be used.
|
||||||
|
//! \param[in] database The path to a Crashpad database. The handler will be
|
||||||
|
//! started with this path as its `--database` argument.
|
||||||
|
//! \param[in] metrics_dir The path to an already existing directory where
|
||||||
|
//! metrics files can be stored. The handler will be started with this
|
||||||
|
//! path as its `--metrics-dir` argument.
|
||||||
|
//! \param[in] url The URL of an upload server. The handler will be started
|
||||||
|
//! with this URL as its `--url` argument.
|
||||||
|
//! \param[in] annotations Process annotations to set in each crash report.
|
||||||
|
//! The handler will be started with an `--annotation` argument for each
|
||||||
|
//! element in this map.
|
||||||
|
//! \param[in] arguments Additional arguments to pass to the Crashpad handler.
|
||||||
|
//! Arguments passed in other parameters and arguments required to perform
|
||||||
|
//! the handshake are the responsibility of this method, and must not be
|
||||||
|
//! specified in this parameter.
|
||||||
|
//!
|
||||||
|
//! \return `true` on success, `false` on failure with a message logged.
|
||||||
|
static bool StartHandlerWithLinkerAtCrash(
|
||||||
|
const std::string& handler_trampoline,
|
||||||
|
const std::string& handler_library,
|
||||||
|
bool is_64_bit,
|
||||||
|
const std::vector<std::string>* env,
|
||||||
|
const base::FilePath& database,
|
||||||
|
const base::FilePath& metrics_dir,
|
||||||
|
const std::string& url,
|
||||||
|
const std::map<std::string, std::string>& annotations,
|
||||||
|
const std::vector<std::string>& arguments);
|
||||||
|
|
||||||
|
//! \brief Starts a Crashpad handler process with an initial client by loading
|
||||||
|
//! it with `/system/bin/linker`.
|
||||||
|
//!
|
||||||
|
//! This method is only supported by Android Q+.
|
||||||
|
//!
|
||||||
|
//! \param[in] handler_trampoline The path to a Crashpad handler trampoline
|
||||||
|
//! executable, possibly located within an apk, e.g.
|
||||||
|
//! "/data/app/myapk.apk!/myabi/libcrashpad_handler_trampoline.so".
|
||||||
|
//! \param[in] handler_library The name of a library exporting the symbol
|
||||||
|
//! `CrashpadHandlerMain()`. The path to this library must be present in
|
||||||
|
//! `LD_LIBRARY_PATH`.
|
||||||
|
//! \param[in] is_64_bit `true` if \a handler_trampoline and \a
|
||||||
|
//! handler_library are 64-bit objects. They must have the same bitness.
|
||||||
|
//! \param[in] env A vector of environment variables of the form `var=value`
|
||||||
|
//! defining the environment in which to execute `app_process`. If this
|
||||||
|
//! value is `nullptr`, the application's current environment will be
|
||||||
|
//! used.
|
||||||
|
//! \param[in] database The path to a Crashpad database. The handler will be
|
||||||
|
//! started with this path as its `--database` argument.
|
||||||
|
//! \param[in] metrics_dir The path to an already existing directory where
|
||||||
|
//! metrics files can be stored. The handler will be started with this
|
||||||
|
//! path as its `--metrics-dir` argument.
|
||||||
|
//! \param[in] url The URL of an upload server. The handler will be started
|
||||||
|
//! with this URL as its `--url` argument.
|
||||||
|
//! \param[in] annotations Process annotations to set in each crash report.
|
||||||
|
//! The handler will be started with an `--annotation` argument for each
|
||||||
|
//! element in this map.
|
||||||
|
//! \param[in] arguments Additional arguments to pass to the Crashpad handler.
|
||||||
|
//! Arguments passed in other parameters and arguments required to perform
|
||||||
|
//! the handshake are the responsibility of this method, and must not be
|
||||||
|
//! specified in this parameter.
|
||||||
|
//! \param[in] socket The server end of a socket pair. The client end should
|
||||||
|
//! be used with an ExceptionHandlerClient.
|
||||||
|
//!
|
||||||
|
//! \return `true` on success, `false` on failure with a message logged.
|
||||||
|
static bool StartHandlerWithLinkerForClient(
|
||||||
|
const std::string& handler_trampoline,
|
||||||
|
const std::string& handler_library,
|
||||||
|
bool is_64_bit,
|
||||||
|
const std::vector<std::string>* env,
|
||||||
|
const base::FilePath& database,
|
||||||
|
const base::FilePath& metrics_dir,
|
||||||
|
const std::string& url,
|
||||||
|
const std::map<std::string, std::string>& annotations,
|
||||||
|
const std::vector<std::string>& arguments,
|
||||||
|
int socket);
|
||||||
#endif // OS_ANDROID || DOXYGEN
|
#endif // OS_ANDROID || DOXYGEN
|
||||||
|
|
||||||
#if defined(OS_LINUX) || defined(OS_ANDROID) || DOXYGEN
|
#if defined(OS_LINUX) || defined(OS_ANDROID) || DOXYGEN
|
||||||
|
@ -77,6 +77,36 @@ std::vector<std::string> BuildAppProcessArgs(
|
|||||||
return argv;
|
return argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> BuildArgsToLaunchWithLinker(
|
||||||
|
const std::string& handler_trampoline,
|
||||||
|
const std::string& handler_library,
|
||||||
|
bool is_64_bit,
|
||||||
|
const base::FilePath& database,
|
||||||
|
const base::FilePath& metrics_dir,
|
||||||
|
const std::string& url,
|
||||||
|
const std::map<std::string, std::string>& annotations,
|
||||||
|
const std::vector<std::string>& arguments,
|
||||||
|
int socket) {
|
||||||
|
std::vector<std::string> argv;
|
||||||
|
if (is_64_bit) {
|
||||||
|
argv.push_back("/system/bin/linker64");
|
||||||
|
} else {
|
||||||
|
argv.push_back("/system/bin/linker");
|
||||||
|
}
|
||||||
|
argv.push_back(handler_trampoline);
|
||||||
|
argv.push_back(handler_library);
|
||||||
|
|
||||||
|
std::vector<std::string> handler_argv = BuildHandlerArgvStrings(
|
||||||
|
base::FilePath(), database, metrics_dir, url, annotations, arguments);
|
||||||
|
|
||||||
|
if (socket != kInvalidFileHandle) {
|
||||||
|
handler_argv.push_back(FormatArgumentInt("initial-client-fd", socket));
|
||||||
|
}
|
||||||
|
|
||||||
|
argv.insert(argv.end(), handler_argv.begin() + 1, handler_argv.end());
|
||||||
|
return argv;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // OS_ANDROID
|
#endif // OS_ANDROID
|
||||||
|
|
||||||
// Launches a single use handler to snapshot this process.
|
// Launches a single use handler to snapshot this process.
|
||||||
@ -251,6 +281,61 @@ bool CrashpadClient::StartJavaHandlerForClient(
|
|||||||
return DoubleForkAndExec(argv, env, socket, false, nullptr);
|
return DoubleForkAndExec(argv, env, socket, false, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool CrashpadClient::StartHandlerWithLinkerAtCrash(
|
||||||
|
const std::string& handler_trampoline,
|
||||||
|
const std::string& handler_library,
|
||||||
|
bool is_64_bit,
|
||||||
|
const std::vector<std::string>* env,
|
||||||
|
const base::FilePath& database,
|
||||||
|
const base::FilePath& metrics_dir,
|
||||||
|
const std::string& url,
|
||||||
|
const std::map<std::string, std::string>& annotations,
|
||||||
|
const std::vector<std::string>& arguments) {
|
||||||
|
std::vector<std::string> argv =
|
||||||
|
BuildArgsToLaunchWithLinker(handler_trampoline,
|
||||||
|
handler_library,
|
||||||
|
is_64_bit,
|
||||||
|
database,
|
||||||
|
metrics_dir,
|
||||||
|
url,
|
||||||
|
annotations,
|
||||||
|
arguments,
|
||||||
|
kInvalidFileHandle);
|
||||||
|
auto signal_handler = LaunchAtCrashHandler::Get();
|
||||||
|
if (signal_handler->Initialize(&argv, env)) {
|
||||||
|
DCHECK(!g_crash_handler);
|
||||||
|
g_crash_handler = signal_handler;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool CrashpadClient::StartHandlerWithLinkerForClient(
|
||||||
|
const std::string& handler_trampoline,
|
||||||
|
const std::string& handler_library,
|
||||||
|
bool is_64_bit,
|
||||||
|
const std::vector<std::string>* env,
|
||||||
|
const base::FilePath& database,
|
||||||
|
const base::FilePath& metrics_dir,
|
||||||
|
const std::string& url,
|
||||||
|
const std::map<std::string, std::string>& annotations,
|
||||||
|
const std::vector<std::string>& arguments,
|
||||||
|
int socket) {
|
||||||
|
std::vector<std::string> argv =
|
||||||
|
BuildArgsToLaunchWithLinker(handler_trampoline,
|
||||||
|
handler_library,
|
||||||
|
is_64_bit,
|
||||||
|
database,
|
||||||
|
metrics_dir,
|
||||||
|
url,
|
||||||
|
annotations,
|
||||||
|
arguments,
|
||||||
|
socket);
|
||||||
|
return DoubleForkAndExec(argv, env, socket, false, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -166,6 +166,21 @@ if (crashpad_is_android) {
|
|||||||
"$root_out_dir/libcrashpad_handler.so",
|
"$root_out_dir/libcrashpad_handler.so",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crashpad_executable("crashpad_handler_trampoline") {
|
||||||
|
set_sources_assignment_filter([])
|
||||||
|
output_name = "libcrashpad_handler_trampoline.so"
|
||||||
|
|
||||||
|
sources = [
|
||||||
|
"linux/handler_trampoline.cc",
|
||||||
|
]
|
||||||
|
|
||||||
|
ldflags = [ "-llog" ]
|
||||||
|
|
||||||
|
if (crashpad_is_in_chromium) {
|
||||||
|
no_default_deps = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crashpad_executable("crashpad_handler_test_extended_handler") {
|
crashpad_executable("crashpad_handler_test_extended_handler") {
|
||||||
|
@ -497,6 +497,18 @@ class ScopedStoppable {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
#if defined(OS_ANDROID)
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
__attribute__((visibility("default"), used)) int CrashpadHandlerMain(
|
||||||
|
int argc,
|
||||||
|
char* argv[]) {
|
||||||
|
return HandlerMain(argc, argv, nullptr);
|
||||||
|
}
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
#endif // OS_ANDROID
|
||||||
|
|
||||||
int HandlerMain(int argc,
|
int HandlerMain(int argc,
|
||||||
char* argv[],
|
char* argv[],
|
||||||
const UserStreamDataSources* user_stream_sources) {
|
const UserStreamDataSources* user_stream_sources) {
|
||||||
|
45
handler/linux/handler_trampoline.cc
Normal file
45
handler/linux/handler_trampoline.cc
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Copyright 2019 The Crashpad Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// The first argument passed to the trampoline is the name of the native library
|
||||||
|
// exporting the symbol `CrashpadHandlerMain`. The remaining arguments are the
|
||||||
|
// same as for `HandlerMain()`.
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
static constexpr char kTag[] = "crashpad";
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
__android_log_print(ANDROID_LOG_FATAL, kTag, "usage: %s <path>", argv[0]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* handle = dlopen(argv[1], RTLD_LAZY | RTLD_GLOBAL);
|
||||||
|
if (!handle) {
|
||||||
|
__android_log_print(ANDROID_LOG_FATAL, kTag, "dlopen: %s", dlerror());
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
using MainType = int (*)(int, char*[]);
|
||||||
|
MainType crashpad_main =
|
||||||
|
reinterpret_cast<MainType>(dlsym(handle, "CrashpadHandlerMain"));
|
||||||
|
if (!crashpad_main) {
|
||||||
|
__android_log_print(ANDROID_LOG_FATAL, kTag, "dlsym: %s", dlerror());
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return crashpad_main(argc - 1, argv + 1);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user