// Copyright 2018 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/fuchsia/process_reader_fuchsia.h"

#include <lib/zx/thread.h>
#include <link.h>
#include <zircon/syscalls.h>

#include "base/fuchsia/fuchsia_logging.h"
#include "base/logging.h"
#include "util/fuchsia/koid_utilities.h"

namespace crashpad {

namespace {

// Based on the thread's SP and the process's memory map, attempts to figure out
// the stack regions for the thread. Fuchsia's C ABI specifies
// https://fuchsia.googlesource.com/zircon/+/master/docs/safestack.md so the
// callstack and locals-that-have-their-address-taken are in two different
// stacks.
void GetStackRegions(
    const zx_thread_state_general_regs_t& regs,
    const MemoryMapFuchsia& memory_map,
    std::vector<CheckedRange<zx_vaddr_t, size_t>>* stack_regions) {
  stack_regions->clear();

  uint64_t sp;
#if defined(ARCH_CPU_X86_64)
  sp = regs.rsp;
#elif defined(ARCH_CPU_ARM64)
  sp = regs.sp;
#else
#error Port
#endif

  // TODO(fxbug.dev/74897): make this work for stack overflows, e.g., by looking
  // up using the initial stack pointer (sp) when the thread was created. Right
  // now, it gets the stack by getting the mapping that contains the current sp.
  // But in the case of stack overflows, the current sp is by definition outside
  // of the stack so the mapping returned is not the stack and fails the type
  // check, at least on arm64.
  zx_info_maps_t range_with_sp;
  if (!memory_map.FindMappingForAddress(sp, &range_with_sp)) {
    LOG(ERROR) << "stack pointer not found in mapping";
    return;
  }

  if (range_with_sp.type != ZX_INFO_MAPS_TYPE_MAPPING) {
    LOG(ERROR) << "stack range has unexpected type " << range_with_sp.type
               << ", stack overflow? Aborting";
    return;
  }

  if (range_with_sp.u.mapping.mmu_flags & ZX_VM_PERM_EXECUTE) {
    LOG(ERROR)
        << "stack range is unexpectedly marked executable, continuing anyway";
  }

  // The stack covers [range_with_sp.base, range_with_sp.base +
  // range_with_sp.size). The stack pointer (sp) can be anywhere in that range.
  // It starts at the end of the range (range_with_sp.base + range_with_sp.size)
  // and goes downwards until range_with_sp.base. Capture the part of the stack
  // that is currently used: [sp, range_with_sp.base + range_with_sp.size).

  // Capture up to kExtraCaptureSize additional bytes of stack, but only if
  // present in the region that was already found.
  constexpr uint64_t kExtraCaptureSize = 128;
  const uint64_t start_address =
      std::max(sp >= kExtraCaptureSize ? sp - kExtraCaptureSize : sp,
               range_with_sp.base);
  const size_t region_size =
      range_with_sp.size - (start_address - range_with_sp.base);

  // Because most Fuchsia processes use safestack, it is very unlikely that a
  // stack this large would be valid. Even if it were, avoid creating
  // unreasonably large dumps by artificially limiting the captured amount.
  constexpr uint64_t kMaxStackCapture = 1048576u;
  LOG_IF(ERROR, region_size > kMaxStackCapture)
      << "clamping unexpectedly large stack capture of " << region_size;
  const size_t clamped_region_size = std::min(region_size, kMaxStackCapture);
  stack_regions->push_back(
      CheckedRange<zx_vaddr_t, size_t>(start_address, clamped_region_size));

  // TODO(scottmg): https://crashpad.chromium.org/bug/196, once the retrievable
  // registers include FS and similar for ARM, retrieve the region for the
  // unsafe part of the stack too.
}

}  // namespace

ProcessReaderFuchsia::Module::Module() = default;

ProcessReaderFuchsia::Module::~Module() = default;

ProcessReaderFuchsia::Thread::Thread() = default;

ProcessReaderFuchsia::Thread::~Thread() = default;

ProcessReaderFuchsia::ProcessReaderFuchsia() = default;

ProcessReaderFuchsia::~ProcessReaderFuchsia() = default;

bool ProcessReaderFuchsia::Initialize(const zx::process& process) {
  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);

  process_ = zx::unowned_process(process);

  process_memory_.reset(new ProcessMemoryFuchsia());
  process_memory_->Initialize(*process_);

  INITIALIZATION_STATE_SET_VALID(initialized_);
  return true;
}

const std::vector<ProcessReaderFuchsia::Module>&
ProcessReaderFuchsia::Modules() {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  if (!initialized_modules_) {
    InitializeModules();
  }

  return modules_;
}

const std::vector<ProcessReaderFuchsia::Thread>&
ProcessReaderFuchsia::Threads() {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  if (!initialized_threads_) {
    InitializeThreads();
  }

  return threads_;
}

const MemoryMapFuchsia* ProcessReaderFuchsia::MemoryMap() {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  if (!initialized_memory_map_) {
    InitializeMemoryMap();
  }

  return memory_map_.get();
}

void ProcessReaderFuchsia::InitializeModules() {
  DCHECK(!initialized_modules_);
  DCHECK(modules_.empty());

  initialized_modules_ = true;

  // TODO(scottmg): <inspector/inspector.h> does some of this, but doesn't
  // expose any of the data that's necessary to fill out a Module after it
  // retrieves (some of) the data into internal structures. It may be worth
  // trying to refactor/upstream some of this into Fuchsia.

  // Starting from the ld.so's _dl_debug_addr, read the link_map structure and
  // walk the list to fill out modules_.

  uintptr_t debug_address;
  zx_status_t status = process_->get_property(
      ZX_PROP_PROCESS_DEBUG_ADDR, &debug_address, sizeof(debug_address));
  if (status != ZX_OK || debug_address == 0) {
    LOG(ERROR) << "zx_object_get_property ZX_PROP_PROCESS_DEBUG_ADDR";
    return;
  }

  constexpr auto k_r_debug_map_offset = offsetof(r_debug, r_map);
  uintptr_t map;
  if (!process_memory_->Read(
          debug_address + k_r_debug_map_offset, sizeof(map), &map)) {
    LOG(ERROR) << "read link_map";
    return;
  }

  int i = 0;
  constexpr int kMaxDso = 1000;  // Stop after an unreasonably large number.
  while (map != 0) {
    if (++i >= kMaxDso) {
      LOG(ERROR) << "possibly circular dso list, terminating";
      return;
    }

    constexpr auto k_link_map_addr_offset = offsetof(link_map, l_addr);
    zx_vaddr_t base;
    if (!process_memory_->Read(
            map + k_link_map_addr_offset, sizeof(base), &base)) {
      LOG(ERROR) << "Read base";
      // Could theoretically continue here, but realistically if any part of
      // link_map fails to read, things are looking bad, so just abort.
      break;
    }

    constexpr auto k_link_map_next_offset = offsetof(link_map, l_next);
    zx_vaddr_t next;
    if (!process_memory_->Read(
            map + k_link_map_next_offset, sizeof(next), &next)) {
      LOG(ERROR) << "Read next";
      break;
    }

    constexpr auto k_link_map_name_offset = offsetof(link_map, l_name);
    zx_vaddr_t name_address;
    if (!process_memory_->Read(map + k_link_map_name_offset,
                               sizeof(name_address),
                               &name_address)) {
      LOG(ERROR) << "Read name address";
      break;
    }

    std::string dsoname;
    if (!process_memory_->ReadCString(name_address, &dsoname)) {
      // In this case, it could be reasonable to continue on to the next module
      // as this data isn't strictly in the link_map.
      LOG(ERROR) << "ReadCString name";
    }

    // Debug symbols are indexed by module name x build-id on the crash server.
    // The module name in the indexed Breakpad files is set at build time. So
    // Crashpad needs to use the same module name at run time for symbol
    // resolution to work properly.
    //
    // TODO(fuchsia/DX-1234): once Crashpad switches to elf-search, the
    // following overwrites won't be necessary as only shared libraries will
    // have a soname at runtime, just like at build time.
    //
    // * For shared libraries, the soname is used as module name at build time,
    //   which is the dsoname here except for libzircon.so (because it is
    //   injected by the kernel, its load name is "<vDSO>" and Crashpad needs to
    //   replace it for symbol resolution to work properly).
    if (dsoname == "<vDSO>") {
      dsoname = "libzircon.so";
    }
    // * For executables and loadable modules, the dummy value "<_>" is used as
    //   module name at build time. This is because executable and loadable
    //   modules don't have a name on Fuchsia. So we need to use the same dummy
    //   value at build and run times.
    //   Most executables have an empty dsoname. Loadable modules (and some rare
    //   executables) have a non-empty dsoname starting with a specific prefix,
    //   which Crashpas can use to identify loadable modules and clear the
    //   dsoname for them.
    static constexpr const char kLoadableModuleLoadNamePrefix[] = "<VMO#";
    // Pre-C++ 20 std::basic_string::starts_with
    if (dsoname.compare(0,
                        strlen(kLoadableModuleLoadNamePrefix),
                        kLoadableModuleLoadNamePrefix) == 0) {
      dsoname = "";
    }

    Module module;
    if (dsoname.empty()) {
      // This value must be kept in sync with what is used at build time to
      // index symbols for executables and loadable modules.
      // See fuchsia/DX-1193 for more details.
      module.name = "<_>";
      module.type = ModuleSnapshot::kModuleTypeExecutable;
    } else {
      module.name = dsoname;
      // TODO(scottmg): Handle kModuleTypeDynamicLoader.
      module.type = ModuleSnapshot::kModuleTypeSharedLibrary;
    }

    std::unique_ptr<ElfImageReader> reader(new ElfImageReader());

    std::unique_ptr<ProcessMemoryRange> process_memory_range(
        new ProcessMemoryRange());
    // TODO(scottmg): Could this be limited range?
    if (process_memory_range->Initialize(process_memory_.get(), true)) {
      process_memory_ranges_.push_back(std::move(process_memory_range));

      if (reader->Initialize(*process_memory_ranges_.back(), base)) {
        module.reader = reader.get();
        module_readers_.push_back(std::move(reader));
        modules_.push_back(module);
      }
    }

    map = next;
  }
}

void ProcessReaderFuchsia::InitializeThreads() {
  DCHECK(!initialized_threads_);
  DCHECK(threads_.empty());

  initialized_threads_ = true;

  std::vector<zx_koid_t> thread_koids =
      GetChildKoids(*process_, ZX_INFO_PROCESS_THREADS);
  std::vector<zx::thread> thread_handles =
      GetHandlesForThreadKoids(*process_, thread_koids);
  DCHECK_EQ(thread_koids.size(), thread_handles.size());

  for (size_t i = 0; i < thread_handles.size(); ++i) {
    Thread thread;
    thread.id = thread_koids[i];

    if (thread_handles[i].is_valid()) {
      char name[ZX_MAX_NAME_LEN] = {0};
      zx_status_t status =
          thread_handles[i].get_property(ZX_PROP_NAME, &name, sizeof(name));
      if (status != ZX_OK) {
        ZX_LOG(WARNING, status) << "zx_object_get_property ZX_PROP_NAME";
      } else {
        thread.name.assign(name);
      }

      zx_info_thread_t thread_info;
      status = thread_handles[i].get_info(
          ZX_INFO_THREAD, &thread_info, sizeof(thread_info), nullptr, nullptr);
      if (status != ZX_OK) {
        ZX_LOG(WARNING, status) << "zx_object_get_info ZX_INFO_THREAD";
      } else {
        thread.state = thread_info.state;
      }

      zx_thread_state_general_regs_t general_regs;
      status = thread_handles[i].read_state(
          ZX_THREAD_STATE_GENERAL_REGS, &general_regs, sizeof(general_regs));
      if (status != ZX_OK) {
        ZX_LOG(WARNING, status)
            << "zx_thread_read_state(ZX_THREAD_STATE_GENERAL_REGS)";
      } else {
        thread.general_registers = general_regs;

        const MemoryMapFuchsia* memory_map = MemoryMap();
        if (memory_map) {
          // Attempt to retrive stack regions if a memory map was retrieved. In
          // particular, this may be null when operating on the current process
          // where the memory map will not be able to be retrieved.
          GetStackRegions(general_regs, *memory_map, &thread.stack_regions);
        }
      }

      zx_thread_state_vector_regs_t vector_regs;
      status = thread_handles[i].read_state(
          ZX_THREAD_STATE_VECTOR_REGS, &vector_regs, sizeof(vector_regs));
      if (status != ZX_OK) {
        ZX_LOG(WARNING, status)
            << "zx_thread_read_state(ZX_THREAD_STATE_VECTOR_REGS)";
      } else {
        thread.vector_registers = vector_regs;
      }
    }

    threads_.push_back(thread);
  }
}

void ProcessReaderFuchsia::InitializeMemoryMap() {
  DCHECK(!initialized_memory_map_);

  initialized_memory_map_ = true;

  memory_map_.reset(new MemoryMapFuchsia);
  if (!memory_map_->Initialize(*process_)) {
    memory_map_.reset();
  }
}

}  // namespace crashpad
