summaryrefslogtreecommitdiff
path: root/source/Breakpoint
diff options
context:
space:
mode:
Diffstat (limited to 'source/Breakpoint')
-rw-r--r--source/Breakpoint/Breakpoint.cpp30
-rw-r--r--source/Breakpoint/BreakpointID.cpp11
-rw-r--r--source/Breakpoint/BreakpointIDList.cpp35
-rw-r--r--source/Breakpoint/BreakpointList.cpp33
-rw-r--r--source/Breakpoint/BreakpointLocation.cpp76
-rw-r--r--source/Breakpoint/BreakpointLocationList.cpp2
-rw-r--r--source/Breakpoint/BreakpointName.cpp91
-rw-r--r--source/Breakpoint/BreakpointOptions.cpp231
-rw-r--r--source/Breakpoint/CMakeLists.txt1
9 files changed, 412 insertions, 98 deletions
diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp
index 17c104ba0c600..3f6c63e1e5ba1 100644
--- a/source/Breakpoint/Breakpoint.cpp
+++ b/source/Breakpoint/Breakpoint.cpp
@@ -53,7 +53,7 @@ Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp,
bool resolve_indirect_symbols)
: m_being_created(true), m_hardware(hardware), m_target(target),
m_filter_sp(filter_sp), m_resolver_sp(resolver_sp),
- m_options_up(new BreakpointOptions()), m_locations(*this),
+ m_options_up(new BreakpointOptions(true)), m_locations(*this),
m_resolve_indirect_symbols(resolve_indirect_symbols), m_hit_count(0) {
m_being_created = false;
}
@@ -210,7 +210,7 @@ lldb::BreakpointSP Breakpoint::CreateFromStructuredData(
llvm::StringRef name;
Status error;
success = names_array->GetItemAtIndexAsString(i, name);
- result_sp->AddName(name, error);
+ target.AddNameToBreakpoint(result_sp, name.str().c_str(), error);
}
}
@@ -348,6 +348,14 @@ void Breakpoint::SetOneShot(bool one_shot) {
m_options_up->SetOneShot(one_shot);
}
+bool Breakpoint::IsAutoContinue() const {
+ return m_options_up->IsAutoContinue();
+}
+
+void Breakpoint::SetAutoContinue(bool auto_continue) {
+ m_options_up->SetAutoContinue(auto_continue);
+}
+
void Breakpoint::SetThreadID(lldb::tid_t thread_id) {
if (m_options_up->GetThreadSpec()->GetTID() == thread_id)
return;
@@ -447,6 +455,10 @@ bool Breakpoint::InvokeCallback(StoppointCallbackContext *context,
BreakpointOptions *Breakpoint::GetOptions() { return m_options_up.get(); }
+const BreakpointOptions *Breakpoint::GetOptions() const {
+ return m_options_up.get();
+}
+
void Breakpoint::ResolveBreakpoint() {
if (m_resolver_sp)
m_resolver_sp->ResolveBreakpoint(*m_filter_sp);
@@ -833,18 +845,8 @@ size_t Breakpoint::GetNumResolvedLocations() const {
size_t Breakpoint::GetNumLocations() const { return m_locations.GetSize(); }
-bool Breakpoint::AddName(llvm::StringRef new_name, Status &error) {
- if (new_name.empty())
- return false;
- if (!BreakpointID::StringIsBreakpointName(new_name, error)) {
- error.SetErrorStringWithFormatv("input name \"{0}\" not a breakpoint name.",
- new_name);
- return false;
- }
- if (!error.Success())
- return false;
-
- m_name_list.insert(new_name);
+bool Breakpoint::AddName(llvm::StringRef new_name) {
+ m_name_list.insert(new_name.str().c_str());
return true;
}
diff --git a/source/Breakpoint/BreakpointID.cpp b/source/Breakpoint/BreakpointID.cpp
index 112f7c0b51956..b801065468221 100644
--- a/source/Breakpoint/BreakpointID.cpp
+++ b/source/Breakpoint/BreakpointID.cpp
@@ -101,15 +101,24 @@ BreakpointID::ParseCanonicalReference(llvm::StringRef input) {
bool BreakpointID::StringIsBreakpointName(llvm::StringRef str, Status &error) {
error.Clear();
if (str.empty())
+ {
+ error.SetErrorStringWithFormat("Empty breakpoint names are not allowed");
return false;
+ }
// First character must be a letter or _
if (!isalpha(str[0]) && str[0] != '_')
+ {
+ error.SetErrorStringWithFormat("Breakpoint names must start with a "
+ "character or underscore: %s",
+ str.str().c_str());
return false;
+ }
// Cannot contain ., -, or space.
if (str.find_first_of(".- ") != llvm::StringRef::npos) {
- error.SetErrorStringWithFormat("invalid breakpoint name: \"%s\"",
+ error.SetErrorStringWithFormat("Breakpoint names cannot contain "
+ "'.' or '-': \"%s\"",
str.str().c_str());
return false;
}
diff --git a/source/Breakpoint/BreakpointIDList.cpp b/source/Breakpoint/BreakpointIDList.cpp
index 7b461147a4e93..6d610d512f3b8 100644
--- a/source/Breakpoint/BreakpointIDList.cpp
+++ b/source/Breakpoint/BreakpointIDList.cpp
@@ -11,6 +11,7 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/lldb-enumerations.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/Breakpoint.h"
@@ -117,6 +118,8 @@ void BreakpointIDList::InsertStringArray(const char **string_array,
void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
bool allow_locations,
+ BreakpointName::Permissions
+ ::PermissionKinds purpose,
CommandReturnObject &result,
Args &new_args) {
llvm::StringRef range_from;
@@ -136,7 +139,6 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
return;
}
- llvm::StringRef range_expr;
Status error;
std::tie(range_from, range_to) =
@@ -302,14 +304,29 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
}
// Okay, now see if we found any names, and if we did, add them:
- if (target && names_found.size()) {
- for (BreakpointSP bkpt_sp : target->GetBreakpointList().Breakpoints()) {
- for (std::string name : names_found) {
- if (bkpt_sp->MatchesName(name.c_str())) {
- StreamString canonical_id_str;
- BreakpointID::GetCanonicalReference(
- &canonical_id_str, bkpt_sp->GetID(), LLDB_INVALID_BREAK_ID);
- new_args.AppendArgument(canonical_id_str.GetString());
+ if (target && !names_found.empty()) {
+ Status error;
+ // Remove any names that aren't visible for this purpose:
+ auto iter = names_found.begin();
+ while (iter != names_found.end()) {
+ BreakpointName *bp_name = target->FindBreakpointName(ConstString(*iter),
+ true,
+ error);
+ if (bp_name && !bp_name->GetPermission(purpose))
+ iter = names_found.erase(iter);
+ else
+ iter++;
+ }
+
+ if (!names_found.empty()) {
+ for (BreakpointSP bkpt_sp : target->GetBreakpointList().Breakpoints()) {
+ for (std::string name : names_found) {
+ if (bkpt_sp->MatchesName(name.c_str())) {
+ StreamString canonical_id_str;
+ BreakpointID::GetCanonicalReference(
+ &canonical_id_str, bkpt_sp->GetID(), LLDB_INVALID_BREAK_ID);
+ new_args.AppendArgument(canonical_id_str.GetString());
+ }
}
}
}
diff --git a/source/Breakpoint/BreakpointList.cpp b/source/Breakpoint/BreakpointList.cpp
index 15bcb34a3d85f..01ac59f0a903e 100644
--- a/source/Breakpoint/BreakpointList.cpp
+++ b/source/Breakpoint/BreakpointList.cpp
@@ -71,6 +71,13 @@ void BreakpointList::SetEnabledAll(bool enabled) {
bp_sp->SetEnabled(enabled);
}
+void BreakpointList::SetEnabledAllowed(bool enabled) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ for (const auto &bp_sp : m_breakpoints)
+ if (bp_sp->AllowDisable())
+ bp_sp->SetEnabled(enabled);
+}
+
void BreakpointList::RemoveAll(bool notify) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
ClearAllBreakpointSites();
@@ -90,6 +97,32 @@ void BreakpointList::RemoveAll(bool notify) {
m_breakpoints.erase(m_breakpoints.begin(), m_breakpoints.end());
}
+void BreakpointList::RemoveAllowed(bool notify) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+
+ bp_collection::iterator pos, end = m_breakpoints.end();
+ if (notify) {
+ for (pos = m_breakpoints.begin(); pos != end; ++pos) {
+ if(!(*pos)->AllowDelete())
+ continue;
+ if ((*pos)->GetTarget().EventTypeHasListeners(
+ Target::eBroadcastBitBreakpointChanged)) {
+ (*pos)->GetTarget().BroadcastEvent(
+ Target::eBroadcastBitBreakpointChanged,
+ new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved,
+ *pos));
+ }
+ }
+ }
+ pos = m_breakpoints.begin();
+ while ( pos != end) {
+ if((*pos)->AllowDelete())
+ pos = m_breakpoints.erase(pos);
+ else
+ pos++;
+ }
+}
+
class BreakpointIDMatches {
public:
BreakpointIDMatches(break_id_t break_id) : m_break_id(break_id) {}
diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp
index ec8f141e8d38a..f59c334fe5c8a 100644
--- a/source/Breakpoint/BreakpointLocation.cpp
+++ b/source/Breakpoint/BreakpointLocation.cpp
@@ -58,6 +58,15 @@ lldb::addr_t BreakpointLocation::GetLoadAddress() const {
return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget());
}
+const BreakpointOptions *
+BreakpointLocation::GetOptionsSpecifyingKind(BreakpointOptions::OptionKind kind)
+const {
+ if (m_options_ap && m_options_ap->IsOptionSet(kind))
+ return m_options_ap.get();
+ else
+ return m_owner.GetOptions();
+}
+
Address &BreakpointLocation::GetAddress() { return m_address; }
Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; }
@@ -84,6 +93,19 @@ void BreakpointLocation::SetEnabled(bool enabled) {
: eBreakpointEventTypeDisabled);
}
+bool BreakpointLocation::IsAutoContinue() const {
+ if (m_options_ap
+ && m_options_ap->IsOptionSet(BreakpointOptions::eAutoContinue))
+ return m_options_ap->IsAutoContinue();
+ else
+ return m_owner.IsAutoContinue();
+}
+
+void BreakpointLocation::SetAutoContinue(bool auto_continue) {
+ GetLocationOptions()->SetAutoContinue(auto_continue);
+ SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
+}
+
void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
if (thread_id != LLDB_INVALID_THREAD_ID)
GetLocationOptions()->SetThreadID(thread_id);
@@ -97,8 +119,11 @@ void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
}
lldb::tid_t BreakpointLocation::GetThreadID() {
- if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
- return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID();
+ const ThreadSpec *thread_spec =
+ GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
+ ->GetThreadSpecNoCreate();
+ if (thread_spec)
+ return thread_spec->GetTID();
else
return LLDB_INVALID_THREAD_ID;
}
@@ -116,8 +141,11 @@ void BreakpointLocation::SetThreadIndex(uint32_t index) {
}
uint32_t BreakpointLocation::GetThreadIndex() const {
- if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
- return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetIndex();
+ const ThreadSpec *thread_spec =
+ GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
+ ->GetThreadSpecNoCreate();
+ if (thread_spec)
+ return thread_spec->GetIndex();
else
return 0;
}
@@ -135,8 +163,11 @@ void BreakpointLocation::SetThreadName(const char *thread_name) {
}
const char *BreakpointLocation::GetThreadName() const {
- if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
- return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetName();
+ const ThreadSpec *thread_spec =
+ GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
+ ->GetThreadSpecNoCreate();
+ if (thread_spec)
+ return thread_spec->GetName();
else
return nullptr;
}
@@ -154,8 +185,11 @@ void BreakpointLocation::SetQueueName(const char *queue_name) {
}
const char *BreakpointLocation::GetQueueName() const {
- if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
- return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetQueueName();
+ const ThreadSpec *thread_spec =
+ GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
+ ->GetThreadSpecNoCreate();
+ if (thread_spec)
+ return thread_spec->GetQueueName();
else
return nullptr;
}
@@ -193,7 +227,8 @@ void BreakpointLocation::SetCondition(const char *condition) {
}
const char *BreakpointLocation::GetConditionText(size_t *hash) const {
- return GetOptionsNoCreate()->GetConditionText(hash);
+ return GetOptionsSpecifyingKind(BreakpointOptions::eCondition)
+ ->GetConditionText(hash);
}
bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
@@ -305,7 +340,8 @@ bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
}
uint32_t BreakpointLocation::GetIgnoreCount() {
- return GetOptionsNoCreate()->GetIgnoreCount();
+ return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
+ ->GetIgnoreCount();
}
void BreakpointLocation::SetIgnoreCount(uint32_t n) {
@@ -335,26 +371,21 @@ bool BreakpointLocation::IgnoreCountShouldStop() {
return true;
}
-const BreakpointOptions *BreakpointLocation::GetOptionsNoCreate() const {
- if (m_options_ap.get() != nullptr)
- return m_options_ap.get();
- else
- return m_owner.GetOptions();
-}
-
BreakpointOptions *BreakpointLocation::GetLocationOptions() {
// If we make the copy we don't copy the callbacks because that is potentially
// expensive and we don't want to do that for the simple case where someone is
// just disabling the location.
if (m_options_ap.get() == nullptr)
m_options_ap.reset(
- BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions()));
+ new BreakpointOptions(false));
return m_options_ap.get();
}
bool BreakpointLocation::ValidForThisThread(Thread *thread) {
- return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate());
+ return thread
+ ->MatchesSpec(GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
+ ->GetThreadSpecNoCreate());
}
// RETURNS - true if we should stop at this breakpoint, false if we
@@ -600,17 +631,20 @@ void BreakpointLocation::Dump(Stream *s) const {
if (s == nullptr)
return;
+ lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
+ ->GetThreadSpecNoCreate()->GetTID();
s->Printf(
"BreakpointLocation %u: tid = %4.4" PRIx64 " load addr = 0x%8.8" PRIx64
" state = %s type = %s breakpoint "
"hw_index = %i hit_count = %-4u ignore_count = %-4u",
- GetID(), GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
+ GetID(), tid,
(uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()),
(m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled())
? "enabled "
: "disabled",
IsHardware() ? "hardware" : "software", GetHardwareIndex(), GetHitCount(),
- GetOptionsNoCreate()->GetIgnoreCount());
+ GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
+ ->GetIgnoreCount());
}
void BreakpointLocation::SendBreakpointLocationChangedEvent(
diff --git a/source/Breakpoint/BreakpointLocationList.cpp b/source/Breakpoint/BreakpointLocationList.cpp
index b4cf0c38e9c28..1e4b4412a427b 100644
--- a/source/Breakpoint/BreakpointLocationList.cpp
+++ b/source/Breakpoint/BreakpointLocationList.cpp
@@ -15,11 +15,11 @@
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/ArchSpec.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Breakpoint/BreakpointName.cpp b/source/Breakpoint/BreakpointName.cpp
new file mode 100644
index 0000000000000..be4710d7849c8
--- /dev/null
+++ b/source/Breakpoint/BreakpointName.cpp
@@ -0,0 +1,91 @@
+//===-- Breakpoint.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details->
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/Casting.h"
+
+// Project includes
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointOptions.h"
+#include "lldb/Breakpoint/BreakpointLocationCollection.h"
+#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/StreamString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+const Flags::ValueType BreakpointName::Permissions::permissions_mask
+ [BreakpointName::Permissions::PermissionKinds::allPerms + 1] = {
+ (1u << 0),
+ (1u << 1),
+ (1u << 2),
+ (0x5u)
+};
+
+BreakpointName::BreakpointName(const ConstString &name, const Breakpoint &bkpt,
+ const char *help) :
+ m_name(name), m_options(bkpt.GetOptions())
+{
+ SetHelp(help);
+}
+
+bool BreakpointName::Permissions::GetDescription(Stream *s,
+ lldb::DescriptionLevel level) {
+ if (!AnySet())
+ return false;
+ s->IndentMore();
+ s->Indent();
+ if (IsSet(listPerm))
+ s->Printf("list: %s", GetAllowList() ? "allowed" : "disallowed");
+
+ if (IsSet(disablePerm))
+ s->Printf("disable: %s", GetAllowDisable() ? "allowed" : "disallowed");
+
+ if (IsSet(deletePerm))
+ s->Printf("delete: %s", GetAllowDelete() ? "allowed" : "disallowed");
+ s->IndentLess();
+ return true;
+}
+
+bool BreakpointName::GetDescription(Stream *s, lldb::DescriptionLevel level) {
+ bool printed_any = false;
+ if (!m_help.empty())
+ s->Printf("Help: %s\n", m_help.c_str());
+
+ if (GetOptions().AnySet())
+ {
+ s->PutCString("Options: \n");
+ s->IndentMore();
+ s->Indent();
+ GetOptions().GetDescription(s, level);
+ printed_any = true;
+ s->IndentLess();
+ }
+ if (GetPermissions().AnySet())
+ {
+ s->PutCString("Permissions: \n");
+ s->IndentMore();
+ s->Indent();
+ GetPermissions().GetDescription(s, level);
+ printed_any = true;
+ s->IndentLess();
+ }
+ return printed_any;
+}
+
+void BreakpointName::ConfigureBreakpoint(lldb::BreakpointSP bp_sp)
+{
+ bp_sp->GetOptions()->CopyOverSetOptions(GetOptions());
+ bp_sp->GetPermissions().MergeInto(GetPermissions());
+}
diff --git a/source/Breakpoint/BreakpointOptions.cpp b/source/Breakpoint/BreakpointOptions.cpp
index bef63cc0f222e..662b288794d3a 100644
--- a/source/Breakpoint/BreakpointOptions.cpp
+++ b/source/Breakpoint/BreakpointOptions.cpp
@@ -114,7 +114,8 @@ BreakpointOptions::CommandData::CreateFromStructuredData(
const char *BreakpointOptions::g_option_names[(
size_t)BreakpointOptions::OptionNames::LastOptionName]{
- "ConditionText", "IgnoreCount", "EnabledState", "OneShotState"};
+ "ConditionText", "IgnoreCount",
+ "EnabledState", "OneShotState", "AutoContinue"};
bool BreakpointOptions::NullCallback(void *baton,
StoppointCallbackContext *context,
@@ -126,20 +127,30 @@ bool BreakpointOptions::NullCallback(void *baton,
//----------------------------------------------------------------------
// BreakpointOptions constructor
//----------------------------------------------------------------------
-BreakpointOptions::BreakpointOptions()
+BreakpointOptions::BreakpointOptions(bool all_flags_set)
: m_callback(BreakpointOptions::NullCallback), m_callback_baton_sp(),
m_baton_is_command_baton(false), m_callback_is_synchronous(false),
m_enabled(true), m_one_shot(false), m_ignore_count(0), m_thread_spec_ap(),
- m_condition_text(), m_condition_text_hash(0) {}
+ m_condition_text(), m_condition_text_hash(0), m_auto_continue(false),
+ m_set_flags(0) {
+ if (all_flags_set)
+ m_set_flags.Set(~((Flags::ValueType) 0));
+ }
BreakpointOptions::BreakpointOptions(const char *condition, bool enabled,
- int32_t ignore, bool one_shot)
+ int32_t ignore, bool one_shot,
+ bool auto_continue)
: m_callback(nullptr), m_baton_is_command_baton(false),
m_callback_is_synchronous(false), m_enabled(enabled),
- m_one_shot(one_shot), m_ignore_count(ignore), m_condition_text(condition),
- m_condition_text_hash(0)
-
-{}
+ m_one_shot(one_shot), m_ignore_count(ignore),
+ m_condition_text_hash(0), m_auto_continue(auto_continue)
+{
+ m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot
+ | eAutoContinue);
+ if (condition && *condition != '\0') {
+ SetCondition(condition);
+ }
+}
//----------------------------------------------------------------------
// BreakpointOptions copy constructor
@@ -149,7 +160,9 @@ BreakpointOptions::BreakpointOptions(const BreakpointOptions &rhs)
m_baton_is_command_baton(rhs.m_baton_is_command_baton),
m_callback_is_synchronous(rhs.m_callback_is_synchronous),
m_enabled(rhs.m_enabled), m_one_shot(rhs.m_one_shot),
- m_ignore_count(rhs.m_ignore_count), m_thread_spec_ap() {
+ m_ignore_count(rhs.m_ignore_count), m_thread_spec_ap(),
+ m_auto_continue(rhs.m_auto_continue),
+ m_set_flags(rhs.m_set_flags) {
if (rhs.m_thread_spec_ap.get() != nullptr)
m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
m_condition_text = rhs.m_condition_text;
@@ -172,21 +185,62 @@ operator=(const BreakpointOptions &rhs) {
m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
m_condition_text = rhs.m_condition_text;
m_condition_text_hash = rhs.m_condition_text_hash;
+ m_auto_continue = rhs.m_auto_continue;
+ m_set_flags = rhs.m_set_flags;
return *this;
}
-BreakpointOptions *
-BreakpointOptions::CopyOptionsNoCallback(BreakpointOptions &orig) {
- BreakpointHitCallback orig_callback = orig.m_callback;
- lldb::BatonSP orig_callback_baton_sp = orig.m_callback_baton_sp;
- bool orig_is_sync = orig.m_callback_is_synchronous;
-
- orig.ClearCallback();
- BreakpointOptions *ret_val = new BreakpointOptions(orig);
-
- orig.SetCallback(orig_callback, orig_callback_baton_sp, orig_is_sync);
-
- return ret_val;
+void BreakpointOptions::CopyOverSetOptions(const BreakpointOptions &incoming)
+{
+ if (incoming.m_set_flags.Test(eEnabled))
+ {
+ m_enabled = incoming.m_enabled;
+ m_set_flags.Set(eEnabled);
+ }
+ if (incoming.m_set_flags.Test(eOneShot))
+ {
+ m_one_shot = incoming.m_one_shot;
+ m_set_flags.Set(eOneShot);
+ }
+ if (incoming.m_set_flags.Test(eCallback))
+ {
+ m_callback = incoming.m_callback;
+ m_callback_baton_sp = incoming.m_callback_baton_sp;
+ m_callback_is_synchronous = incoming.m_callback_is_synchronous;
+ m_baton_is_command_baton = incoming.m_baton_is_command_baton;
+ m_set_flags.Set(eCallback);
+ }
+ if (incoming.m_set_flags.Test(eIgnoreCount))
+ {
+ m_ignore_count = incoming.m_ignore_count;
+ m_set_flags.Set(eIgnoreCount);
+ }
+ if (incoming.m_set_flags.Test(eCondition))
+ {
+ // If we're copying over an empty condition, mark it as unset.
+ if (incoming.m_condition_text.empty()) {
+ m_condition_text.clear();
+ m_condition_text_hash = 0;
+ m_set_flags.Clear(eCondition);
+ } else {
+ m_condition_text = incoming.m_condition_text;
+ m_condition_text_hash = incoming.m_condition_text_hash;
+ m_set_flags.Set(eCondition);
+ }
+ }
+ if (incoming.m_set_flags.Test(eAutoContinue))
+ {
+ m_auto_continue = incoming.m_auto_continue;
+ m_set_flags.Set(eAutoContinue);
+ }
+ if (incoming.m_set_flags.Test(eThreadSpec) && incoming.m_thread_spec_ap)
+ {
+ if (!m_thread_spec_ap)
+ m_thread_spec_ap.reset(new ThreadSpec(*incoming.m_thread_spec_ap.get()));
+ else
+ *m_thread_spec_ap.get() = *incoming.m_thread_spec_ap.get();
+ m_set_flags.Set(eThreadSpec);
+ }
}
//----------------------------------------------------------------------
@@ -199,30 +253,65 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
Status &error) {
bool enabled = true;
bool one_shot = false;
+ bool auto_continue = false;
int32_t ignore_count = 0;
- std::string condition_text;
-
- bool success = options_dict.GetValueForKeyAsBoolean(
- GetKey(OptionNames::EnabledState), enabled);
- if (!success) {
- error.SetErrorStringWithFormat("%s key is not a boolean.",
+ llvm::StringRef condition_ref("");
+ Flags set_options;
+
+ const char *key = GetKey(OptionNames::EnabledState);
+ bool success;
+ if (key) {
+ success = options_dict.GetValueForKeyAsBoolean(key, enabled);
+ if (!success) {
+ error.SetErrorStringWithFormat("%s key is not a boolean.",
GetKey(OptionNames::EnabledState));
- return nullptr;
+ return nullptr;
+ }
+ set_options.Set(eEnabled);
}
- success = options_dict.GetValueForKeyAsBoolean(
- GetKey(OptionNames::OneShotState), one_shot);
- if (!success) {
- error.SetErrorStringWithFormat("%s key is not a boolean.",
- GetKey(OptionNames::OneShotState));
- return nullptr;
+ key = GetKey(OptionNames::OneShotState);
+ if (key) {
+ success = options_dict.GetValueForKeyAsBoolean(key, one_shot);
+ if (!success) {
+ error.SetErrorStringWithFormat("%s key is not a boolean.",
+ GetKey(OptionNames::OneShotState));
+ return nullptr;
+ }
+ set_options.Set(eOneShot);
}
- success = options_dict.GetValueForKeyAsInteger(
- GetKey(OptionNames::IgnoreCount), ignore_count);
- if (!success) {
- error.SetErrorStringWithFormat("%s key is not an integer.",
- GetKey(OptionNames::IgnoreCount));
- return nullptr;
+
+ key = GetKey(OptionNames::AutoContinue);
+ if (key) {
+ success = options_dict.GetValueForKeyAsBoolean(key, auto_continue);
+ if (!success) {
+ error.SetErrorStringWithFormat("%s key is not a boolean.",
+ GetKey(OptionNames::AutoContinue));
+ return nullptr;
+ }
+ set_options.Set(eAutoContinue);
+ }
+
+ key = GetKey(OptionNames::IgnoreCount);
+ if (key) {
+ success = options_dict.GetValueForKeyAsInteger(key, ignore_count);
+ if (!success) {
+ error.SetErrorStringWithFormat("%s key is not an integer.",
+ GetKey(OptionNames::IgnoreCount));
+ return nullptr;
+ }
+ set_options.Set(eIgnoreCount);
+ }
+
+ key = GetKey(OptionNames::ConditionText);
+ if (key) {
+ success = options_dict.GetValueForKeyAsString(key, condition_ref);
+ if (!success) {
+ error.SetErrorStringWithFormat("%s key is not an string.",
+ GetKey(OptionNames::ConditionText));
+ return nullptr;
+ }
+ set_options.Set(eCondition);
}
std::unique_ptr<CommandData> cmd_data_up;
@@ -241,7 +330,8 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
}
auto bp_options = llvm::make_unique<BreakpointOptions>(
- condition_text.c_str(), enabled, ignore_count, one_shot);
+ condition_ref.str().c_str(), enabled,
+ ignore_count, one_shot, auto_continue);
if (cmd_data_up.get()) {
if (cmd_data_up->interpreter == eScriptLanguageNone)
bp_options->SetCommandDataCallback(cmd_data_up);
@@ -293,14 +383,23 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() {
StructuredData::DictionarySP options_dict_sp(
new StructuredData::Dictionary());
- options_dict_sp->AddBooleanItem(GetKey(OptionNames::EnabledState), m_enabled);
- options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState),
- m_one_shot);
- options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount),
- m_ignore_count);
- options_dict_sp->AddStringItem(GetKey(OptionNames::ConditionText),
- m_condition_text);
- if (m_baton_is_command_baton) {
+ if (m_set_flags.Test(eEnabled))
+ options_dict_sp->AddBooleanItem(GetKey(OptionNames::EnabledState),
+ m_enabled);
+ if (m_set_flags.Test(eOneShot))
+ options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState),
+ m_one_shot);
+ if (m_set_flags.Test(eAutoContinue))
+ options_dict_sp->AddBooleanItem(GetKey(OptionNames::AutoContinue),
+ m_auto_continue);
+ if (m_set_flags.Test(eIgnoreCount))
+ options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount),
+ m_ignore_count);
+ if (m_set_flags.Test(eCondition))
+ options_dict_sp->AddStringItem(GetKey(OptionNames::ConditionText),
+ m_condition_text);
+
+ if (m_set_flags.Test(eCallback) && m_baton_is_command_baton) {
auto cmd_baton =
std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
StructuredData::ObjectSP commands_sp =
@@ -310,7 +409,7 @@ StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() {
BreakpointOptions::CommandData::GetSerializationKey(), commands_sp);
}
}
- if (m_thread_spec_ap) {
+ if (m_set_flags.Test(eThreadSpec) && m_thread_spec_ap) {
StructuredData::ObjectSP thread_spec_sp =
m_thread_spec_ap->SerializeToStructuredData();
options_dict_sp->AddItem(ThreadSpec::GetSerializationKey(), thread_spec_sp);
@@ -340,6 +439,7 @@ void BreakpointOptions::SetCallback(BreakpointHitCallback callback,
m_callback = callback;
m_callback_baton_sp = callback_baton_sp;
m_baton_is_command_baton = false;
+ m_set_flags.Set(eCallback);
}
void BreakpointOptions::SetCallback(
@@ -350,6 +450,7 @@ void BreakpointOptions::SetCallback(
m_callback = callback;
m_callback_baton_sp = callback_baton_sp;
m_baton_is_command_baton = true;
+ m_set_flags.Set(eCallback);
}
void BreakpointOptions::ClearCallback() {
@@ -357,6 +458,7 @@ void BreakpointOptions::ClearCallback() {
m_callback_is_synchronous = false;
m_callback_baton_sp.reset();
m_baton_is_command_baton = false;
+ m_set_flags.Clear(eCallback);
}
Baton *BreakpointOptions::GetBaton() { return m_callback_baton_sp.get(); }
@@ -395,8 +497,12 @@ bool BreakpointOptions::GetCommandLineCallbacks(StringList &command_list) {
}
void BreakpointOptions::SetCondition(const char *condition) {
- if (!condition)
+ if (!condition || condition[0] == '\0') {
condition = "";
+ m_set_flags.Clear(eCondition);
+ }
+ else
+ m_set_flags.Set(eCondition);
m_condition_text.assign(condition);
std::hash<std::string> hasher;
@@ -427,11 +533,13 @@ ThreadSpec *BreakpointOptions::GetThreadSpec() {
void BreakpointOptions::SetThreadID(lldb::tid_t thread_id) {
GetThreadSpec()->SetTID(thread_id);
+ m_set_flags.Set(eThreadSpec);
}
void BreakpointOptions::SetThreadSpec(
std::unique_ptr<ThreadSpec> &thread_spec_up) {
m_thread_spec_ap = std::move(thread_spec_up);
+ m_set_flags.Set(eThreadSpec);
}
void BreakpointOptions::GetDescription(Stream *s,
@@ -440,7 +548,7 @@ void BreakpointOptions::GetDescription(Stream *s,
// print
// anything if there are:
- if (m_ignore_count != 0 || !m_enabled || m_one_shot ||
+ if (m_ignore_count != 0 || !m_enabled || m_one_shot || m_auto_continue ||
(GetThreadSpecNoCreate() != nullptr &&
GetThreadSpecNoCreate()->HasSpecification())) {
if (level == lldb::eDescriptionLevelVerbose) {
@@ -460,6 +568,9 @@ void BreakpointOptions::GetDescription(Stream *s,
if (m_one_shot)
s->Printf("one-shot ");
+ if (m_auto_continue)
+ s->Printf("auto-continue ");
+
if (m_thread_spec_ap.get())
m_thread_spec_ap->GetDescription(s, level);
@@ -520,6 +631,7 @@ void BreakpointOptions::SetCommandDataCallback(
cmd_data->interpreter = eScriptLanguageNone;
auto baton_sp = std::make_shared<CommandBaton>(std::move(cmd_data));
SetCallback(BreakpointOptions::BreakpointOptionsCallbackFunction, baton_sp);
+ m_set_flags.Set(eCallback);
}
bool BreakpointOptions::BreakpointOptionsCallbackFunction(
@@ -562,3 +674,18 @@ bool BreakpointOptions::BreakpointOptionsCallbackFunction(
}
return ret_value;
}
+
+void BreakpointOptions::Clear()
+{
+ m_set_flags.Clear();
+ m_thread_spec_ap.release();
+ m_one_shot = false;
+ m_ignore_count = 0;
+ m_auto_continue = false;
+ m_callback = nullptr;
+ m_callback_baton_sp.reset();
+ m_baton_is_command_baton = false;
+ m_callback_is_synchronous = false;
+ m_enabled = false;
+ m_condition_text.clear();
+}
diff --git a/source/Breakpoint/CMakeLists.txt b/source/Breakpoint/CMakeLists.txt
index f6278528eab8a..f93d48579ad7d 100644
--- a/source/Breakpoint/CMakeLists.txt
+++ b/source/Breakpoint/CMakeLists.txt
@@ -6,6 +6,7 @@ add_lldb_library(lldbBreakpoint
BreakpointLocation.cpp
BreakpointLocationCollection.cpp
BreakpointLocationList.cpp
+ BreakpointName.cpp
BreakpointOptions.cpp
BreakpointResolver.cpp
BreakpointResolverAddress.cpp