// Copyright 2020 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 "snapshot/ios/process_snapshot_ios_intermediate_dump.h"

#include <sys/stat.h>

#include "base/logging.h"
#include "snapshot/ios/intermediate_dump_reader_util.h"
#include "util/ios/ios_intermediate_dump_data.h"
#include "util/ios/ios_intermediate_dump_list.h"
#include "util/ios/ios_intermediate_dump_map.h"

namespace {

void MachTimeValueToTimeval(const time_value& mach, timeval* tv) {
  tv->tv_sec = mach.seconds;
  tv->tv_usec = mach.microseconds;
}

}  // namespace

namespace crashpad {
namespace internal {

using Key = internal::IntermediateDumpKey;

bool ProcessSnapshotIOSIntermediateDump::InitializeWithFilePath(
    const base::FilePath& dump_path,
    const std::map<std::string, std::string>& annotations) {
  IOSIntermediateDumpFilePath dump_interface;
  if (!dump_interface.Initialize(dump_path))
    return false;

  return InitializeWithFileInterface(dump_interface, annotations);
}

bool ProcessSnapshotIOSIntermediateDump::InitializeWithFileInterface(
    const IOSIntermediateDumpInterface& dump_interface,
    const std::map<std::string, std::string>& annotations) {
  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);

  annotations_simple_map_ = annotations;
  client_id_.InitializeToZero();

  IOSIntermediateDumpReaderInitializeResult result =
      reader_.Initialize(dump_interface);
  if (result == IOSIntermediateDumpReaderInitializeResult::kFailure) {
    return false;
  } else if (result == IOSIntermediateDumpReaderInitializeResult::kIncomplete) {
    annotations_simple_map_["crashpad_intermediate_dump_incomplete"] = "yes";
  }

  const IOSIntermediateDumpMap* root_map = reader_.RootMap();
  if (root_map->empty())
    return false;

  uint8_t version;
  if (!GetDataValueFromMap(root_map, Key::kVersion, &version) || version != 1) {
    LOG(ERROR) << "Root map version mismatch";
    return false;
  }

  const internal::IOSIntermediateDumpMap* process_info =
      GetMapFromMap(root_map, Key::kProcessInfo);
  if (!process_info) {
    LOG(ERROR) << "Process snapshot missing required process info map.";
    return false;
  }

  GetDataValueFromMap(process_info, Key::kPID, &p_pid_);
  GetDataValueFromMap(process_info, Key::kParentPID, &e_ppid_);
  GetDataValueFromMap(process_info, Key::kStartTime, &p_starttime_);
  const IOSIntermediateDumpMap* basic_info =
      process_info->GetAsMap(Key::kTaskBasicInfo);
  if (basic_info) {
    GetDataValueFromMap(basic_info, Key::kUserTime, &basic_info_user_time_);
    GetDataValueFromMap(basic_info, Key::kSystemTime, &basic_info_system_time_);
  }

  const IOSIntermediateDumpMap* thread_times =
      process_info->GetAsMap(Key::kTaskThreadTimes);
  if (thread_times) {
    GetDataValueFromMap(thread_times, Key::kUserTime, &thread_times_user_time_);
    GetDataValueFromMap(
        thread_times, Key::kSystemTime, &thread_times_system_time_);
  }

  GetDataValueFromMap(process_info, Key::kSnapshotTime, &snapshot_time_);

  const IOSIntermediateDumpList* simple_map_dump =
      process_info->GetAsList(IntermediateDumpKey::kAnnotationsSimpleMap);
  if (simple_map_dump) {
    for (auto& annotation : *simple_map_dump) {
      const IOSIntermediateDumpData* name_dump =
          annotation->GetAsData(IntermediateDumpKey::kAnnotationName);
      const IOSIntermediateDumpData* value_dump =
          annotation->GetAsData(IntermediateDumpKey::kAnnotationValue);
      if (name_dump && value_dump) {
        annotations_simple_map_.insert(
            make_pair(name_dump->GetString(), value_dump->GetString()));
      }
    }
  }

  const IOSIntermediateDumpMap* system_info =
      GetMapFromMap(root_map, Key::kSystemInfo);
  if (!system_info) {
    LOG(ERROR) << "Process snapshot missing required system info map.";
    return false;
  }
  system_.Initialize(system_info);

  annotations_simple_map_["crashpad_uptime_ns"] =
      std::to_string(system_.CrashpadUptime());

  // Threads
  const IOSIntermediateDumpList* thread_list =
      GetListFromMap(root_map, Key::kThreads);
  if (thread_list) {
    for (const auto& value : *thread_list) {
      auto thread =
          std::make_unique<internal::ThreadSnapshotIOSIntermediateDump>();
      if (thread->Initialize(value.get())) {
        threads_.push_back(std::move(thread));
      }
    }
  }

  const IOSIntermediateDumpList* module_list =
      GetListFromMap(root_map, Key::kModules);
  if (module_list) {
    for (const auto& value : *module_list) {
      auto module =
          std::make_unique<internal::ModuleSnapshotIOSIntermediateDump>();
      if (module->Initialize(value.get())) {
        modules_.push_back(std::move(module));
      }
    }
  }

  // Exceptions
  const IOSIntermediateDumpMap* signal_exception =
      root_map->GetAsMap(Key::kSignalException);
  const IOSIntermediateDumpMap* mach_exception =
      root_map->GetAsMap(Key::kMachException);
  const IOSIntermediateDumpMap* ns_exception =
      root_map->GetAsMap(Key::kNSException);
  if (signal_exception) {
    exception_.reset(new internal::ExceptionSnapshotIOSIntermediateDump());
    if (!exception_->InitializeFromSignal(signal_exception)) {
      LOG(ERROR) << "Process snapshot could not initialize signal exception.";
      return false;
    }
  } else if (mach_exception) {
    exception_.reset(new internal::ExceptionSnapshotIOSIntermediateDump());
    if (!exception_->InitializeFromMachException(
            mach_exception, GetListFromMap(root_map, Key::kThreads))) {
      LOG(ERROR) << "Process snapshot could not initialize Mach exception.";
      return false;
    }
  } else if (ns_exception) {
    exception_.reset(new internal::ExceptionSnapshotIOSIntermediateDump());
    if (!exception_->InitializeFromNSException(
            ns_exception, GetListFromMap(root_map, Key::kThreads))) {
      LOG(ERROR) << "Process snapshot could not initialize NSException.";
      return false;
    }
  }

  INITIALIZATION_STATE_SET_VALID(initialized_);
  return true;
}

void ProcessSnapshotIOSIntermediateDump::SetClientID(const UUID& client_id) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  client_id_ = client_id;
}

void ProcessSnapshotIOSIntermediateDump::SetReportID(const UUID& report_id) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  report_id_ = report_id;
}

pid_t ProcessSnapshotIOSIntermediateDump::ProcessID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return p_pid_;
}

pid_t ProcessSnapshotIOSIntermediateDump::ParentProcessID() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return e_ppid_;
}

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

void ProcessSnapshotIOSIntermediateDump::ProcessStartTime(
    timeval* start_time) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  *start_time = p_starttime_;
}

void ProcessSnapshotIOSIntermediateDump::ProcessCPUTimes(
    timeval* user_time,
    timeval* system_time) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  // Calculate user and system time the same way the kernel does for
  // getrusage(). See 10.15.0 xnu-6153.11.26/bsd/kern/kern_resource.c calcru().
  timerclear(user_time);
  timerclear(system_time);

  MachTimeValueToTimeval(basic_info_user_time_, user_time);
  MachTimeValueToTimeval(basic_info_system_time_, system_time);

  timeval thread_user_time;
  MachTimeValueToTimeval(thread_times_user_time_, &thread_user_time);
  timeval thread_system_time;
  MachTimeValueToTimeval(thread_times_system_time_, &thread_system_time);

  timeradd(user_time, &thread_user_time, user_time);
  timeradd(system_time, &thread_system_time, system_time);
}

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

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

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

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

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

const ExceptionSnapshot* ProcessSnapshotIOSIntermediateDump::Exception() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return exception_.get();
}

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

std::vector<HandleSnapshot> ProcessSnapshotIOSIntermediateDump::Handles()
    const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return std::vector<HandleSnapshot>();
}

std::vector<const MemorySnapshot*>
ProcessSnapshotIOSIntermediateDump::ExtraMemory() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return std::vector<const MemorySnapshot*>();
}

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

}  // namespace internal
}  // namespace crashpad
