#include "client/crashpad_client.h"
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <linux/futex.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <atomic>
#include "base/check_op.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "client/client_argv_handling.h"
#include "third_party/lss/lss.h"
#include "util/file/file_io.h"
#include "util/file/filesystem.h"
#include "util/linux/exception_handler_client.h"
#include "util/linux/exception_information.h"
#include "util/linux/scoped_pr_set_dumpable.h"
#include "util/linux/scoped_pr_set_ptracer.h"
#include "util/linux/socket.h"
#include "util/misc/address_sanitizer.h"
#include "util/misc/from_pointer_cast.h"
#include "util/posix/scoped_mmap.h"
#include "util/posix/signals.h"
#include "util/posix/spawn_subprocess.h"
namespace crashpad {
namespace {
std::string FormatArgumentInt(const std::string& name, int value) { … }
std::string FormatArgumentAddress(const std::string& name, const void* addr) { … }
#if BUILDFLAG(IS_ANDROID)
std::vector<std::string> BuildAppProcessArgs(
const std::string& class_name,
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) {
#if defined(ARCH_CPU_64_BITS)
static constexpr char kAppProcess[] = "/system/bin/app_process64";
#else
static constexpr char kAppProcess[] = "/system/bin/app_process32";
#endif
std::vector<std::string> argv;
argv.push_back(kAppProcess);
argv.push_back("/system/bin");
argv.push_back("--application");
argv.push_back(class_name);
std::vector<std::string> handler_argv =
BuildHandlerArgvStrings(base::FilePath(kAppProcess),
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(), handler_argv.end());
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
LastChanceHandler;
class SignalHandler { … };
SignalHandler* SignalHandler::handler_ = …;
class LaunchAtCrashHandler : public SignalHandler { … };
class RequestCrashDumpHandler : public SignalHandler { … };
}
CrashpadClient::CrashpadClient() { … }
CrashpadClient::~CrashpadClient() { … }
bool CrashpadClient::StartHandler(
const base::FilePath& handler,
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,
bool restartable,
bool asynchronous_start,
const std::vector<base::FilePath>& attachments) { … }
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
bool CrashpadClient::GetHandlerSocket(int* sock, pid_t* pid) { … }
bool CrashpadClient::SetHandlerSocket(ScopedFileHandle sock, pid_t pid) { … }
bool CrashpadClient::InitializeSignalStackForThread() { … }
#endif
#if BUILDFLAG(IS_ANDROID)
bool CrashpadClient::StartJavaHandlerAtCrash(
const std::string& class_name,
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 = BuildAppProcessArgs(class_name,
database,
metrics_dir,
url,
annotations,
arguments,
kInvalidFileHandle);
auto signal_handler = LaunchAtCrashHandler::Get();
return signal_handler->Initialize(&argv, env, &unhandled_signals_);
}
bool CrashpadClient::StartJavaHandlerForClient(
const std::string& class_name,
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 = BuildAppProcessArgs(
class_name, database, metrics_dir, url, annotations, arguments, socket);
return SpawnSubprocess(argv, env, socket, false, nullptr);
}
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();
return signal_handler->Initialize(&argv, env, &unhandled_signals_);
}
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 SpawnSubprocess(argv, env, socket, false, nullptr);
}
#endif
bool CrashpadClient::StartHandlerAtCrash(
const base::FilePath& handler,
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,
const std::vector<base::FilePath>& attachments) { … }
bool CrashpadClient::StartHandlerForClient(
const base::FilePath& handler,
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) { … }
void CrashpadClient::DumpWithoutCrash(NativeCPUContext* context) { … }
void CrashpadClient::CrashWithoutDump(const std::string& message) { … }
void CrashpadClient::SetFirstChanceExceptionHandler(
FirstChanceHandler handler) { … }
void CrashpadClient::SetLastChanceExceptionHandler(LastChanceHandler handler) { … }
void CrashpadClient::SetUnhandledSignals(const std::set<int>& signals) { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
void CrashpadClient::SetCrashLoopBefore(uint64_t crash_loop_before_time) {
auto request_crash_dump_handler = RequestCrashDumpHandler::Get();
request_crash_dump_handler->SetCrashLoopBefore(crash_loop_before_time);
}
#endif
}