mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 22:16:13 +00:00
Migrate from ScopedZxHandle to libzx containers.
Bug: chromium:852541 Change-Id: Ie05c70f249e6f843183a02ec61fd09f6a0607598 Reviewed-on: https://chromium-review.googlesource.com/1148923 Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Wez <wez@chromium.org>
This commit is contained in:
parent
6759969bf6
commit
bc50af15a2
@ -88,10 +88,11 @@ static_library("client") {
|
|||||||
cflags = [ "/wd4201" ] # nonstandard extension used : nameless struct/union
|
cflags = [ "/wd4201" ] # nonstandard extension used : nameless struct/union
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crashpad_is_fuchsia && crashpad_is_in_fuchsia) {
|
if (crashpad_is_fuchsia) {
|
||||||
deps += [
|
deps += [ "../third_party/fuchsia:zx" ]
|
||||||
"//zircon/public/lib/fdio",
|
if (crashpad_is_in_fuchsia) {
|
||||||
]
|
deps += [ "//zircon/public/lib/fdio" ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,11 +15,12 @@
|
|||||||
#include "client/crashpad_client.h"
|
#include "client/crashpad_client.h"
|
||||||
|
|
||||||
#include <lib/fdio/spawn.h>
|
#include <lib/fdio/spawn.h>
|
||||||
#include <zircon/process.h>
|
#include <lib/zx/job.h>
|
||||||
|
#include <lib/zx/port.h>
|
||||||
|
#include <lib/zx/process.h>
|
||||||
#include <zircon/processargs.h>
|
#include <zircon/processargs.h>
|
||||||
|
|
||||||
#include "base/fuchsia/fuchsia_logging.h"
|
#include "base/fuchsia/fuchsia_logging.h"
|
||||||
#include "base/fuchsia/scoped_zx_handle.h"
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/strings/stringprintf.h"
|
#include "base/strings/stringprintf.h"
|
||||||
#include "client/client_argv_handling.h"
|
#include "client/client_argv_handling.h"
|
||||||
@ -43,16 +44,15 @@ bool CrashpadClient::StartHandler(
|
|||||||
DCHECK_EQ(restartable, false); // Not used on Fuchsia.
|
DCHECK_EQ(restartable, false); // Not used on Fuchsia.
|
||||||
DCHECK_EQ(asynchronous_start, false); // Not used on Fuchsia.
|
DCHECK_EQ(asynchronous_start, false); // Not used on Fuchsia.
|
||||||
|
|
||||||
zx_handle_t exception_port_raw;
|
zx::port exception_port;
|
||||||
zx_status_t status = zx_port_create(0, &exception_port_raw);
|
zx_status_t status = zx::port::create(0, &exception_port);
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
ZX_LOG(ERROR, status) << "zx_port_create";
|
ZX_LOG(ERROR, status) << "zx_port_create";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
base::ScopedZxHandle exception_port(exception_port_raw);
|
|
||||||
|
|
||||||
status = zx_task_bind_exception_port(
|
status = zx::job::default_job()->bind_exception_port(
|
||||||
zx_job_default(), exception_port.get(), kSystemExceptionPortKey, 0);
|
exception_port, kSystemExceptionPortKey, 0);
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
ZX_LOG(ERROR, status) << "zx_task_bind_exception_port";
|
ZX_LOG(ERROR, status) << "zx_task_bind_exception_port";
|
||||||
return false;
|
return false;
|
||||||
@ -88,7 +88,7 @@ bool CrashpadClient::StartHandler(
|
|||||||
actions[1].h.handle = exception_port.release();
|
actions[1].h.handle = exception_port.release();
|
||||||
|
|
||||||
char error_message[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
|
char error_message[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
|
||||||
zx_handle_t child_raw;
|
zx::process child;
|
||||||
// TODO(scottmg): https://crashpad.chromium.org/bug/196, FDIO_SPAWN_CLONE_ALL
|
// TODO(scottmg): https://crashpad.chromium.org/bug/196, FDIO_SPAWN_CLONE_ALL
|
||||||
// is useful during bringup, but should probably be made minimal for real
|
// is useful during bringup, but should probably be made minimal for real
|
||||||
// usage.
|
// usage.
|
||||||
@ -99,9 +99,8 @@ bool CrashpadClient::StartHandler(
|
|||||||
nullptr,
|
nullptr,
|
||||||
kActionCount,
|
kActionCount,
|
||||||
actions,
|
actions,
|
||||||
&child_raw,
|
child.reset_and_get_address(),
|
||||||
error_message);
|
error_message);
|
||||||
base::ScopedZxHandle child(child_raw);
|
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
ZX_LOG(ERROR, status) << "fdio_spawn_etc: " << error_message;
|
ZX_LOG(ERROR, status) << "fdio_spawn_etc: " << error_message;
|
||||||
return false;
|
return false;
|
||||||
|
@ -80,6 +80,10 @@ static_library("handler") {
|
|||||||
if (crashpad_is_win) {
|
if (crashpad_is_win) {
|
||||||
cflags = [ "/wd4201" ] # nonstandard extension used : nameless struct/union
|
cflags = [ "/wd4201" ] # nonstandard extension used : nameless struct/union
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (crashpad_is_fuchsia) {
|
||||||
|
deps += [ "../third_party/fuchsia:zx" ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
source_set("handler_test") {
|
source_set("handler_test") {
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "handler/fuchsia/crash_report_exception_handler.h"
|
#include "handler/fuchsia/crash_report_exception_handler.h"
|
||||||
|
|
||||||
|
#include <lib/zx/thread.h>
|
||||||
#include <zircon/syscalls/exception.h>
|
#include <zircon/syscalls/exception.h>
|
||||||
|
|
||||||
#include "base/fuchsia/fuchsia_logging.h"
|
#include "base/fuchsia/fuchsia_logging.h"
|
||||||
@ -22,28 +23,28 @@
|
|||||||
#include "minidump/minidump_user_extension_stream_data_source.h"
|
#include "minidump/minidump_user_extension_stream_data_source.h"
|
||||||
#include "snapshot/fuchsia/process_snapshot_fuchsia.h"
|
#include "snapshot/fuchsia/process_snapshot_fuchsia.h"
|
||||||
#include "util/fuchsia/koid_utilities.h"
|
#include "util/fuchsia/koid_utilities.h"
|
||||||
#include "util/fuchsia/scoped_task_suspend.h"
|
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct ScopedZxTaskResumeAfterException {
|
class ScopedThreadResumeAfterException {
|
||||||
ScopedZxTaskResumeAfterException(zx_handle_t thread) : thread_(thread) {}
|
public:
|
||||||
~ScopedZxTaskResumeAfterException() {
|
ScopedThreadResumeAfterException(const zx::thread& thread)
|
||||||
DCHECK_NE(thread_, ZX_HANDLE_INVALID);
|
: thread_(thread) {}
|
||||||
|
~ScopedThreadResumeAfterException() {
|
||||||
|
DCHECK(thread_->is_valid());
|
||||||
// Resuming with ZX_RESUME_TRY_NEXT chains to the next handler. In normal
|
// Resuming with ZX_RESUME_TRY_NEXT chains to the next handler. In normal
|
||||||
// operation, there won't be another beyond this one, which will result in
|
// operation, there won't be another beyond this one, which will result in
|
||||||
// the kernel terminating the process.
|
// the kernel terminating the process.
|
||||||
zx_status_t status =
|
zx_status_t status =
|
||||||
zx_task_resume(thread_, ZX_RESUME_EXCEPTION | ZX_RESUME_TRY_NEXT);
|
thread_->resume(ZX_RESUME_EXCEPTION | ZX_RESUME_TRY_NEXT);
|
||||||
if (status != ZX_OK) {
|
ZX_LOG_IF(ERROR, status != ZX_OK, status) << "zx_task_resume";
|
||||||
ZX_LOG(ERROR, status) << "zx_task_resume";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
zx_handle_t thread_; // weak
|
zx::unowned_thread thread_;
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(ScopedThreadResumeAfterException);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -67,27 +68,28 @@ bool CrashReportExceptionHandler::HandleException(uint64_t process_id,
|
|||||||
// TODO(scottmg): This function needs to be instrumented with metrics calls,
|
// TODO(scottmg): This function needs to be instrumented with metrics calls,
|
||||||
// https://crashpad.chromium.org/bug/230.
|
// https://crashpad.chromium.org/bug/230.
|
||||||
|
|
||||||
base::ScopedZxHandle process(GetProcessFromKoid(process_id));
|
zx::process process(GetProcessFromKoid(process_id));
|
||||||
if (!process.is_valid()) {
|
if (!process.is_valid()) {
|
||||||
// There's no way to zx_task_resume() the thread if the process retrieval
|
// There's no way to zx_task_resume() the thread if the process retrieval
|
||||||
// fails. Assume that the process has been already killed, and bail.
|
// fails. Assume that the process has been already killed, and bail.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
base::ScopedZxHandle thread(GetChildHandleByKoid(process.get(), thread_id));
|
zx::thread thread(GetThreadHandleByKoid(process, thread_id));
|
||||||
if (!thread.is_valid()) {
|
if (!thread.is_valid()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return HandleExceptionHandles(process.get(), thread.get());
|
return HandleExceptionHandles(process, thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CrashReportExceptionHandler::HandleExceptionHandles(zx_handle_t process,
|
bool CrashReportExceptionHandler::HandleExceptionHandles(
|
||||||
zx_handle_t thread) {
|
const zx::process& process,
|
||||||
|
const zx::thread& thread) {
|
||||||
// Now that the thread has been successfully retrieved, it is possible to
|
// Now that the thread has been successfully retrieved, it is possible to
|
||||||
// correctly call zx_task_resume() to continue exception processing, even if
|
// correctly call zx_task_resume() to continue exception processing, even if
|
||||||
// something else during this function fails.
|
// something else during this function fails.
|
||||||
ScopedZxTaskResumeAfterException resume(thread);
|
ScopedThreadResumeAfterException resume(thread);
|
||||||
|
|
||||||
ProcessSnapshotFuchsia process_snapshot;
|
ProcessSnapshotFuchsia process_snapshot;
|
||||||
if (!process_snapshot.Initialize(process)) {
|
if (!process_snapshot.Initialize(process)) {
|
||||||
@ -99,12 +101,11 @@ bool CrashReportExceptionHandler::HandleExceptionHandles(zx_handle_t process,
|
|||||||
|
|
||||||
if (client_options.crashpad_handler_behavior != TriState::kDisabled) {
|
if (client_options.crashpad_handler_behavior != TriState::kDisabled) {
|
||||||
zx_exception_report_t report;
|
zx_exception_report_t report;
|
||||||
zx_status_t status = zx_object_get_info(thread,
|
zx_status_t status = thread.get_info(ZX_INFO_THREAD_EXCEPTION_REPORT,
|
||||||
ZX_INFO_THREAD_EXCEPTION_REPORT,
|
&report,
|
||||||
&report,
|
sizeof(report),
|
||||||
sizeof(report),
|
nullptr,
|
||||||
nullptr,
|
nullptr);
|
||||||
nullptr);
|
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
ZX_LOG(ERROR, status)
|
ZX_LOG(ERROR, status)
|
||||||
<< "zx_object_get_info ZX_INFO_THREAD_EXCEPTION_REPORT";
|
<< "zx_object_get_info ZX_INFO_THREAD_EXCEPTION_REPORT";
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#ifndef CRASHPAD_HANDLER_FUCHSIA_CRASH_REPORT_EXCEPTION_HANDLER_H_
|
#ifndef CRASHPAD_HANDLER_FUCHSIA_CRASH_REPORT_EXCEPTION_HANDLER_H_
|
||||||
#define CRASHPAD_HANDLER_FUCHSIA_CRASH_REPORT_EXCEPTION_HANDLER_H_
|
#define CRASHPAD_HANDLER_FUCHSIA_CRASH_REPORT_EXCEPTION_HANDLER_H_
|
||||||
|
|
||||||
|
#include <lib/zx/process.h>
|
||||||
|
#include <lib/zx/thread.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <zircon/types.h>
|
#include <zircon/types.h>
|
||||||
|
|
||||||
@ -88,7 +90,8 @@ class CrashReportExceptionHandler {
|
|||||||
//! \param[in] thread The handle to the thread of \a process which sustained
|
//! \param[in] thread The handle to the thread of \a process which sustained
|
||||||
//! the exception.
|
//! the exception.
|
||||||
//! \return `true` on success, or `false` with an error logged.
|
//! \return `true` on success, or `false` with an error logged.
|
||||||
bool HandleExceptionHandles(zx_handle_t process, zx_handle_t thread);
|
bool HandleExceptionHandles(const zx::process& process,
|
||||||
|
const zx::thread& thread);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CrashReportDatabase* database_; // weak
|
CrashReportDatabase* database_; // weak
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#include "handler/fuchsia/exception_handler_server.h"
|
#include "handler/fuchsia/exception_handler_server.h"
|
||||||
|
|
||||||
#include <zircon/syscalls/exception.h>
|
#include <lib/zx/time.h>
|
||||||
#include <zircon/syscalls/port.h>
|
#include <zircon/syscalls/port.h>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -26,9 +26,8 @@
|
|||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
|
|
||||||
ExceptionHandlerServer::ExceptionHandlerServer(
|
ExceptionHandlerServer::ExceptionHandlerServer(zx::job root_job,
|
||||||
base::ScopedZxHandle root_job,
|
zx::port exception_port)
|
||||||
base::ScopedZxHandle exception_port)
|
|
||||||
: root_job_(std::move(root_job)),
|
: root_job_(std::move(root_job)),
|
||||||
exception_port_(std::move(exception_port)) {}
|
exception_port_(std::move(exception_port)) {}
|
||||||
|
|
||||||
@ -37,8 +36,7 @@ ExceptionHandlerServer::~ExceptionHandlerServer() = default;
|
|||||||
void ExceptionHandlerServer::Run(CrashReportExceptionHandler* handler) {
|
void ExceptionHandlerServer::Run(CrashReportExceptionHandler* handler) {
|
||||||
while (true) {
|
while (true) {
|
||||||
zx_port_packet_t packet;
|
zx_port_packet_t packet;
|
||||||
zx_status_t status =
|
zx_status_t status = exception_port_.wait(zx::time::infinite(), &packet);
|
||||||
zx_port_wait(exception_port_.get(), ZX_TIME_INFINITE, &packet);
|
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
ZX_LOG(ERROR, status) << "zx_port_wait, aborting";
|
ZX_LOG(ERROR, status) << "zx_port_wait, aborting";
|
||||||
return;
|
return;
|
||||||
|
@ -15,8 +15,10 @@
|
|||||||
#ifndef CRASHPAD_HANDLER_FUCHSIA_EXCEPTION_HANDLER_SERVER_H_
|
#ifndef CRASHPAD_HANDLER_FUCHSIA_EXCEPTION_HANDLER_SERVER_H_
|
||||||
#define CRASHPAD_HANDLER_FUCHSIA_EXCEPTION_HANDLER_SERVER_H_
|
#define CRASHPAD_HANDLER_FUCHSIA_EXCEPTION_HANDLER_SERVER_H_
|
||||||
|
|
||||||
|
#include <lib/zx/job.h>
|
||||||
|
#include <lib/zx/port.h>
|
||||||
|
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/fuchsia/scoped_zx_handle.h"
|
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
|
|
||||||
@ -33,8 +35,7 @@ class ExceptionHandlerServer {
|
|||||||
//! port of this job.
|
//! port of this job.
|
||||||
//! \param[in] exception_port The exception port that this server will
|
//! \param[in] exception_port The exception port that this server will
|
||||||
//! monitor.
|
//! monitor.
|
||||||
ExceptionHandlerServer(base::ScopedZxHandle root_job,
|
ExceptionHandlerServer(zx::job root_job, zx::port exception_port);
|
||||||
base::ScopedZxHandle exception_port);
|
|
||||||
~ExceptionHandlerServer();
|
~ExceptionHandlerServer();
|
||||||
|
|
||||||
//! \brief Runs the exception-handling server.
|
//! \brief Runs the exception-handling server.
|
||||||
@ -44,8 +45,8 @@ class ExceptionHandlerServer {
|
|||||||
void Run(CrashReportExceptionHandler* handler);
|
void Run(CrashReportExceptionHandler* handler);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
base::ScopedZxHandle root_job_;
|
zx::job root_job_;
|
||||||
base::ScopedZxHandle exception_port_;
|
zx::port exception_port_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ExceptionHandlerServer);
|
DISALLOW_COPY_AND_ASSIGN(ExceptionHandlerServer);
|
||||||
};
|
};
|
||||||
|
@ -943,14 +943,13 @@ int HandlerMain(int argc,
|
|||||||
// owns them in this process. There is currently no "connect-later" mode on
|
// owns them in this process. There is currently no "connect-later" mode on
|
||||||
// Fuchsia, all the binding must be done by the client before starting
|
// Fuchsia, all the binding must be done by the client before starting
|
||||||
// crashpad_handler.
|
// crashpad_handler.
|
||||||
base::ScopedZxHandle root_job(zx_take_startup_handle(PA_HND(PA_USER0, 0)));
|
zx::job root_job(zx_take_startup_handle(PA_HND(PA_USER0, 0)));
|
||||||
if (!root_job.is_valid()) {
|
if (!root_job.is_valid()) {
|
||||||
LOG(ERROR) << "no process handle passed in startup handle 0";
|
LOG(ERROR) << "no process handle passed in startup handle 0";
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
base::ScopedZxHandle exception_port(
|
zx::port exception_port(zx_take_startup_handle(PA_HND(PA_USER0, 1)));
|
||||||
zx_take_startup_handle(PA_HND(PA_USER0, 1)));
|
|
||||||
if (!exception_port.is_valid()) {
|
if (!exception_port.is_valid()) {
|
||||||
LOG(ERROR) << "no exception port handle passed in startup handle 1";
|
LOG(ERROR) << "no exception port handle passed in startup handle 1";
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "snapshot/win/process_snapshot_win.h"
|
#include "snapshot/win/process_snapshot_win.h"
|
||||||
#elif defined(OS_FUCHSIA)
|
#elif defined(OS_FUCHSIA)
|
||||||
#include <zircon/process.h>
|
#include <lib/zx/process.h>
|
||||||
#include "snapshot/fuchsia/process_snapshot_fuchsia.h"
|
#include "snapshot/fuchsia/process_snapshot_fuchsia.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ CrashpadInfoClientOptions SelfProcessSnapshotAndGetCrashpadOptions() {
|
|||||||
GetCurrentProcess(), ProcessSuspensionState::kRunning, 0, 0));
|
GetCurrentProcess(), ProcessSuspensionState::kRunning, 0, 0));
|
||||||
#elif defined(OS_FUCHSIA)
|
#elif defined(OS_FUCHSIA)
|
||||||
ProcessSnapshotFuchsia process_snapshot;
|
ProcessSnapshotFuchsia process_snapshot;
|
||||||
EXPECT_TRUE(process_snapshot.Initialize(zx_process_self()));
|
EXPECT_TRUE(process_snapshot.Initialize(*zx::process::self()));
|
||||||
#else
|
#else
|
||||||
#error Port.
|
#error Port.
|
||||||
#endif // OS_MACOSX
|
#endif // OS_MACOSX
|
||||||
|
@ -32,8 +32,7 @@
|
|||||||
#include "util/process/process_memory_native.h"
|
#include "util/process/process_memory_native.h"
|
||||||
|
|
||||||
#if defined(OS_FUCHSIA)
|
#if defined(OS_FUCHSIA)
|
||||||
|
#include <lib/zx/process.h>
|
||||||
#include <zircon/syscalls.h>
|
|
||||||
|
|
||||||
#include "base/fuchsia/fuchsia_logging.h"
|
#include "base/fuchsia/fuchsia_logging.h"
|
||||||
|
|
||||||
@ -61,14 +60,12 @@ namespace {
|
|||||||
|
|
||||||
#if defined(OS_FUCHSIA)
|
#if defined(OS_FUCHSIA)
|
||||||
|
|
||||||
void LocateExecutable(ProcessType process,
|
void LocateExecutable(const ProcessType& process,
|
||||||
ProcessMemory* memory,
|
ProcessMemory* memory,
|
||||||
VMAddress* elf_address) {
|
VMAddress* elf_address) {
|
||||||
uintptr_t debug_address;
|
uintptr_t debug_address;
|
||||||
zx_status_t status = zx_object_get_property(process,
|
zx_status_t status = process->get_property(
|
||||||
ZX_PROP_PROCESS_DEBUG_ADDR,
|
ZX_PROP_PROCESS_DEBUG_ADDR, &debug_address, sizeof(debug_address));
|
||||||
&debug_address,
|
|
||||||
sizeof(debug_address));
|
|
||||||
ASSERT_EQ(status, ZX_OK)
|
ASSERT_EQ(status, ZX_OK)
|
||||||
<< "zx_object_get_property: ZX_PROP_PROCESS_DEBUG_ADDR";
|
<< "zx_object_get_property: ZX_PROP_PROCESS_DEBUG_ADDR";
|
||||||
// Can be 0 if requested before the loader has loaded anything.
|
// Can be 0 if requested before the loader has loaded anything.
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
|
|
||||||
#include "snapshot/fuchsia/memory_map_fuchsia.h"
|
#include "snapshot/fuchsia/memory_map_fuchsia.h"
|
||||||
|
|
||||||
#include <zircon/syscalls.h>
|
|
||||||
|
|
||||||
#include "base/fuchsia/fuchsia_logging.h"
|
#include "base/fuchsia/fuchsia_logging.h"
|
||||||
#include "util/numeric/checked_range.h"
|
#include "util/numeric/checked_range.h"
|
||||||
|
|
||||||
@ -25,7 +23,7 @@ MemoryMapFuchsia::MemoryMapFuchsia() = default;
|
|||||||
|
|
||||||
MemoryMapFuchsia::~MemoryMapFuchsia() = default;
|
MemoryMapFuchsia::~MemoryMapFuchsia() = default;
|
||||||
|
|
||||||
bool MemoryMapFuchsia::Initialize(zx_handle_t process) {
|
bool MemoryMapFuchsia::Initialize(const zx::process& process) {
|
||||||
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
||||||
|
|
||||||
// There's no way to know what an appropriate buffer size is before starting.
|
// There's no way to know what an appropriate buffer size is before starting.
|
||||||
@ -40,12 +38,11 @@ bool MemoryMapFuchsia::Initialize(zx_handle_t process) {
|
|||||||
size_t actual;
|
size_t actual;
|
||||||
size_t available;
|
size_t available;
|
||||||
zx_status_t status =
|
zx_status_t status =
|
||||||
zx_object_get_info(process,
|
process.get_info(ZX_INFO_PROCESS_MAPS,
|
||||||
ZX_INFO_PROCESS_MAPS,
|
&map_entries_[0],
|
||||||
&map_entries_[0],
|
map_entries_.size() * sizeof(map_entries_[0]),
|
||||||
map_entries_.size() * sizeof(map_entries_[0]),
|
&actual,
|
||||||
&actual,
|
&available);
|
||||||
&available);
|
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
ZX_LOG(ERROR, status) << "zx_object_get_info ZX_INFO_PROCESS_MAPS";
|
ZX_LOG(ERROR, status) << "zx_object_get_info ZX_INFO_PROCESS_MAPS";
|
||||||
map_entries_.clear();
|
map_entries_.clear();
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#ifndef CRASHPAD_SNAPSHOT_FUCHSIA_MEMORY_MAP_FUCHSIA_H_
|
#ifndef CRASHPAD_SNAPSHOT_FUCHSIA_MEMORY_MAP_FUCHSIA_H_
|
||||||
#define CRASHPAD_SNAPSHOT_FUCHSIA_MEMORY_MAP_FUCHSIA_H_
|
#define CRASHPAD_SNAPSHOT_FUCHSIA_MEMORY_MAP_FUCHSIA_H_
|
||||||
|
|
||||||
|
#include <lib/zx/process.h>
|
||||||
#include <zircon/syscalls/object.h>
|
#include <zircon/syscalls/object.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -33,7 +34,7 @@ class MemoryMapFuchsia {
|
|||||||
//! regions in the given process.
|
//! regions in the given process.
|
||||||
//!
|
//!
|
||||||
//! \return `true` on success, or `false`, with an error logged.
|
//! \return `true` on success, or `false`, with an error logged.
|
||||||
bool Initialize(zx_handle_t process);
|
bool Initialize(const zx::process& process);
|
||||||
|
|
||||||
//! \brief Searches through the previously retrieved memory map for the given
|
//! \brief Searches through the previously retrieved memory map for the given
|
||||||
//! address. If found, returns the deepest `zx_info_maps_t` mapping that
|
//! address. If found, returns the deepest `zx_info_maps_t` mapping that
|
||||||
|
@ -14,11 +14,11 @@
|
|||||||
|
|
||||||
#include "snapshot/fuchsia/process_reader_fuchsia.h"
|
#include "snapshot/fuchsia/process_reader_fuchsia.h"
|
||||||
|
|
||||||
|
#include <lib/zx/thread.h>
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#include <zircon/syscalls.h>
|
#include <zircon/syscalls.h>
|
||||||
|
|
||||||
#include "base/fuchsia/fuchsia_logging.h"
|
#include "base/fuchsia/fuchsia_logging.h"
|
||||||
#include "base/fuchsia/scoped_zx_handle.h"
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "util/fuchsia/koid_utilities.h"
|
#include "util/fuchsia/koid_utilities.h"
|
||||||
|
|
||||||
@ -83,15 +83,15 @@ ProcessReaderFuchsia::ProcessReaderFuchsia() = default;
|
|||||||
|
|
||||||
ProcessReaderFuchsia::~ProcessReaderFuchsia() = default;
|
ProcessReaderFuchsia::~ProcessReaderFuchsia() = default;
|
||||||
|
|
||||||
bool ProcessReaderFuchsia::Initialize(zx_handle_t process) {
|
bool ProcessReaderFuchsia::Initialize(const zx::process& process) {
|
||||||
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
||||||
|
|
||||||
process_ = process;
|
process_ = zx::unowned_process(process);
|
||||||
|
|
||||||
process_memory_.reset(new ProcessMemoryFuchsia());
|
process_memory_.reset(new ProcessMemoryFuchsia());
|
||||||
process_memory_->Initialize(process_);
|
process_memory_->Initialize(*process_);
|
||||||
|
|
||||||
memory_map_.Initialize(process_);
|
memory_map_.Initialize(*process_);
|
||||||
|
|
||||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||||
return true;
|
return true;
|
||||||
@ -134,7 +134,7 @@ void ProcessReaderFuchsia::InitializeModules() {
|
|||||||
{
|
{
|
||||||
char name[ZX_MAX_NAME_LEN];
|
char name[ZX_MAX_NAME_LEN];
|
||||||
zx_status_t status =
|
zx_status_t status =
|
||||||
zx_object_get_property(process_, ZX_PROP_NAME, name, sizeof(name));
|
process_->get_property(ZX_PROP_NAME, name, sizeof(name));
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
LOG(ERROR) << "zx_object_get_property ZX_PROP_NAME";
|
LOG(ERROR) << "zx_object_get_property ZX_PROP_NAME";
|
||||||
return;
|
return;
|
||||||
@ -147,10 +147,8 @@ void ProcessReaderFuchsia::InitializeModules() {
|
|||||||
// walk the list to fill out modules_.
|
// walk the list to fill out modules_.
|
||||||
|
|
||||||
uintptr_t debug_address;
|
uintptr_t debug_address;
|
||||||
zx_status_t status = zx_object_get_property(process_,
|
zx_status_t status = process_->get_property(
|
||||||
ZX_PROP_PROCESS_DEBUG_ADDR,
|
ZX_PROP_PROCESS_DEBUG_ADDR, &debug_address, sizeof(debug_address));
|
||||||
&debug_address,
|
|
||||||
sizeof(debug_address));
|
|
||||||
if (status != ZX_OK || debug_address == 0) {
|
if (status != ZX_OK || debug_address == 0) {
|
||||||
LOG(ERROR) << "zx_object_get_property ZX_PROP_PROCESS_DEBUG_ADDR";
|
LOG(ERROR) << "zx_object_get_property ZX_PROP_PROCESS_DEBUG_ADDR";
|
||||||
return;
|
return;
|
||||||
@ -250,9 +248,9 @@ void ProcessReaderFuchsia::InitializeThreads() {
|
|||||||
initialized_threads_ = true;
|
initialized_threads_ = true;
|
||||||
|
|
||||||
std::vector<zx_koid_t> thread_koids =
|
std::vector<zx_koid_t> thread_koids =
|
||||||
GetChildKoids(process_, ZX_INFO_PROCESS_THREADS);
|
GetChildKoids(*process_, ZX_INFO_PROCESS_THREADS);
|
||||||
std::vector<base::ScopedZxHandle> thread_handles =
|
std::vector<zx::thread> thread_handles =
|
||||||
GetHandlesForChildKoids(process_, thread_koids);
|
GetHandlesForThreadKoids(*process_, thread_koids);
|
||||||
DCHECK_EQ(thread_koids.size(), thread_handles.size());
|
DCHECK_EQ(thread_koids.size(), thread_handles.size());
|
||||||
|
|
||||||
for (size_t i = 0; i < thread_handles.size(); ++i) {
|
for (size_t i = 0; i < thread_handles.size(); ++i) {
|
||||||
@ -261,8 +259,8 @@ void ProcessReaderFuchsia::InitializeThreads() {
|
|||||||
|
|
||||||
if (thread_handles[i].is_valid()) {
|
if (thread_handles[i].is_valid()) {
|
||||||
char name[ZX_MAX_NAME_LEN] = {0};
|
char name[ZX_MAX_NAME_LEN] = {0};
|
||||||
zx_status_t status = zx_object_get_property(
|
zx_status_t status =
|
||||||
thread_handles[i].get(), ZX_PROP_NAME, &name, sizeof(name));
|
thread_handles[i].get_property(ZX_PROP_NAME, &name, sizeof(name));
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
ZX_LOG(WARNING, status) << "zx_object_get_property ZX_PROP_NAME";
|
ZX_LOG(WARNING, status) << "zx_object_get_property ZX_PROP_NAME";
|
||||||
} else {
|
} else {
|
||||||
@ -270,12 +268,8 @@ void ProcessReaderFuchsia::InitializeThreads() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
zx_info_thread_t thread_info;
|
zx_info_thread_t thread_info;
|
||||||
status = zx_object_get_info(thread_handles[i].get(),
|
status = thread_handles[i].get_info(
|
||||||
ZX_INFO_THREAD,
|
ZX_INFO_THREAD, &thread_info, sizeof(thread_info), nullptr, nullptr);
|
||||||
&thread_info,
|
|
||||||
sizeof(thread_info),
|
|
||||||
nullptr,
|
|
||||||
nullptr);
|
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
ZX_LOG(WARNING, status) << "zx_object_get_info ZX_INFO_THREAD";
|
ZX_LOG(WARNING, status) << "zx_object_get_info ZX_INFO_THREAD";
|
||||||
} else {
|
} else {
|
||||||
@ -283,10 +277,8 @@ void ProcessReaderFuchsia::InitializeThreads() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
zx_thread_state_general_regs_t regs;
|
zx_thread_state_general_regs_t regs;
|
||||||
status = zx_thread_read_state(thread_handles[i].get(),
|
status = thread_handles[i].read_state(
|
||||||
ZX_THREAD_STATE_GENERAL_REGS,
|
ZX_THREAD_STATE_GENERAL_REGS, ®s, sizeof(regs));
|
||||||
®s,
|
|
||||||
sizeof(regs));
|
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
ZX_LOG(WARNING, status) << "zx_thread_read_state";
|
ZX_LOG(WARNING, status) << "zx_thread_read_state";
|
||||||
} else {
|
} else {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#ifndef CRASHPAD_SNAPSHOT_FUCHSIA_PROCESS_READER_H_
|
#ifndef CRASHPAD_SNAPSHOT_FUCHSIA_PROCESS_READER_H_
|
||||||
#define CRASHPAD_SNAPSHOT_FUCHSIA_PROCESS_READER_H_
|
#define CRASHPAD_SNAPSHOT_FUCHSIA_PROCESS_READER_H_
|
||||||
|
|
||||||
|
#include <lib/zx/process.h>
|
||||||
#include <zircon/syscalls/debug.h>
|
#include <zircon/syscalls/debug.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -94,7 +95,7 @@ class ProcessReaderFuchsia {
|
|||||||
//! \return `true` on success, indicating that this object will respond
|
//! \return `true` on success, indicating that this object will respond
|
||||||
//! validly to further method calls. `false` on failure. On failure, no
|
//! validly to further method calls. `false` on failure. On failure, no
|
||||||
//! further method calls should be made.
|
//! further method calls should be made.
|
||||||
bool Initialize(zx_handle_t process);
|
bool Initialize(const zx::process& process);
|
||||||
|
|
||||||
//! \return The modules loaded in the process. The first element (at index
|
//! \return The modules loaded in the process. The first element (at index
|
||||||
//! `0`) corresponds to the main executable.
|
//! `0`) corresponds to the main executable.
|
||||||
@ -121,7 +122,7 @@ class ProcessReaderFuchsia {
|
|||||||
std::vector<std::unique_ptr<ProcessMemoryRange>> process_memory_ranges_;
|
std::vector<std::unique_ptr<ProcessMemoryRange>> process_memory_ranges_;
|
||||||
std::unique_ptr<ProcessMemoryFuchsia> process_memory_;
|
std::unique_ptr<ProcessMemoryFuchsia> process_memory_;
|
||||||
MemoryMapFuchsia memory_map_;
|
MemoryMapFuchsia memory_map_;
|
||||||
zx_handle_t process_;
|
zx::unowned_process process_;
|
||||||
bool initialized_modules_ = false;
|
bool initialized_modules_ = false;
|
||||||
bool initialized_threads_ = false;
|
bool initialized_threads_ = false;
|
||||||
InitializationStateDcheck initialized_;
|
InitializationStateDcheck initialized_;
|
||||||
|
@ -31,7 +31,7 @@ namespace {
|
|||||||
|
|
||||||
TEST(ProcessReaderFuchsia, SelfBasic) {
|
TEST(ProcessReaderFuchsia, SelfBasic) {
|
||||||
ProcessReaderFuchsia process_reader;
|
ProcessReaderFuchsia process_reader;
|
||||||
ASSERT_TRUE(process_reader.Initialize(zx_process_self()));
|
ASSERT_TRUE(process_reader.Initialize(*zx::process::self()));
|
||||||
|
|
||||||
static constexpr char kTestMemory[] = "Some test memory";
|
static constexpr char kTestMemory[] = "Some test memory";
|
||||||
char buffer[arraysize(kTestMemory)];
|
char buffer[arraysize(kTestMemory)];
|
||||||
@ -82,7 +82,7 @@ class BasicChildTest : public MultiprocessExec {
|
|||||||
private:
|
private:
|
||||||
void MultiprocessParent() override {
|
void MultiprocessParent() override {
|
||||||
ProcessReaderFuchsia process_reader;
|
ProcessReaderFuchsia process_reader;
|
||||||
ASSERT_TRUE(process_reader.Initialize(ChildProcess()));
|
ASSERT_TRUE(process_reader.Initialize(*ChildProcess()));
|
||||||
|
|
||||||
zx_vaddr_t addr;
|
zx_vaddr_t addr;
|
||||||
ASSERT_TRUE(ReadFileExactly(ReadPipeHandle(), &addr, sizeof(addr)));
|
ASSERT_TRUE(ReadFileExactly(ReadPipeHandle(), &addr, sizeof(addr)));
|
||||||
@ -149,10 +149,10 @@ class ThreadsChildTest : public MultiprocessExec {
|
|||||||
ASSERT_TRUE(ReadFileExactly(ReadPipeHandle(), &c, 1));
|
ASSERT_TRUE(ReadFileExactly(ReadPipeHandle(), &c, 1));
|
||||||
ASSERT_EQ(c, ' ');
|
ASSERT_EQ(c, ' ');
|
||||||
|
|
||||||
ScopedTaskSuspend suspend(ChildProcess());
|
ScopedTaskSuspend suspend(*ChildProcess());
|
||||||
|
|
||||||
ProcessReaderFuchsia process_reader;
|
ProcessReaderFuchsia process_reader;
|
||||||
ASSERT_TRUE(process_reader.Initialize(ChildProcess()));
|
ASSERT_TRUE(process_reader.Initialize(*ChildProcess()));
|
||||||
|
|
||||||
const auto& threads = process_reader.Threads();
|
const auto& threads = process_reader.Threads();
|
||||||
EXPECT_EQ(threads.size(), 6u);
|
EXPECT_EQ(threads.size(), 6u);
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
|
|
||||||
#include "snapshot/fuchsia/process_snapshot_fuchsia.h"
|
#include "snapshot/fuchsia/process_snapshot_fuchsia.h"
|
||||||
|
|
||||||
#include <zircon/process.h>
|
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "util/fuchsia/koid_utilities.h"
|
#include "util/fuchsia/koid_utilities.h"
|
||||||
|
|
||||||
@ -25,7 +23,7 @@ ProcessSnapshotFuchsia::ProcessSnapshotFuchsia() = default;
|
|||||||
|
|
||||||
ProcessSnapshotFuchsia::~ProcessSnapshotFuchsia() = default;
|
ProcessSnapshotFuchsia::~ProcessSnapshotFuchsia() = default;
|
||||||
|
|
||||||
bool ProcessSnapshotFuchsia::Initialize(zx_handle_t process) {
|
bool ProcessSnapshotFuchsia::Initialize(const zx::process& process) {
|
||||||
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
||||||
|
|
||||||
if (gettimeofday(&snapshot_time_, nullptr) != 0) {
|
if (gettimeofday(&snapshot_time_, nullptr) != 0) {
|
||||||
@ -95,7 +93,7 @@ void ProcessSnapshotFuchsia::GetCrashpadOptions(
|
|||||||
|
|
||||||
pid_t ProcessSnapshotFuchsia::ProcessID() const {
|
pid_t ProcessSnapshotFuchsia::ProcessID() const {
|
||||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||||
return GetKoidForHandle(zx_process_self());
|
return GetKoidForHandle(*zx::process::self());
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t ProcessSnapshotFuchsia::ParentProcessID() const {
|
pid_t ProcessSnapshotFuchsia::ParentProcessID() const {
|
||||||
|
@ -15,9 +15,10 @@
|
|||||||
#ifndef CRASHPAD_SNAPSHOT_FUCHSIA_PROCESS_SNAPSHOT_FUCHSIA_H_
|
#ifndef CRASHPAD_SNAPSHOT_FUCHSIA_PROCESS_SNAPSHOT_FUCHSIA_H_
|
||||||
#define CRASHPAD_SNAPSHOT_FUCHSIA_PROCESS_SNAPSHOT_FUCHSIA_H_
|
#define CRASHPAD_SNAPSHOT_FUCHSIA_PROCESS_SNAPSHOT_FUCHSIA_H_
|
||||||
|
|
||||||
|
#include <lib/zx/process.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <zircon/types.h>
|
|
||||||
#include <zircon/syscalls/exception.h>
|
#include <zircon/syscalls/exception.h>
|
||||||
|
#include <zircon/types.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -50,7 +51,7 @@ class ProcessSnapshotFuchsia : public ProcessSnapshot {
|
|||||||
//!
|
//!
|
||||||
//! \return `true` if the snapshot could be created, `false` otherwise with
|
//! \return `true` if the snapshot could be created, `false` otherwise with
|
||||||
//! an appropriate message logged.
|
//! an appropriate message logged.
|
||||||
bool Initialize(zx_handle_t process);
|
bool Initialize(const zx::process& process);
|
||||||
|
|
||||||
//! \brief Initializes the object's exception.
|
//! \brief Initializes the object's exception.
|
||||||
//!
|
//!
|
||||||
|
@ -101,7 +101,7 @@ static_library("test") {
|
|||||||
|
|
||||||
configs += [
|
configs += [
|
||||||
"../build:crashpad_is_in_chromium",
|
"../build:crashpad_is_in_chromium",
|
||||||
"../build:crashpad_is_in_fuchsia"
|
"../build:crashpad_is_in_fuchsia",
|
||||||
]
|
]
|
||||||
|
|
||||||
data = [
|
data = [
|
||||||
@ -127,10 +127,13 @@ static_library("test") {
|
|||||||
libs = [ "shell32.lib" ]
|
libs = [ "shell32.lib" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crashpad_is_fuchsia && crashpad_is_in_fuchsia) {
|
if (crashpad_is_fuchsia) {
|
||||||
deps += [
|
public_deps = [
|
||||||
"//zircon/public/lib/fdio",
|
"../third_party/fuchsia:zx",
|
||||||
]
|
]
|
||||||
|
if (crashpad_is_in_fuchsia) {
|
||||||
|
deps += [ "//zircon/public/lib/fdio" ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,13 +16,12 @@
|
|||||||
|
|
||||||
#include <lib/fdio/io.h>
|
#include <lib/fdio/io.h>
|
||||||
#include <lib/fdio/spawn.h>
|
#include <lib/fdio/spawn.h>
|
||||||
#include <zircon/process.h>
|
#include <lib/zx/process.h>
|
||||||
|
#include <lib/zx/time.h>
|
||||||
#include <zircon/processargs.h>
|
#include <zircon/processargs.h>
|
||||||
#include <zircon/syscalls.h>
|
|
||||||
|
|
||||||
#include "base/files/scoped_file.h"
|
#include "base/files/scoped_file.h"
|
||||||
#include "base/fuchsia/fuchsia_logging.h"
|
#include "base/fuchsia/fuchsia_logging.h"
|
||||||
#include "base/fuchsia/scoped_zx_handle.h"
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
@ -49,7 +48,7 @@ struct MultiprocessInfo {
|
|||||||
MultiprocessInfo() {}
|
MultiprocessInfo() {}
|
||||||
base::ScopedFD stdin_write;
|
base::ScopedFD stdin_write;
|
||||||
base::ScopedFD stdout_read;
|
base::ScopedFD stdout_read;
|
||||||
base::ScopedZxHandle child;
|
zx::process child;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
@ -68,19 +67,14 @@ void Multiprocess::Run() {
|
|||||||
// Wait until the child exits.
|
// Wait until the child exits.
|
||||||
zx_signals_t signals;
|
zx_signals_t signals;
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
zx_object_wait_one(
|
info_->child.wait_one(ZX_TASK_TERMINATED, zx::time::infinite(), &signals),
|
||||||
info_->child.get(), ZX_TASK_TERMINATED, ZX_TIME_INFINITE, &signals),
|
|
||||||
ZX_OK);
|
ZX_OK);
|
||||||
ASSERT_EQ(signals, ZX_TASK_TERMINATED);
|
ASSERT_EQ(signals, ZX_TASK_TERMINATED);
|
||||||
|
|
||||||
// Get the child's exit code.
|
// Get the child's exit code.
|
||||||
zx_info_process_t proc_info;
|
zx_info_process_t proc_info;
|
||||||
zx_status_t status = zx_object_get_info(info_->child.get(),
|
zx_status_t status = info_->child.get_info(
|
||||||
ZX_INFO_PROCESS,
|
ZX_INFO_PROCESS, &proc_info, sizeof(proc_info), nullptr, nullptr);
|
||||||
&proc_info,
|
|
||||||
sizeof(proc_info),
|
|
||||||
nullptr,
|
|
||||||
nullptr);
|
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
ZX_LOG(ERROR, status) << "zx_object_get_info";
|
ZX_LOG(ERROR, status) << "zx_object_get_info";
|
||||||
ADD_FAILURE() << "Unable to get exit code of child";
|
ADD_FAILURE() << "Unable to get exit code of child";
|
||||||
@ -188,7 +182,7 @@ void MultiprocessExec::MultiprocessChild() {
|
|||||||
uint32_t flags = FDIO_SPAWN_CLONE_ALL & ~FDIO_SPAWN_CLONE_STDIO;
|
uint32_t flags = FDIO_SPAWN_CLONE_ALL & ~FDIO_SPAWN_CLONE_STDIO;
|
||||||
|
|
||||||
char error_message[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
|
char error_message[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
|
||||||
zx_handle_t child;
|
zx::process child;
|
||||||
zx_status_t status = fdio_spawn_etc(ZX_HANDLE_INVALID,
|
zx_status_t status = fdio_spawn_etc(ZX_HANDLE_INVALID,
|
||||||
flags,
|
flags,
|
||||||
command_.value().c_str(),
|
command_.value().c_str(),
|
||||||
@ -196,14 +190,14 @@ void MultiprocessExec::MultiprocessChild() {
|
|||||||
nullptr,
|
nullptr,
|
||||||
kActionCount,
|
kActionCount,
|
||||||
actions,
|
actions,
|
||||||
&child,
|
child.reset_and_get_address(),
|
||||||
error_message);
|
error_message);
|
||||||
ZX_CHECK(status == ZX_OK, status) << "fdio_spawn_etc: " << error_message;
|
ZX_CHECK(status == ZX_OK, status) << "fdio_spawn_etc: " << error_message;
|
||||||
info()->child.reset(child);
|
info()->child = std::move(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessType MultiprocessExec::ChildProcess() {
|
ProcessType MultiprocessExec::ChildProcess() {
|
||||||
return info()->child.get();
|
return zx::unowned_process(info()->child);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include "test/process_type.h"
|
#include "test/process_type.h"
|
||||||
|
|
||||||
#if defined(OS_FUCHSIA)
|
#if defined(OS_FUCHSIA)
|
||||||
#include <zircon/process.h>
|
#include <lib/zx/process.h>
|
||||||
#elif defined(OS_POSIX)
|
#elif defined(OS_POSIX)
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
@ -25,7 +25,7 @@ namespace test {
|
|||||||
|
|
||||||
ProcessType GetSelfProcess() {
|
ProcessType GetSelfProcess() {
|
||||||
#if defined(OS_FUCHSIA)
|
#if defined(OS_FUCHSIA)
|
||||||
return zx_process_self();
|
return zx::process::self();
|
||||||
#elif defined(OS_POSIX)
|
#elif defined(OS_POSIX)
|
||||||
return getpid();
|
return getpid();
|
||||||
#elif defined(OS_WIN)
|
#elif defined(OS_WIN)
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
#if defined(OS_FUCHSIA)
|
#if defined(OS_FUCHSIA)
|
||||||
#include <zircon/types.h>
|
#include <lib/zx/process.h>
|
||||||
#elif defined(OS_POSIX)
|
#elif defined(OS_POSIX)
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#elif defined(OS_WIN)
|
#elif defined(OS_WIN)
|
||||||
@ -29,7 +29,7 @@ namespace crashpad {
|
|||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
#if defined(OS_FUCHSIA)
|
#if defined(OS_FUCHSIA)
|
||||||
using ProcessType = zx_handle_t;
|
using ProcessType = zx::unowned_process;
|
||||||
#elif defined(OS_POSIX) || DOXYGEN
|
#elif defined(OS_POSIX) || DOXYGEN
|
||||||
//! \brief Alias for platform-specific type to represent a process.
|
//! \brief Alias for platform-specific type to represent a process.
|
||||||
using ProcessType = pid_t;
|
using ProcessType = pid_t;
|
||||||
|
82
third_party/fuchsia/BUILD.gn
vendored
Normal file
82
third_party/fuchsia/BUILD.gn
vendored
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# Copyright 2018 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.
|
||||||
|
|
||||||
|
import("../../build/crashpad_buildconfig.gni")
|
||||||
|
|
||||||
|
if (crashpad_is_in_fuchsia) {
|
||||||
|
group("zx") {
|
||||||
|
public_deps = [
|
||||||
|
"//zircon/public/lib/zx",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
} else if (crashpad_is_in_chromium) {
|
||||||
|
group("zx") {
|
||||||
|
public_deps = [
|
||||||
|
"//third_party/fuchsia-sdk:zx",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sdk_pkg_path = "sdk/linux-amd64/pkg"
|
||||||
|
|
||||||
|
config("zx_config") {
|
||||||
|
visibility = [ ":zx" ]
|
||||||
|
include_dirs = [ "$sdk_pkg_path/zx/include" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
static_library("zx") {
|
||||||
|
sources = [
|
||||||
|
"$sdk_pkg_path/zx/channel.cpp",
|
||||||
|
"$sdk_pkg_path/zx/event.cpp",
|
||||||
|
"$sdk_pkg_path/zx/eventpair.cpp",
|
||||||
|
"$sdk_pkg_path/zx/fifo.cpp",
|
||||||
|
"$sdk_pkg_path/zx/guest.cpp",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/bti.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/channel.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/event.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/eventpair.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/fifo.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/guest.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/handle.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/interrupt.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/job.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/log.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/object.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/object_traits.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/pmt.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/port.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/process.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/resource.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/socket.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/task.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/thread.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/time.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/timer.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/vmar.h",
|
||||||
|
"$sdk_pkg_path/zx/include/lib/zx/vmo.h",
|
||||||
|
"$sdk_pkg_path/zx/interrupt.cpp",
|
||||||
|
"$sdk_pkg_path/zx/job.cpp",
|
||||||
|
"$sdk_pkg_path/zx/log.cpp",
|
||||||
|
"$sdk_pkg_path/zx/port.cpp",
|
||||||
|
"$sdk_pkg_path/zx/process.cpp",
|
||||||
|
"$sdk_pkg_path/zx/resource.cpp",
|
||||||
|
"$sdk_pkg_path/zx/socket.cpp",
|
||||||
|
"$sdk_pkg_path/zx/thread.cpp",
|
||||||
|
"$sdk_pkg_path/zx/timer.cpp",
|
||||||
|
"$sdk_pkg_path/zx/vmar.cpp",
|
||||||
|
"$sdk_pkg_path/zx/vmo.cpp",
|
||||||
|
]
|
||||||
|
|
||||||
|
public_configs = [ ":zx_config" ]
|
||||||
|
}
|
||||||
|
}
|
@ -46,7 +46,8 @@
|
|||||||
#include "util/win/scoped_process_suspend.h"
|
#include "util/win/scoped_process_suspend.h"
|
||||||
#include "util/win/xp_compat.h"
|
#include "util/win/xp_compat.h"
|
||||||
#elif defined(OS_FUCHSIA)
|
#elif defined(OS_FUCHSIA)
|
||||||
#include "base/fuchsia/scoped_zx_handle.h"
|
#include <lib/zx/process.h>
|
||||||
|
|
||||||
#include "snapshot/fuchsia/process_snapshot_fuchsia.h"
|
#include "snapshot/fuchsia/process_snapshot_fuchsia.h"
|
||||||
#include "util/fuchsia/koid_utilities.h"
|
#include "util/fuchsia/koid_utilities.h"
|
||||||
#include "util/fuchsia/scoped_task_suspend.h"
|
#include "util/fuchsia/scoped_task_suspend.h"
|
||||||
@ -165,8 +166,8 @@ int GenerateDumpMain(int argc, char* argv[]) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
#elif defined(OS_FUCHSIA)
|
#elif defined(OS_FUCHSIA)
|
||||||
base::ScopedZxHandle task = GetProcessFromKoid(options.pid);
|
zx::process process = GetProcessFromKoid(options.pid);
|
||||||
if (!task.is_valid()) {
|
if (!process.is_valid()) {
|
||||||
LOG(ERROR) << "could not open process " << options.pid;
|
LOG(ERROR) << "could not open process " << options.pid;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -190,7 +191,7 @@ int GenerateDumpMain(int argc, char* argv[]) {
|
|||||||
#elif defined(OS_FUCHSIA)
|
#elif defined(OS_FUCHSIA)
|
||||||
std::unique_ptr<ScopedTaskSuspend> suspend;
|
std::unique_ptr<ScopedTaskSuspend> suspend;
|
||||||
if (options.suspend) {
|
if (options.suspend) {
|
||||||
suspend.reset(new ScopedTaskSuspend(task.get()));
|
suspend.reset(new ScopedTaskSuspend(process));
|
||||||
}
|
}
|
||||||
#endif // OS_MACOSX
|
#endif // OS_MACOSX
|
||||||
|
|
||||||
@ -211,7 +212,7 @@ int GenerateDumpMain(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
#elif defined(OS_FUCHSIA)
|
#elif defined(OS_FUCHSIA)
|
||||||
ProcessSnapshotFuchsia process_snapshot;
|
ProcessSnapshotFuchsia process_snapshot;
|
||||||
if (!process_snapshot.Initialize(task.get())) {
|
if (!process_snapshot.Initialize(process)) {
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
#elif defined(OS_LINUX) || defined(OS_ANDROID)
|
#elif defined(OS_LINUX) || defined(OS_ANDROID)
|
||||||
|
@ -454,6 +454,10 @@ static_library("util") {
|
|||||||
asmflags = [ "/safeseh" ]
|
asmflags = [ "/safeseh" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (crashpad_is_fuchsia) {
|
||||||
|
public_deps += [ "../third_party/fuchsia:zx" ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_boringssl_for_http_transport_socket) {
|
if (use_boringssl_for_http_transport_socket) {
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include "util/fuchsia/koid_utilities.h"
|
#include "util/fuchsia/koid_utilities.h"
|
||||||
|
|
||||||
|
#include <lib/zx/job.h>
|
||||||
|
#include <lib/zx/process.h>
|
||||||
#include <zircon/device/sysinfo.h>
|
#include <zircon/device/sysinfo.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -26,62 +28,104 @@ namespace crashpad {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
base::ScopedZxHandle GetRootJob() {
|
// Casts |handle| into a container of type T, returning a null handle if the
|
||||||
|
// actual handle type does not match that of T.
|
||||||
|
template <typename T>
|
||||||
|
T CastHandle(zx::handle handle) {
|
||||||
|
zx_info_handle_basic_t actual = {};
|
||||||
|
zx_status_t status = handle.get_info(
|
||||||
|
ZX_INFO_HANDLE_BASIC, &actual, sizeof(actual), nullptr, nullptr);
|
||||||
|
if (status != ZX_OK) {
|
||||||
|
ZX_LOG(ERROR, status) << "zx_object_get_info";
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
if (actual.type != T::TYPE) {
|
||||||
|
LOG(ERROR) << "Wrong type: " << actual.type << ", expected " << T::TYPE;
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
return T(std::move(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
zx::job GetRootJob() {
|
||||||
ScopedFileHandle sysinfo(
|
ScopedFileHandle sysinfo(
|
||||||
LoggingOpenFileForRead(base::FilePath("/dev/misc/sysinfo")));
|
LoggingOpenFileForRead(base::FilePath("/dev/misc/sysinfo")));
|
||||||
if (!sysinfo.is_valid())
|
if (!sysinfo.is_valid())
|
||||||
return base::ScopedZxHandle();
|
return zx::job();
|
||||||
|
|
||||||
zx_handle_t root_job;
|
zx::handle root_job;
|
||||||
size_t n = ioctl_sysinfo_get_root_job(sysinfo.get(), &root_job);
|
size_t n = ioctl_sysinfo_get_root_job(sysinfo.get(),
|
||||||
if (n != sizeof(root_job)) {
|
root_job.reset_and_get_address());
|
||||||
|
if (n != sizeof(zx_handle_t)) {
|
||||||
LOG(ERROR) << "unexpected root job size";
|
LOG(ERROR) << "unexpected root job size";
|
||||||
return base::ScopedZxHandle();
|
return zx::job();
|
||||||
}
|
}
|
||||||
return base::ScopedZxHandle(root_job);
|
return CastHandle<zx::job>(std::move(root_job));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FindProcess(const base::ScopedZxHandle& job,
|
// Returns null handle if |koid| is not found or an error occurs. If |was_found|
|
||||||
zx_koid_t koid,
|
// is non-null then it will be set, to distinguish not-found from other errors.
|
||||||
base::ScopedZxHandle* out) {
|
template <typename T, typename U>
|
||||||
for (auto& proc : GetChildHandles(job.get(), ZX_INFO_JOB_PROCESSES)) {
|
T GetChildHandleByKoid(const U& parent, zx_koid_t child_koid, bool* was_found) {
|
||||||
if (GetKoidForHandle(proc.get()) == koid) {
|
zx::handle handle;
|
||||||
*out = std::move(proc);
|
zx_status_t status =
|
||||||
return true;
|
parent.get_child(child_koid, ZX_RIGHT_SAME_RIGHTS, &handle);
|
||||||
}
|
if (was_found)
|
||||||
|
*was_found = (status != ZX_ERR_NOT_FOUND);
|
||||||
|
if (status != ZX_OK) {
|
||||||
|
ZX_LOG(ERROR, status) << "zx_object_get_child";
|
||||||
|
return T();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(scottmg): As this is recursing down the job tree all the handles are
|
return CastHandle<T>(std::move(handle));
|
||||||
// kept open, so this could be very expensive in terms of number of open
|
}
|
||||||
// handles. This function should be replaced by a syscall in the
|
|
||||||
// not-too-distant future, so hopefully OK for now.
|
// Returns an invalid handle if the |koid| was found, but was of the wrong
|
||||||
for (const auto& child_job :
|
// type, or we could not open a handle to it.
|
||||||
GetChildHandles(job.get(), ZX_INFO_JOB_CHILDREN)) {
|
zx::process FindProcess(const zx::job& job, zx_koid_t koid, bool* was_found) {
|
||||||
if (FindProcess(child_job, koid, out))
|
DCHECK(!*was_found);
|
||||||
return true;
|
|
||||||
|
// Look for |koid| as a direct descendent of |job|.
|
||||||
|
auto process = GetChildHandleByKoid<zx::process>(job, koid, was_found);
|
||||||
|
if (*was_found) {
|
||||||
|
// |koid| was found. |process| may still be null, e.g. if a handle could not
|
||||||
|
// be opened to it.
|
||||||
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
// |koid| was not found under |job|, so search child jobs, if any.
|
||||||
|
// Since we only hold a handle to the job we are currently enumerating, child
|
||||||
|
// jobs may go away mid-enumeration.
|
||||||
|
for (auto child_koid : GetChildKoids(job, ZX_INFO_JOB_CHILDREN)) {
|
||||||
|
zx::job child_job = GetChildHandleByKoid<zx::job>(job, child_koid, nullptr);
|
||||||
|
if (!child_job.is_valid())
|
||||||
|
continue;
|
||||||
|
zx::process process = FindProcess(child_job, koid, was_found);
|
||||||
|
if (*was_found)
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
|
||||||
|
DCHECK(!*was_found);
|
||||||
|
return zx::process();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::vector<zx_koid_t> GetChildKoids(zx_handle_t parent,
|
std::vector<zx_koid_t> GetChildKoids(const zx::object_base& parent_object,
|
||||||
zx_object_info_topic_t child_kind) {
|
zx_object_info_topic_t child_kind) {
|
||||||
size_t actual = 0;
|
size_t actual = 0;
|
||||||
size_t available = 0;
|
size_t available = 0;
|
||||||
std::vector<zx_koid_t> result(100);
|
std::vector<zx_koid_t> result(100);
|
||||||
|
zx::unowned_handle parent(parent_object.get());
|
||||||
|
|
||||||
// This is inherently racy. Better if the process is suspended, but there's
|
// This is inherently racy. Better if the process is suspended, but there's
|
||||||
// still no guarantee that a thread isn't externally created. As a result,
|
// still no guarantee that a thread isn't externally created. As a result,
|
||||||
// must be in a retry loop.
|
// must be in a retry loop.
|
||||||
for (;;) {
|
for (;;) {
|
||||||
zx_status_t status = zx_object_get_info(parent,
|
zx_status_t status = parent->get_info(child_kind,
|
||||||
child_kind,
|
result.data(),
|
||||||
result.data(),
|
result.size() * sizeof(zx_koid_t),
|
||||||
result.size() * sizeof(zx_koid_t),
|
&actual,
|
||||||
&actual,
|
&available);
|
||||||
&available);
|
|
||||||
// If the buffer is too small (even zero), the result is still ZX_OK, not
|
// If the buffer is too small (even zero), the result is still ZX_OK, not
|
||||||
// ZX_ERR_BUFFER_TOO_SMALL.
|
// ZX_ERR_BUFFER_TOO_SMALL.
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
@ -102,42 +146,38 @@ std::vector<zx_koid_t> GetChildKoids(zx_handle_t parent,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<base::ScopedZxHandle> GetChildHandles(zx_handle_t parent,
|
std::vector<zx::thread> GetThreadHandles(const zx::process& parent) {
|
||||||
zx_object_info_topic_t type) {
|
auto koids = GetChildKoids(parent, ZX_INFO_PROCESS_THREADS);
|
||||||
auto koids = GetChildKoids(parent, type);
|
return GetHandlesForThreadKoids(parent, koids);
|
||||||
return GetHandlesForChildKoids(parent, koids);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<base::ScopedZxHandle> GetHandlesForChildKoids(
|
std::vector<zx::thread> GetHandlesForThreadKoids(
|
||||||
zx_handle_t parent,
|
const zx::process& parent,
|
||||||
const std::vector<zx_koid_t>& koids) {
|
const std::vector<zx_koid_t>& koids) {
|
||||||
std::vector<base::ScopedZxHandle> result;
|
std::vector<zx::thread> result;
|
||||||
result.reserve(koids.size());
|
result.reserve(koids.size());
|
||||||
for (zx_koid_t koid : koids) {
|
for (zx_koid_t koid : koids) {
|
||||||
result.emplace_back(GetChildHandleByKoid(parent, koid));
|
result.emplace_back(GetThreadHandleByKoid(parent, koid));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
base::ScopedZxHandle GetChildHandleByKoid(zx_handle_t parent,
|
zx::thread GetThreadHandleByKoid(const zx::process& parent,
|
||||||
zx_koid_t child_koid) {
|
zx_koid_t child_koid) {
|
||||||
zx_handle_t handle;
|
return GetChildHandleByKoid<zx::thread>(parent, child_koid, nullptr);
|
||||||
zx_status_t status =
|
|
||||||
zx_object_get_child(parent, child_koid, ZX_RIGHT_SAME_RIGHTS, &handle);
|
|
||||||
if (status != ZX_OK) {
|
|
||||||
ZX_LOG(ERROR, status) << "zx_object_get_child";
|
|
||||||
return base::ScopedZxHandle();
|
|
||||||
}
|
|
||||||
return base::ScopedZxHandle(handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zx_koid_t GetKoidForHandle(zx_handle_t object) {
|
zx_koid_t GetKoidForHandle(const zx::object_base& object) {
|
||||||
zx_info_handle_basic_t info;
|
zx_info_handle_basic_t info;
|
||||||
zx_status_t status = zx_object_get_info(
|
zx_status_t status = zx_object_get_info(object.get(),
|
||||||
object, ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
|
ZX_INFO_HANDLE_BASIC,
|
||||||
|
&info,
|
||||||
|
sizeof(info),
|
||||||
|
nullptr,
|
||||||
|
nullptr);
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
ZX_LOG(ERROR, status) << "zx_object_get_info";
|
ZX_LOG(ERROR, status) << "zx_object_get_info";
|
||||||
return ZX_HANDLE_INVALID;
|
return ZX_KOID_INVALID;
|
||||||
}
|
}
|
||||||
return info.koid;
|
return info.koid;
|
||||||
}
|
}
|
||||||
@ -146,11 +186,11 @@ zx_koid_t GetKoidForHandle(zx_handle_t object) {
|
|||||||
// ioctls that are currently the only way to go from pid to handle. This should
|
// ioctls that are currently the only way to go from pid to handle. This should
|
||||||
// hopefully eventually be replaced by more or less a single
|
// hopefully eventually be replaced by more or less a single
|
||||||
// zx_debug_something() syscall.
|
// zx_debug_something() syscall.
|
||||||
base::ScopedZxHandle GetProcessFromKoid(zx_koid_t koid) {
|
zx::process GetProcessFromKoid(zx_koid_t koid) {
|
||||||
base::ScopedZxHandle result;
|
bool was_found = false;
|
||||||
if (!FindProcess(GetRootJob(), koid, &result)) {
|
zx::process result = FindProcess(GetRootJob(), koid, &was_found);
|
||||||
|
if (!result.is_valid())
|
||||||
LOG(ERROR) << "process " << koid << " not found";
|
LOG(ERROR) << "process " << koid << " not found";
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,13 +15,14 @@
|
|||||||
#ifndef CRASHPAD_UTIL_FUCHSIA_KOID_UTILITIES_H_
|
#ifndef CRASHPAD_UTIL_FUCHSIA_KOID_UTILITIES_H_
|
||||||
#define CRASHPAD_UTIL_FUCHSIA_KOID_UTILITIES_H_
|
#define CRASHPAD_UTIL_FUCHSIA_KOID_UTILITIES_H_
|
||||||
|
|
||||||
|
#include <lib/zx/object.h>
|
||||||
|
#include <lib/zx/process.h>
|
||||||
|
#include <lib/zx/thread.h>
|
||||||
#include <zircon/syscalls/object.h>
|
#include <zircon/syscalls/object.h>
|
||||||
#include <zircon/types.h>
|
#include <zircon/types.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/fuchsia/scoped_zx_handle.h"
|
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
|
|
||||||
//! \brief Get a list of child koids for a parent handle.
|
//! \brief Get a list of child koids for a parent handle.
|
||||||
@ -38,57 +39,50 @@ namespace crashpad {
|
|||||||
//! \return A vector of the koids representing the child objects.
|
//! \return A vector of the koids representing the child objects.
|
||||||
//!
|
//!
|
||||||
//! \sa GetChildHandles
|
//! \sa GetChildHandles
|
||||||
std::vector<zx_koid_t> GetChildKoids(zx_handle_t parent,
|
std::vector<zx_koid_t> GetChildKoids(const zx::object_base& parent,
|
||||||
zx_object_info_topic_t child_kind);
|
zx_object_info_topic_t child_kind);
|
||||||
|
|
||||||
//! \brief Get handles representing a list of child objects of a given parent.
|
//! \brief Get handles representing a list of child objects of a given parent.
|
||||||
//!
|
//!
|
||||||
//! \param[in] parent The handle to the parent object.
|
//! \param[in] parent The handle to the parent object.
|
||||||
//! \param[in] child_kind The type of children to retrieve from \a parent. Valid
|
|
||||||
//! values depend on the type of \a parent, but include
|
|
||||||
//! `ZX_INFO_JOB_CHILDREN` (child jobs of a job), `ZX_INFO_JOB_PROCESSES`
|
|
||||||
//! (child processes of a job), and `ZX_INFO_PROCESS_THREADS` (child threads
|
|
||||||
//! of a process).
|
|
||||||
//! \return The resulting list of handles corresponding to the child objects.
|
//! \return The resulting list of handles corresponding to the child objects.
|
||||||
//!
|
//!
|
||||||
//! \sa GetChildKoids
|
//! \sa GetChildKoids
|
||||||
std::vector<base::ScopedZxHandle> GetChildHandles(
|
std::vector<zx::thread> GetThreadHandles(const zx::process& parent);
|
||||||
zx_handle_t parent,
|
|
||||||
zx_object_info_topic_t child_kind);
|
|
||||||
|
|
||||||
//! \brief Convert a list of koids that are all children of a particular object
|
//! \brief Convert a list of koids that are all children of a particular process
|
||||||
//! into handles.
|
//! into thread handles.
|
||||||
//!
|
//!
|
||||||
//! \param[in] parent The parent object to which the koids belong.
|
//! \param[in] parent The parent object to which the koids belong.
|
||||||
//! \param[in] koids The list of koids.
|
//! \param[in] koids The list of koids.
|
||||||
//! \return The resulting list of handles corresponding to the koids. If an
|
//! \return The resulting list of handles corresponding to the koids. If an
|
||||||
//! element of \a koids is invalid or can't be retrieved, there will be a
|
//! element of \a koids is invalid or can't be retrieved, there will be a
|
||||||
//! corresponding `ZX_HANDLE_INVALID` entry in the return.
|
//! corresponding `ZX_HANDLE_INVALID` entry in the return.
|
||||||
std::vector<base::ScopedZxHandle> GetHandlesForChildKoids(
|
std::vector<zx::thread> GetHandlesForThreadKoids(
|
||||||
zx_handle_t parent,
|
const zx::process& parent,
|
||||||
const std::vector<zx_koid_t>& koids);
|
const std::vector<zx_koid_t>& koids);
|
||||||
|
|
||||||
//! \brief Retrieve the child of a parent handle, based on koid.
|
//! \brief Retrieve the handle of a process' thread, based on koid.
|
||||||
//!
|
//!
|
||||||
//! \param[in] parent The parent object to which the child belongs.
|
//! \param[in] parent The parent object to which the child belongs.
|
||||||
//! \param[in] child_koid The koid of the child to retrieve.
|
//! \param[in] child_koid The koid of the child to retrieve.
|
||||||
//! \return A handle representing \a child_koid, or `ZX_HANDLE_INVALID` if the
|
//! \return A handle representing \a child_koid, or `ZX_HANDLE_INVALID` if the
|
||||||
//! handle could not be retrieved, in which case an error will be logged.
|
//! handle could not be retrieved, in which case an error will be logged.
|
||||||
base::ScopedZxHandle GetChildHandleByKoid(zx_handle_t parent,
|
zx::thread GetThreadHandleByKoid(const zx::process& parent,
|
||||||
zx_koid_t child_koid);
|
zx_koid_t child_koid);
|
||||||
|
|
||||||
//! \brief Gets a process handle given the process' koid.
|
//! \brief Gets a process handle given the process' koid.
|
||||||
//!
|
//!
|
||||||
//! \param[in] koid The process id.
|
//! \param[in] koid The process id.
|
||||||
//! \return A zx_handle_t (owned by a base::ScopedZxHandle) for the process. If
|
//! \return A zx_handle_t (owned by a base::ScopedZxHandle) for the process. If
|
||||||
//! the handle is invalid, an error will have been logged.
|
//! the handle is invalid, an error will have been logged.
|
||||||
base::ScopedZxHandle GetProcessFromKoid(zx_koid_t koid);
|
zx::process GetProcessFromKoid(zx_koid_t koid);
|
||||||
|
|
||||||
//! \brief Retrieves the koid for a given object handle.
|
//! \brief Retrieves the koid for a given object handle.
|
||||||
//!
|
//!
|
||||||
//! \param[in] object The handle for which the koid is to be retrieved.
|
//! \param[in] object The handle for which the koid is to be retrieved.
|
||||||
//! \return The koid of \a handle, or `ZX_HANDLE_INVALID` with an error logged.
|
//! \return The koid of \a handle, or `ZX_HANDLE_INVALID` with an error logged.
|
||||||
zx_koid_t GetKoidForHandle(zx_handle_t object);
|
zx_koid_t GetKoidForHandle(const zx::object_base& object);
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
|
||||||
|
@ -14,14 +14,11 @@
|
|||||||
|
|
||||||
#include "util/fuchsia/scoped_task_suspend.h"
|
#include "util/fuchsia/scoped_task_suspend.h"
|
||||||
|
|
||||||
#include <zircon/process.h>
|
#include <lib/zx/time.h>
|
||||||
#include <zircon/syscalls.h>
|
|
||||||
#include <zircon/syscalls/debug.h>
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/fuchsia/fuchsia_logging.h"
|
#include "base/fuchsia/fuchsia_logging.h"
|
||||||
#include "base/fuchsia/scoped_zx_handle.h"
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "util/fuchsia/koid_utilities.h"
|
#include "util/fuchsia/koid_utilities.h"
|
||||||
|
|
||||||
@ -29,53 +26,37 @@ namespace crashpad {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
zx_obj_type_t GetHandleType(zx_handle_t handle) {
|
|
||||||
zx_info_handle_basic_t basic;
|
|
||||||
zx_status_t status = zx_object_get_info(
|
|
||||||
handle, ZX_INFO_HANDLE_BASIC, &basic, sizeof(basic), nullptr, nullptr);
|
|
||||||
if (status != ZX_OK) {
|
|
||||||
ZX_LOG(ERROR, status) << "zx_object_get_info";
|
|
||||||
return ZX_OBJ_TYPE_NONE;
|
|
||||||
}
|
|
||||||
return basic.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the suspend token of the suspended thread. This function attempts
|
// Returns the suspend token of the suspended thread. This function attempts
|
||||||
// to wait a short time for the thread to actually suspend before returning
|
// to wait a short time for the thread to actually suspend before returning
|
||||||
// but this is not guaranteed.
|
// but this is not guaranteed.
|
||||||
base::ScopedZxHandle SuspendThread(zx_handle_t thread) {
|
zx::suspend_token SuspendThread(const zx::thread& thread) {
|
||||||
zx_handle_t token = ZX_HANDLE_INVALID;
|
zx::suspend_token token;
|
||||||
zx_status_t status = zx_task_suspend_token(thread, &token);
|
zx_status_t status = thread.suspend(&token);
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
ZX_LOG(ERROR, status) << "zx_task_suspend";
|
ZX_LOG(ERROR, status) << "zx_task_suspend";
|
||||||
base::ScopedZxHandle();
|
return zx::suspend_token();
|
||||||
}
|
}
|
||||||
|
|
||||||
zx_signals_t observed = 0u;
|
zx_signals_t observed = 0u;
|
||||||
if (zx_object_wait_one(thread, ZX_THREAD_SUSPENDED,
|
if (thread.wait_one(ZX_THREAD_SUSPENDED,
|
||||||
zx_deadline_after(ZX_MSEC(50)), &observed) != ZX_OK) {
|
zx::deadline_after(zx::msec(50)),
|
||||||
|
&observed) != ZX_OK) {
|
||||||
LOG(ERROR) << "thread failed to suspend";
|
LOG(ERROR) << "thread failed to suspend";
|
||||||
}
|
}
|
||||||
return base::ScopedZxHandle(token);
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ScopedTaskSuspend::ScopedTaskSuspend(zx_handle_t task) {
|
ScopedTaskSuspend::ScopedTaskSuspend(const zx::process& process) {
|
||||||
DCHECK_NE(task, zx_process_self());
|
DCHECK_NE(process.get(), zx::process::self()->get());
|
||||||
DCHECK_NE(task, zx_thread_self());
|
for (const auto& thread : GetThreadHandles(process))
|
||||||
|
suspend_tokens_.push_back(SuspendThread(thread));
|
||||||
zx_obj_type_t type = GetHandleType(task);
|
|
||||||
if (type == ZX_OBJ_TYPE_THREAD) {
|
|
||||||
suspend_tokens_.push_back(SuspendThread(task));
|
|
||||||
} else if (type == ZX_OBJ_TYPE_PROCESS) {
|
|
||||||
for (const auto& thread : GetChildHandles(task, ZX_INFO_PROCESS_THREADS))
|
|
||||||
suspend_tokens_.push_back(SuspendThread(thread.get()));
|
|
||||||
} else {
|
|
||||||
LOG(ERROR) << "unexpected handle type";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedTaskSuspend::~ScopedTaskSuspend() = default;
|
ScopedTaskSuspend::ScopedTaskSuspend(const zx::thread& thread) {
|
||||||
|
DCHECK_NE(thread.get(), zx::thread::self()->get());
|
||||||
|
suspend_tokens_.push_back(SuspendThread(thread));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
@ -15,11 +15,12 @@
|
|||||||
#ifndef CRASHPAD_UTIL_FUCHSIA_SCOPED_TASK_SUSPEND_H_
|
#ifndef CRASHPAD_UTIL_FUCHSIA_SCOPED_TASK_SUSPEND_H_
|
||||||
#define CRASHPAD_UTIL_FUCHSIA_SCOPED_TASK_SUSPEND_H_
|
#define CRASHPAD_UTIL_FUCHSIA_SCOPED_TASK_SUSPEND_H_
|
||||||
|
|
||||||
#include <zircon/types.h>
|
#include <lib/zx/process.h>
|
||||||
|
#include <lib/zx/suspend_token.h>
|
||||||
|
#include <lib/zx/thread.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/fuchsia/scoped_zx_handle.h"
|
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
@ -40,12 +41,13 @@ namespace crashpad {
|
|||||||
//! `zx_process_self()`.
|
//! `zx_process_self()`.
|
||||||
class ScopedTaskSuspend {
|
class ScopedTaskSuspend {
|
||||||
public:
|
public:
|
||||||
explicit ScopedTaskSuspend(zx_handle_t task);
|
explicit ScopedTaskSuspend(const zx::process& process);
|
||||||
~ScopedTaskSuspend();
|
explicit ScopedTaskSuspend(const zx::thread& thread);
|
||||||
|
~ScopedTaskSuspend() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Could be one (for a thread) or many (for every process in a thread).
|
// Could be one (for a thread) or many (for every thread in a process).
|
||||||
std::vector<base::ScopedZxHandle> suspend_tokens_;
|
std::vector<zx::suspend_token> suspend_tokens_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ScopedTaskSuspend);
|
DISALLOW_COPY_AND_ASSIGN(ScopedTaskSuspend);
|
||||||
};
|
};
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
|
|
||||||
#include "util/process/process_memory_fuchsia.h"
|
#include "util/process/process_memory_fuchsia.h"
|
||||||
|
|
||||||
#include <zircon/syscalls.h>
|
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
@ -28,9 +26,13 @@ ProcessMemoryFuchsia::ProcessMemoryFuchsia()
|
|||||||
|
|
||||||
ProcessMemoryFuchsia::~ProcessMemoryFuchsia() {}
|
ProcessMemoryFuchsia::~ProcessMemoryFuchsia() {}
|
||||||
|
|
||||||
bool ProcessMemoryFuchsia::Initialize(zx_handle_t process) {
|
bool ProcessMemoryFuchsia::Initialize(const zx::unowned_process& process) {
|
||||||
|
return Initialize(*process);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProcessMemoryFuchsia::Initialize(const zx::process& process) {
|
||||||
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
||||||
process_ = process;
|
process_ = zx::unowned_process(process);
|
||||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -42,8 +44,7 @@ ssize_t ProcessMemoryFuchsia::ReadUpTo(VMAddress address,
|
|||||||
DCHECK_LE(size, size_t{std::numeric_limits<ssize_t>::max()});
|
DCHECK_LE(size, size_t{std::numeric_limits<ssize_t>::max()});
|
||||||
|
|
||||||
size_t actual;
|
size_t actual;
|
||||||
zx_status_t status =
|
zx_status_t status = process_->read_memory(address, buffer, size, &actual);
|
||||||
zx_process_read_memory(process_, address, buffer, size, &actual);
|
|
||||||
|
|
||||||
if (status != ZX_OK) {
|
if (status != ZX_OK) {
|
||||||
ZX_LOG(ERROR, status) << "zx_process_read_memory";
|
ZX_LOG(ERROR, status) << "zx_process_read_memory";
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#ifndef CRASHPAD_UTIL_PROCESS_PROCESS_MEMORY_FUCHSIA_H_
|
#ifndef CRASHPAD_UTIL_PROCESS_PROCESS_MEMORY_FUCHSIA_H_
|
||||||
#define CRASHPAD_UTIL_PROCESS_PROCESS_MEMORY_FUCHSIA_H_
|
#define CRASHPAD_UTIL_PROCESS_PROCESS_MEMORY_FUCHSIA_H_
|
||||||
|
|
||||||
#include <zircon/types.h>
|
#include <lib/zx/process.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -40,12 +40,15 @@ class ProcessMemoryFuchsia final : public ProcessMemory {
|
|||||||
//! \param[in] process The handle to the target process.
|
//! \param[in] process The handle to the target process.
|
||||||
//!
|
//!
|
||||||
//! \return `true` on success, `false` on failure with a message logged.
|
//! \return `true` on success, `false` on failure with a message logged.
|
||||||
bool Initialize(zx_handle_t process);
|
bool Initialize(const zx::process& process);
|
||||||
|
// TODO(wez): Remove this overload when zx::unowned_process allows implicit
|
||||||
|
// copy.
|
||||||
|
bool Initialize(const zx::unowned_process& process);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ssize_t ReadUpTo(VMAddress address, size_t size, void* buffer) const override;
|
ssize_t ReadUpTo(VMAddress address, size_t size, void* buffer) const override;
|
||||||
|
|
||||||
zx_handle_t process_;
|
zx::unowned_process process_;
|
||||||
InitializationStateDcheck initialized_;
|
InitializationStateDcheck initialized_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ProcessMemoryFuchsia);
|
DISALLOW_COPY_AND_ASSIGN(ProcessMemoryFuchsia);
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include "util/misc/from_pointer_cast.h"
|
#include "util/misc/from_pointer_cast.h"
|
||||||
|
|
||||||
#if defined(OS_FUCHSIA)
|
#if defined(OS_FUCHSIA)
|
||||||
#include <zircon/process.h>
|
#include <lib/zx/process.h>
|
||||||
|
|
||||||
#include "util/process/process_memory_fuchsia.h"
|
#include "util/process/process_memory_fuchsia.h"
|
||||||
#else
|
#else
|
||||||
@ -43,7 +43,7 @@ struct TestObject {
|
|||||||
TEST(ProcessMemoryRange, Basic) {
|
TEST(ProcessMemoryRange, Basic) {
|
||||||
#if defined(OS_FUCHSIA)
|
#if defined(OS_FUCHSIA)
|
||||||
ProcessMemoryFuchsia memory;
|
ProcessMemoryFuchsia memory;
|
||||||
ASSERT_TRUE(memory.Initialize(zx_process_self()));
|
ASSERT_TRUE(memory.Initialize(*zx::process::self()));
|
||||||
constexpr bool is_64_bit = true;
|
constexpr bool is_64_bit = true;
|
||||||
#else
|
#else
|
||||||
pid_t pid = getpid();
|
pid_t pid = getpid();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user