// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "garnet/bin/debug_agent/unwind.h"

#include <inttypes.h>
#include <ngunwind/fuchsia.h>
#include <ngunwind/libunwind.h>
#include <algorithm>

#include "garnet/bin/debug_agent/process_info.h"
#include "garnet/third_party/libunwindstack/fuchsia/MemoryFuchsia.h"
#include "garnet/third_party/libunwindstack/fuchsia/RegsFuchsia.h"
#include "garnet/third_party/libunwindstack/include/unwindstack/Unwinder.h"

namespace debug_agent {

namespace {

using ModuleVector = std::vector<debug_ipc::Module>;

// Default unwinder type to use.
UnwinderType unwinder_type = UnwinderType::kNgUnwind;

zx_status_t UnwindStackAndroid(const zx::process& process,
                               uint64_t dl_debug_addr, const zx::thread& thread,
                               uint64_t ip, uint64_t sp, uint64_t bp,
                               size_t max_depth,
                               std::vector<debug_ipc::StackFrame>* stack) {
  ModuleVector modules;
  zx_status_t status = GetModulesForProcess(process, dl_debug_addr, &modules);
  if (status != ZX_OK)
    return status;
  std::sort(modules.begin(), modules.end(),
            [](const debug_ipc::Module& a, const debug_ipc::Module& b) {
              return a.base < b.base;
            });

  unwindstack::Maps maps;
  for (size_t i = 0; i < modules.size(); i++) {
    // Our module currently doesn't have a size so just report the next
    // address boundary.
    // TODO(brettw) hook up the real size.
    uint64_t end;
    if (i < modules.size() - 1)
      end = modules[i + 1].base;
    else
      end = std::numeric_limits<uint64_t>::max();

    // The offset of the module is the offset in the file where the memory map
    // starts. For libraries, we can currently always assume 0.
    uint64_t offset = 0;

    uint64_t flags = 0;  // We don't have flags.

    // Don't know what this is, it's not set by the Android impl that reads
    // from /proc.
    uint64_t load_bias = 0;

    maps.Add(modules[i].base, end, offset, flags, modules[i].name, load_bias);
  }

  unwindstack::RegsFuchsia regs;
  status = regs.Read(thread.get());
  if (status != ZX_OK)
    return status;

  auto memory = std::make_shared<unwindstack::MemoryFuchsia>(process.get());

  unwindstack::Unwinder unwinder(max_depth, &maps, &regs, std::move(memory));

  unwinder.Unwind();

  stack->resize(unwinder.NumFrames());
  for (size_t i = 0; i < unwinder.NumFrames(); i++) {
    const auto& src = unwinder.frames()[i];
    debug_ipc::StackFrame* dest = &(*stack)[i];
    dest->ip = src.pc;
    dest->sp = src.sp;
  }

  // Add the base pointer for the top stack frame.
  // TODO(brettw) libstackunwind should be able to give us base pointers for
  // other frames when we're compiling with frame pointers.
  (*stack)[0].bp = bp;

  return 0;
}

// Libunwind doesn't have a cross-platform typedef for the frame pointer
// register so define one.
#if defined(__x86_64__)
#define LIBUNWIND_FRAME_POINTER_REGISTER UNW_X86_64_RBP
#elif defined(__aarch64__)
#define LIBUNWIND_FRAME_POINTER_REGISTER UNW_AARCH64_X29
#else
#error Need frame pointer.
#endif

using ModuleVector = std::vector<debug_ipc::Module>;

// Callback for ngunwind.
int LookupDso(void* context, unw_word_t pc, unw_word_t* base,
              const char** name) {
  // Context is a ModuleVector sorted by load address, need to find the
  // largest one smaller than or equal to the pc.
  //
  // We could use lower_bound for better perf with lots of modules but we
  // expect O(10) modules.
  const ModuleVector* modules = static_cast<const ModuleVector*>(context);
  for (int i = static_cast<int>(modules->size()) - 1; i >= 0; i--) {
    const debug_ipc::Module& module = (*modules)[i];
    if (pc >= module.base) {
      *base = module.base;
      *name = module.name.c_str();
      return 1;
    }
  }
  return 0;
}

zx_status_t UnwindStackNgUnwind(const zx::process& process,
                                uint64_t dl_debug_addr,
                                const zx::thread& thread, uint64_t ip,
                                uint64_t sp, uint64_t bp, size_t max_depth,
                                std::vector<debug_ipc::StackFrame>* stack) {
  stack->clear();

  // Get the modules sorted by load address.
  ModuleVector modules;
  zx_status_t status = GetModulesForProcess(process, dl_debug_addr, &modules);
  if (status != ZX_OK)
    return status;
  std::sort(modules.begin(), modules.end(),
            [](const debug_ipc::Module& a, const debug_ipc::Module& b) {
              return a.base < b.base;
            });

  unw_fuchsia_info_t* fuchsia =
      unw_create_fuchsia(process.get(), thread.get(), &modules, &LookupDso);
  if (!fuchsia)
    return ZX_ERR_INTERNAL;

  unw_addr_space_t remote_aspace = unw_create_addr_space(
      const_cast<unw_accessors_t*>(&_UFuchsia_accessors), 0);
  if (!remote_aspace)
    return ZX_ERR_INTERNAL;

  unw_cursor_t cursor;
  if (unw_init_remote(&cursor, remote_aspace, fuchsia) < 0)
    return ZX_ERR_INTERNAL;

  debug_ipc::StackFrame frame;
  frame.ip = ip;
  frame.sp = sp;
  frame.bp = bp;
  stack->push_back(frame);
  while (frame.sp >= 0x1000000 && stack->size() < max_depth) {
    int ret = unw_step(&cursor);
    if (ret <= 0)
      break;

    unw_word_t val;
    unw_get_reg(&cursor, UNW_REG_IP, &val);
    frame.ip = val;

    unw_get_reg(&cursor, UNW_REG_SP, &val);
    frame.sp = val;

    unw_get_reg(&cursor, LIBUNWIND_FRAME_POINTER_REGISTER, &val);
    frame.bp = val;

    // Note that libunwind may theoretically be able to give us all
    // callee-saved register values for a given frame. Currently asking for any
    // register always returns success, making it impossible to tell what is
    // valid and what is not.
    //
    // If we switch unwinders (maybe to LLVM's or a custom one), this should be
    // re-evaluated. We may be able to attach a vector of Register structs on
    // each frame for the values we know about.

    stack->push_back(frame);
  }

  // The last stack entry will typically have a 0 IP address. We want to send
  // this anyway because it will hold the initial stack pointer for the thread,
  // which in turn allows computation of the first real frame's fingerprint.

  return ZX_OK;
}

}  // namespace

void SetUnwinderType(UnwinderType type) { unwinder_type = type; }

zx_status_t UnwindStack(const zx::process& process, uint64_t dl_debug_addr,
                        const zx::thread& thread, uint64_t ip, uint64_t sp,
                        uint64_t bp, size_t max_depth,
                        std::vector<debug_ipc::StackFrame>* stack) {
  switch (unwinder_type) {
    case UnwinderType::kNgUnwind:
      return UnwindStackNgUnwind(process, dl_debug_addr, thread, ip, sp, bp,
                                 max_depth, stack);
    case UnwinderType::kAndroid:
      return UnwindStackAndroid(process, dl_debug_addr, thread, ip, sp, bp,
                                max_depth, stack);
  }
  return ZX_ERR_NOT_SUPPORTED;
}

}  // namespace debug_agent
