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

#include <stddef.h>
#include <wchar.h>

#include <algorithm>
#include <utility>

#include "base/cxx17_backports.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "util/misc/from_pointer_cast.h"
#include "util/misc/time.h"
#include "util/win/nt_internals.h"
#include "util/win/registration_protocol_win.h"

namespace crashpad {

ProcessSnapshotWin::ProcessSnapshotWin()
    : ProcessSnapshot(),
      system_(),
      threads_(),
      modules_(),
      exception_(),
      memory_map_(),
      process_reader_(),
      report_id_(),
      client_id_(),
      annotations_simple_map_(),
      snapshot_time_(),
      options_(),
      initialized_() {
}

ProcessSnapshotWin::~ProcessSnapshotWin() {
}

bool ProcessSnapshotWin::Initialize(
    HANDLE process,
    ProcessSuspensionState suspension_state,
    WinVMAddress exception_information_address,
    WinVMAddress debug_critical_section_address) {
  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);

  GetTimeOfDay(&snapshot_time_);

  if (!process_reader_.Initialize(process, suspension_state))
    return false;

  if (exception_information_address != 0) {
    ExceptionInformation exception_information = {};
    if (!process_reader_.Memory()->Read(exception_information_address,
                                        sizeof(exception_information),
                                        &exception_information)) {
      LOG(WARNING) << "ReadMemory ExceptionInformation failed";
      return false;
    }

    exception_.reset(new internal::ExceptionSnapshotWin());
    if (!exception_->Initialize(&process_reader_,
                                exception_information.thread_id,
                                exception_information.exception_pointers)) {
      exception_.reset();
      return false;
    }
  }


  system_.Initialize(&process_reader_);

  if (process_reader_.Is64Bit()) {
    InitializePebData<process_types::internal::Traits64>(
        debug_critical_section_address);
  } else {
    InitializePebData<process_types::internal::Traits32>(
        debug_critical_section_address);
  }

  InitializeModules();
  InitializeUnloadedModules();

  GetCrashpadOptionsInternal(&options_);

  InitializeThreads(
      options_.gather_indirectly_referenced_memory == TriState::kEnabled,
      options_.indirectly_referenced_memory_cap);

  for (const MEMORY_BASIC_INFORMATION64& mbi :
       process_reader_.GetProcessInfo().MemoryInfo()) {
    memory_map_.push_back(
        std::make_unique<internal::MemoryMapRegionSnapshotWin>(mbi));
  }

  for (const auto& module : modules_) {
    for (const auto& range : module->ExtraMemoryRanges()) {
      AddMemorySnapshot(range.base(), range.size(), &extra_memory_);
    }
  }

  INITIALIZATION_STATE_SET_VALID(initialized_);
  return true;
}

void ProcessSnapshotWin::GetCrashpadOptions(
    CrashpadInfoClientOptions* options) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  *options = options_;
}

crashpad::ProcessID ProcessSnapshotWin::ProcessID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return process_reader_.GetProcessInfo().ProcessID();
}

crashpad::ProcessID ProcessSnapshotWin::ParentProcessID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return process_reader_.GetProcessInfo().ParentProcessID();
}

void ProcessSnapshotWin::SnapshotTime(timeval* snapshot_time) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  *snapshot_time = snapshot_time_;
}

void ProcessSnapshotWin::ProcessStartTime(timeval* start_time) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  process_reader_.StartTime(start_time);
}

void ProcessSnapshotWin::ProcessCPUTimes(timeval* user_time,
                                         timeval* system_time) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  process_reader_.CPUTimes(user_time, system_time);
}

void ProcessSnapshotWin::ReportID(UUID* report_id) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  *report_id = report_id_;
}

void ProcessSnapshotWin::ClientID(UUID* client_id) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  *client_id = client_id_;
}

const std::map<std::string, std::string>&
ProcessSnapshotWin::AnnotationsSimpleMap() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return annotations_simple_map_;
}

const SystemSnapshot* ProcessSnapshotWin::System() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return &system_;
}

std::vector<const ThreadSnapshot*> ProcessSnapshotWin::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*> ProcessSnapshotWin::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> ProcessSnapshotWin::UnloadedModules()
    const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return unloaded_modules_;
}

const ExceptionSnapshot* ProcessSnapshotWin::Exception() const {
  return exception_.get();
}

std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotWin::MemoryMap()
    const {
  std::vector<const MemoryMapRegionSnapshot*> memory_map;
  for (const auto& item : memory_map_) {
    memory_map.push_back(item.get());
  }
  return memory_map;
}

std::vector<HandleSnapshot> ProcessSnapshotWin::Handles() const {
  std::vector<HandleSnapshot> result;
  for (const auto& handle : process_reader_.GetProcessInfo().Handles()) {
    HandleSnapshot snapshot;
    // This is probably not strictly correct, but these are not localized so we
    // expect them all to be in ASCII range anyway. This will need to be more
    // carefully done if the object name is added.
    snapshot.type_name = base::WideToUTF8(handle.type_name);
    snapshot.handle = handle.handle;
    snapshot.attributes = handle.attributes;
    snapshot.granted_access = handle.granted_access;
    snapshot.pointer_count = handle.pointer_count;
    snapshot.handle_count = handle.handle_count;
    result.push_back(snapshot);
  }
  return result;
}

std::vector<const MemorySnapshot*> ProcessSnapshotWin::ExtraMemory() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  std::vector<const MemorySnapshot*> extra_memory;
  for (const auto& em : extra_memory_) {
    extra_memory.push_back(em.get());
  }
  return extra_memory;
}

const ProcessMemory* ProcessSnapshotWin::Memory() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return process_reader_.Memory();
}

void ProcessSnapshotWin::InitializeThreads(
    bool gather_indirectly_referenced_memory,
    uint32_t indirectly_referenced_memory_cap) {
  const std::vector<ProcessReaderWin::Thread>& process_reader_threads =
      process_reader_.Threads();
  uint32_t* budget_remaining_pointer = nullptr;
  uint32_t budget_remaining = indirectly_referenced_memory_cap;
  if (gather_indirectly_referenced_memory)
    budget_remaining_pointer = &budget_remaining;
  for (const ProcessReaderWin::Thread& process_reader_thread :
       process_reader_threads) {
    auto thread = std::make_unique<internal::ThreadSnapshotWin>();
    if (thread->Initialize(&process_reader_,
                           process_reader_thread,
                           budget_remaining_pointer)) {
      threads_.push_back(std::move(thread));
    }
  }
}

void ProcessSnapshotWin::InitializeModules() {
  const std::vector<ProcessInfo::Module>& process_reader_modules =
      process_reader_.Modules();
  for (const ProcessInfo::Module& process_reader_module :
       process_reader_modules) {
    auto module = std::make_unique<internal::ModuleSnapshotWin>();
    if (module->Initialize(&process_reader_, process_reader_module)) {
      modules_.push_back(std::move(module));
    }
  }
}

void ProcessSnapshotWin::InitializeUnloadedModules() {
  // As documented by https://msdn.microsoft.com/library/cc678403.aspx, we can
  // retrieve the location for our unload events, and use that address in the
  // target process. Unfortunately, this of course only works for 64-reading-64
  // and 32-reading-32, so at the moment, we simply do not retrieve unloaded
  // modules for 64-reading-32. See https://crashpad.chromium.org/bug/89.

#if defined(ARCH_CPU_X86_64) || defined(ARCH_CPU_ARM64)
  if (!process_reader_.Is64Bit()) {
    LOG(ERROR)
        << "reading unloaded modules across bitness not currently supported";
    return;
  }
  using Traits = process_types::internal::Traits64;
#elif defined(ARCH_CPU_X86)
  using Traits = process_types::internal::Traits32;
#else
#error port
#endif

  ULONG* element_size;
  ULONG* element_count;
  void* event_trace_address;
  RtlGetUnloadEventTraceEx(&element_size, &element_count, &event_trace_address);

  if (*element_size < sizeof(RTL_UNLOAD_EVENT_TRACE<Traits>)) {
    LOG(ERROR) << "unexpected unloaded module list element size";
    return;
  }

  const WinVMAddress address_in_target_process =
      FromPointerCast<WinVMAddress>(event_trace_address);

  Traits::Pointer pointer_to_array;
  if (!process_reader_.Memory()->Read(address_in_target_process,
                                      sizeof(pointer_to_array),
                                      &pointer_to_array)) {
    LOG(ERROR) << "failed to read target address";
    return;
  }

  // No unloaded modules.
  if (pointer_to_array == 0)
    return;

  const size_t data_size = *element_size * *element_count;
  std::vector<uint8_t> data(data_size);
  if (!process_reader_.Memory()->Read(pointer_to_array, data_size, &data[0])) {
    LOG(ERROR) << "failed to read unloaded module data";
    return;
  }

  for (ULONG i = 0; i < *element_count; ++i) {
    const uint8_t* base_address = &data[i * *element_size];
    const auto& uet =
        *reinterpret_cast<const RTL_UNLOAD_EVENT_TRACE<Traits>*>(base_address);
    if (uet.ImageName[0] != 0) {
      unloaded_modules_.push_back(UnloadedModuleSnapshot(
          uet.BaseAddress,
          uet.SizeOfImage,
          uet.CheckSum,
          uet.TimeDateStamp,
          base::WideToUTF8(base::WStringPiece(
              uet.ImageName,
              wcsnlen(uet.ImageName, base::size(uet.ImageName))))));
    }
  }
}

void ProcessSnapshotWin::GetCrashpadOptionsInternal(
    CrashpadInfoClientOptions* options) {
  CrashpadInfoClientOptions local_options;

  for (const auto& module : modules_) {
    CrashpadInfoClientOptions module_options;
    module->GetCrashpadOptions(&module_options);

    if (local_options.crashpad_handler_behavior == TriState::kUnset) {
      local_options.crashpad_handler_behavior =
          module_options.crashpad_handler_behavior;
    }
    if (local_options.system_crash_reporter_forwarding == TriState::kUnset) {
      local_options.system_crash_reporter_forwarding =
          module_options.system_crash_reporter_forwarding;
    }
    if (local_options.gather_indirectly_referenced_memory == TriState::kUnset) {
      local_options.gather_indirectly_referenced_memory =
          module_options.gather_indirectly_referenced_memory;
      local_options.indirectly_referenced_memory_cap =
          module_options.indirectly_referenced_memory_cap;
    }

    // If non-default values have been found for all options, the loop can end
    // early.
    if (local_options.crashpad_handler_behavior != TriState::kUnset &&
        local_options.system_crash_reporter_forwarding != TriState::kUnset &&
        local_options.gather_indirectly_referenced_memory != TriState::kUnset) {
      break;
    }
  }

  *options = local_options;
}

template <class Traits>
void ProcessSnapshotWin::InitializePebData(
    WinVMAddress debug_critical_section_address) {
  WinVMAddress peb_address;
  WinVMSize peb_size;
  process_reader_.GetProcessInfo().Peb(&peb_address, &peb_size);
  AddMemorySnapshot(peb_address, peb_size, &extra_memory_);

  process_types::PEB<Traits> peb_data;
  if (!process_reader_.Memory()->Read(
          peb_address, base::checked_cast<size_t>(peb_size), &peb_data)) {
    LOG(ERROR) << "ReadMemory PEB";
    return;
  }

  process_types::PEB_LDR_DATA<Traits> peb_ldr_data;
  AddMemorySnapshot(peb_data.Ldr, sizeof(peb_ldr_data), &extra_memory_);
  if (!process_reader_.Memory()->Read(
          peb_data.Ldr, sizeof(peb_ldr_data), &peb_ldr_data)) {
    LOG(ERROR) << "ReadMemory PEB_LDR_DATA";
  } else {
    // Walk the LDR structure to retrieve its pointed-to data.
    AddMemorySnapshotForLdrLIST_ENTRY(
        peb_ldr_data.InLoadOrderModuleList,
        offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>, InLoadOrderLinks),
        &extra_memory_);
    AddMemorySnapshotForLdrLIST_ENTRY(
        peb_ldr_data.InMemoryOrderModuleList,
        offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>,
                 InMemoryOrderLinks),
        &extra_memory_);
    AddMemorySnapshotForLdrLIST_ENTRY(
        peb_ldr_data.InInitializationOrderModuleList,
        offsetof(process_types::LDR_DATA_TABLE_ENTRY<Traits>,
                 InInitializationOrderLinks),
        &extra_memory_);
  }

  process_types::RTL_USER_PROCESS_PARAMETERS<Traits> process_parameters;
  if (!process_reader_.Memory()->Read(peb_data.ProcessParameters,
                                      sizeof(process_parameters),
                                      &process_parameters)) {
    LOG(ERROR) << "ReadMemory RTL_USER_PROCESS_PARAMETERS";
    return;
  }
  AddMemorySnapshot(
      peb_data.ProcessParameters, sizeof(process_parameters), &extra_memory_);

  AddMemorySnapshotForUNICODE_STRING(
      process_parameters.CurrentDirectory.DosPath, &extra_memory_);
  AddMemorySnapshotForUNICODE_STRING(process_parameters.DllPath,
                                     &extra_memory_);
  AddMemorySnapshotForUNICODE_STRING(process_parameters.ImagePathName,
                                     &extra_memory_);
  AddMemorySnapshotForUNICODE_STRING(process_parameters.CommandLine,
                                     &extra_memory_);
  AddMemorySnapshotForUNICODE_STRING(process_parameters.WindowTitle,
                                     &extra_memory_);
  AddMemorySnapshotForUNICODE_STRING(process_parameters.DesktopInfo,
                                     &extra_memory_);
  AddMemorySnapshotForUNICODE_STRING(process_parameters.ShellInfo,
                                     &extra_memory_);
  AddMemorySnapshotForUNICODE_STRING(process_parameters.RuntimeData,
                                     &extra_memory_);
  AddMemorySnapshot(
      process_parameters.Environment,
      DetermineSizeOfEnvironmentBlock(process_parameters.Environment),
      &extra_memory_);

  // Walk the loader lock which is directly referenced by the PEB.
  ReadLock<Traits>(peb_data.LoaderLock, &extra_memory_);

  // TODO(scottmg): Use debug_critical_section_address to walk the list of
  // locks (see history of this file for walking code). In some configurations
  // this can walk many thousands of locks, so we may want to get some
  // annotation from the client for which locks to grab. Unfortunately, without
  // walking the list, the !locks command in windbg won't work because it
  // requires the lock pointed to by ntdll!RtlCriticalSectionList, which we
  // won't have captured.
}

void ProcessSnapshotWin::AddMemorySnapshot(
    WinVMAddress address,
    WinVMSize size,
    std::vector<std::unique_ptr<internal::MemorySnapshotGeneric>>* into) {
  if (size == 0)
    return;

  if (!process_reader_.GetProcessInfo().LoggingRangeIsFullyReadable(
          CheckedRange<WinVMAddress, WinVMSize>(address, size))) {
    return;
  }

  // If we have already added this exact range, don't add it again. This is
  // useful for the LDR module lists which are a set of doubly-linked lists, all
  // pointing to the same module name strings.
  // TODO(scottmg): A more general version of this, handling overlapping,
  // contained, etc. https://crashpad.chromium.org/bug/61.
  for (const auto& memory_snapshot : *into) {
    if (memory_snapshot->Address() == address &&
        memory_snapshot->Size() == size) {
      return;
    }
  }

  into->push_back(std::make_unique<internal::MemorySnapshotGeneric>());
  into->back()->Initialize(process_reader_.Memory(), address, size);
}

template <class Traits>
void ProcessSnapshotWin::AddMemorySnapshotForUNICODE_STRING(
    const process_types::UNICODE_STRING<Traits>& us,
    std::vector<std::unique_ptr<internal::MemorySnapshotGeneric>>* into) {
  AddMemorySnapshot(us.Buffer, us.Length, into);
}

template <class Traits>
void ProcessSnapshotWin::AddMemorySnapshotForLdrLIST_ENTRY(
    const process_types::LIST_ENTRY<Traits>& le,
    size_t offset_of_member,
    std::vector<std::unique_ptr<internal::MemorySnapshotGeneric>>* into) {
  // Walk the doubly-linked list of entries, adding the list memory itself, as
  // well as pointed-to strings.
  typename Traits::Pointer last = le.Blink;
  process_types::LDR_DATA_TABLE_ENTRY<Traits> entry;
  typename Traits::Pointer cur = le.Flink;
  for (;;) {
    // |cur| is the pointer to LIST_ENTRY embedded in the LDR_DATA_TABLE_ENTRY.
    // So we need to offset back to the beginning of the structure.
    if (!process_reader_.Memory()->Read(
            cur - offset_of_member, sizeof(entry), &entry)) {
      return;
    }
    AddMemorySnapshot(cur - offset_of_member, sizeof(entry), into);
    AddMemorySnapshotForUNICODE_STRING(entry.FullDllName, into);
    AddMemorySnapshotForUNICODE_STRING(entry.BaseDllName, into);

    process_types::LIST_ENTRY<Traits>* links =
        reinterpret_cast<process_types::LIST_ENTRY<Traits>*>(
            reinterpret_cast<unsigned char*>(&entry) + offset_of_member);
    cur = links->Flink;
    if (cur == last)
      break;
  }
}

WinVMSize ProcessSnapshotWin::DetermineSizeOfEnvironmentBlock(
    WinVMAddress start_of_environment_block) {
  // https://blogs.msdn.microsoft.com/oldnewthing/20100203-00/?p=15083: On newer
  // OSs there's no stated limit, but in practice grabbing 32k characters should
  // be more than enough.
  std::wstring env_block;
  env_block.resize(32768);
  size_t bytes_read = process_reader_.Memory()->ReadAvailableMemory(
      start_of_environment_block,
      env_block.size() * sizeof(env_block[0]),
      &env_block[0]);
  env_block.resize(
      static_cast<unsigned int>(bytes_read / sizeof(env_block[0])));
  static constexpr wchar_t terminator[] = {0, 0};
  size_t at = env_block.find(std::wstring(terminator, base::size(terminator)));
  if (at != std::wstring::npos)
    env_block.resize(at + base::size(terminator));

  return env_block.size() * sizeof(env_block[0]);
}

template <class Traits>
void ProcessSnapshotWin::ReadLock(
    WinVMAddress start,
    std::vector<std::unique_ptr<internal::MemorySnapshotGeneric>>* into) {
  // We're walking the RTL_CRITICAL_SECTION_DEBUG ProcessLocksList, but starting
  // from an actual RTL_CRITICAL_SECTION, so start by getting to the first
  // RTL_CRITICAL_SECTION_DEBUG.

  process_types::RTL_CRITICAL_SECTION<Traits> critical_section;
  if (!process_reader_.Memory()->Read(
          start, sizeof(critical_section), &critical_section)) {
    LOG(ERROR) << "failed to read RTL_CRITICAL_SECTION";
    return;
  }

  AddMemorySnapshot(
      start, sizeof(process_types::RTL_CRITICAL_SECTION<Traits>), into);

  constexpr decltype(critical_section.DebugInfo) kInvalid =
      static_cast<decltype(critical_section.DebugInfo)>(-1);
  if (critical_section.DebugInfo == kInvalid)
    return;

  AddMemorySnapshot(critical_section.DebugInfo,
                    sizeof(process_types::RTL_CRITICAL_SECTION_DEBUG<Traits>),
                    into);
}

}  // namespace crashpad
