// Copyright 2014 The Crashpad Authors
//
// 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.

#include "minidump/minidump_file_writer.h"

#include <utility>

#include "base/logging.h"
#include "minidump/minidump_crashpad_info_writer.h"
#include "minidump/minidump_exception_writer.h"
#include "minidump/minidump_handle_writer.h"
#include "minidump/minidump_memory_info_writer.h"
#include "minidump/minidump_memory_writer.h"
#include "minidump/minidump_misc_info_writer.h"
#include "minidump/minidump_module_writer.h"
#include "minidump/minidump_system_info_writer.h"
#include "minidump/minidump_thread_id_map.h"
#include "minidump/minidump_thread_name_list_writer.h"
#include "minidump/minidump_thread_writer.h"
#include "minidump/minidump_unloaded_module_writer.h"
#include "minidump/minidump_user_extension_stream_data_source.h"
#include "minidump/minidump_user_stream_writer.h"
#include "minidump/minidump_writer_util.h"
#include "snapshot/exception_snapshot.h"
#include "snapshot/module_snapshot.h"
#include "snapshot/process_snapshot.h"
#include "snapshot/thread_snapshot.h"
#include "util/file/file_writer.h"
#include "util/numeric/safe_assignment.h"

namespace crashpad {

MinidumpFileWriter::MinidumpFileWriter()
    : MinidumpWritable(), header_(), streams_(), stream_types_() {
  // Don’t set the signature field right away. Leave it set to 0, so that a
  // partially-written minidump file isn’t confused for a complete and valid
  // one. The header will be rewritten in WriteToFile().
  header_.Signature = 0;

  header_.Version = MINIDUMP_VERSION;
  header_.CheckSum = 0;
  header_.Flags = MiniDumpNormal;
}

MinidumpFileWriter::~MinidumpFileWriter() {
}

void MinidumpFileWriter::InitializeFromSnapshot(
    const ProcessSnapshot* process_snapshot) {
  DCHECK_EQ(state(), kStateMutable);
  DCHECK_EQ(header_.Signature, 0u);
  DCHECK_EQ(header_.TimeDateStamp, 0u);
  DCHECK_EQ(static_cast<MINIDUMP_TYPE>(header_.Flags), MiniDumpNormal);
  DCHECK(streams_.empty());

  // This time is truncated to an integer number of seconds, not rounded, for
  // compatibility with the truncation of process_snapshot->ProcessStartTime()
  // done by MinidumpMiscInfoWriter::InitializeFromSnapshot(). Handling both
  // timestamps in the same way allows the highest-fidelity computation of
  // process uptime as the difference between the two values.
  timeval snapshot_time;
  process_snapshot->SnapshotTime(&snapshot_time);
  SetTimestamp(snapshot_time.tv_sec);

  const SystemSnapshot* system_snapshot = process_snapshot->System();
  auto system_info = std::make_unique<MinidumpSystemInfoWriter>();
  system_info->InitializeFromSnapshot(system_snapshot);
  bool add_stream_result = AddStream(std::move(system_info));
  DCHECK(add_stream_result);

  auto misc_info = std::make_unique<MinidumpMiscInfoWriter>();
  misc_info->InitializeFromSnapshot(process_snapshot);
  if (misc_info->HasXStateData())
    header_.Flags = header_.Flags | MiniDumpWithAvxXStateContext;

  add_stream_result = AddStream(std::move(misc_info));
  DCHECK(add_stream_result);

  auto memory_list = std::make_unique<MinidumpMemoryListWriter>();
  auto thread_list = std::make_unique<MinidumpThreadListWriter>();
  thread_list->SetMemoryListWriter(memory_list.get());
  MinidumpThreadIDMap thread_id_map;
  thread_list->InitializeFromSnapshot(process_snapshot->Threads(),
                                      &thread_id_map);
  add_stream_result = AddStream(std::move(thread_list));
  DCHECK(add_stream_result);

  bool has_thread_name = false;
  for (const ThreadSnapshot* thread_snapshot : process_snapshot->Threads()) {
    if (!thread_snapshot->ThreadName().empty()) {
      has_thread_name = true;
      break;
    }
  }
  if (has_thread_name) {
    auto thread_name_list = std::make_unique<MinidumpThreadNameListWriter>();
    thread_name_list->InitializeFromSnapshot(process_snapshot->Threads(),
                                             thread_id_map);
    add_stream_result = AddStream(std::move(thread_name_list));
    DCHECK(add_stream_result);
  }

  const ExceptionSnapshot* exception_snapshot = process_snapshot->Exception();
  if (exception_snapshot) {
    auto exception = std::make_unique<MinidumpExceptionWriter>();
    exception->InitializeFromSnapshot(exception_snapshot, thread_id_map);
    add_stream_result = AddStream(std::move(exception));
    DCHECK(add_stream_result);
  }

  auto module_list = std::make_unique<MinidumpModuleListWriter>();
  module_list->InitializeFromSnapshot(process_snapshot->Modules());
  add_stream_result = AddStream(std::move(module_list));
  DCHECK(add_stream_result);

  auto unloaded_modules = process_snapshot->UnloadedModules();
  if (!unloaded_modules.empty()) {
    auto unloaded_module_list =
        std::make_unique<MinidumpUnloadedModuleListWriter>();
    unloaded_module_list->InitializeFromSnapshot(unloaded_modules);
    add_stream_result = AddStream(std::move(unloaded_module_list));
    DCHECK(add_stream_result);
  }

  auto crashpad_info = std::make_unique<MinidumpCrashpadInfoWriter>();
  crashpad_info->InitializeFromSnapshot(process_snapshot);

  // Since the MinidumpCrashpadInfo stream is an extension, it’s safe to not add
  // it to the minidump file if it wouldn’t carry any useful information.
  if (crashpad_info->IsUseful()) {
    add_stream_result = AddStream(std::move(crashpad_info));
    DCHECK(add_stream_result);
  }

  std::vector<const MemoryMapRegionSnapshot*> memory_map_snapshot =
      process_snapshot->MemoryMap();
  if (!memory_map_snapshot.empty()) {
    auto memory_info_list = std::make_unique<MinidumpMemoryInfoListWriter>();
    memory_info_list->InitializeFromSnapshot(memory_map_snapshot);
    add_stream_result = AddStream(std::move(memory_info_list));
    DCHECK(add_stream_result);
  }

  std::vector<HandleSnapshot> handles_snapshot = process_snapshot->Handles();
  if (!handles_snapshot.empty()) {
    auto handle_data_writer = std::make_unique<MinidumpHandleDataWriter>();
    handle_data_writer->InitializeFromSnapshot(handles_snapshot);
    add_stream_result = AddStream(std::move(handle_data_writer));
    DCHECK(add_stream_result);
  }

  memory_list->AddFromSnapshot(process_snapshot->ExtraMemory());
  if (exception_snapshot) {
    memory_list->AddFromSnapshot(exception_snapshot->ExtraMemory());
  }

  // These user streams must be added last. Otherwise, a user stream with the
  // same type as a well-known stream could preempt the well-known stream. As it
  // stands now, earlier-discovered user streams can still preempt
  // later-discovered ones. The well-known memory list stream is added after
  // these user streams, but only with a check here to avoid adding a user
  // stream that would preempt the memory list stream.
  for (const auto& module : process_snapshot->Modules()) {
    for (const UserMinidumpStream* stream : module->CustomMinidumpStreams()) {
      if (stream->stream_type() == kMinidumpStreamTypeMemoryList) {
        LOG(WARNING) << "discarding duplicate stream of type "
                     << stream->stream_type();
        continue;
      }
      auto user_stream = std::make_unique<MinidumpUserStreamWriter>();
      user_stream->InitializeFromSnapshot(stream);
      AddStream(std::move(user_stream));
    }
  }

  // The memory list stream should be added last. This keeps the “extra memory”
  // at the end so that if the minidump file is truncated, other, more critical
  // data is more likely to be preserved. Note that non-“extra” memory regions
  // will not have to ride at the end of the file. Thread stack memory, for
  // example, exists as a children of threads, and appears alongside them in the
  // file, despite also being mentioned by the memory list stream.
  add_stream_result = AddStream(std::move(memory_list));
  DCHECK(add_stream_result);
}

void MinidumpFileWriter::SetTimestamp(time_t timestamp) {
  DCHECK_EQ(state(), kStateMutable);

  internal::MinidumpWriterUtil::AssignTimeT(&header_.TimeDateStamp, timestamp);
}

bool MinidumpFileWriter::AddStream(
    std::unique_ptr<internal::MinidumpStreamWriter> stream) {
  DCHECK_EQ(state(), kStateMutable);

  MinidumpStreamType stream_type = stream->StreamType();

  auto rv = stream_types_.insert(stream_type);
  if (!rv.second) {
    LOG(WARNING) << "discarding duplicate stream of type " << stream_type;
    return false;
  }

  streams_.push_back(std::move(stream));

  DCHECK_EQ(streams_.size(), stream_types_.size());
  return true;
}

bool MinidumpFileWriter::AddUserExtensionStream(
    std::unique_ptr<MinidumpUserExtensionStreamDataSource>
        user_extension_stream_data) {
  DCHECK_EQ(state(), kStateMutable);

  auto user_stream = std::make_unique<MinidumpUserStreamWriter>();
  user_stream->InitializeFromUserExtensionStream(
      std::move(user_extension_stream_data));

  return AddStream(std::move(user_stream));
}

bool MinidumpFileWriter::WriteEverything(FileWriterInterface* file_writer) {
  return WriteMinidump(file_writer, true);
}

bool MinidumpFileWriter::WriteMinidump(FileWriterInterface* file_writer,
                                       bool allow_seek) {
  DCHECK_EQ(state(), kStateMutable);

  FileOffset start_offset = -1;
  if (allow_seek) {
    start_offset = file_writer->Seek(0, SEEK_CUR);
    if (start_offset < 0) {
      return false;
    }
  } else {
    header_.Signature = MINIDUMP_SIGNATURE;
  }

  if (!MinidumpWritable::WriteEverything(file_writer)) {
    return false;
  }

  if (!allow_seek)
    return true;

  FileOffset end_offset = file_writer->Seek(0, SEEK_CUR);
  if (end_offset < 0) {
    return false;
  }

  // Now that the entire minidump file has been completely written, go back to
  // the beginning and rewrite the header with the correct signature to identify
  // it as a valid minidump file.
  header_.Signature = MINIDUMP_SIGNATURE;

  if (file_writer->Seek(start_offset, SEEK_SET) < 0) {
    return false;
  }

  if (!file_writer->Write(&header_, sizeof(header_))) {
    return false;
  }

  // Seek back to the end of the file, in case some non-minidump content will be
  // written to the file after the minidump content.
  return file_writer->Seek(end_offset, SEEK_SET) >= 0;
}

bool MinidumpFileWriter::Freeze() {
  DCHECK_EQ(state(), kStateMutable);

  if (!MinidumpWritable::Freeze()) {
    return false;
  }

  size_t stream_count = streams_.size();
  CHECK_EQ(stream_count, stream_types_.size());

  if (!AssignIfInRange(&header_.NumberOfStreams, stream_count)) {
    LOG(ERROR) << "stream_count " << stream_count << " out of range";
    return false;
  }

  return true;
}

size_t MinidumpFileWriter::SizeOfObject() {
  DCHECK_GE(state(), kStateFrozen);
  DCHECK_EQ(streams_.size(), stream_types_.size());

  return sizeof(header_) + streams_.size() * sizeof(MINIDUMP_DIRECTORY);
}

std::vector<internal::MinidumpWritable*> MinidumpFileWriter::Children() {
  DCHECK_GE(state(), kStateFrozen);
  DCHECK_EQ(streams_.size(), stream_types_.size());

  std::vector<MinidumpWritable*> children;
  for (const auto& stream : streams_) {
    children.push_back(stream.get());
  }

  return children;
}

bool MinidumpFileWriter::WillWriteAtOffsetImpl(FileOffset offset) {
  DCHECK_EQ(state(), kStateFrozen);
  DCHECK_EQ(offset, 0);
  DCHECK_EQ(streams_.size(), stream_types_.size());

  auto directory_offset = streams_.empty() ? 0 : offset + sizeof(header_);
  if (!AssignIfInRange(&header_.StreamDirectoryRva, directory_offset)) {
    LOG(ERROR) << "offset " << directory_offset << " out of range";
    return false;
  }

  return MinidumpWritable::WillWriteAtOffsetImpl(offset);
}

bool MinidumpFileWriter::WriteObject(FileWriterInterface* file_writer) {
  DCHECK_EQ(state(), kStateWritable);
  DCHECK_EQ(streams_.size(), stream_types_.size());

  WritableIoVec iov;
  iov.iov_base = &header_;
  iov.iov_len = sizeof(header_);
  std::vector<WritableIoVec> iovecs(1, iov);

  for (const auto& stream : streams_) {
    iov.iov_base = stream->DirectoryListEntry();
    iov.iov_len = sizeof(MINIDUMP_DIRECTORY);
    iovecs.push_back(iov);
  }

  return file_writer->WriteIoVec(&iovecs);
}

}  // namespace crashpad
