// 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) || defined(NATIVE_TARGET_BUILD)
#include "third_party/crashpad/util/linux/exception_handler_protocol.h"
// TODO(b/201538792): resolve conflict between mini_chromium and base functions.
#ifdef LogMessage
#define LOG_MESSAGE_DEFINED
#undef LogMessage
#endif
#include "third_party/crashpad/wrapper/proto/crashpad_annotations.pb.h"
#ifdef LOG_MESSAGE_DEFINED
#define LogMessage MLogMessage
#endif
#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) || defined(NATIVE_TARGET_BUILD)
bool ProcessSnapshotLinux::Initialize(PtraceConnection* connection,
                                      VMAddress evergreen_information_address,
                                      VMAddress serialized_annotations_address,
                                      int serialized_annotations_size,
                                      ExceptionHandlerProtocol::HandlerStartType handler_start_type) {
  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;
  }

  if (handler_start_type == ExceptionHandlerProtocol::kStartAtCrash) {
    LOG(INFO) << "Annotations do not need to be read from client process";
  } else {
    AddAnnotations(serialized_annotations_address, serialized_annotations_size);
  }

  system_.Initialize(&process_reader_, &snapshot_time_);

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

  INITIALIZATION_STATE_SET_VALID(initialized_);
  return true;
}

void ProcessSnapshotLinux::AddAnnotations(
    VMAddress serialized_annotations_address, int serialized_annotations_size) {
  std::vector<char> buffer(serialized_annotations_size);
  if (!memory_range_.Read(serialized_annotations_address,
                          serialized_annotations_size,
                          buffer.data())) {
    LOG(ERROR) << "Could not read annotations";
    return;
  }

  crashpad::wrapper::CrashpadAnnotations annotations;
  if (!annotations.ParseFromArray(buffer.data(), serialized_annotations_size)) {
      LOG(ERROR) << "Could not parse annotations";
      return;
  }

  AddAnnotation("user_agent_string",
                std::string(annotations.user_agent_string()));
  AddAnnotation("prod", std::string(annotations.prod()));
  AddAnnotation("ver", std::string(annotations.ver()));

  for (auto& runtime_annotation : annotations.runtime_annotations()) {
    AddAnnotation(runtime_annotation.first, runtime_annotation.second);
  }
  LOG(INFO) << "Annotations successfully added from client process";
}
#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) || defined(NATIVE_TARGET_BUILD)
  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) || defined(NATIVE_TARGET_BUILD)
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
