blob: 2f5eaf77243a4132b6c2c5689775633abca40279 [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.
#ifndef SRC_LIB_FIDL_CODEC_SEMANTIC_H_
#define SRC_LIB_FIDL_CODEC_SEMANTIC_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "src/lib/fidl_codec/printer.h"
namespace fidl_codec {
namespace semantic {
// Holds the information we have about a handle.
// Usually we can associate a type to a handle.
// Depending on the type, we can also associate:
// - a path (for example for directories and files).
// - a file descriptor (for example for sockets).
class HandleDescription {
public:
HandleDescription() = default;
explicit HandleDescription(std::string_view type) : type_(type) {}
HandleDescription(std::string_view type, int64_t fd) : type_(type), fd_(fd) {}
HandleDescription(std::string_view type, std::string_view path) : type_(type), path_(path) {}
HandleDescription(std::string_view type, int64_t fd, std::string_view path)
: type_(type), fd_(fd), path_(path) {}
const std::string& type() const { return type_; }
int64_t fd() const { return fd_; }
const std::string& path() const { return path_; }
// Convert a handle type (found in zircon/system/public/zircon/processargs.h) into a string.
static std::string_view Convert(uint32_t type);
// Display the information we have about a handle.
void Display(const fidl_codec::Colors& colors, std::ostream& os) const;
private:
// Type of the handle. This can be a predefined type (when set by Convert) or
// any string when it is an applicative type.
const std::string type_;
// Numerical value associated with the handle. Mostly used by file descriptors.
const int64_t fd_ = -1;
// Path associated with the handle. We can have both fd and path defined at the
// same time.
const std::string path_;
};
// Holds the handle semantic for one process. That is all the meaningful information we have been
// able to infer for the handles owned by one process.
struct ProcessSemantic {
// All the handles for which we have some information.
std::map<zx_handle_t, std::unique_ptr<HandleDescription>> handles;
// All the links between handle pairs.
std::map<zx_handle_t, zx_handle_t> linked_handles;
};
// Object which hold the information we have about handles for all the processes.
class HandleSemantic {
public:
HandleSemantic() = default;
size_t handle_size(zx_koid_t pid) const {
const auto& process_semantic = process_handles_.find(pid);
if (process_semantic == process_handles_.end()) {
return 0;
}
return process_semantic->second.handles.size();
}
const HandleDescription* GetHandleDescription(zx_koid_t pid, zx_handle_t handle) const {
const auto& process_semantic = process_handles_.find(pid);
if (process_semantic == process_handles_.end()) {
return nullptr;
}
const auto& result = process_semantic->second.handles.find(handle);
if (result == process_semantic->second.handles.end()) {
return nullptr;
}
return result->second.get();
}
void AddHandleDescription(zx_koid_t pid, zx_handle_t handle,
const HandleDescription& handle_description) {
process_handles_[pid].handles[handle] = std::make_unique<HandleDescription>(handle_description);
}
void AddHandleDescription(zx_koid_t pid, zx_handle_t handle, std::string_view type) {
process_handles_[pid].handles[handle] = std::make_unique<HandleDescription>(type);
}
void AddHandleDescription(zx_koid_t pid, zx_handle_t handle, std::string_view type, int64_t fd) {
process_handles_[pid].handles[handle] = std::make_unique<HandleDescription>(type, fd);
}
void AddHandleDescription(zx_koid_t pid, zx_handle_t handle, std::string_view type,
std::string_view path) {
process_handles_[pid].handles[handle] = std::make_unique<HandleDescription>(type, path);
}
void AddHandleDescription(zx_koid_t pid, zx_handle_t handle, uint32_t type) {
process_handles_[pid].handles[handle] =
std::make_unique<HandleDescription>(HandleDescription::Convert(type));
}
// Returns the handle peer for a channel.
zx_handle_t GetLinkedHandle(zx_koid_t pid, zx_handle_t handle) const {
const auto& process_semantic = process_handles_.find(pid);
if (process_semantic == process_handles_.end()) {
return ZX_HANDLE_INVALID;
}
auto linked = process_semantic->second.linked_handles.find(handle);
if (linked == process_semantic->second.linked_handles.end()) {
return ZX_HANDLE_INVALID;
}
return linked->second;
}
// Associates two channels which have been created by the same zx_channel_create.
void AddLinkedHandles(zx_koid_t pid, zx_handle_t handle0, zx_handle_t handle1) {
ProcessSemantic& process_semantic = process_handles_[pid];
process_semantic.linked_handles.insert(std::make_pair(handle0, handle1));
process_semantic.linked_handles.insert(std::make_pair(handle1, handle0));
}
private:
std::map<zx_koid_t, ProcessSemantic> process_handles_;
};
} // namespace semantic
} // namespace fidl_codec
#endif // SRC_LIB_FIDL_CODEC_SEMANTIC_H_