blob: 47be5f87b01834211cfdf2f15e29a9e7d6933bfd [file] [log] [blame]
// Copyright 2019 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/watchpoint.h"
#include "garnet/lib/debug_ipc/records_utils.h"
namespace debug_agent {
Watchpoint::Watchpoint(ProcessDelegate* delegate) : delegate_(delegate) {}
Watchpoint::~Watchpoint() {
for (auto& [process_koid, range] : installed_watchpoints_) {
delegate_->UnregisterWatchpoint(this, process_koid, range);
}
}
zx_status_t Watchpoint::SetSettings(
const debug_ipc::WatchpointSettings& settings) {
zx_status_t result = ZX_OK;
settings_ = settings;
// The updated set of locations.
std::set<WatchpointInstallation> updated_locations;
for (const auto& cur : settings.locations) {
WatchpointInstallation installation = {cur.process_koid, cur.range};
updated_locations.insert(std::move(installation));
}
// Removed locations.
for (const auto& loc : installed_watchpoints_) {
if (updated_locations.find(loc) == updated_locations.end())
delegate_ ->UnregisterWatchpoint(this, loc.process_koid, loc.range);
}
// Added locations.
for (const auto& loc : updated_locations) {
if (installed_watchpoints_.find(loc) == installed_watchpoints_.end()) {
zx_status_t process_status =
delegate_->RegisterWatchpoint(this, loc.process_koid, loc.range);
if (process_status != ZX_OK)
result = process_status;
}
}
installed_watchpoints_ = std::move(updated_locations);
return result;
}
bool Watchpoint::ThreadsToInstall(zx_koid_t process_koid,
std::set<zx_koid_t>* out) const {
std::set<zx_koid_t> thread_koids = {};
for (const auto& location : settings_.locations) {
if (location.process_koid != process_koid)
continue;
// |thread_koid| == 0 means all the threads.
if (location.thread_koid == 0) {
*out = {};
return true;
}
thread_koids.insert(location.thread_koid);
}
if (thread_koids.empty())
return false;
*out = std::move(thread_koids);
return true;
}
bool Watchpoint::WatchpointInstallation::operator<(const WatchpointInstallation& other) const {
if (process_koid != other.process_koid)
return process_koid < other.process_koid;
debug_ipc::AddressRangeCompare comparer;
return comparer(range, other.range);
}
} // namespace debug_agent