// 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
