// 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_module_writer.h"

#include <stddef.h>

#include <limits>
#include <utility>

#include "base/check_op.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "minidump/minidump_string_writer.h"
#include "minidump/minidump_writer_util.h"
#include "snapshot/module_snapshot.h"
#include "util/file/file_writer.h"
#include "util/misc/implicit_cast.h"
#include "util/numeric/in_range_cast.h"
#include "util/numeric/safe_assignment.h"

namespace crashpad {

MinidumpModuleCodeViewRecordWriter::~MinidumpModuleCodeViewRecordWriter() {}

namespace internal {

template <typename CodeViewRecordType>
MinidumpModuleCodeViewRecordPDBLinkWriter<
    CodeViewRecordType>::MinidumpModuleCodeViewRecordPDBLinkWriter()
    : MinidumpModuleCodeViewRecordWriter(), codeview_record_(), pdb_name_() {
  codeview_record_.signature = CodeViewRecordType::kSignature;
}

template <typename CodeViewRecordType>
MinidumpModuleCodeViewRecordPDBLinkWriter<
    CodeViewRecordType>::~MinidumpModuleCodeViewRecordPDBLinkWriter() {}

template <typename CodeViewRecordType>
size_t
MinidumpModuleCodeViewRecordPDBLinkWriter<CodeViewRecordType>::SizeOfObject() {
  DCHECK_GE(state(), kStateFrozen);

  // NUL-terminate.
  return offsetof(decltype(codeview_record_), pdb_name) +
         (pdb_name_.size() + 1) * sizeof(pdb_name_[0]);
}

template <typename CodeViewRecordType>
bool MinidumpModuleCodeViewRecordPDBLinkWriter<CodeViewRecordType>::WriteObject(
    FileWriterInterface* file_writer) {
  DCHECK_EQ(state(), kStateWritable);

  WritableIoVec iov;
  iov.iov_base = &codeview_record_;
  iov.iov_len = offsetof(decltype(codeview_record_), pdb_name);
  std::vector<WritableIoVec> iovecs(1, iov);

  // NUL-terminate.
  iov.iov_base = &pdb_name_[0];
  iov.iov_len = (pdb_name_.size() + 1) * sizeof(pdb_name_[0]);
  iovecs.push_back(iov);

  return file_writer->WriteIoVec(&iovecs);
}

}  // namespace internal

template class internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
    CodeViewRecordPDB20>;

MinidumpModuleCodeViewRecordPDB20Writer::
    ~MinidumpModuleCodeViewRecordPDB20Writer() {}

void MinidumpModuleCodeViewRecordPDB20Writer::SetTimestampAndAge(
    time_t timestamp,
    uint32_t age) {
  DCHECK_EQ(state(), kStateMutable);

  internal::MinidumpWriterUtil::AssignTimeT(&codeview_record()->timestamp,
                                            timestamp);

  codeview_record()->age = age;
}

template class internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
    CodeViewRecordPDB70>;

MinidumpModuleCodeViewRecordPDB70Writer::
    ~MinidumpModuleCodeViewRecordPDB70Writer() {}

void MinidumpModuleCodeViewRecordPDB70Writer::InitializeFromSnapshot(
    const ModuleSnapshot* module_snapshot) {
  DCHECK_EQ(state(), kStateMutable);

  SetPDBName(module_snapshot->DebugFileName());

  UUID uuid;
  uint32_t age;
  module_snapshot->UUIDAndAge(&uuid, &age);
  SetUUIDAndAge(uuid, age);
}

MinidumpModuleCodeViewRecordBuildIDWriter::
    MinidumpModuleCodeViewRecordBuildIDWriter()
    : MinidumpModuleCodeViewRecordWriter(), build_id_() {}

MinidumpModuleCodeViewRecordBuildIDWriter::
    ~MinidumpModuleCodeViewRecordBuildIDWriter() {}

size_t MinidumpModuleCodeViewRecordBuildIDWriter::SizeOfObject() {
  DCHECK_GE(state(), kStateFrozen);
  return offsetof(CodeViewRecordBuildID, build_id) + build_id_.size();
}

void MinidumpModuleCodeViewRecordBuildIDWriter::SetBuildID(
    const std::vector<uint8_t>& build_id) {
  DCHECK_EQ(state(), kStateMutable);
  build_id_ = build_id;
}

bool MinidumpModuleCodeViewRecordBuildIDWriter::WriteObject(
    FileWriterInterface* file_writer) {
  DCHECK_EQ(state(), kStateWritable);

  CodeViewRecordBuildID cv;
  cv.signature = CodeViewRecordBuildID::kSignature;

  WritableIoVec iov;
  iov.iov_base = &cv;
  iov.iov_len = offsetof(CodeViewRecordBuildID, build_id);
  std::vector<WritableIoVec> iovecs(1, iov);

  if (!build_id_.empty()) {
    iov.iov_base = build_id_.data();
    iov.iov_len = build_id_.size();
    iovecs.push_back(iov);
  }

  return file_writer->WriteIoVec(&iovecs);
}

MinidumpModuleMiscDebugRecordWriter::MinidumpModuleMiscDebugRecordWriter()
    : internal::MinidumpWritable(),
      image_debug_misc_(),
      data_(),
      data_utf16_() {}

MinidumpModuleMiscDebugRecordWriter::~MinidumpModuleMiscDebugRecordWriter() {}

void MinidumpModuleMiscDebugRecordWriter::SetData(const std::string& data,
                                                  bool utf16) {
  DCHECK_EQ(state(), kStateMutable);

  if (!utf16) {
    data_utf16_.clear();
    image_debug_misc_.Unicode = 0;
    data_ = data;
  } else {
    data_.clear();
    image_debug_misc_.Unicode = 1;
    data_utf16_ = internal::MinidumpWriterUtil::ConvertUTF8ToUTF16(data);
  }
}

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

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

  // NUL-terminate.
  if (!image_debug_misc_.Unicode) {
    DCHECK(data_utf16_.empty());
    image_debug_misc_.Length = base::checked_cast<uint32_t>(
        offsetof(decltype(image_debug_misc_), Data) +
        (data_.size() + 1) * sizeof(data_[0]));
  } else {
    DCHECK(data_.empty());
    image_debug_misc_.Length = base::checked_cast<uint32_t>(
        offsetof(decltype(image_debug_misc_), Data) +
        (data_utf16_.size() + 1) * sizeof(data_utf16_[0]));
  }

  return true;
}

size_t MinidumpModuleMiscDebugRecordWriter::SizeOfObject() {
  DCHECK_GE(state(), kStateFrozen);

  return image_debug_misc_.Length;
}

bool MinidumpModuleMiscDebugRecordWriter::WriteObject(
    FileWriterInterface* file_writer) {
  DCHECK_EQ(state(), kStateWritable);

  const size_t base_length = offsetof(decltype(image_debug_misc_), Data);

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

  if (!image_debug_misc_.Unicode) {
    DCHECK(data_utf16_.empty());
    iov.iov_base = &data_[0];
  } else {
    DCHECK(data_.empty());
    iov.iov_base = &data_utf16_[0];
  }
  iov.iov_len = image_debug_misc_.Length - base_length;
  iovecs.push_back(iov);

  return file_writer->WriteIoVec(&iovecs);
}

MinidumpModuleWriter::MinidumpModuleWriter()
    : MinidumpWritable(),
      module_(),
      name_(),
      codeview_record_(nullptr),
      misc_debug_record_(nullptr) {
  module_.VersionInfo.dwSignature = VS_FFI_SIGNATURE;
  module_.VersionInfo.dwStrucVersion = VS_FFI_STRUCVERSION;
}

MinidumpModuleWriter::~MinidumpModuleWriter() {}

void MinidumpModuleWriter::InitializeFromSnapshot(
    const ModuleSnapshot* module_snapshot) {
  DCHECK_EQ(state(), kStateMutable);
  DCHECK(!name_);
  DCHECK(!codeview_record_);
  DCHECK(!misc_debug_record_);

  SetName(module_snapshot->Name());

  SetImageBaseAddress(module_snapshot->Address());
  SetImageSize(InRangeCast<uint32_t>(module_snapshot->Size(),
                                     std::numeric_limits<uint32_t>::max()));
  SetTimestamp(module_snapshot->Timestamp());

  uint16_t v[4];
  module_snapshot->FileVersion(&v[0], &v[1], &v[2], &v[3]);
  SetFileVersion(v[0], v[1], v[2], v[3]);

  module_snapshot->SourceVersion(&v[0], &v[1], &v[2], &v[3]);
  SetProductVersion(v[0], v[1], v[2], v[3]);

  uint32_t file_type;
  switch (module_snapshot->GetModuleType()) {
    case ModuleSnapshot::kModuleTypeExecutable:
      file_type = VFT_APP;
      break;
    case ModuleSnapshot::kModuleTypeSharedLibrary:
    case ModuleSnapshot::kModuleTypeLoadableModule:
      file_type = VFT_DLL;
      break;
    default:
      file_type = VFT_UNKNOWN;
      break;
  }
  SetFileTypeAndSubtype(file_type, VFT2_UNKNOWN);

  auto build_id = module_snapshot->BuildID();

  std::unique_ptr<MinidumpModuleCodeViewRecordWriter> codeview_record;
  if (!build_id.empty()) {
    auto cv_record_build_id =
        std::make_unique<MinidumpModuleCodeViewRecordBuildIDWriter>();
    cv_record_build_id->SetBuildID(build_id);
    codeview_record = std::move(cv_record_build_id);
  } else {
    auto cv_record_pdb70 =
        std::make_unique<MinidumpModuleCodeViewRecordPDB70Writer>();
    cv_record_pdb70->InitializeFromSnapshot(module_snapshot);
    codeview_record = std::move(cv_record_pdb70);
  }

  SetCodeViewRecord(std::move(codeview_record));
}

const MINIDUMP_MODULE* MinidumpModuleWriter::MinidumpModule() const {
  DCHECK_EQ(state(), kStateWritable);

  return &module_;
}

void MinidumpModuleWriter::SetName(const std::string& name) {
  DCHECK_EQ(state(), kStateMutable);

  if (!name_) {
    name_.reset(new internal::MinidumpUTF16StringWriter());
  }
  name_->SetUTF8(name);
}

void MinidumpModuleWriter::SetCodeViewRecord(
    std::unique_ptr<MinidumpModuleCodeViewRecordWriter> codeview_record) {
  DCHECK_EQ(state(), kStateMutable);

  codeview_record_ = std::move(codeview_record);
}

void MinidumpModuleWriter::SetMiscDebugRecord(
    std::unique_ptr<MinidumpModuleMiscDebugRecordWriter> misc_debug_record) {
  DCHECK_EQ(state(), kStateMutable);

  misc_debug_record_ = std::move(misc_debug_record);
}

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

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

void MinidumpModuleWriter::SetFileVersion(uint16_t version_0,
                                          uint16_t version_1,
                                          uint16_t version_2,
                                          uint16_t version_3) {
  DCHECK_EQ(state(), kStateMutable);

  module_.VersionInfo.dwFileVersionMS =
      (implicit_cast<uint32_t>(version_0) << 16) | version_1;
  module_.VersionInfo.dwFileVersionLS =
      (implicit_cast<uint32_t>(version_2) << 16) | version_3;
}

void MinidumpModuleWriter::SetProductVersion(uint16_t version_0,
                                             uint16_t version_1,
                                             uint16_t version_2,
                                             uint16_t version_3) {
  DCHECK_EQ(state(), kStateMutable);

  module_.VersionInfo.dwProductVersionMS =
      (implicit_cast<uint32_t>(version_0) << 16) | version_1;
  module_.VersionInfo.dwProductVersionLS =
      (implicit_cast<uint32_t>(version_2) << 16) | version_3;
}

void MinidumpModuleWriter::SetFileFlagsAndMask(uint32_t file_flags,
                                               uint32_t file_flags_mask) {
  DCHECK_EQ(state(), kStateMutable);
  DCHECK_EQ(file_flags & ~file_flags_mask, 0u);

  module_.VersionInfo.dwFileFlags = file_flags;
  module_.VersionInfo.dwFileFlagsMask = file_flags_mask;
}

bool MinidumpModuleWriter::Freeze() {
  DCHECK_EQ(state(), kStateMutable);
  CHECK(name_);

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

  name_->RegisterRVA(&module_.ModuleNameRva);

  if (codeview_record_) {
    codeview_record_->RegisterLocationDescriptor(&module_.CvRecord);
  }

  if (misc_debug_record_) {
    misc_debug_record_->RegisterLocationDescriptor(&module_.MiscRecord);
  }

  return true;
}

size_t MinidumpModuleWriter::SizeOfObject() {
  DCHECK_GE(state(), kStateFrozen);

  // This object doesn’t directly write anything itself. Its MINIDUMP_MODULE is
  // written by its parent as part of a MINIDUMP_MODULE_LIST, and its children
  // are responsible for writing themselves.
  return 0;
}

std::vector<internal::MinidumpWritable*> MinidumpModuleWriter::Children() {
  DCHECK_GE(state(), kStateFrozen);
  DCHECK(name_);

  std::vector<MinidumpWritable*> children;
  children.push_back(name_.get());
  if (codeview_record_) {
    children.push_back(codeview_record_.get());
  }
  if (misc_debug_record_) {
    children.push_back(misc_debug_record_.get());
  }

  return children;
}

bool MinidumpModuleWriter::WriteObject(FileWriterInterface* file_writer) {
  DCHECK_EQ(state(), kStateWritable);

  // This object doesn’t directly write anything itself. Its MINIDUMP_MODULE is
  // written by its parent as part of a MINIDUMP_MODULE_LIST, and its children
  // are responsible for writing themselves.
  return true;
}

MinidumpModuleListWriter::MinidumpModuleListWriter()
    : MinidumpStreamWriter(), modules_(), module_list_base_() {}

MinidumpModuleListWriter::~MinidumpModuleListWriter() {}

void MinidumpModuleListWriter::InitializeFromSnapshot(
    const std::vector<const ModuleSnapshot*>& module_snapshots) {
  DCHECK_EQ(state(), kStateMutable);
  DCHECK(modules_.empty());

  for (const ModuleSnapshot* module_snapshot : module_snapshots) {
    auto module = std::make_unique<MinidumpModuleWriter>();
    module->InitializeFromSnapshot(module_snapshot);
    AddModule(std::move(module));
  }
}

void MinidumpModuleListWriter::AddModule(
    std::unique_ptr<MinidumpModuleWriter> module) {
  DCHECK_EQ(state(), kStateMutable);

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

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

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

  size_t module_count = modules_.size();
  if (!AssignIfInRange(&module_list_base_.NumberOfModules, module_count)) {
    LOG(ERROR) << "module_count " << module_count << " out of range";
    return false;
  }

  return true;
}

size_t MinidumpModuleListWriter::SizeOfObject() {
  DCHECK_GE(state(), kStateFrozen);

  return sizeof(module_list_base_) + modules_.size() * sizeof(MINIDUMP_MODULE);
}

std::vector<internal::MinidumpWritable*> MinidumpModuleListWriter::Children() {
  DCHECK_GE(state(), kStateFrozen);

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

  return children;
}

bool MinidumpModuleListWriter::WriteObject(FileWriterInterface* file_writer) {
  DCHECK_EQ(state(), kStateWritable);

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

  for (const auto& module : modules_) {
    iov.iov_base = module->MinidumpModule();
    iov.iov_len = sizeof(MINIDUMP_MODULE);
    iovecs.push_back(iov);
  }

  return file_writer->WriteIoVec(&iovecs);
}

MinidumpStreamType MinidumpModuleListWriter::StreamType() const {
  return kMinidumpStreamTypeModuleList;
}

}  // namespace crashpad
