| // Copyright 2022 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/component_manager.h" |
| |
| #include "src/developer/debug/debug_agent/process_handle.h" |
| #include "src/developer/debug/debug_agent/system_interface.h" |
| #include "src/developer/debug/ipc/records.h" |
| |
| namespace debug_agent { |
| |
| namespace { |
| // Returns a function that can be used to compare other |debug_ipc::ComponentInfo| objects to the |
| // supplied |needle|. The |needle| controls what is compared by setting only the desired fields to |
| // be compared. Setting all fields is equivalent to directly comparing the two ComponentInfo |
| // objects. This is intended to be shared between all subclasses that provide an implementation for |
| // |FindComponentInfo| with a debug_ipc::ComponentInfo argument without being opinionated about how |
| // the derived classes keep track of the actual component information being looked up. |
| auto MakeComponentInfoComparator(const debug_ipc::ComponentInfo& needle) { |
| // We check either or both strings depending on what's populated from the caller. |
| bool check_moniker = !needle.moniker.empty(); |
| bool check_url = !needle.url.empty(); |
| |
| return [=, &needle](const debug_ipc::ComponentInfo& info) -> bool { |
| // We can check all fields of the component info in this manner: if any check is enabled, then |
| // it must pass. If more than one check is enabled, then they must all pass, effectively |
| // performing a logical "and" over all enabled checks as provided by the input needle. Any |
| // checks that are not enabled are ignored. |
| if (check_moniker && needle.moniker != info.moniker) { |
| return false; |
| } |
| |
| if (check_url && needle.url != info.url) { |
| return false; |
| } |
| |
| // All checks passed, this is a match. |
| return true; |
| }; |
| } |
| } // namespace |
| |
| std::vector<debug_ipc::ComponentInfo> ComponentManager::FindComponentInfo( |
| const ProcessHandle& process) const { |
| zx_koid_t job_koid = process.GetJobKoid(); |
| while (job_koid) { |
| auto components = FindComponentInfo(job_koid); |
| if (!components.empty()) |
| return components; |
| job_koid = system_interface_->GetParentJobKoid(job_koid); |
| } |
| return {}; |
| } |
| |
| std::vector<debug_ipc::ComponentInfo> ComponentManager::FindComponentInfo( |
| const debug_ipc::ComponentInfo& needle) const { |
| if (needle.moniker.empty() && needle.url.empty()) { |
| return {}; |
| } |
| |
| return FindComponentInfoWithComparator(MakeComponentInfoComparator(needle)); |
| } |
| |
| std::optional<debug_ipc::ComponentInfo> ComponentManager::FindComponentInfoByMoniker( |
| const std::string& moniker) const { |
| debug_ipc::ComponentInfo info; |
| info.moniker = moniker; |
| |
| auto result = FindComponentInfo(info); |
| if (result.empty()) { |
| return std::nullopt; |
| } |
| |
| FX_DCHECK(result.size() == 1); |
| return result[0]; |
| } |
| |
| std::vector<debug_ipc::ComponentInfo> ComponentManager::FindComponentInfoByUrl( |
| const std::string& url) const { |
| debug_ipc::ComponentInfo info; |
| info.url = url; |
| |
| return FindComponentInfo(info); |
| } |
| |
| } // namespace debug_agent |