blob: e82444b8145f609cef86df2c55172bc32781a79e [file] [log] [blame]
// 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 "src/developer/debug/zxdb/client/breakpoint.h"
#include "src/developer/debug/zxdb/client/setting_schema.h"
#include "src/developer/debug/zxdb/client/setting_schema_definition.h"
#include "src/lib/fxl/logging.h"
namespace zxdb {
const char* ClientSettings::Breakpoint::kLocation = "location";
const char* ClientSettings::Breakpoint::kLocationDescription =
R"( The location (symbol, line number, address, or expression) where this
breakpoint will be set. See "help break" for documentation on how to specify.)";
const char* ClientSettings::Breakpoint::kScope = "scope";
const char* ClientSettings::Breakpoint::kScopeDescription =
R"( What this breakpoint applies to. Examples:
global: All processes (the default).
"pr 3": All threads in a process 3.
"pr 3 t 2": Only thread 2 of process 3.)";
const char* ClientSettings::Breakpoint::kEnabled = "enabled";
const char* ClientSettings::Breakpoint::kEnabledDescription =
R"( Whether this breakpoint is enabled. Disabled breakpoints keep their settings
but are not installed and will not stop or increment their hit count.)";
const char* ClientSettings::Breakpoint::kOneShot = "one-shot";
const char* ClientSettings::Breakpoint::kOneShotDescription =
R"( Whether this breakpoint is one-shot. One-shot breakpoints are automatically
deleted when hit.)";
const char* ClientSettings::Breakpoint::kType = "type";
const char* ClientSettings::Breakpoint::kTypeDescription =
" Type of breakpoint. Possible values are:\n\n" BREAKPOINT_TYPE_HELP(" ");
const char* ClientSettings::Breakpoint::kType_Software = "software";
const char* ClientSettings::Breakpoint::kType_Hardware = "execute";
const char* ClientSettings::Breakpoint::kType_ReadWrite = "read-write";
const char* ClientSettings::Breakpoint::kType_Write = "write";
const char* ClientSettings::Breakpoint::kStopMode = "stop";
const char* ClientSettings::Breakpoint::kStopModeDescription =
R"( What to stop when this breakpoint is hit. Possible values are:
none
Do not stop anything when this breakpoint is hit. The breakpoint will
still be installed and will still accumulate hit counts.
thread
Stop only the thread that hit the breakpoint. Other threads in the same
process and other processes will be unaffected.
process
Stop all threads in the process that hit the breakpoint. Other processes
being debugged will be unaffected.
all
Stop all processes currently being debugged.)";
const char* ClientSettings::Breakpoint::kStopMode_None = "none";
const char* ClientSettings::Breakpoint::kStopMode_Thread = "thread";
const char* ClientSettings::Breakpoint::kStopMode_Process = "process";
const char* ClientSettings::Breakpoint::kStopMode_All = "all";
namespace {
fxl::RefPtr<SettingSchema> CreateSchema() {
auto schema = fxl::MakeRefCounted<SettingSchema>();
schema->AddInputLocations(ClientSettings::Breakpoint::kLocation,
ClientSettings::Breakpoint::kLocationDescription);
schema->AddExecutionScope(ClientSettings::Breakpoint::kScope,
ClientSettings::Breakpoint::kScopeDescription);
schema->AddBool(ClientSettings::Breakpoint::kEnabled,
ClientSettings::Breakpoint::kEnabledDescription, true);
schema->AddBool(ClientSettings::Breakpoint::kOneShot,
ClientSettings::Breakpoint::kOneShotDescription, false);
schema->AddString(
ClientSettings::Breakpoint::kType, ClientSettings::Breakpoint::kTypeDescription,
ClientSettings::Breakpoint::kType_Software,
{ClientSettings::Breakpoint::kType_Software, ClientSettings::Breakpoint::kType_Hardware,
ClientSettings::Breakpoint::kType_ReadWrite, ClientSettings::Breakpoint::kType_Write});
schema->AddString(
ClientSettings::Breakpoint::kStopMode, ClientSettings::Breakpoint::kStopModeDescription,
ClientSettings::Breakpoint::kStopMode_All,
{ClientSettings::Breakpoint::kStopMode_None, ClientSettings::Breakpoint::kStopMode_Thread,
ClientSettings::Breakpoint::kStopMode_Process, ClientSettings::Breakpoint::kStopMode_All});
return schema;
}
} // namespace
Breakpoint::Settings::Settings(Breakpoint* bp) : SettingStore(Breakpoint::GetSchema()), bp_(bp) {}
SettingValue Breakpoint::Settings::GetStorageValue(const std::string& key) const {
BreakpointSettings settings = bp_->GetSettings();
if (key == ClientSettings::Breakpoint::kLocation) {
return SettingValue(settings.locations);
} else if (key == ClientSettings::Breakpoint::kScope) {
return SettingValue(settings.scope);
} else if (key == ClientSettings::Breakpoint::kStopMode) {
return SettingValue(BreakpointSettings::StopModeToString(settings.stop_mode));
} else if (key == ClientSettings::Breakpoint::kEnabled) {
return SettingValue(settings.enabled);
} else if (key == ClientSettings::Breakpoint::kOneShot) {
return SettingValue(settings.one_shot);
} else if (key == ClientSettings::Breakpoint::kType) {
return SettingValue(BreakpointSettings::TypeToString(settings.type));
}
FXL_NOTREACHED();
return SettingValue();
}
Err Breakpoint::Settings::SetStorageValue(const std::string& key, SettingValue value) {
BreakpointSettings settings = bp_->GetSettings();
if (key == ClientSettings::Breakpoint::kLocation) {
settings.locations = value.get_input_locations();
} else if (key == ClientSettings::Breakpoint::kScope) {
settings.scope = value.get_execution_scope();
} else if (key == ClientSettings::Breakpoint::kStopMode) {
std::optional<BreakpointSettings::StopMode> stop_mode =
BreakpointSettings::StringToStopMode(value.get_string());
FXL_DCHECK(stop_mode); // Schema should have validated the input.
settings.stop_mode = *stop_mode;
} else if (key == ClientSettings::Breakpoint::kEnabled) {
settings.enabled = value.get_bool();
} else if (key == ClientSettings::Breakpoint::kOneShot) {
settings.one_shot = value.get_bool();
} else if (key == ClientSettings::Breakpoint::kType) {
std::optional<BreakpointSettings::Type> type =
BreakpointSettings::StringToType(value.get_string());
FXL_DCHECK(type); // Schema should have validated the input.
settings.type = *type;
} else {
FXL_NOTREACHED();
}
// This code doesn't have a good way to communicate breakpoint set failures from this location.
// TODO(brettw) we may need a notification that the frontend can listen for and display.
bp_->SetSettings(settings, [](const Err&) {});
return Err();
}
Breakpoint::Breakpoint(Session* session)
: ClientObject(session), settings_(this), weak_factory_(this) {}
Breakpoint::~Breakpoint() {}
fxl::WeakPtr<Breakpoint> Breakpoint::GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
// static
fxl::RefPtr<SettingSchema> Breakpoint::GetSchema() {
static fxl::RefPtr<SettingSchema> schema = CreateSchema();
return schema;
}
} // namespace zxdb