// Copyright 2017 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/linux/process_snapshot_linux.h"

#include <utility>

#include "base/logging.h"
#include "util/linux/exception_information.h"

#if defined(STARBOARD)
#include "third_party/crashpad/wrapper/annotations.h"
#endif

namespace crashpad {

ProcessSnapshotLinux::ProcessSnapshotLinux() = default;

ProcessSnapshotLinux::~ProcessSnapshotLinux() = default;

bool ProcessSnapshotLinux::Initialize(PtraceConnection* connection) {
  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);

  if (gettimeofday(&snapshot_time_, nullptr) != 0) {
    PLOG(ERROR) << "gettimeofday";
    return false;
  }

  if (!process_reader_.Initialize(connection) ||
      !memory_range_.Initialize(process_reader_.Memory(),
                                process_reader_.Is64Bit())) {
    return false;
  }

  system_.Initialize(&process_reader_, &snapshot_time_);

  InitializeThreads();
  InitializeModules();
  InitializeAnnotations();

  INITIALIZATION_STATE_SET_VALID(initialized_);
  return true;
}

#if defined(STARBOARD)
bool ProcessSnapshotLinux::Initialize(PtraceConnection* connection,
                                      VMAddress evergreen_information_address,
                                      VMAddress annotations_address) {
  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);

  if (gettimeofday(&snapshot_time_, nullptr) != 0) {
    PLOG(ERROR) << "gettimeofday";
    return false;
  }

  if (!process_reader_.Initialize(connection) ||
      !memory_range_.Initialize(process_reader_.Memory(),
                                process_reader_.Is64Bit())) {
    return false;
  }

  CrashpadAnnotations annotations;
  if (!memory_range_.Read(
          annotations_address, sizeof(CrashpadAnnotations), &annotations)) {
    LOG(ERROR) << "Could not read annotations";
  } else {
    AddAnnotation("user_agent_string",
                  std::string(annotations.user_agent_string));
    AddAnnotation("prod", std::string(annotations.product));
    AddAnnotation("ver", std::string(annotations.version));
  }

  system_.Initialize(&process_reader_, &snapshot_time_);

  InitializeThreads();
  InitializeModules(evergreen_information_address);
  InitializeAnnotations();

  INITIALIZATION_STATE_SET_VALID(initialized_);
  return true;
}
#endif

pid_t ProcessSnapshotLinux::FindThreadWithStackAddress(
    VMAddress stack_address) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  for (const auto& thread : process_reader_.Threads()) {
    if (stack_address >= thread.stack_region_address &&
        stack_address <
            thread.stack_region_address + thread.stack_region_size) {
      return thread.tid;
    }
  }
  return -1;
}

bool ProcessSnapshotLinux::InitializeException(
    LinuxVMAddress exception_info_address,
    pid_t exception_thread_id) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  DCHECK(!exception_);

  ExceptionInformation info;
  if (!process_reader_.Memory()->Read(
          exception_info_address, sizeof(info), &info)) {
    LOG(ERROR) << "Couldn't read exception info";
    return false;
  }

  if (exception_thread_id >= 0) {
    info.thread_id = exception_thread_id;
  }

  exception_.reset(new internal::ExceptionSnapshotLinux());
  if (!exception_->Initialize(&process_reader_,
                              info.siginfo_address,
                              info.context_address,
                              info.thread_id)) {
    exception_.reset();
    return false;
  }

  // The thread's existing snapshot will have captured the stack for the signal
  // handler. Replace it with a thread snapshot which captures the stack for the
  // exception context.
  for (const auto& reader_thread : process_reader_.Threads()) {
    if (reader_thread.tid == info.thread_id) {
      ProcessReaderLinux::Thread thread = reader_thread;
      thread.InitializeStackFromSP(&process_reader_,
                                   exception_->Context()->StackPointer());

      auto exc_thread_snapshot =
          std::make_unique<internal::ThreadSnapshotLinux>();
      if (!exc_thread_snapshot->Initialize(&process_reader_, thread)) {
        return false;
      }

      for (auto& thread_snapshot : threads_) {
        if (thread_snapshot->ThreadID() ==
            static_cast<uint64_t>(info.thread_id)) {
          thread_snapshot.reset(exc_thread_snapshot.release());
          return true;
        }
      }

      LOG(ERROR) << "thread not found " << info.thread_id;
      return false;
    }
  }

  LOG(ERROR) << "thread not found " << info.thread_id;
  return false;
}

void ProcessSnapshotLinux::GetCrashpadOptions(
    CrashpadInfoClientOptions* options) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  CrashpadInfoClientOptions local_options;

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

    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;
}

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

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

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

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

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

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

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

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

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

std::vector<const ThreadSnapshot*> ProcessSnapshotLinux::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*> ProcessSnapshotLinux::Modules() const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  std::vector<const ModuleSnapshot*> modules;
  for (const auto& module : modules_) {
    modules.push_back(module.get());
  }
#if defined(STARBOARD)
  if (evergreen_module_) {
    modules.push_back(evergreen_module_.get());
  }
#endif
  return modules;
}

std::vector<UnloadedModuleSnapshot> ProcessSnapshotLinux::UnloadedModules()
    const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  // TODO(jperaza): Can this be implemented on Linux?
  return std::vector<UnloadedModuleSnapshot>();
}

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

std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotLinux::MemoryMap()
    const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  // TODO(jperaza): do this.
  return std::vector<const MemoryMapRegionSnapshot*>();
}

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

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

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

void ProcessSnapshotLinux::InitializeThreads() {
  const std::vector<ProcessReaderLinux::Thread>& process_reader_threads =
      process_reader_.Threads();
  for (const ProcessReaderLinux::Thread& process_reader_thread :
       process_reader_threads) {
    auto thread = std::make_unique<internal::ThreadSnapshotLinux>();
    if (thread->Initialize(&process_reader_, process_reader_thread)) {
      threads_.push_back(std::move(thread));
    }
  }
}

void ProcessSnapshotLinux::InitializeModules() {
  for (const ProcessReaderLinux::Module& reader_module :
       process_reader_.Modules()) {
    auto module =
        std::make_unique<internal::ModuleSnapshotElf>(reader_module.name,
                                                      reader_module.elf_reader,
                                                      reader_module.type,
                                                      &memory_range_,
                                                      process_reader_.Memory());
    if (module->Initialize()) {
      modules_.push_back(std::move(module));
    }
  }
}

#if defined(STARBOARD)
void ProcessSnapshotLinux::InitializeModules(
    VMAddress evergreen_information_address) {
  for (const ProcessReaderLinux::Module& reader_module :
       process_reader_.Modules()) {
    auto module =
        std::make_unique<internal::ModuleSnapshotElf>(reader_module.name,
                                                      reader_module.elf_reader,
                                                      reader_module.type,
                                                      &memory_range_,
                                                      process_reader_.Memory());
    if (module->Initialize()) {
      modules_.push_back(std::move(module));
    }
  }

  // Add evergreen module
  EvergreenInfo evergreen_info;
  if (!memory_range_.Read(evergreen_information_address,
                          sizeof(evergreen_info),
                          &evergreen_info)) {
    LOG(ERROR) << "Could not read evergreen info";
    return;
  }

  std::vector<uint8_t> build_id(evergreen_info.build_id_length);
  for (int i = 0; i < build_id.size(); i++) {
    build_id[i] = reinterpret_cast<uint8_t*>(evergreen_info.build_id)[i];
  }

  evergreen_module_ = std::make_unique<internal::ModuleSnapshotEvergreen>(
      std::string(evergreen_info.file_path_buf),
      ModuleSnapshot::ModuleType::kModuleTypeLoadableModule,
      evergreen_info.base_address,
      evergreen_info.load_size,
      build_id);
}
#endif

void ProcessSnapshotLinux::InitializeAnnotations() {
#if defined(OS_ANDROID)
  const std::string& abort_message = process_reader_.AbortMessage();
  if (!abort_message.empty()) {
    annotations_simple_map_["abort_message"] = abort_message;
  }
#endif
}

}  // namespace crashpad
