// 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/lib/debugger_utils/jobs.h"

#include <inttypes.h>
#include <lib/zx/job.h>
#include <lib/zx/process.h>
#include <lib/zx/thread.h>
#include <stdlib.h>
#include <zircon/syscalls.h>

#include <list>

#include "garnet/lib/debugger_utils/util.h"
#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/macros.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace debugger_utils {

struct WalkContext {
  JobTreeJobCallback* job_callback;
  JobTreeProcessCallback* process_callback;
  JobTreeThreadCallback* thread_callback;
};

// When reallocating koid buffer because we were too small add this much extra
// on top of what the kernel says is currently needed.
static const size_t kNumExtraKoids = 10;

class KoidTable {
 public:
  explicit KoidTable() : koids_(&initial_buf_[0]), size_(0), capacity_(kNumInitialKoids) {}

  ~KoidTable() {
    if (koids_ != &initial_buf_[0]) {
      free(koids_);
    }
  }

  size_t size() const { return size_; }
  size_t capacity() const { return capacity_; }
  zx_koid_t* data() const { return koids_; }
  bool empty() const { return size_ == 0; }

  size_t CapacityInBytes() const { return capacity() * sizeof(zx_koid_t); }

  zx_koid_t Get(size_t index) const {
    FX_DCHECK(index < size_);
    return koids_[index];
  }

  // If this fails then we just continue to use the current capacity.
  void TryReserve(size_t new_capacity) {
    auto new_buf = malloc(new_capacity * sizeof(zx_koid_t));
    if (new_buf) {
      if (koids_ != &initial_buf_[0]) {
        free(koids_);
      }
      koids_ = reinterpret_cast<zx_koid_t*>(new_buf);
      capacity_ = new_capacity;
    }
  }

  void SetSize(size_t size) {
    FX_DCHECK(size <= capacity_);
    size_ = size;
  }

 private:
  // Allocate space for this many koids within the object, it can live on the
  // stack. Only if we need more than this do we use the heap.
  // Note that for jobs, due to potentially deep nesting, this object should
  // always be allocated in the heap.
  static constexpr size_t kNumInitialKoids = 32;
  zx_koid_t initial_buf_[kNumInitialKoids];

  // A pointer to |initial_buf_| or a heap-allocated object.
  zx_koid_t* koids_;

  // The number of entries in |koids_|.
  size_t size_;

  // The amount of koids available in |koids_|.
  size_t capacity_;

  FXL_DISALLOW_COPY_ASSIGN_AND_MOVE(KoidTable);
};

// A stack of job koid tables, to avoid recursion.
// Jobs aren't normally nested *that* deep, but we can't assume that of course.
class JobKoidTableStackEntry {
 public:
  explicit JobKoidTableStackEntry(zx::job job, zx_handle_t job_h, zx_koid_t jid, int depth,
                                  std::unique_ptr<KoidTable> subjob_koids)
      : job_(std::move(job)),
        job_h_(job_h),
        jid_(jid),
        depth_(depth),
        subjob_koids_(std::move(subjob_koids)),
        current_subjob_index_(0) {}

  zx_handle_t job_h() const { return job_h_; }

  zx_koid_t jid() const { return jid_; }

  int depth() const { return depth_; }

  bool empty() const { return current_subjob_index_ == subjob_koids_->size(); }

  zx_koid_t PopNext() {
    FX_DCHECK(!empty());
    auto koid = subjob_koids_->Get(current_subjob_index_);
    ++current_subjob_index_;
    return koid;
  }

 private:
  // The only use of this member is to automagically free the handle when
  // the object is destructed. In the case of the top job this object is
  // not valid.
  zx::job job_;
  // This is the handle of the job to use.
  zx_handle_t job_h_;
  zx_koid_t jid_;
  int depth_;
  std::unique_ptr<KoidTable> subjob_koids_;
  size_t current_subjob_index_;

  FXL_DISALLOW_COPY_ASSIGN_AND_MOVE(JobKoidTableStackEntry);
};

using JobKoidTableStack = std::list<JobKoidTableStackEntry>;

static zx_status_t GetChild(zx_handle_t parent_h, zx_koid_t parent_koid, zx_koid_t koid,
                            zx_handle_t* out_task_h) {
  auto status = zx_object_get_child(parent_h, koid, ZX_RIGHT_SAME_RIGHTS, out_task_h);
  if (status != ZX_OK) {
    // The task could have terminated in the interim.
    if (status == ZX_ERR_NOT_FOUND) {
      FX_VLOGS(1) << fxl::StringPrintf("zx_object_get_child(%" PRIu64 ", %" PRIu64
                                       ", ...) failed: %s\n",
                                       parent_koid, koid, ZxErrorString(status).c_str());
    } else {
      FX_LOGS(ERROR) << fxl::StringPrintf("zx_object_get_child(%" PRIu64 ", %" PRIu64
                                          ", ...) failed: %s\n",
                                          parent_koid, koid, ZxErrorString(status).c_str());
    }
  }
  return status;
}

static zx_status_t FetchChildren(zx_handle_t parent_h, zx_koid_t parent_koid, int children_kind,
                                 const char* kind_name, KoidTable* out_koids) {
  size_t actual = 0;
  size_t avail = 0;
  zx_status_t status;

  // This is inherently racy, but we retry once with a bit of slop to try to
  // get a complete list.
  for (int pass = 0; pass < 2; ++pass) {
    if (actual < avail) {
      out_koids->TryReserve(avail + kNumExtraKoids);
    }
    status = zx_object_get_info(parent_h, children_kind, out_koids->data(),
                                out_koids->CapacityInBytes(), &actual, &avail);
    if (status != ZX_OK) {
      FX_LOGS(ERROR) << fxl::StringPrintf("zx_object_get_info(%" PRIu64 ", %s, ...) failed: %s\n",
                                          parent_koid, kind_name, ZxErrorString(status).c_str());
      return status;
    }
    if (actual == avail) {
      break;
    }
  }

  // If we're still too small at least warn the user.
  if (actual < avail) {
    FX_LOGS(WARNING) << fxl::StringPrintf("zx_object_get_info(%" PRIu64
                                          ", %s, ...)"
                                          " truncated results, got %zu/%zu\n",
                                          parent_koid, kind_name, actual, avail);
  }

  out_koids->SetSize(actual);
  return ZX_OK;
}

static zx_status_t DoThreads(const WalkContext* ctx, zx_handle_t process_h, zx_koid_t pid,
                             int depth) {
  FX_DCHECK(ctx->thread_callback);

  KoidTable koids;
  auto status =
      FetchChildren(process_h, pid, ZX_INFO_PROCESS_THREADS, "ZX_INFO_PROCESS_THREADS", &koids);
  if (status != ZX_OK) {
    return status;
  }

  for (size_t i = 0; i < koids.size(); ++i) {
    zx_handle_t thread_h;
    zx_koid_t tid = koids.Get(i);
    status = GetChild(process_h, pid, tid, &thread_h);
    if (status == ZX_ERR_NOT_FOUND) {
      // Thread died.
      continue;
    }
    if (status != ZX_OK) {
      // Other errors shouldn't happen.
      return status;
    }

    zx::thread thread(thread_h);
    status = (*ctx->thread_callback)(&thread, tid, pid, depth);
    if (status != ZX_OK) {
      return status;
    }

    // There's nothing special we need to do here if the callback took
    // ownership of the handle.
  }

  return ZX_OK;
}

static zx_status_t DoProcesses(const WalkContext* ctx, zx_handle_t job_h, zx_koid_t jid,
                               int depth) {
  KoidTable koids;
  auto status = FetchChildren(job_h, jid, ZX_INFO_JOB_PROCESSES, "ZX_INFO_JOB_PROCESSES", &koids);
  if (status != ZX_OK) {
    return status;
  }

  for (size_t i = 0; i < koids.size(); ++i) {
    zx_handle_t process_h;
    zx_koid_t pid = koids.Get(i);
    status = GetChild(job_h, jid, pid, &process_h);
    if (status == ZX_ERR_NOT_FOUND) {
      // Process died.
      continue;
    }
    if (status != ZX_OK) {
      // Other errors shouldn't happen.
      return status;
    }

    zx::process process(process_h);
    if (ctx->process_callback) {
      status = (*ctx->process_callback)(&process, pid, jid, depth);
      if (status != ZX_OK) {
        return status;
      }
    }

    // If the callback took ownership of the process handle we can still scan
    // the threads using |child|. The callback is required to not close the
    // process handle until WalkJobTree() returns.
    if (ctx->thread_callback) {
      status = DoThreads(ctx, process_h, pid, depth + 1);
      if (status != ZX_OK) {
        return status;
      }
    }
  }

  return ZX_OK;
}

// This function is bi-modal: It handles both the top job and all subjobs.
// When processing the top job |job| is nullptr, otherwise it is a pointer
// to the subjob's object. |job_h| is the handle of the job. In the case of
// subjobs it is |job.get()|.

static zx_status_t DoJob(JobKoidTableStack* stack, const WalkContext* ctx, zx::job* job,
                         zx_handle_t job_h, zx_koid_t jid, zx_koid_t parent_jid, int depth) {
  zx_status_t status;

  if (job) {
    // Things are a bit tricky here as |job_callback| could take ownership of
    // the job, but we still need to call DoProcesses().
    FX_DCHECK(job->get() == job_h);
    if (ctx->job_callback) {
      status = (*ctx->job_callback)(job, jid, parent_jid, depth);
      if (status != ZX_OK) {
        return status;
      }
    }
  }

  if (ctx->process_callback || ctx->thread_callback) {
    status = DoProcesses(ctx, job_h, jid, depth + 1);
    if (status != ZX_OK) {
      return status;
    }
  }

  auto subjob_koids = std::unique_ptr<KoidTable>(new KoidTable());
  status =
      FetchChildren(job_h, jid, ZX_INFO_JOB_CHILDREN, "ZX_INFO_JOB_CHILDREN", subjob_koids.get());
  if (status != ZX_OK) {
    return status;
  }
  if (!subjob_koids->empty()) {
    if (job) {
      stack->emplace_front(std::move(*job), job_h, jid, depth + 1, std::move(subjob_koids));
    } else {
      stack->emplace_front(zx::job(), job_h, jid, depth + 1, std::move(subjob_koids));
    }
  }

  return ZX_OK;
}

static zx_status_t WalkJobTreeInternal(JobKoidTableStack* stack, const WalkContext* ctx) {
  while (!stack->empty()) {
    auto& stack_entry = stack->front();
    if (stack_entry.empty()) {
      stack->pop_front();
    } else {
      auto parent_job_h = stack_entry.job_h();
      auto parent_jid = stack_entry.jid();
      auto depth = stack_entry.depth();
      auto jid = stack_entry.PopNext();
      zx_handle_t job_h;
      auto status = GetChild(parent_job_h, parent_jid, jid, &job_h);
      if (status == ZX_ERR_NOT_FOUND) {
        // Job is gone.
        continue;
      }
      if (status != ZX_OK) {
        // Other errors shouldn't happen.
        return status;
      }

      zx::job job(job_h);
      status = DoJob(stack, ctx, &job, job_h, jid, parent_jid, depth);
      if (status != ZX_OK) {
        return status;
      }
    }
  }

  return ZX_OK;
}

zx_status_t WalkJobTree(const zx::job& job, JobTreeJobCallback* job_callback,
                        JobTreeProcessCallback* process_callback,
                        JobTreeThreadCallback* thread_callback) {
  FX_DCHECK(job.is_valid());
  zx_info_handle_basic_t info;
  auto status =
      zx_object_get_info(job.get(), ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << fxl::StringPrintf(
        "zx_object_get_info(search_job, ZX_INFO_HANDLE_BASIC, ...) failed: "
        "%s\n",
        ZxErrorString(status).c_str());
    return status;
  }
  auto jid = info.koid;
  auto parent_jid = info.related_koid;

  WalkContext ctx;
  ctx.job_callback = job_callback;
  ctx.process_callback = process_callback;
  ctx.thread_callback = thread_callback;

  JobKoidTableStack stack;
  status = DoJob(&stack, &ctx, nullptr, job.get(), jid, parent_jid, 0);
  if (status != ZX_OK) {
    return status;
  }

  return WalkJobTreeInternal(&stack, &ctx);
}

zx::process FindProcess(const zx::job& job, zx_koid_t pid) {
  zx::process process;
  JobTreeProcessCallback find_process_callback =
      [&](zx::process* task, zx_koid_t koid, zx_koid_t parent_koid, int depth) -> zx_status_t {
    if (koid == pid) {
      process.reset(task->release());
      return ZX_ERR_STOP;
    }
    return ZX_OK;
  };
  // There's no real need to check the result here.
  WalkJobTree(job, nullptr, &find_process_callback, nullptr);
  return process;
}

zx::process FindProcess(zx_handle_t job_h, zx_koid_t pid) {
  zx::job job(job_h);
  auto result = FindProcess(job, pid);
  // Don't close |job_h| when we return.
  auto released_handle __UNUSED = job.release();
  return result;
}

// The default job is not ours to own so we need to make a copy.
// This is a simple wrapper to do that.
zx::job GetDefaultJob() {
  auto job = zx_job_default();
  if (job == ZX_HANDLE_INVALID) {
    FX_VLOGS(1) << "no default job";
    return zx::job();
  }
  zx_handle_t dupe_h;
  auto status = zx_handle_duplicate(job, ZX_RIGHT_SAME_RIGHTS, &dupe_h);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "unable to create dupe of default job: " << ZxErrorString(status);
    return zx::job();
  }

  return zx::job(dupe_h);
}

}  // namespace debugger_utils
