blob: b97e66479d5e4753a52ed62209a467464b510294 [file] [log] [blame]
// Copyright 2020 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 "src/developer/debug/debug_agent/zircon_utils.h"
#include <fuchsia/kernel/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fdio.h>
#include <lib/syslog/cpp/macros.h>
#include "src/lib/files/file.h"
namespace debug_agent {
namespace zircon {
namespace {
template <typename ResultObject>
std::vector<ResultObject> GetChildObjects(const zx::object_base& 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.get(), koid, ZX_RIGHT_SAME_RIGHTS, &handle) == ZX_OK)
result.push_back(ResultObject(handle));
}
return result;
}
} // namespace
zx_koid_t KoidForObject(const zx::object_base& object) {
zx_info_handle_basic_t info;
if (object.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr) != ZX_OK)
return ZX_KOID_INVALID;
return info.koid;
}
std::string NameForObject(const zx::object_base& object) {
char name[ZX_MAX_NAME_LEN];
if (object.get_property(ZX_PROP_NAME, name, sizeof(name)) == ZX_OK)
return std::string(name);
return std::string();
}
zx::job GetRootJob() {
zx::job root_job;
fuchsia::kernel::RootJobSyncPtr root_job_ptr;
std::string root_job_path("/svc/");
root_job_path.append(fuchsia::kernel::RootJob::Name_);
zx_status_t status = fdio_service_connect(root_job_path.c_str(),
root_job_ptr.NewRequest().TakeChannel().release());
if (status != ZX_OK) {
FX_NOTREACHED();
return zx::job();
}
status = root_job_ptr->Get(&root_job);
if (status != ZX_OK) {
FX_NOTREACHED();
return zx::job();
}
return root_job;
}
// The hub writes the job it uses to create components in a special file.
//
// This is note quite correct. This code actually returns the job that contains the debug agent
// itself, which is usually the right thing because the debug agent normally runs in the component
// root.
//
// TODO: Find the correct job even when the debug agent is run from elsewhere.
zx_koid_t GetComponentRootJobKoid() {
// TODO(bug 56725) this function seems to no longer work and the job-id file is not found.
std::string koid_str;
bool file_read = files::ReadFileToString("/hub/job-id", &koid_str);
if (!file_read)
return ZX_KOID_INVALID;
char* end = NULL;
uint64_t koid = strtoul(koid_str.c_str(), &end, 10);
if (*end)
return ZX_KOID_INVALID;
return koid;
}
std::vector<zx_koid_t> GetChildKoids(const zx::object_base& 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 = parent.get_info(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::thread> GetChildThreads(const zx::process& process) {
return GetChildObjects<zx::thread>(process, ZX_INFO_PROCESS_THREADS);
}
std::vector<zx::process> GetChildProcesses(const zx::job& job) {
return GetChildObjects<zx::process>(job, ZX_INFO_JOB_PROCESSES);
}
std::vector<zx::job> GetChildJobs(const zx::job& job) {
return GetChildObjects<zx::job>(job, ZX_INFO_JOB_CHILDREN);
}
} // namespace zircon
} // namespace debug_agent