// Copyright 2015 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.

#include "snapshot/minidump/process_snapshot_minidump.h"

#include <utility>

#include "base/strings/utf_string_conversions.h"
#include "minidump/minidump_extensions.h"
#include "snapshot/memory_map_region_snapshot.h"
#include "snapshot/minidump/minidump_simple_string_dictionary_reader.h"
#include "util/file/file_io.h"

namespace crashpad {

namespace internal {

class MemoryMapRegionSnapshotMinidump : public MemoryMapRegionSnapshot {
 public:
  MemoryMapRegionSnapshotMinidump(MINIDUMP_MEMORY_INFO info) : info_(info) {}
  ~MemoryMapRegionSnapshotMinidump() override = default;

  const MINIDUMP_MEMORY_INFO& AsMinidumpMemoryInfo() const override {
    return info_;
  }

 private:
  MINIDUMP_MEMORY_INFO info_;
};

}  // namespace internal

ProcessSnapshotMinidump::ProcessSnapshotMinidump()
    : ProcessSnapshot(),
      header_(),
      stream_directory_(),
      stream_map_(),
      modules_(),
      threads_(),
      unloaded_modules_(),
      mem_regions_(),
      mem_regions_exposed_(),
      custom_streams_(),
      crashpad_info_(),
      system_snapshot_(),
      exception_snapshot_(),
      arch_(CPUArchitecture::kCPUArchitectureUnknown),
      annotations_simple_map_(),
      file_reader_(nullptr),
      process_id_(kInvalidProcessID),
      create_time_(0),
      user_time_(0),
      kernel_time_(0),
      initialized_() {}

ProcessSnapshotMinidump::~ProcessSnapshotMinidump() {}

bool ProcessSnapshotMinidump::Initialize(FileReaderInterface* file_reader) {
  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);

  file_reader_ = file_reader;

  if (!file_reader_->SeekSet(0)) {
    return false;
  }

  if (!file_reader_->ReadExactly(&header_, sizeof(header_))) {
    return false;
  }

  if (header_.Signature != MINIDUMP_SIGNATURE) {
    LOG(ERROR) << "minidump signature mismatch";
    return false;
  }

  if (header_.Version != MINIDUMP_VERSION) {
    LOG(ERROR) << "minidump version mismatch";
    return false;
  }

  if (!file_reader->SeekSet(header_.StreamDirectoryRva)) {
    return false;
  }

  stream_directory_.resize(header_.NumberOfStreams);
  if (!stream_directory_.empty() &&
      !file_reader_->ReadExactly(
          &stream_directory_[0],
          header_.NumberOfStreams * sizeof(stream_directory_[0]))) {
    return false;
  }

  for (const MINIDUMP_DIRECTORY& directory : stream_directory_) {
    const MinidumpStreamType stream_type =
        static_cast<MinidumpStreamType>(directory.StreamType);
    if (stream_map_.find(stream_type) != stream_map_.end()) {
      LOG(ERROR) << "duplicate streams for type " << directory.StreamType;
      return false;
    }

    stream_map_[stream_type] = &directory.Location;
  }

  if (!InitializeCrashpadInfo() || !InitializeMiscInfo() ||
      !InitializeModules() || !InitializeSystemSnapshot() ||
      !InitializeMemoryInfo() || !InitializeThreads() ||
      !InitializeCustomMinidumpStreams() || !InitializeExceptionSnapshot()) {
    return false;
  }

  INITIALIZATION_STATE_SET_VALID(initialized_);
  return true;
}

crashpad::ProcessID ProcessSnapshotMinidump::ProcessID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return process_id_;
}

crashpad::ProcessID ProcessSnapshotMinidump::ParentProcessID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  NOTREACHED();  // https://crashpad.chromium.org/bug/10
  return 0;
}

void ProcessSnapshotMinidump::SnapshotTime(timeval* snapshot_time) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  snapshot_time->tv_sec = header_.TimeDateStamp;
  snapshot_time->tv_usec = 0;
}

void ProcessSnapshotMinidump::ProcessStartTime(timeval* start_time) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  start_time->tv_sec = create_time_;
  start_time->tv_usec = 0;
}

void ProcessSnapshotMinidump::ProcessCPUTimes(timeval* user_time,
                                              timeval* system_time) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  user_time->tv_sec = user_time_;
  user_time->tv_usec = 0;
  system_time->tv_sec = kernel_time_;
  system_time->tv_usec = 0;
}

void ProcessSnapshotMinidump::ReportID(UUID* report_id) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  *report_id = crashpad_info_.report_id;
}

void ProcessSnapshotMinidump::ClientID(UUID* client_id) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  *client_id = crashpad_info_.client_id;
}

const std::map<std::string, std::string>&
ProcessSnapshotMinidump::AnnotationsSimpleMap() const {
  // TODO(mark): This method should not be const, although the interface
  // currently imposes this requirement. Making it non-const would allow
  // annotations_simple_map_ to be lazily constructed: InitializeCrashpadInfo()
  // could be called here, and from other locations that require it, rather than
  // calling it from Initialize().
  // https://crashpad.chromium.org/bug/9
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return annotations_simple_map_;
}

const SystemSnapshot* ProcessSnapshotMinidump::System() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return &system_snapshot_;
}

std::vector<const ThreadSnapshot*> ProcessSnapshotMinidump::Threads() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  std::vector<const ThreadSnapshot*> threads;
  for (const auto& thread : threads_) {
    threads.push_back(thread.get());
  }
  return threads;
}

std::vector<const ModuleSnapshot*> ProcessSnapshotMinidump::Modules() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  std::vector<const ModuleSnapshot*> modules;
  for (const auto& module : modules_) {
    modules.push_back(module.get());
  }
  return modules;
}

std::vector<UnloadedModuleSnapshot> ProcessSnapshotMinidump::UnloadedModules()
    const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  NOTREACHED();  // https://crashpad.chromium.org/bug/10
  return unloaded_modules_;
}

const ExceptionSnapshot* ProcessSnapshotMinidump::Exception() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  if (exception_snapshot_.IsValid()) {
    return &exception_snapshot_;
  }
  // Allow caller to know whether the minidump contained an exception stream.
  return nullptr;
}

std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotMinidump::MemoryMap()
    const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return mem_regions_exposed_;
}

std::vector<HandleSnapshot> ProcessSnapshotMinidump::Handles() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  NOTREACHED();  // https://crashpad.chromium.org/bug/10
  return std::vector<HandleSnapshot>();
}

std::vector<const MemorySnapshot*> ProcessSnapshotMinidump::ExtraMemory()
    const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  NOTREACHED();  // https://crashpad.chromium.org/bug/10
  return std::vector<const MemorySnapshot*>();
}

const ProcessMemory* ProcessSnapshotMinidump::Memory() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return nullptr;
}

std::vector<const MinidumpStream*>
ProcessSnapshotMinidump::CustomMinidumpStreams() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::vector<const MinidumpStream*> result;
  result.reserve(custom_streams_.size());
  for (const auto& custom_stream : custom_streams_) {
    result.push_back(custom_stream.get());
  }
  return result;
}

bool ProcessSnapshotMinidump::InitializeCrashpadInfo() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeCrashpadInfo);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  if (stream_it->second->DataSize < sizeof(crashpad_info_)) {
    LOG(ERROR) << "crashpad_info size mismatch";
    return false;
  }

  if (!file_reader_->SeekSet(stream_it->second->Rva)) {
    return false;
  }

  if (!file_reader_->ReadExactly(&crashpad_info_, sizeof(crashpad_info_))) {
    return false;
  }

  if (crashpad_info_.version != MinidumpCrashpadInfo::kVersion) {
    LOG(ERROR) << "crashpad_info version mismatch";
    return false;
  }

  return internal::ReadMinidumpSimpleStringDictionary(
      file_reader_,
      crashpad_info_.simple_annotations,
      &annotations_simple_map_);
}

bool ProcessSnapshotMinidump::InitializeMiscInfo() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeMiscInfo);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  if (!file_reader_->SeekSet(stream_it->second->Rva)) {
    return false;
  }

  const size_t size = stream_it->second->DataSize;
  if (size != sizeof(MINIDUMP_MISC_INFO_5) &&
      size != sizeof(MINIDUMP_MISC_INFO_4) &&
      size != sizeof(MINIDUMP_MISC_INFO_3) &&
      size != sizeof(MINIDUMP_MISC_INFO_2) &&
      size != sizeof(MINIDUMP_MISC_INFO)) {
    LOG(ERROR) << "misc_info size mismatch";
    return false;
  }

  MINIDUMP_MISC_INFO_5 info;
  if (!file_reader_->ReadExactly(&info, size)) {
    return false;
  }

  switch (stream_it->second->DataSize) {
    case sizeof(MINIDUMP_MISC_INFO_5):
    case sizeof(MINIDUMP_MISC_INFO_4):
      full_version_ = base::UTF16ToUTF8(info.BuildString);
      full_version_ = full_version_.substr(0, full_version_.find(";"));
      FALLTHROUGH;
    case sizeof(MINIDUMP_MISC_INFO_3):
    case sizeof(MINIDUMP_MISC_INFO_2):
    case sizeof(MINIDUMP_MISC_INFO):
      // TODO(jperaza): Save the remaining misc info.
      // https://crashpad.chromium.org/bug/10
      process_id_ = info.ProcessId;
      create_time_ = info.ProcessCreateTime;
      user_time_ = info.ProcessUserTime;
      kernel_time_ = info.ProcessKernelTime;
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeModules() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeModuleList);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  std::map<uint32_t, MINIDUMP_LOCATION_DESCRIPTOR> module_crashpad_info_links;
  if (!InitializeModulesCrashpadInfo(&module_crashpad_info_links)) {
    return false;
  }

  if (stream_it->second->DataSize < sizeof(MINIDUMP_MODULE_LIST)) {
    LOG(ERROR) << "module_list size mismatch";
    return false;
  }

  if (!file_reader_->SeekSet(stream_it->second->Rva)) {
    return false;
  }

  uint32_t module_count;
  if (!file_reader_->ReadExactly(&module_count, sizeof(module_count))) {
    return false;
  }

  if (sizeof(MINIDUMP_MODULE_LIST) + module_count * sizeof(MINIDUMP_MODULE) !=
      stream_it->second->DataSize) {
    LOG(ERROR) << "module_list size mismatch";
    return false;
  }

  for (uint32_t module_index = 0; module_index < module_count; ++module_index) {
    const RVA module_rva = stream_it->second->Rva + sizeof(module_count) +
                           module_index * sizeof(MINIDUMP_MODULE);

    const auto& module_crashpad_info_it =
        module_crashpad_info_links.find(module_index);
    const MINIDUMP_LOCATION_DESCRIPTOR* module_crashpad_info_location =
        module_crashpad_info_it != module_crashpad_info_links.end()
            ? &module_crashpad_info_it->second
            : nullptr;

    auto module = std::make_unique<internal::ModuleSnapshotMinidump>();
    if (!module->Initialize(
            file_reader_, module_rva, module_crashpad_info_location)) {
      return false;
    }

    modules_.push_back(std::move(module));
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeModulesCrashpadInfo(
    std::map<uint32_t, MINIDUMP_LOCATION_DESCRIPTOR>*
        module_crashpad_info_links) {
  module_crashpad_info_links->clear();

  if (crashpad_info_.version != MinidumpCrashpadInfo::kVersion) {
    return false;
  }

  if (crashpad_info_.module_list.Rva == 0) {
    return true;
  }

  if (crashpad_info_.module_list.DataSize <
      sizeof(MinidumpModuleCrashpadInfoList)) {
    LOG(ERROR) << "module_crashpad_info_list size mismatch";
    return false;
  }

  if (!file_reader_->SeekSet(crashpad_info_.module_list.Rva)) {
    return false;
  }

  uint32_t crashpad_module_count;
  if (!file_reader_->ReadExactly(&crashpad_module_count,
                                 sizeof(crashpad_module_count))) {
    return false;
  }

  if (crashpad_info_.module_list.DataSize !=
      sizeof(MinidumpModuleCrashpadInfoList) +
          crashpad_module_count * sizeof(MinidumpModuleCrashpadInfoLink)) {
    LOG(ERROR) << "module_crashpad_info_list size mismatch";
    return false;
  }

  std::unique_ptr<MinidumpModuleCrashpadInfoLink[]> minidump_links(
      new MinidumpModuleCrashpadInfoLink[crashpad_module_count]);
  if (!file_reader_->ReadExactly(
          &minidump_links[0],
          crashpad_module_count * sizeof(MinidumpModuleCrashpadInfoLink))) {
    return false;
  }

  for (uint32_t crashpad_module_index = 0;
       crashpad_module_index < crashpad_module_count;
       ++crashpad_module_index) {
    const MinidumpModuleCrashpadInfoLink& minidump_link =
        minidump_links[crashpad_module_index];
    if (!module_crashpad_info_links
             ->insert(std::make_pair(minidump_link.minidump_module_list_index,
                                     minidump_link.location))
             .second) {
      LOG(WARNING)
          << "duplicate module_crashpad_info_list minidump_module_list_index "
          << minidump_link.minidump_module_list_index;
      return false;
    }
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeMemoryInfo() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeMemoryInfoList);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  if (stream_it->second->DataSize < sizeof(MINIDUMP_MEMORY_INFO_LIST)) {
    LOG(ERROR) << "memory_info_list size mismatch";
    return false;
  }

  if (!file_reader_->SeekSet(stream_it->second->Rva)) {
    return false;
  }

  MINIDUMP_MEMORY_INFO_LIST list;

  if (!file_reader_->ReadExactly(&list, sizeof(list))) {
    return false;
  }

  if (list.SizeOfHeader != sizeof(list)) {
    return false;
  }

  if (list.SizeOfEntry != sizeof(MINIDUMP_MEMORY_INFO)) {
    return false;
  }

  if (sizeof(MINIDUMP_MEMORY_INFO_LIST) +
          list.NumberOfEntries * list.SizeOfEntry !=
      stream_it->second->DataSize) {
    LOG(ERROR) << "memory_info_list size mismatch";
    return false;
  }

  for (uint32_t i = 0; i < list.NumberOfEntries; i++) {
    MINIDUMP_MEMORY_INFO info;

    if (!file_reader_->ReadExactly(&info, sizeof(info))) {
      return false;
    }

    mem_regions_.emplace_back(
        std::make_unique<internal::MemoryMapRegionSnapshotMinidump>(info));
    mem_regions_exposed_.emplace_back(mem_regions_.back().get());
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeThreads() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeThreadList);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  if (stream_it->second->DataSize < sizeof(MINIDUMP_THREAD_LIST)) {
    LOG(ERROR) << "thread_list size mismatch";
    return false;
  }

  if (!file_reader_->SeekSet(stream_it->second->Rva)) {
    return false;
  }

  uint32_t thread_count;
  if (!file_reader_->ReadExactly(&thread_count, sizeof(thread_count))) {
    return false;
  }

  if (sizeof(MINIDUMP_THREAD_LIST) + thread_count * sizeof(MINIDUMP_THREAD) !=
      stream_it->second->DataSize) {
    LOG(ERROR) << "thread_list size mismatch";
    return false;
  }

  for (uint32_t thread_index = 0; thread_index < thread_count; ++thread_index) {
    const RVA thread_rva = stream_it->second->Rva + sizeof(thread_count) +
                           thread_index * sizeof(MINIDUMP_THREAD);

    auto thread = std::make_unique<internal::ThreadSnapshotMinidump>();
    if (!thread->Initialize(file_reader_, thread_rva, arch_)) {
      return false;
    }

    threads_.push_back(std::move(thread));
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeSystemSnapshot() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeSystemInfo);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  if (stream_it->second->DataSize < sizeof(MINIDUMP_SYSTEM_INFO)) {
    LOG(ERROR) << "system info size mismatch";
    return false;
  }

  if (!system_snapshot_.Initialize(
          file_reader_, stream_it->second->Rva, full_version_)) {
    return false;
  }

  arch_ = system_snapshot_.GetCPUArchitecture();
  return true;
}

bool ProcessSnapshotMinidump::InitializeCustomMinidumpStreams() {
  for (size_t i = 0; i < stream_directory_.size(); i++) {
    const auto& stream = stream_directory_[i];

    // Filter out reserved minidump and crashpad streams.
    const uint32_t stream_type = stream.StreamType;
    if (stream_type <=
            MinidumpStreamType::kMinidumpStreamTypeLastReservedStream ||
        (stream_type >= MinidumpStreamType::kMinidumpStreamTypeCrashpadInfo &&
         stream_type <= MinidumpStreamType::
                            kMinidumpStreamTypeCrashpadLastReservedStream)) {
      continue;
    }

    std::vector<uint8_t> data(stream.Location.DataSize);
    if (!file_reader_->SeekSet(stream.Location.Rva) ||
        !file_reader_->ReadExactly(data.data(), data.size())) {
      LOG(ERROR) << "Failed to read stream with ID 0x" << std::hex
                 << stream_type << std::dec << " at index " << i;
      return false;
    }

    custom_streams_.push_back(
        std::make_unique<MinidumpStream>(stream_type, std::move(data)));
  }

  return true;
}

bool ProcessSnapshotMinidump::InitializeExceptionSnapshot() {
  const auto& stream_it = stream_map_.find(kMinidumpStreamTypeException);
  if (stream_it == stream_map_.end()) {
    return true;
  }

  if (stream_it->second->DataSize < sizeof(MINIDUMP_EXCEPTION_STREAM)) {
    LOG(ERROR) << "system info size mismatch";
    return false;
  }

  if (!exception_snapshot_.Initialize(
          file_reader_, arch_, stream_it->second->Rva)) {
    return false;
  }

  return true;
}

}  // namespace crashpad
