diff options
Diffstat (limited to 'source/Breakpoint')
-rw-r--r-- | source/Breakpoint/Breakpoint.cpp | 30 | ||||
-rw-r--r-- | source/Breakpoint/BreakpointID.cpp | 11 | ||||
-rw-r--r-- | source/Breakpoint/BreakpointIDList.cpp | 35 | ||||
-rw-r--r-- | source/Breakpoint/BreakpointList.cpp | 33 | ||||
-rw-r--r-- | source/Breakpoint/BreakpointLocation.cpp | 76 | ||||
-rw-r--r-- | source/Breakpoint/BreakpointLocationList.cpp | 2 | ||||
-rw-r--r-- | source/Breakpoint/BreakpointName.cpp | 91 | ||||
-rw-r--r-- | source/Breakpoint/BreakpointOptions.cpp | 231 | ||||
-rw-r--r-- | source/Breakpoint/CMakeLists.txt | 1 |
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 |