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

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

namespace debug_agent {

namespace {

template <typename ResultObject>
std::vector<ResultObject> GetChildObjects(zx_handle_t parent,
                                          uint32_t child_kind) {
  auto koids = GetChildKoids(parent, child_kind);

  std::vector<ResultObject> result;
  result.reserve(koids.size());

  for (zx_koid_t koid : koids) {
    zx_handle_t handle;
    if (zx_object_get_child(parent, koid, ZX_RIGHT_SAME_RIGHTS, &handle) ==
        ZX_OK)
      result.push_back(ResultObject(handle));
  }
  return result;
}

}  // namespace

zx::thread ThreadForKoid(zx_handle_t process, zx_koid_t thread_koid) {
  zx_handle_t thread_handle = ZX_HANDLE_INVALID;
  zx_object_get_child(process, thread_koid, ZX_RIGHT_SAME_RIGHTS,
                      &thread_handle);
  return zx::thread(thread_handle);
}

zx_koid_t KoidForProcess(const zx::process& process) {
  return KoidForObject(process.get());
}

zx_koid_t KoidForObject(zx_handle_t object) {
  zx_info_handle_basic_t info;
  if (zx_object_get_info(object, ZX_INFO_HANDLE_BASIC, &info, sizeof(info),
                         nullptr, nullptr) != ZX_OK)
    return 0;
  return info.koid;
}

std::string NameForObject(zx_handle_t object) {
  char name[ZX_MAX_NAME_LEN];
  if (zx_object_get_property(object, ZX_PROP_NAME, name, sizeof(name)) == ZX_OK)
    return std::string(name);
  return std::string();
}

std::vector<zx_koid_t> GetChildKoids(zx_handle_t parent, uint32_t child_kind) {
  constexpr size_t kNumExtraKoids = 10u;

  size_t actual = 0;
  size_t available = 0;
  std::vector<zx_koid_t> result;

  // 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 < available)
      result.resize(available + kNumExtraKoids);
    zx_status_t status = zx_object_get_info(parent, child_kind, result.data(),
                                            result.size() * sizeof(zx_koid_t),
                                            &actual, &available);
    if (status != ZX_OK || actual == available)
      break;
  }
  result.resize(actual);
  return result;
}

std::vector<zx::job> GetChildJobs(zx_handle_t job) {
  return GetChildObjects<zx::job>(job, ZX_INFO_JOB_CHILDREN);
}

std::vector<zx::process> GetChildProcesses(zx_handle_t job) {
  return GetChildObjects<zx::process>(job, ZX_INFO_JOB_PROCESSES);
}

std::vector<zx::thread> GetChildThreads(zx_handle_t process) {
  return GetChildObjects<zx::thread>(process, ZX_INFO_PROCESS_THREADS);
}

}  // namespace debug_agent
