| // Copyright 2019 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. | |
| #include "src/developer/forensics/exceptions/handler/minidump.h" | |
| #include <lib/syslog/cpp/macros.h> | |
| #include <lib/zx/process.h> | |
| #include <lib/zx/thread.h> | |
| #include <zircon/syscalls/exception.h> | |
| #include <third_party/crashpad/minidump/minidump_file_writer.h> | |
| #include <third_party/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.h> | |
| #include <third_party/crashpad/util/fuchsia/scoped_task_suspend.h> | |
| #include "src/lib/fsl/handles/object_info.h" | |
| namespace forensics { | |
| namespace exceptions { | |
| namespace handler { | |
| // GenerateVMOFromStringFile ----------------------------------------------------------------------- | |
| zx::vmo GenerateVMOFromStringFile(const crashpad::StringFile& string_file) { | |
| // We don't want to generate empty vmos. | |
| const std::string& data = string_file.string(); | |
| if (data.empty()) | |
| return {}; | |
| zx::vmo vmo; | |
| if (zx_status_t status = zx::vmo::create(data.size(), 0, &vmo); status != ZX_OK) { | |
| FX_PLOGS(ERROR, status) << "Could not create minidump VMO."; | |
| return {}; | |
| } | |
| // Write the data into the vmo. | |
| if (zx_status_t status = vmo.write(data.data(), 0, data.size()); status != ZX_OK) { | |
| FX_PLOGS(ERROR, status) << "Could not write data into VMO."; | |
| return {}; | |
| } | |
| return vmo; | |
| } | |
| // GenerateMinidumpVMO ----------------------------------------------------------------------------- | |
| namespace { | |
| zx::process GetProcess(const zx::exception& exception) { | |
| zx::process process; | |
| zx_status_t status = exception.get_process(&process); | |
| if (status != ZX_OK) { | |
| FX_PLOGS(ERROR, status) << "Could not get process handle from exception."; | |
| return {}; | |
| } | |
| return process; | |
| } | |
| zx::thread GetThread(const zx::exception& exception) { | |
| zx::thread thread; | |
| zx_status_t status = exception.get_thread(&thread); | |
| if (status != ZX_OK) { | |
| FX_PLOGS(ERROR, status) << "Could not get thread handle from exception."; | |
| return {}; | |
| } | |
| return thread; | |
| } | |
| } // namespace | |
| zx::vmo GenerateMinidump(const zx::exception& exception) { | |
| zx::process process = GetProcess(exception); | |
| if (!process.is_valid()) | |
| return {}; | |
| zx::thread thread = GetThread(exception); | |
| if (!thread.is_valid()) | |
| return {}; | |
| zx_koid_t thread_koid = fsl::GetKoid(thread.get()); | |
| if (thread_koid == 0) | |
| return {}; | |
| // Will unsuspend the process upon exiting the block. | |
| crashpad::ScopedTaskSuspend suspend(process); | |
| const std::string process_name = fsl::GetObjectName(process.get()); | |
| zx_exception_report_t report; | |
| zx_status_t status = | |
| thread.get_info(ZX_INFO_THREAD_EXCEPTION_REPORT, &report, sizeof(report), nullptr, nullptr); | |
| if (status != ZX_OK) { | |
| FX_PLOGS(ERROR, status) << "Process " << process_name | |
| << ": Could not obtain ZX_INFO_THREAD_EXCEPTION_REPORT."; | |
| return {}; | |
| } | |
| // Create a process snapshot form the process and the exception thread. | |
| crashpad::ProcessSnapshotFuchsia process_snapshot; | |
| if (!process_snapshot.Initialize(process) || | |
| !process_snapshot.InitializeException(thread_koid, report)) { | |
| FX_LOGS(ERROR) << "Process " << process_name << ": Could not create process snapshot."; | |
| return {}; | |
| } | |
| crashpad::MinidumpFileWriter minidump; | |
| minidump.InitializeFromSnapshot(&process_snapshot); | |
| // Represents an in-memory backed file writer interface. | |
| crashpad::StringFile string_file; | |
| if (!minidump.WriteEverything(&string_file)) { | |
| FX_LOGS(ERROR) << "Process " << process_name << ": Failed to generate minidump."; | |
| return {}; | |
| } | |
| zx::vmo vmo = GenerateVMOFromStringFile(string_file); | |
| if (!vmo.is_valid()) { | |
| FX_LOGS(ERROR) << "Process " << process_name << ": Could not generate vmo from minidump."; | |
| return {}; | |
| } | |
| return vmo; | |
| } | |
| } // namespace handler | |
| } // namespace exceptions | |
| } // namespace forensics |