// 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 "debug_info_retriever.h"

#include <lib/syslog/cpp/macros.h>

#include <list>

#include "inspector/inspector.h"

namespace component {

namespace {
struct thread_entry {
  zx_koid_t id;
  zx::thread thread;
  zx::suspend_token suspend_token;
  fbl::String name;
};
}  // namespace

fbl::String DebugInfoRetriever::GetInfo(const zx::process* process, zx_koid_t* thread_ids,
                                        size_t num) {
  assert(process);
  zx_koid_t thread_ids_storage[kMaxThreads];

  if (thread_ids == nullptr || num == 0) {
    return "ERROR (fxbug.dev/4687): Full thread dump disabled";
    if (process->get_info(ZX_INFO_PROCESS_THREADS, &thread_ids_storage,
                          kMaxThreads * sizeof(zx_koid_t), &num, nullptr) != ZX_OK) {
      return "ERROR: failed to get threads for process";
    };
    thread_ids = thread_ids_storage;
  }

  std::list<thread_entry> threads;
  zx_status_t status;

  for (size_t i = 0; i < num; i++) {
    zx::thread thread;
    if (process->get_child(thread_ids[i], ZX_RIGHT_SAME_RIGHTS, &thread) == ZX_OK) {
      threads.push_back({.id = thread_ids[i], .thread = std::move(thread)});
    };
  }

  for (auto it = threads.begin(); it != threads.end();) {
    zx_info_thread_t thread_info;
    it->thread.get_info(ZX_INFO_THREAD, &thread_info, sizeof(thread_info), nullptr, nullptr);

    auto prev = it++;
    // All threads will resume when their suspend token goes out of scope.
    if ((status = prev->thread.suspend(&prev->suspend_token)) != ZX_OK) {
      FX_LOGS(INFO) << "Failed to suspend thread: " << status;
      threads.erase(prev);
    }
  }

  for (auto it = threads.begin(); it != threads.end();) {
    // Wait for the thread to actually get suspended, but also react if the
    // thread was terminated in between these operations.
    zx_signals_t signals = 0;

    auto prev = it++;
    if ((status = prev->thread.wait_one(ZX_THREAD_SUSPENDED | ZX_THREAD_TERMINATED,
                                        zx::deadline_after(zx::msec(100)), &signals)) != ZX_OK ||
        (signals & ZX_THREAD_TERMINATED)) {
      FX_LOGS(INFO) << "Thread failed to suspend in time. Status: " << status
                    << ", signals: " << signals;
      threads.erase(prev);
    }
  }

  for (auto& entry : threads) {
    char temp_name[ZX_MAX_NAME_LEN];
    entry.thread.get_property(ZX_PROP_NAME, &temp_name, ZX_MAX_NAME_LEN);
    entry.name = temp_name;
  }

  DsoListWrapper dso(*process);
  FILE* output = tmpfile();
  if (output == nullptr) {
    FX_LOGS(ERROR) << "Failed to open tmpfile for output.";
    return "";
  }

  for (const auto& entry : threads) {
    fprintf(output, "%s (%lu):\n", entry.name.c_str(), entry.id);

    zx_thread_state_general_regs_t regs;
    if ((status = inspector_read_general_regs(entry.thread.get(), &regs)) != ZX_OK) {
      fprintf(output, "ERROR: failed to read regs, code=%d", status);
      continue;
    };
    inspector_print_general_regs(output, &regs, nullptr);

    // Get the program counter, stack, and frame pointers.
    zx_vaddr_t pc, sp, fp;
    const char* arch = "unknown";
#if defined(__x86_64__)
    arch = "x86_64";
    pc = regs.rip;
    sp = regs.rsp;
    fp = regs.rbp;
#elif defined(__aarch64__)
    arch = "aarch64";
    pc = regs.pc;
    sp = regs.sp;
    fp = regs.r[29];
#else
    fprintf(output, "unsupported architecture\n");
    continue;
#endif

    fprintf(output, "arch: %s\n", arch);
    inspector_print_backtrace_markup(output, process->get(), entry.thread.get(), dso.info, pc, sp,
                                     fp);

    fprintf(output, "\n");
  }

  rewind(output);

  std::vector<uint8_t> data;
  if (!files::ReadFileDescriptorToVector(fileno(output), &data)) {
    fclose(output);
    return "ERROR: Failed to read file contents";
  }

  fclose(output);
  return fbl::String((char*)data.data(), data.size());
}

}  // namespace component
