| // 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/exception_broker/crash_report_generation.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" |
| #include "src/lib/syslog/cpp/logger.h" |
| |
| namespace fuchsia { |
| namespace exception { |
| |
| // 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 GenerateMinidumpVMO(const zx::exception& exception, std::string* process_name) { |
| 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); |
| |
| *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 minidump_vmo = GenerateVMOFromStringFile(string_file); |
| if (!minidump_vmo.is_valid()) { |
| FX_LOGS(ERROR) << "Process " << *process_name << ": Could not generate vmo from minidump."; |
| return {}; |
| } |
| |
| return minidump_vmo; |
| } |
| |
| } // namespace exception |
| } // namespace fuchsia |