180814287SRaphael Isemann //===-- Breakpoint.cpp ----------------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner
916fd7511SEugene Zelenko #include "llvm/Support/Casting.h"
1030fdc8d8SChris Lattner
1130fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h"
1230fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h"
13b7234e40SJohnny Chen #include "lldb/Breakpoint/BreakpointLocationCollection.h"
147f9c9f22SAlex Langford #include "lldb/Breakpoint/BreakpointPrecondition.h"
1530fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointResolver.h"
16b7234e40SJohnny Chen #include "lldb/Breakpoint/BreakpointResolverFileLine.h"
17b9c1b51eSKate Stone #include "lldb/Core/Address.h"
1877fd738fSJim Ingham #include "lldb/Core/Module.h"
1930fdc8d8SChris Lattner #include "lldb/Core/ModuleList.h"
2030fdc8d8SChris Lattner #include "lldb/Core/SearchFilter.h"
211f746071SGreg Clayton #include "lldb/Core/Section.h"
2277fd738fSJim Ingham #include "lldb/Symbol/CompileUnit.h"
2377fd738fSJim Ingham #include "lldb/Symbol/Function.h"
242f3df613SZachary Turner #include "lldb/Symbol/Symbol.h"
2530fdc8d8SChris Lattner #include "lldb/Symbol/SymbolContext.h"
26c34698a8SPavel Labath #include "lldb/Target/SectionLoadList.h"
2730fdc8d8SChris Lattner #include "lldb/Target/Target.h"
281b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h"
29c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
306f9e6901SZachary Turner #include "lldb/Utility/Log.h"
31bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
32bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
3330fdc8d8SChris Lattner
34796ac80bSJonas Devlieghere #include <memory>
35796ac80bSJonas Devlieghere
3630fdc8d8SChris Lattner using namespace lldb;
3730fdc8d8SChris Lattner using namespace lldb_private;
38b7234e40SJohnny Chen using namespace llvm;
3930fdc8d8SChris Lattner
GetEventIdentifier()400e4c4821SAdrian Prantl ConstString Breakpoint::GetEventIdentifier() {
4130fdc8d8SChris Lattner static ConstString g_identifier("event-identifier.breakpoint.changed");
4230fdc8d8SChris Lattner return g_identifier;
4330fdc8d8SChris Lattner }
4430fdc8d8SChris Lattner
4592d1960eSJim Ingham const char *Breakpoint::g_option_names[static_cast<uint32_t>(
4692d1960eSJim Ingham Breakpoint::OptionNames::LastOptionName)]{"Names", "Hardware"};
4792d1960eSJim Ingham
4830fdc8d8SChris Lattner // Breakpoint constructor
Breakpoint(Target & target,SearchFilterSP & filter_sp,BreakpointResolverSP & resolver_sp,bool hardware,bool resolve_indirect_symbols)49b9c1b51eSKate Stone Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp,
50b9c1b51eSKate Stone BreakpointResolverSP &resolver_sp, bool hardware,
51b9c1b51eSKate Stone bool resolve_indirect_symbols)
52b9c1b51eSKate Stone : m_being_created(true), m_hardware(hardware), m_target(target),
53cfb96d84SJim Ingham m_filter_sp(filter_sp), m_resolver_sp(resolver_sp), m_options(true),
54cfb96d84SJim Ingham m_locations(*this), m_resolve_indirect_symbols(resolve_indirect_symbols),
55cfb96d84SJim Ingham m_hit_counter() {
56e6bc6cb9SJim Ingham m_being_created = false;
5730fdc8d8SChris Lattner }
5830fdc8d8SChris Lattner
Breakpoint(Target & new_target,const Breakpoint & source_bp)59185ef697STatyana Krasnukha Breakpoint::Breakpoint(Target &new_target, const Breakpoint &source_bp)
60b9c1b51eSKate Stone : m_being_created(true), m_hardware(source_bp.m_hardware),
61b9c1b51eSKate Stone m_target(new_target), m_name_list(source_bp.m_name_list),
62cfb96d84SJim Ingham m_options(source_bp.m_options), m_locations(*this),
63d762df8cSJim Ingham m_resolve_indirect_symbols(source_bp.m_resolve_indirect_symbols),
64da0bba5cSTatyana Krasnukha m_hit_counter() {}
6533df7cd3SJim Ingham
6630fdc8d8SChris Lattner // Destructor
6716fd7511SEugene Zelenko Breakpoint::~Breakpoint() = default;
6830fdc8d8SChris Lattner
CopyFromBreakpoint(TargetSP new_target,const Breakpoint & bp_to_copy_from)69b624b7dfSTatyana Krasnukha BreakpointSP Breakpoint::CopyFromBreakpoint(TargetSP new_target,
70185ef697STatyana Krasnukha const Breakpoint& bp_to_copy_from) {
71b624b7dfSTatyana Krasnukha if (!new_target)
72b624b7dfSTatyana Krasnukha return BreakpointSP();
73b624b7dfSTatyana Krasnukha
74b624b7dfSTatyana Krasnukha BreakpointSP bp(new Breakpoint(*new_target, bp_to_copy_from));
75185ef697STatyana Krasnukha // Now go through and copy the filter & resolver:
766c17cc53STatyana Krasnukha bp->m_resolver_sp = bp_to_copy_from.m_resolver_sp->CopyForBreakpoint(bp);
777fb06796STatyana Krasnukha bp->m_filter_sp = bp_to_copy_from.m_filter_sp->CreateCopy(new_target);
78185ef697STatyana Krasnukha return bp;
79185ef697STatyana Krasnukha }
80185ef697STatyana Krasnukha
81e14dc268SJim Ingham // Serialization
SerializeToStructuredData()82e14dc268SJim Ingham StructuredData::ObjectSP Breakpoint::SerializeToStructuredData() {
83e14dc268SJim Ingham // Serialize the resolver:
84e14dc268SJim Ingham StructuredData::DictionarySP breakpoint_dict_sp(
85e14dc268SJim Ingham new StructuredData::Dictionary());
86e14dc268SJim Ingham StructuredData::DictionarySP breakpoint_contents_sp(
87e14dc268SJim Ingham new StructuredData::Dictionary());
88e14dc268SJim Ingham
8992d1960eSJim Ingham if (!m_name_list.empty()) {
9092d1960eSJim Ingham StructuredData::ArraySP names_array_sp(new StructuredData::Array());
9192d1960eSJim Ingham for (auto name : m_name_list) {
9292d1960eSJim Ingham names_array_sp->AddItem(
9392d1960eSJim Ingham StructuredData::StringSP(new StructuredData::String(name)));
9492d1960eSJim Ingham }
9592d1960eSJim Ingham breakpoint_contents_sp->AddItem(Breakpoint::GetKey(OptionNames::Names),
9692d1960eSJim Ingham names_array_sp);
9792d1960eSJim Ingham }
9892d1960eSJim Ingham
9992d1960eSJim Ingham breakpoint_contents_sp->AddBooleanItem(
10092d1960eSJim Ingham Breakpoint::GetKey(OptionNames::Hardware), m_hardware);
10192d1960eSJim Ingham
102e14dc268SJim Ingham StructuredData::ObjectSP resolver_dict_sp(
103e14dc268SJim Ingham m_resolver_sp->SerializeToStructuredData());
104e14dc268SJim Ingham if (!resolver_dict_sp)
105e14dc268SJim Ingham return StructuredData::ObjectSP();
106e14dc268SJim Ingham
107e14dc268SJim Ingham breakpoint_contents_sp->AddItem(BreakpointResolver::GetSerializationKey(),
108e14dc268SJim Ingham resolver_dict_sp);
109e14dc268SJim Ingham
110e14dc268SJim Ingham StructuredData::ObjectSP filter_dict_sp(
111e14dc268SJim Ingham m_filter_sp->SerializeToStructuredData());
112e14dc268SJim Ingham if (!filter_dict_sp)
113e14dc268SJim Ingham return StructuredData::ObjectSP();
114e14dc268SJim Ingham
115e14dc268SJim Ingham breakpoint_contents_sp->AddItem(SearchFilter::GetSerializationKey(),
116e14dc268SJim Ingham filter_dict_sp);
117e14dc268SJim Ingham
118e14dc268SJim Ingham StructuredData::ObjectSP options_dict_sp(
119cfb96d84SJim Ingham m_options.SerializeToStructuredData());
120e14dc268SJim Ingham if (!options_dict_sp)
121e14dc268SJim Ingham return StructuredData::ObjectSP();
122e14dc268SJim Ingham
123e14dc268SJim Ingham breakpoint_contents_sp->AddItem(BreakpointOptions::GetSerializationKey(),
124e14dc268SJim Ingham options_dict_sp);
125e14dc268SJim Ingham
126e14dc268SJim Ingham breakpoint_dict_sp->AddItem(GetSerializationKey(), breakpoint_contents_sp);
127e14dc268SJim Ingham return breakpoint_dict_sp;
128e14dc268SJim Ingham }
129e14dc268SJim Ingham
CreateFromStructuredData(TargetSP target_sp,StructuredData::ObjectSP & object_data,Status & error)130e14dc268SJim Ingham lldb::BreakpointSP Breakpoint::CreateFromStructuredData(
131b624b7dfSTatyana Krasnukha TargetSP target_sp, StructuredData::ObjectSP &object_data, Status &error) {
132e14dc268SJim Ingham BreakpointSP result_sp;
133b624b7dfSTatyana Krasnukha if (!target_sp)
134b624b7dfSTatyana Krasnukha return result_sp;
135e14dc268SJim Ingham
136e14dc268SJim Ingham StructuredData::Dictionary *breakpoint_dict = object_data->GetAsDictionary();
137e14dc268SJim Ingham
138e14dc268SJim Ingham if (!breakpoint_dict || !breakpoint_dict->IsValid()) {
139e14dc268SJim Ingham error.SetErrorString("Can't deserialize from an invalid data object.");
140e14dc268SJim Ingham return result_sp;
141e14dc268SJim Ingham }
142e14dc268SJim Ingham
143e14dc268SJim Ingham StructuredData::Dictionary *resolver_dict;
144e14dc268SJim Ingham bool success = breakpoint_dict->GetValueForKeyAsDictionary(
145e14dc268SJim Ingham BreakpointResolver::GetSerializationKey(), resolver_dict);
146e14dc268SJim Ingham if (!success) {
14789533764SJonas Devlieghere error.SetErrorString("Breakpoint data missing toplevel resolver key");
148e14dc268SJim Ingham return result_sp;
149e14dc268SJim Ingham }
150e14dc268SJim Ingham
15197206d57SZachary Turner Status create_error;
152e14dc268SJim Ingham BreakpointResolverSP resolver_sp =
153e14dc268SJim Ingham BreakpointResolver::CreateFromStructuredData(*resolver_dict,
154e14dc268SJim Ingham create_error);
155e14dc268SJim Ingham if (create_error.Fail()) {
156e14dc268SJim Ingham error.SetErrorStringWithFormat(
157e14dc268SJim Ingham "Error creating breakpoint resolver from data: %s.",
158e14dc268SJim Ingham create_error.AsCString());
159e14dc268SJim Ingham return result_sp;
160e14dc268SJim Ingham }
161e14dc268SJim Ingham
162e14dc268SJim Ingham StructuredData::Dictionary *filter_dict;
163e14dc268SJim Ingham success = breakpoint_dict->GetValueForKeyAsDictionary(
164e14dc268SJim Ingham SearchFilter::GetSerializationKey(), filter_dict);
165e14dc268SJim Ingham SearchFilterSP filter_sp;
166e14dc268SJim Ingham if (!success)
167b624b7dfSTatyana Krasnukha filter_sp =
168b624b7dfSTatyana Krasnukha std::make_shared<SearchFilterForUnconstrainedSearches>(target_sp);
169e14dc268SJim Ingham else {
170b624b7dfSTatyana Krasnukha filter_sp = SearchFilter::CreateFromStructuredData(target_sp, *filter_dict,
1711a81b273SJim Ingham create_error);
172e14dc268SJim Ingham if (create_error.Fail()) {
173e14dc268SJim Ingham error.SetErrorStringWithFormat(
174e14dc268SJim Ingham "Error creating breakpoint filter from data: %s.",
175e14dc268SJim Ingham create_error.AsCString());
176e14dc268SJim Ingham return result_sp;
177e14dc268SJim Ingham }
178e14dc268SJim Ingham }
179e14dc268SJim Ingham
1801a81b273SJim Ingham std::unique_ptr<BreakpointOptions> options_up;
181e14dc268SJim Ingham StructuredData::Dictionary *options_dict;
182b624b7dfSTatyana Krasnukha Target& target = *target_sp;
183e14dc268SJim Ingham success = breakpoint_dict->GetValueForKeyAsDictionary(
184e14dc268SJim Ingham BreakpointOptions::GetSerializationKey(), options_dict);
185e14dc268SJim Ingham if (success) {
186f7e07256SJim Ingham options_up = BreakpointOptions::CreateFromStructuredData(
187f7e07256SJim Ingham target, *options_dict, create_error);
188e14dc268SJim Ingham if (create_error.Fail()) {
189e14dc268SJim Ingham error.SetErrorStringWithFormat(
190e14dc268SJim Ingham "Error creating breakpoint options from data: %s.",
191e14dc268SJim Ingham create_error.AsCString());
192e14dc268SJim Ingham return result_sp;
193e14dc268SJim Ingham }
194e14dc268SJim Ingham }
19592d1960eSJim Ingham
19692d1960eSJim Ingham bool hardware = false;
19792d1960eSJim Ingham success = breakpoint_dict->GetValueForKeyAsBoolean(
19892d1960eSJim Ingham Breakpoint::GetKey(OptionNames::Hardware), hardware);
19992d1960eSJim Ingham
200b624b7dfSTatyana Krasnukha result_sp = target.CreateBreakpoint(filter_sp, resolver_sp, false,
201b624b7dfSTatyana Krasnukha hardware, true);
20292d1960eSJim Ingham
2031a81b273SJim Ingham if (result_sp && options_up) {
204cfb96d84SJim Ingham result_sp->m_options = *options_up;
205e14dc268SJim Ingham }
20692d1960eSJim Ingham
20792d1960eSJim Ingham StructuredData::Array *names_array;
20892d1960eSJim Ingham success = breakpoint_dict->GetValueForKeyAsArray(
20992d1960eSJim Ingham Breakpoint::GetKey(OptionNames::Names), names_array);
21092d1960eSJim Ingham if (success && names_array) {
21192d1960eSJim Ingham size_t num_names = names_array->GetSize();
21292d1960eSJim Ingham for (size_t i = 0; i < num_names; i++) {
2132833321fSZachary Turner llvm::StringRef name;
21497206d57SZachary Turner Status error;
21592d1960eSJim Ingham success = names_array->GetItemAtIndexAsString(i, name);
216b842f2ecSJim Ingham target.AddNameToBreakpoint(result_sp, name.str().c_str(), error);
21792d1960eSJim Ingham }
21892d1960eSJim Ingham }
21992d1960eSJim Ingham
220e14dc268SJim Ingham return result_sp;
221e14dc268SJim Ingham }
222e14dc268SJim Ingham
SerializedBreakpointMatchesNames(StructuredData::ObjectSP & bkpt_object_sp,std::vector<std::string> & names)2233acdf385SJim Ingham bool Breakpoint::SerializedBreakpointMatchesNames(
2243acdf385SJim Ingham StructuredData::ObjectSP &bkpt_object_sp, std::vector<std::string> &names) {
2253acdf385SJim Ingham if (!bkpt_object_sp)
2263acdf385SJim Ingham return false;
2273acdf385SJim Ingham
2283acdf385SJim Ingham StructuredData::Dictionary *bkpt_dict = bkpt_object_sp->GetAsDictionary();
2293acdf385SJim Ingham if (!bkpt_dict)
2303acdf385SJim Ingham return false;
2313acdf385SJim Ingham
2323acdf385SJim Ingham if (names.empty())
2333acdf385SJim Ingham return true;
2343acdf385SJim Ingham
2353acdf385SJim Ingham StructuredData::Array *names_array;
2363acdf385SJim Ingham
2373acdf385SJim Ingham bool success =
2383acdf385SJim Ingham bkpt_dict->GetValueForKeyAsArray(GetKey(OptionNames::Names), names_array);
2393acdf385SJim Ingham // If there are no names, it can't match these names;
2403acdf385SJim Ingham if (!success)
2413acdf385SJim Ingham return false;
2423acdf385SJim Ingham
2433acdf385SJim Ingham size_t num_names = names_array->GetSize();
2443acdf385SJim Ingham
2453acdf385SJim Ingham for (size_t i = 0; i < num_names; i++) {
2462833321fSZachary Turner llvm::StringRef name;
2473acdf385SJim Ingham if (names_array->GetItemAtIndexAsString(i, name)) {
2488af160b0SRaphael Isemann if (llvm::is_contained(names, name))
2493acdf385SJim Ingham return true;
2503acdf385SJim Ingham }
2513acdf385SJim Ingham }
2523acdf385SJim Ingham return false;
2533acdf385SJim Ingham }
2543acdf385SJim Ingham
GetTargetSP()255b9c1b51eSKate Stone const lldb::TargetSP Breakpoint::GetTargetSP() {
25633df7cd3SJim Ingham return m_target.shared_from_this();
25733df7cd3SJim Ingham }
25833df7cd3SJim Ingham
IsInternal() const259b9c1b51eSKate Stone bool Breakpoint::IsInternal() const { return LLDB_BREAK_ID_IS_INTERNAL(m_bid); }
260b9c1b51eSKate Stone
AddLocation(const Address & addr,bool * new_location)261b9c1b51eSKate Stone BreakpointLocationSP Breakpoint::AddLocation(const Address &addr,
262b9c1b51eSKate Stone bool *new_location) {
263b9c1b51eSKate Stone return m_locations.AddLocation(addr, m_resolve_indirect_symbols,
264b9c1b51eSKate Stone new_location);
26530fdc8d8SChris Lattner }
26630fdc8d8SChris Lattner
FindLocationByAddress(const Address & addr)267b9c1b51eSKate Stone BreakpointLocationSP Breakpoint::FindLocationByAddress(const Address &addr) {
26830fdc8d8SChris Lattner return m_locations.FindByAddress(addr);
26930fdc8d8SChris Lattner }
27030fdc8d8SChris Lattner
FindLocationIDByAddress(const Address & addr)271b9c1b51eSKate Stone break_id_t Breakpoint::FindLocationIDByAddress(const Address &addr) {
27230fdc8d8SChris Lattner return m_locations.FindIDByAddress(addr);
27330fdc8d8SChris Lattner }
27430fdc8d8SChris Lattner
FindLocationByID(break_id_t bp_loc_id)275b9c1b51eSKate Stone BreakpointLocationSP Breakpoint::FindLocationByID(break_id_t bp_loc_id) {
27630fdc8d8SChris Lattner return m_locations.FindByID(bp_loc_id);
27730fdc8d8SChris Lattner }
27830fdc8d8SChris Lattner
GetLocationAtIndex(size_t index)279b9c1b51eSKate Stone BreakpointLocationSP Breakpoint::GetLocationAtIndex(size_t index) {
28030fdc8d8SChris Lattner return m_locations.GetByIndex(index);
28130fdc8d8SChris Lattner }
28230fdc8d8SChris Lattner
RemoveInvalidLocations(const ArchSpec & arch)283b9c1b51eSKate Stone void Breakpoint::RemoveInvalidLocations(const ArchSpec &arch) {
284b35db639SGreg Clayton m_locations.RemoveInvalidLocations(arch);
285b35db639SGreg Clayton }
286b35db639SGreg Clayton
28705097246SAdrian Prantl // For each of the overall options we need to decide how they propagate to the
28805097246SAdrian Prantl // location options. This will determine the precedence of options on the
28905097246SAdrian Prantl // breakpoint vs. its locations.
29030fdc8d8SChris Lattner
29105097246SAdrian Prantl // Disable at the breakpoint level should override the location settings. That
29205097246SAdrian Prantl // way you can conveniently turn off a whole breakpoint without messing up the
29305097246SAdrian Prantl // individual settings.
29430fdc8d8SChris Lattner
SetEnabled(bool enable)295b9c1b51eSKate Stone void Breakpoint::SetEnabled(bool enable) {
296cfb96d84SJim Ingham if (enable == m_options.IsEnabled())
297e6bc6cb9SJim Ingham return;
298e6bc6cb9SJim Ingham
299cfb96d84SJim Ingham m_options.SetEnabled(enable);
30030fdc8d8SChris Lattner if (enable)
30130fdc8d8SChris Lattner m_locations.ResolveAllBreakpointSites();
30230fdc8d8SChris Lattner else
30330fdc8d8SChris Lattner m_locations.ClearAllBreakpointSites();
304e6bc6cb9SJim Ingham
305b9c1b51eSKate Stone SendBreakpointChangedEvent(enable ? eBreakpointEventTypeEnabled
306b9c1b51eSKate Stone : eBreakpointEventTypeDisabled);
30730fdc8d8SChris Lattner }
30830fdc8d8SChris Lattner
IsEnabled()309cfb96d84SJim Ingham bool Breakpoint::IsEnabled() { return m_options.IsEnabled(); }
31030fdc8d8SChris Lattner
SetIgnoreCount(uint32_t n)311b9c1b51eSKate Stone void Breakpoint::SetIgnoreCount(uint32_t n) {
312cfb96d84SJim Ingham if (m_options.GetIgnoreCount() == n)
313e6bc6cb9SJim Ingham return;
314e6bc6cb9SJim Ingham
315cfb96d84SJim Ingham m_options.SetIgnoreCount(n);
316e6bc6cb9SJim Ingham SendBreakpointChangedEvent(eBreakpointEventTypeIgnoreChanged);
31730fdc8d8SChris Lattner }
31830fdc8d8SChris Lattner
DecrementIgnoreCount()319b9c1b51eSKate Stone void Breakpoint::DecrementIgnoreCount() {
320cfb96d84SJim Ingham uint32_t ignore = m_options.GetIgnoreCount();
3210fd1b75fSJim Ingham if (ignore != 0)
322cfb96d84SJim Ingham m_options.SetIgnoreCount(ignore - 1);
3230fd1b75fSJim Ingham }
3240fd1b75fSJim Ingham
GetIgnoreCount() const325b9c1b51eSKate Stone uint32_t Breakpoint::GetIgnoreCount() const {
326cfb96d84SJim Ingham return m_options.GetIgnoreCount();
32730fdc8d8SChris Lattner }
32830fdc8d8SChris Lattner
GetHitCount() const329da0bba5cSTatyana Krasnukha uint32_t Breakpoint::GetHitCount() const { return m_hit_counter.GetValue(); }
3309fed0d85SGreg Clayton
IsOneShot() const331cfb96d84SJim Ingham bool Breakpoint::IsOneShot() const { return m_options.IsOneShot(); }
332ca36cd16SJim Ingham
SetOneShot(bool one_shot)333cfb96d84SJim Ingham void Breakpoint::SetOneShot(bool one_shot) { m_options.SetOneShot(one_shot); }
334ca36cd16SJim Ingham
IsAutoContinue() const335cfb96d84SJim Ingham bool Breakpoint::IsAutoContinue() const { return m_options.IsAutoContinue(); }
336f08f5c99SJim Ingham
SetAutoContinue(bool auto_continue)337f08f5c99SJim Ingham void Breakpoint::SetAutoContinue(bool auto_continue) {
338cfb96d84SJim Ingham m_options.SetAutoContinue(auto_continue);
339f08f5c99SJim Ingham }
340f08f5c99SJim Ingham
SetThreadID(lldb::tid_t thread_id)341b9c1b51eSKate Stone void Breakpoint::SetThreadID(lldb::tid_t thread_id) {
342cfb96d84SJim Ingham if (m_options.GetThreadSpec()->GetTID() == thread_id)
343e6bc6cb9SJim Ingham return;
344e6bc6cb9SJim Ingham
345cfb96d84SJim Ingham m_options.GetThreadSpec()->SetTID(thread_id);
346e6bc6cb9SJim Ingham SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
34730fdc8d8SChris Lattner }
34830fdc8d8SChris Lattner
GetThreadID() const349b9c1b51eSKate Stone lldb::tid_t Breakpoint::GetThreadID() const {
350cfb96d84SJim Ingham if (m_options.GetThreadSpecNoCreate() == nullptr)
3511b54c88cSJim Ingham return LLDB_INVALID_THREAD_ID;
3521b54c88cSJim Ingham else
353cfb96d84SJim Ingham return m_options.GetThreadSpecNoCreate()->GetTID();
354e6bc6cb9SJim Ingham }
355e6bc6cb9SJim Ingham
SetThreadIndex(uint32_t index)356b9c1b51eSKate Stone void Breakpoint::SetThreadIndex(uint32_t index) {
357cfb96d84SJim Ingham if (m_options.GetThreadSpec()->GetIndex() == index)
358e6bc6cb9SJim Ingham return;
359e6bc6cb9SJim Ingham
360cfb96d84SJim Ingham m_options.GetThreadSpec()->SetIndex(index);
361e6bc6cb9SJim Ingham SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
362e6bc6cb9SJim Ingham }
363e6bc6cb9SJim Ingham
GetThreadIndex() const364b9c1b51eSKate Stone uint32_t Breakpoint::GetThreadIndex() const {
365cfb96d84SJim Ingham if (m_options.GetThreadSpecNoCreate() == nullptr)
366e6bc6cb9SJim Ingham return 0;
367e6bc6cb9SJim Ingham else
368cfb96d84SJim Ingham return m_options.GetThreadSpecNoCreate()->GetIndex();
369e6bc6cb9SJim Ingham }
370e6bc6cb9SJim Ingham
SetThreadName(const char * thread_name)371b9c1b51eSKate Stone void Breakpoint::SetThreadName(const char *thread_name) {
372cfb96d84SJim Ingham if (m_options.GetThreadSpec()->GetName() != nullptr &&
373cfb96d84SJim Ingham ::strcmp(m_options.GetThreadSpec()->GetName(), thread_name) == 0)
374e6bc6cb9SJim Ingham return;
375e6bc6cb9SJim Ingham
376cfb96d84SJim Ingham m_options.GetThreadSpec()->SetName(thread_name);
377e6bc6cb9SJim Ingham SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
378e6bc6cb9SJim Ingham }
379e6bc6cb9SJim Ingham
GetThreadName() const380b9c1b51eSKate Stone const char *Breakpoint::GetThreadName() const {
381cfb96d84SJim Ingham if (m_options.GetThreadSpecNoCreate() == nullptr)
38216fd7511SEugene Zelenko return nullptr;
383e6bc6cb9SJim Ingham else
384cfb96d84SJim Ingham return m_options.GetThreadSpecNoCreate()->GetName();
385e6bc6cb9SJim Ingham }
386e6bc6cb9SJim Ingham
SetQueueName(const char * queue_name)387b9c1b51eSKate Stone void Breakpoint::SetQueueName(const char *queue_name) {
388cfb96d84SJim Ingham if (m_options.GetThreadSpec()->GetQueueName() != nullptr &&
389cfb96d84SJim Ingham ::strcmp(m_options.GetThreadSpec()->GetQueueName(), queue_name) == 0)
390e6bc6cb9SJim Ingham return;
391e6bc6cb9SJim Ingham
392cfb96d84SJim Ingham m_options.GetThreadSpec()->SetQueueName(queue_name);
393e6bc6cb9SJim Ingham SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
394e6bc6cb9SJim Ingham }
395e6bc6cb9SJim Ingham
GetQueueName() const396b9c1b51eSKate Stone const char *Breakpoint::GetQueueName() const {
397cfb96d84SJim Ingham if (m_options.GetThreadSpecNoCreate() == nullptr)
39816fd7511SEugene Zelenko return nullptr;
399e6bc6cb9SJim Ingham else
400cfb96d84SJim Ingham return m_options.GetThreadSpecNoCreate()->GetQueueName();
40130fdc8d8SChris Lattner }
40230fdc8d8SChris Lattner
SetCondition(const char * condition)403b9c1b51eSKate Stone void Breakpoint::SetCondition(const char *condition) {
404cfb96d84SJim Ingham m_options.SetCondition(condition);
405e6bc6cb9SJim Ingham SendBreakpointChangedEvent(eBreakpointEventTypeConditionChanged);
40636f3b369SJim Ingham }
40736f3b369SJim Ingham
GetConditionText() const408b9c1b51eSKate Stone const char *Breakpoint::GetConditionText() const {
409cfb96d84SJim Ingham return m_options.GetConditionText();
41036f3b369SJim Ingham }
41136f3b369SJim Ingham
41230fdc8d8SChris Lattner // This function is used when "baton" doesn't need to be freed
SetCallback(BreakpointHitCallback callback,void * baton,bool is_synchronous)413b9c1b51eSKate Stone void Breakpoint::SetCallback(BreakpointHitCallback callback, void *baton,
414b9c1b51eSKate Stone bool is_synchronous) {
41505097246SAdrian Prantl // The default "Baton" class will keep a copy of "baton" and won't free or
41605097246SAdrian Prantl // delete it when it goes goes out of scope.
417cfb96d84SJim Ingham m_options.SetCallback(callback, std::make_shared<UntypedBaton>(baton),
418e14dc268SJim Ingham is_synchronous);
419e6bc6cb9SJim Ingham
420e6bc6cb9SJim Ingham SendBreakpointChangedEvent(eBreakpointEventTypeCommandChanged);
42130fdc8d8SChris Lattner }
42230fdc8d8SChris Lattner
42330fdc8d8SChris Lattner // This function is used when a baton needs to be freed and therefore is
42430fdc8d8SChris Lattner // contained in a "Baton" subclass.
SetCallback(BreakpointHitCallback callback,const BatonSP & callback_baton_sp,bool is_synchronous)425b9c1b51eSKate Stone void Breakpoint::SetCallback(BreakpointHitCallback callback,
426b9c1b51eSKate Stone const BatonSP &callback_baton_sp,
427b9c1b51eSKate Stone bool is_synchronous) {
428cfb96d84SJim Ingham m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
42930fdc8d8SChris Lattner }
43030fdc8d8SChris Lattner
ClearCallback()431cfb96d84SJim Ingham void Breakpoint::ClearCallback() { m_options.ClearCallback(); }
43230fdc8d8SChris Lattner
InvokeCallback(StoppointCallbackContext * context,break_id_t bp_loc_id)433b9c1b51eSKate Stone bool Breakpoint::InvokeCallback(StoppointCallbackContext *context,
434b9c1b51eSKate Stone break_id_t bp_loc_id) {
435cfb96d84SJim Ingham return m_options.InvokeCallback(context, GetID(), bp_loc_id);
43630fdc8d8SChris Lattner }
43730fdc8d8SChris Lattner
GetOptions()438cfb96d84SJim Ingham BreakpointOptions &Breakpoint::GetOptions() { return m_options; }
43930fdc8d8SChris Lattner
GetOptions() const440cfb96d84SJim Ingham const BreakpointOptions &Breakpoint::GetOptions() const { return m_options; }
441b842f2ecSJim Ingham
ResolveBreakpoint()442b9c1b51eSKate Stone void Breakpoint::ResolveBreakpoint() {
443fb254968SGreg Clayton if (m_resolver_sp) {
444fb254968SGreg Clayton ElapsedTime elapsed(m_resolve_time);
44530fdc8d8SChris Lattner m_resolver_sp->ResolveBreakpoint(*m_filter_sp);
44630fdc8d8SChris Lattner }
447fb254968SGreg Clayton }
44830fdc8d8SChris Lattner
ResolveBreakpointInModules(ModuleList & module_list,BreakpointLocationCollection & new_locations)449b9c1b51eSKate Stone void Breakpoint::ResolveBreakpointInModules(
450b9c1b51eSKate Stone ModuleList &module_list, BreakpointLocationCollection &new_locations) {
451fb254968SGreg Clayton ElapsedTime elapsed(m_resolve_time);
45277fd738fSJim Ingham m_locations.StartRecordingNewLocations(new_locations);
45377fd738fSJim Ingham
45477fd738fSJim Ingham m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
45577fd738fSJim Ingham
45677fd738fSJim Ingham m_locations.StopRecordingNewLocations();
45777fd738fSJim Ingham }
45877fd738fSJim Ingham
ResolveBreakpointInModules(ModuleList & module_list,bool send_event)459b9c1b51eSKate Stone void Breakpoint::ResolveBreakpointInModules(ModuleList &module_list,
460b9c1b51eSKate Stone bool send_event) {
461b9c1b51eSKate Stone if (m_resolver_sp) {
462b9c1b51eSKate Stone // If this is not an internal breakpoint, set up to record the new
46305097246SAdrian Prantl // locations, then dispatch an event with the new locations.
464b9c1b51eSKate Stone if (!IsInternal() && send_event) {
465b9c1b51eSKate Stone BreakpointEventData *new_locations_event = new BreakpointEventData(
466b9c1b51eSKate Stone eBreakpointEventTypeLocationsAdded, shared_from_this());
46777fd738fSJim Ingham
468b9c1b51eSKate Stone ResolveBreakpointInModules(
469b9c1b51eSKate Stone module_list, new_locations_event->GetBreakpointLocationCollection());
47077fd738fSJim Ingham
471b9c1b51eSKate Stone if (new_locations_event->GetBreakpointLocationCollection().GetSize() !=
472b9c1b51eSKate Stone 0) {
47377fd738fSJim Ingham SendBreakpointChangedEvent(new_locations_event);
474b9c1b51eSKate Stone } else
47577fd738fSJim Ingham delete new_locations_event;
476b9c1b51eSKate Stone } else {
477fb254968SGreg Clayton ElapsedTime elapsed(m_resolve_time);
47830fdc8d8SChris Lattner m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
47930fdc8d8SChris Lattner }
48077fd738fSJim Ingham }
48177fd738fSJim Ingham }
48230fdc8d8SChris Lattner
ClearAllBreakpointSites()483b9c1b51eSKate Stone void Breakpoint::ClearAllBreakpointSites() {
48430fdc8d8SChris Lattner m_locations.ClearAllBreakpointSites();
48530fdc8d8SChris Lattner }
48630fdc8d8SChris Lattner
48730fdc8d8SChris Lattner // ModulesChanged: Pass in a list of new modules, and
48830fdc8d8SChris Lattner
ModulesChanged(ModuleList & module_list,bool load,bool delete_locations)489b9c1b51eSKate Stone void Breakpoint::ModulesChanged(ModuleList &module_list, bool load,
490b9c1b51eSKate Stone bool delete_locations) {
491a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Breakpoints);
49263e5fb76SJonas Devlieghere LLDB_LOGF(log,
49363e5fb76SJonas Devlieghere "Breakpoint::ModulesChanged: num_modules: %zu load: %i "
494b9c1b51eSKate Stone "delete_locations: %i\n",
49577fd738fSJim Ingham module_list.GetSize(), load, delete_locations);
49677fd738fSJim Ingham
497b9c1b51eSKate Stone if (load) {
49830fdc8d8SChris Lattner // The logic for handling new modules is:
49905097246SAdrian Prantl // 1) If the filter rejects this module, then skip it. 2) Run through the
50005097246SAdrian Prantl // current location list and if there are any locations
501b9c1b51eSKate Stone // for that module, we mark the module as "seen" and we don't try to
502b9c1b51eSKate Stone // re-resolve
50330fdc8d8SChris Lattner // breakpoint locations for that module.
50430fdc8d8SChris Lattner // However, we do add breakpoint sites to these locations if needed.
505b9c1b51eSKate Stone // 3) If we don't see this module in our breakpoint location list, call
506b9c1b51eSKate Stone // ResolveInModules.
50730fdc8d8SChris Lattner
508b9c1b51eSKate Stone ModuleList new_modules; // We'll stuff the "unseen" modules in this list,
509b9c1b51eSKate Stone // and then resolve
51005097246SAdrian Prantl // them after the locations pass. Have to do it this way because resolving
51105097246SAdrian Prantl // breakpoints will add new locations potentially.
51230fdc8d8SChris Lattner
513f2e05855SJonas Devlieghere for (ModuleSP module_sp : module_list.Modules()) {
51430fdc8d8SChris Lattner bool seen = false;
51530fdc8d8SChris Lattner if (!m_filter_sp->ModulePasses(module_sp))
51630fdc8d8SChris Lattner continue;
51730fdc8d8SChris Lattner
5185ec7cd72SJim Ingham BreakpointLocationCollection locations_with_no_section;
519b9c1b51eSKate Stone for (BreakpointLocationSP break_loc_sp :
520b9c1b51eSKate Stone m_locations.BreakpointLocations()) {
5215ec7cd72SJim Ingham
52205097246SAdrian Prantl // If the section for this location was deleted, that means it's Module
52305097246SAdrian Prantl // has gone away but somebody forgot to tell us. Let's clean it up
52405097246SAdrian Prantl // here.
5255ec7cd72SJim Ingham Address section_addr(break_loc_sp->GetAddress());
5265ec7cd72SJim Ingham if (section_addr.SectionWasDeleted()) {
5275ec7cd72SJim Ingham locations_with_no_section.Add(break_loc_sp);
5285ec7cd72SJim Ingham continue;
5295ec7cd72SJim Ingham }
5305ec7cd72SJim Ingham
53177fd738fSJim Ingham if (!break_loc_sp->IsEnabled())
532d4ce0a15SJim Ingham continue;
5335ec7cd72SJim Ingham
5345ec7cd72SJim Ingham SectionSP section_sp(section_addr.GetSection());
5355ec7cd72SJim Ingham
53605097246SAdrian Prantl // If we don't have a Section, that means this location is a raw
53705097246SAdrian Prantl // address that we haven't resolved to a section yet. So we'll have to
53805097246SAdrian Prantl // look in all the new modules to resolve this location. Otherwise, if
53905097246SAdrian Prantl // it was set in this module, re-resolve it here.
540ae3f793eSDavide Italiano if (section_sp && section_sp->GetModule() == module_sp) {
54130fdc8d8SChris Lattner if (!seen)
54230fdc8d8SChris Lattner seen = true;
54330fdc8d8SChris Lattner
544b9c1b51eSKate Stone if (!break_loc_sp->ResolveBreakpointSite()) {
54563e5fb76SJonas Devlieghere LLDB_LOGF(log,
54663e5fb76SJonas Devlieghere "Warning: could not set breakpoint site for "
547b9c1b51eSKate Stone "breakpoint location %d of breakpoint %d.\n",
54877fd738fSJim Ingham break_loc_sp->GetID(), GetID());
54930fdc8d8SChris Lattner }
55030fdc8d8SChris Lattner }
55130fdc8d8SChris Lattner }
55230fdc8d8SChris Lattner
5535ec7cd72SJim Ingham size_t num_to_delete = locations_with_no_section.GetSize();
5545ec7cd72SJim Ingham
5555ec7cd72SJim Ingham for (size_t i = 0; i < num_to_delete; i++)
5565ec7cd72SJim Ingham m_locations.RemoveLocation(locations_with_no_section.GetByIndex(i));
5575ec7cd72SJim Ingham
55830fdc8d8SChris Lattner if (!seen)
5597d07a45fSGreg Clayton new_modules.AppendIfNeeded(module_sp);
56030fdc8d8SChris Lattner }
561e6bc6cb9SJim Ingham
562b9c1b51eSKate Stone if (new_modules.GetSize() > 0) {
56330fdc8d8SChris Lattner ResolveBreakpointInModules(new_modules);
56430fdc8d8SChris Lattner }
565b9c1b51eSKate Stone } else {
56630fdc8d8SChris Lattner // Go through the currently set locations and if any have breakpoints in
567b9c1b51eSKate Stone // the module list, then remove their breakpoint sites, and their locations
568b9c1b51eSKate Stone // if asked to.
56930fdc8d8SChris Lattner
570e6bc6cb9SJim Ingham BreakpointEventData *removed_locations_event;
571e6bc6cb9SJim Ingham if (!IsInternal())
572b9c1b51eSKate Stone removed_locations_event = new BreakpointEventData(
573b9c1b51eSKate Stone eBreakpointEventTypeLocationsRemoved, shared_from_this());
574e6bc6cb9SJim Ingham else
57516fd7511SEugene Zelenko removed_locations_event = nullptr;
576e6bc6cb9SJim Ingham
577f2e05855SJonas Devlieghere for (ModuleSP module_sp : module_list.Modules()) {
578b9c1b51eSKate Stone if (m_filter_sp->ModulePasses(module_sp)) {
579e72dfb32SGreg Clayton size_t loc_idx = 0;
5804a94c910SJim Ingham size_t num_locations = m_locations.GetSize();
5814a94c910SJim Ingham BreakpointLocationCollection locations_to_remove;
582b9c1b51eSKate Stone for (loc_idx = 0; loc_idx < num_locations; loc_idx++) {
583e72dfb32SGreg Clayton BreakpointLocationSP break_loc_sp(m_locations.GetByIndex(loc_idx));
584e72dfb32SGreg Clayton SectionSP section_sp(break_loc_sp->GetAddress().GetSection());
585b9c1b51eSKate Stone if (section_sp && section_sp->GetModule() == module_sp) {
58605097246SAdrian Prantl // Remove this breakpoint since the shared library is unloaded, but
58705097246SAdrian Prantl // keep the breakpoint location around so we always get complete
58805097246SAdrian Prantl // hit count and breakpoint lifetime info
589e72dfb32SGreg Clayton break_loc_sp->ClearBreakpointSite();
590b9c1b51eSKate Stone if (removed_locations_event) {
591b9c1b51eSKate Stone removed_locations_event->GetBreakpointLocationCollection().Add(
592b9c1b51eSKate Stone break_loc_sp);
59330fdc8d8SChris Lattner }
5944a94c910SJim Ingham if (delete_locations)
5954a94c910SJim Ingham locations_to_remove.Add(break_loc_sp);
596a4d78300SGreg Clayton }
5974a94c910SJim Ingham }
5984a94c910SJim Ingham
599b9c1b51eSKate Stone if (delete_locations) {
6004a94c910SJim Ingham size_t num_locations_to_remove = locations_to_remove.GetSize();
6014a94c910SJim Ingham for (loc_idx = 0; loc_idx < num_locations_to_remove; loc_idx++)
6024a94c910SJim Ingham m_locations.RemoveLocation(locations_to_remove.GetByIndex(loc_idx));
60330fdc8d8SChris Lattner }
60430fdc8d8SChris Lattner }
60530fdc8d8SChris Lattner }
606e6bc6cb9SJim Ingham SendBreakpointChangedEvent(removed_locations_event);
607e6bc6cb9SJim Ingham }
60830fdc8d8SChris Lattner }
60930fdc8d8SChris Lattner
SymbolContextsMightBeEquivalent(SymbolContext & old_sc,SymbolContext & new_sc)610b9c1b51eSKate Stone static bool SymbolContextsMightBeEquivalent(SymbolContext &old_sc,
611b9c1b51eSKate Stone SymbolContext &new_sc) {
61277fd738fSJim Ingham bool equivalent_scs = false;
61377fd738fSJim Ingham
614b9c1b51eSKate Stone if (old_sc.module_sp.get() == new_sc.module_sp.get()) {
61505097246SAdrian Prantl // If these come from the same module, we can directly compare the
61605097246SAdrian Prantl // pointers:
617b9c1b51eSKate Stone if (old_sc.comp_unit && new_sc.comp_unit &&
618b9c1b51eSKate Stone (old_sc.comp_unit == new_sc.comp_unit)) {
619b9c1b51eSKate Stone if (old_sc.function && new_sc.function &&
620b9c1b51eSKate Stone (old_sc.function == new_sc.function)) {
62177fd738fSJim Ingham equivalent_scs = true;
62277fd738fSJim Ingham }
623b9c1b51eSKate Stone } else if (old_sc.symbol && new_sc.symbol &&
624b9c1b51eSKate Stone (old_sc.symbol == new_sc.symbol)) {
62577fd738fSJim Ingham equivalent_scs = true;
62677fd738fSJim Ingham }
627b9c1b51eSKate Stone } else {
62877fd738fSJim Ingham // Otherwise we will compare by name...
629b9c1b51eSKate Stone if (old_sc.comp_unit && new_sc.comp_unit) {
630532290e6SPavel Labath if (old_sc.comp_unit->GetPrimaryFile() ==
631532290e6SPavel Labath new_sc.comp_unit->GetPrimaryFile()) {
63277fd738fSJim Ingham // Now check the functions:
633b9c1b51eSKate Stone if (old_sc.function && new_sc.function &&
634b9c1b51eSKate Stone (old_sc.function->GetName() == new_sc.function->GetName())) {
63577fd738fSJim Ingham equivalent_scs = true;
63677fd738fSJim Ingham }
63777fd738fSJim Ingham }
638b9c1b51eSKate Stone } else if (old_sc.symbol && new_sc.symbol) {
639b9c1b51eSKate Stone if (Mangled::Compare(old_sc.symbol->GetMangled(),
640b9c1b51eSKate Stone new_sc.symbol->GetMangled()) == 0) {
64177fd738fSJim Ingham equivalent_scs = true;
64277fd738fSJim Ingham }
64377fd738fSJim Ingham }
64477fd738fSJim Ingham }
64577fd738fSJim Ingham return equivalent_scs;
64677fd738fSJim Ingham }
64777fd738fSJim Ingham
ModuleReplaced(ModuleSP old_module_sp,ModuleSP new_module_sp)648b9c1b51eSKate Stone void Breakpoint::ModuleReplaced(ModuleSP old_module_sp,
649b9c1b51eSKate Stone ModuleSP new_module_sp) {
650a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Breakpoints);
65163e5fb76SJonas Devlieghere LLDB_LOGF(log, "Breakpoint::ModulesReplaced for %s\n",
65277fd738fSJim Ingham old_module_sp->GetSpecificationDescription().c_str());
65377fd738fSJim Ingham // First find all the locations that are in the old module
65477fd738fSJim Ingham
65577fd738fSJim Ingham BreakpointLocationCollection old_break_locs;
656b9c1b51eSKate Stone for (BreakpointLocationSP break_loc_sp : m_locations.BreakpointLocations()) {
65777fd738fSJim Ingham SectionSP section_sp = break_loc_sp->GetAddress().GetSection();
658b9c1b51eSKate Stone if (section_sp && section_sp->GetModule() == old_module_sp) {
65977fd738fSJim Ingham old_break_locs.Add(break_loc_sp);
66077fd738fSJim Ingham }
66177fd738fSJim Ingham }
66277fd738fSJim Ingham
66377fd738fSJim Ingham size_t num_old_locations = old_break_locs.GetSize();
66477fd738fSJim Ingham
665b9c1b51eSKate Stone if (num_old_locations == 0) {
666b9c1b51eSKate Stone // There were no locations in the old module, so we just need to check if
667b9c1b51eSKate Stone // there were any in the new module.
6684a94c910SJim Ingham ModuleList temp_list;
6694a94c910SJim Ingham temp_list.Append(new_module_sp);
67077fd738fSJim Ingham ResolveBreakpointInModules(temp_list);
671b9c1b51eSKate Stone } else {
67205097246SAdrian Prantl // First search the new module for locations. Then compare this with the
67305097246SAdrian Prantl // old list, copy over locations that "look the same" Then delete the old
67405097246SAdrian Prantl // locations. Finally remember to post the creation event.
67577fd738fSJim Ingham //
67605097246SAdrian Prantl // Two locations are the same if they have the same comp unit & function
67705097246SAdrian Prantl // (by name) and there are the same number of locations in the old function
67805097246SAdrian Prantl // as in the new one.
6794a94c910SJim Ingham
68077fd738fSJim Ingham ModuleList temp_list;
68177fd738fSJim Ingham temp_list.Append(new_module_sp);
68277fd738fSJim Ingham BreakpointLocationCollection new_break_locs;
68377fd738fSJim Ingham ResolveBreakpointInModules(temp_list, new_break_locs);
68477fd738fSJim Ingham BreakpointLocationCollection locations_to_remove;
68577fd738fSJim Ingham BreakpointLocationCollection locations_to_announce;
6864a94c910SJim Ingham
68777fd738fSJim Ingham size_t num_new_locations = new_break_locs.GetSize();
68877fd738fSJim Ingham
689b9c1b51eSKate Stone if (num_new_locations > 0) {
690b9c1b51eSKate Stone // Break out the case of one location -> one location since that's the
69105097246SAdrian Prantl // most common one, and there's no need to build up the structures needed
69205097246SAdrian Prantl // for the merge in that case.
693b9c1b51eSKate Stone if (num_new_locations == 1 && num_old_locations == 1) {
69477fd738fSJim Ingham bool equivalent_locations = false;
69577fd738fSJim Ingham SymbolContext old_sc, new_sc;
696b9c1b51eSKate Stone // The only way the old and new location can be equivalent is if they
697b9c1b51eSKate Stone // have the same amount of information:
69877fd738fSJim Ingham BreakpointLocationSP old_loc_sp = old_break_locs.GetByIndex(0);
69977fd738fSJim Ingham BreakpointLocationSP new_loc_sp = new_break_locs.GetByIndex(0);
70077fd738fSJim Ingham
701b9c1b51eSKate Stone if (old_loc_sp->GetAddress().CalculateSymbolContext(&old_sc) ==
702b9c1b51eSKate Stone new_loc_sp->GetAddress().CalculateSymbolContext(&new_sc)) {
703b9c1b51eSKate Stone equivalent_locations =
704b9c1b51eSKate Stone SymbolContextsMightBeEquivalent(old_sc, new_sc);
70577fd738fSJim Ingham }
70677fd738fSJim Ingham
707b9c1b51eSKate Stone if (equivalent_locations) {
70877fd738fSJim Ingham m_locations.SwapLocation(old_loc_sp, new_loc_sp);
709b9c1b51eSKate Stone } else {
71077fd738fSJim Ingham locations_to_remove.Add(old_loc_sp);
71177fd738fSJim Ingham locations_to_announce.Add(new_loc_sp);
71277fd738fSJim Ingham }
713b9c1b51eSKate Stone } else {
714b9c1b51eSKate Stone // We don't want to have to keep computing the SymbolContexts for these
71505097246SAdrian Prantl // addresses over and over, so lets get them up front:
71677fd738fSJim Ingham
71777fd738fSJim Ingham typedef std::map<lldb::break_id_t, SymbolContext> IDToSCMap;
71877fd738fSJim Ingham IDToSCMap old_sc_map;
719b9c1b51eSKate Stone for (size_t idx = 0; idx < num_old_locations; idx++) {
72077fd738fSJim Ingham SymbolContext sc;
72177fd738fSJim Ingham BreakpointLocationSP bp_loc_sp = old_break_locs.GetByIndex(idx);
72277fd738fSJim Ingham lldb::break_id_t loc_id = bp_loc_sp->GetID();
72377fd738fSJim Ingham bp_loc_sp->GetAddress().CalculateSymbolContext(&old_sc_map[loc_id]);
72477fd738fSJim Ingham }
72577fd738fSJim Ingham
72677fd738fSJim Ingham std::map<lldb::break_id_t, SymbolContext> new_sc_map;
727b9c1b51eSKate Stone for (size_t idx = 0; idx < num_new_locations; idx++) {
72877fd738fSJim Ingham SymbolContext sc;
72977fd738fSJim Ingham BreakpointLocationSP bp_loc_sp = new_break_locs.GetByIndex(idx);
73077fd738fSJim Ingham lldb::break_id_t loc_id = bp_loc_sp->GetID();
73177fd738fSJim Ingham bp_loc_sp->GetAddress().CalculateSymbolContext(&new_sc_map[loc_id]);
73277fd738fSJim Ingham }
73377fd738fSJim Ingham // Take an element from the old Symbol Contexts
734b9c1b51eSKate Stone while (old_sc_map.size() > 0) {
73577fd738fSJim Ingham lldb::break_id_t old_id = old_sc_map.begin()->first;
73677fd738fSJim Ingham SymbolContext &old_sc = old_sc_map.begin()->second;
73777fd738fSJim Ingham
73805097246SAdrian Prantl // Count the number of entries equivalent to this SC for the old
73905097246SAdrian Prantl // list:
74077fd738fSJim Ingham std::vector<lldb::break_id_t> old_id_vec;
74177fd738fSJim Ingham old_id_vec.push_back(old_id);
74277fd738fSJim Ingham
74377fd738fSJim Ingham IDToSCMap::iterator tmp_iter;
744b9c1b51eSKate Stone for (tmp_iter = ++old_sc_map.begin(); tmp_iter != old_sc_map.end();
745b9c1b51eSKate Stone tmp_iter++) {
74677fd738fSJim Ingham if (SymbolContextsMightBeEquivalent(old_sc, tmp_iter->second))
74777fd738fSJim Ingham old_id_vec.push_back(tmp_iter->first);
74877fd738fSJim Ingham }
74977fd738fSJim Ingham
75077fd738fSJim Ingham // Now find all the equivalent locations in the new list.
75177fd738fSJim Ingham std::vector<lldb::break_id_t> new_id_vec;
752b9c1b51eSKate Stone for (tmp_iter = new_sc_map.begin(); tmp_iter != new_sc_map.end();
753b9c1b51eSKate Stone tmp_iter++) {
75477fd738fSJim Ingham if (SymbolContextsMightBeEquivalent(old_sc, tmp_iter->second))
75577fd738fSJim Ingham new_id_vec.push_back(tmp_iter->first);
75677fd738fSJim Ingham }
75777fd738fSJim Ingham
758b9c1b51eSKate Stone // Alright, if we have the same number of potentially equivalent
75905097246SAdrian Prantl // locations in the old and new modules, we'll just map them one to
76005097246SAdrian Prantl // one in ascending ID order (assuming the resolver's order would
76105097246SAdrian Prantl // match the equivalent ones. Otherwise, we'll dump all the old ones,
76205097246SAdrian Prantl // and just take the new ones, erasing the elements from both maps as
76305097246SAdrian Prantl // we go.
76477fd738fSJim Ingham
765b9c1b51eSKate Stone if (old_id_vec.size() == new_id_vec.size()) {
76623a61196SFangrui Song llvm::sort(old_id_vec);
76723a61196SFangrui Song llvm::sort(new_id_vec);
76877fd738fSJim Ingham size_t num_elements = old_id_vec.size();
769b9c1b51eSKate Stone for (size_t idx = 0; idx < num_elements; idx++) {
770b9c1b51eSKate Stone BreakpointLocationSP old_loc_sp =
771b9c1b51eSKate Stone old_break_locs.FindByIDPair(GetID(), old_id_vec[idx]);
772b9c1b51eSKate Stone BreakpointLocationSP new_loc_sp =
773b9c1b51eSKate Stone new_break_locs.FindByIDPair(GetID(), new_id_vec[idx]);
77477fd738fSJim Ingham m_locations.SwapLocation(old_loc_sp, new_loc_sp);
77577fd738fSJim Ingham old_sc_map.erase(old_id_vec[idx]);
77677fd738fSJim Ingham new_sc_map.erase(new_id_vec[idx]);
77777fd738fSJim Ingham }
778b9c1b51eSKate Stone } else {
779b9c1b51eSKate Stone for (lldb::break_id_t old_id : old_id_vec) {
780b9c1b51eSKate Stone locations_to_remove.Add(
781b9c1b51eSKate Stone old_break_locs.FindByIDPair(GetID(), old_id));
78277fd738fSJim Ingham old_sc_map.erase(old_id);
78377fd738fSJim Ingham }
784b9c1b51eSKate Stone for (lldb::break_id_t new_id : new_id_vec) {
785b9c1b51eSKate Stone locations_to_announce.Add(
786b9c1b51eSKate Stone new_break_locs.FindByIDPair(GetID(), new_id));
78777fd738fSJim Ingham new_sc_map.erase(new_id);
78877fd738fSJim Ingham }
78977fd738fSJim Ingham }
79077fd738fSJim Ingham }
79177fd738fSJim Ingham }
79277fd738fSJim Ingham }
79377fd738fSJim Ingham
794b9c1b51eSKate Stone // Now remove the remaining old locations, and cons up a removed locations
79505097246SAdrian Prantl // event. Note, we don't put the new locations that were swapped with an
79605097246SAdrian Prantl // old location on the locations_to_remove list, so we don't need to worry
79705097246SAdrian Prantl // about telling the world about removing a location we didn't tell them
79877fd738fSJim Ingham // about adding.
79977fd738fSJim Ingham
80077fd738fSJim Ingham BreakpointEventData *locations_event;
80177fd738fSJim Ingham if (!IsInternal())
802b9c1b51eSKate Stone locations_event = new BreakpointEventData(
803b9c1b51eSKate Stone eBreakpointEventTypeLocationsRemoved, shared_from_this());
80477fd738fSJim Ingham else
80516fd7511SEugene Zelenko locations_event = nullptr;
80677fd738fSJim Ingham
807b9c1b51eSKate Stone for (BreakpointLocationSP loc_sp :
808b9c1b51eSKate Stone locations_to_remove.BreakpointLocations()) {
80977fd738fSJim Ingham m_locations.RemoveLocation(loc_sp);
81077fd738fSJim Ingham if (locations_event)
81177fd738fSJim Ingham locations_event->GetBreakpointLocationCollection().Add(loc_sp);
81277fd738fSJim Ingham }
81377fd738fSJim Ingham SendBreakpointChangedEvent(locations_event);
81477fd738fSJim Ingham
81577fd738fSJim Ingham // And announce the new ones.
81677fd738fSJim Ingham
817b9c1b51eSKate Stone if (!IsInternal()) {
818b9c1b51eSKate Stone locations_event = new BreakpointEventData(
819b9c1b51eSKate Stone eBreakpointEventTypeLocationsAdded, shared_from_this());
820b9c1b51eSKate Stone for (BreakpointLocationSP loc_sp :
821b9c1b51eSKate Stone locations_to_announce.BreakpointLocations())
82277fd738fSJim Ingham locations_event->GetBreakpointLocationCollection().Add(loc_sp);
82377fd738fSJim Ingham
82477fd738fSJim Ingham SendBreakpointChangedEvent(locations_event);
82577fd738fSJim Ingham }
82677fd738fSJim Ingham m_locations.Compact();
82777fd738fSJim Ingham }
8284a94c910SJim Ingham }
8294a94c910SJim Ingham
Dump(Stream *)830b9c1b51eSKate Stone void Breakpoint::Dump(Stream *) {}
83130fdc8d8SChris Lattner
GetNumResolvedLocations() const832b9c1b51eSKate Stone size_t Breakpoint::GetNumResolvedLocations() const {
83305097246SAdrian Prantl // Return the number of breakpoints that are actually resolved and set down
83405097246SAdrian Prantl // in the inferior process.
83530fdc8d8SChris Lattner return m_locations.GetNumResolvedLocations();
83630fdc8d8SChris Lattner }
83730fdc8d8SChris Lattner
HasResolvedLocations() const838e103ae92SJonas Devlieghere bool Breakpoint::HasResolvedLocations() const {
839e103ae92SJonas Devlieghere return GetNumResolvedLocations() > 0;
840e103ae92SJonas Devlieghere }
841e103ae92SJonas Devlieghere
GetNumLocations() const842b9c1b51eSKate Stone size_t Breakpoint::GetNumLocations() const { return m_locations.GetSize(); }
84330fdc8d8SChris Lattner
AddName(llvm::StringRef new_name)844b842f2ecSJim Ingham bool Breakpoint::AddName(llvm::StringRef new_name) {
845b842f2ecSJim Ingham m_name_list.insert(new_name.str().c_str());
8465e09c8c3SJim Ingham return true;
8475e09c8c3SJim Ingham }
8485e09c8c3SJim Ingham
GetDescription(Stream * s,lldb::DescriptionLevel level,bool show_locations)849b9c1b51eSKate Stone void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level,
850b9c1b51eSKate Stone bool show_locations) {
85116fd7511SEugene Zelenko assert(s != nullptr);
8521391cc7dSJim Ingham
853b9c1b51eSKate Stone if (!m_kind_description.empty()) {
854b9c1b51eSKate Stone if (level == eDescriptionLevelBrief) {
8552995077dSJim Ingham s->PutCString(GetBreakpointKind());
8562995077dSJim Ingham return;
857b9c1b51eSKate Stone } else
8582995077dSJim Ingham s->Printf("Kind: %s\n", GetBreakpointKind());
8592995077dSJim Ingham }
8601391cc7dSJim Ingham
8612995077dSJim Ingham const size_t num_locations = GetNumLocations();
8622995077dSJim Ingham const size_t num_resolved_locations = GetNumResolvedLocations();
8631391cc7dSJim Ingham
864b9c1b51eSKate Stone // They just made the breakpoint, they don't need to be told HOW they made
86505097246SAdrian Prantl // it... Also, we'll print the breakpoint number differently depending on
86605097246SAdrian Prantl // whether there is 1 or more locations.
867b9c1b51eSKate Stone if (level != eDescriptionLevelInitial) {
8680c5cd90dSGreg Clayton s->Printf("%i: ", GetID());
86930fdc8d8SChris Lattner GetResolverDescription(s);
87030fdc8d8SChris Lattner GetFilterDescription(s);
8711391cc7dSJim Ingham }
87230fdc8d8SChris Lattner
873b9c1b51eSKate Stone switch (level) {
87430fdc8d8SChris Lattner case lldb::eDescriptionLevelBrief:
87530fdc8d8SChris Lattner case lldb::eDescriptionLevelFull:
876b9c1b51eSKate Stone if (num_locations > 0) {
877d01b2953SDaniel Malea s->Printf(", locations = %" PRIu64, (uint64_t)num_locations);
87830fdc8d8SChris Lattner if (num_resolved_locations > 0)
879b9c1b51eSKate Stone s->Printf(", resolved = %" PRIu64 ", hit count = %d",
880b9c1b51eSKate Stone (uint64_t)num_resolved_locations, GetHitCount());
881b9c1b51eSKate Stone } else {
882b9c1b51eSKate Stone // Don't print the pending notification for exception resolvers since we
88305097246SAdrian Prantl // don't generally know how to set them until the target is run.
884b9c1b51eSKate Stone if (m_resolver_sp->getResolverID() !=
885b9c1b51eSKate Stone BreakpointResolver::ExceptionResolver)
8860c5cd90dSGreg Clayton s->Printf(", locations = 0 (pending)");
88730fdc8d8SChris Lattner }
88830fdc8d8SChris Lattner
889cfb96d84SJim Ingham m_options.GetDescription(s, level);
8900136309fSJim Ingham
891a2023571SJim Ingham if (m_precondition_sp)
892a2023571SJim Ingham m_precondition_sp->GetDescription(*s, level);
893a2023571SJim Ingham
894b9c1b51eSKate Stone if (level == lldb::eDescriptionLevelFull) {
895b9c1b51eSKate Stone if (!m_name_list.empty()) {
8965e09c8c3SJim Ingham s->EOL();
8975e09c8c3SJim Ingham s->Indent();
8985e09c8c3SJim Ingham s->Printf("Names:");
8995e09c8c3SJim Ingham s->EOL();
9005e09c8c3SJim Ingham s->IndentMore();
901b9c1b51eSKate Stone for (std::string name : m_name_list) {
9025e09c8c3SJim Ingham s->Indent();
9035e09c8c3SJim Ingham s->Printf("%s\n", name.c_str());
9045e09c8c3SJim Ingham }
9055e09c8c3SJim Ingham s->IndentLess();
9065e09c8c3SJim Ingham }
9070136309fSJim Ingham s->IndentLess();
90830fdc8d8SChris Lattner s->EOL();
90930fdc8d8SChris Lattner }
91030fdc8d8SChris Lattner break;
91130fdc8d8SChris Lattner
9121391cc7dSJim Ingham case lldb::eDescriptionLevelInitial:
9131391cc7dSJim Ingham s->Printf("Breakpoint %i: ", GetID());
914b9c1b51eSKate Stone if (num_locations == 0) {
9151391cc7dSJim Ingham s->Printf("no locations (pending).");
916b9c1b51eSKate Stone } else if (num_locations == 1 && !show_locations) {
917b9c1b51eSKate Stone // There is only one location, so we'll just print that location
918b9c1b51eSKate Stone // information.
9191391cc7dSJim Ingham GetLocationAtIndex(0)->GetDescription(s, level);
920b9c1b51eSKate Stone } else {
921e704c4ffSAdrian McCarthy s->Printf("%" PRIu64 " locations.", static_cast<uint64_t>(num_locations));
9221391cc7dSJim Ingham }
9231391cc7dSJim Ingham s->EOL();
9241391cc7dSJim Ingham break;
925e704c4ffSAdrian McCarthy
92630fdc8d8SChris Lattner case lldb::eDescriptionLevelVerbose:
92730fdc8d8SChris Lattner // Verbose mode does a debug dump of the breakpoint
92830fdc8d8SChris Lattner Dump(s);
92930fdc8d8SChris Lattner s->EOL();
930ded470d3SGreg Clayton // s->Indent();
931cfb96d84SJim Ingham m_options.GetDescription(s, level);
93230fdc8d8SChris Lattner break;
933c982c768SGreg Clayton
934c982c768SGreg Clayton default:
935c982c768SGreg Clayton break;
93630fdc8d8SChris Lattner }
93730fdc8d8SChris Lattner
938b9c1b51eSKate Stone // The brief description is just the location name (1.2 or whatever). That's
93905097246SAdrian Prantl // pointless to show in the breakpoint's description, so suppress it.
940b9c1b51eSKate Stone if (show_locations && level != lldb::eDescriptionLevelBrief) {
94130fdc8d8SChris Lattner s->IndentMore();
942b9c1b51eSKate Stone for (size_t i = 0; i < num_locations; ++i) {
94330fdc8d8SChris Lattner BreakpointLocation *loc = GetLocationAtIndex(i).get();
94430fdc8d8SChris Lattner loc->GetDescription(s, level);
94530fdc8d8SChris Lattner s->EOL();
94630fdc8d8SChris Lattner }
94730fdc8d8SChris Lattner s->IndentLess();
94830fdc8d8SChris Lattner }
94930fdc8d8SChris Lattner }
95030fdc8d8SChris Lattner
GetResolverDescription(Stream * s)951b9c1b51eSKate Stone void Breakpoint::GetResolverDescription(Stream *s) {
9526a4617bbSJim Ingham if (m_resolver_sp)
9536a4617bbSJim Ingham m_resolver_sp->GetDescription(s);
9546a4617bbSJim Ingham }
9556a4617bbSJim Ingham
GetMatchingFileLine(ConstString filename,uint32_t line_number,BreakpointLocationCollection & loc_coll)9560e4c4821SAdrian Prantl bool Breakpoint::GetMatchingFileLine(ConstString filename,
957b9c1b51eSKate Stone uint32_t line_number,
958b9c1b51eSKate Stone BreakpointLocationCollection &loc_coll) {
959b9c1b51eSKate Stone // TODO: To be correct, this method needs to fill the breakpoint location
960b9c1b51eSKate Stone // collection
9616a4617bbSJim Ingham // with the location IDs which match the filename and line_number.
9626a4617bbSJim Ingham //
9636a4617bbSJim Ingham
964b9c1b51eSKate Stone if (m_resolver_sp) {
965b9c1b51eSKate Stone BreakpointResolverFileLine *resolverFileLine =
966b9c1b51eSKate Stone dyn_cast<BreakpointResolverFileLine>(m_resolver_sp.get());
9673e2ed744SMed Ismail Bennani
9683e2ed744SMed Ismail Bennani // TODO: Handle SourceLocationSpec column information
9696a4617bbSJim Ingham if (resolverFileLine &&
9703e2ed744SMed Ismail Bennani resolverFileLine->m_location_spec.GetFileSpec().GetFilename() ==
9713e2ed744SMed Ismail Bennani filename &&
9723e2ed744SMed Ismail Bennani resolverFileLine->m_location_spec.GetLine() == line_number) {
9736a4617bbSJim Ingham return true;
9746a4617bbSJim Ingham }
9756a4617bbSJim Ingham }
9766a4617bbSJim Ingham return false;
9776a4617bbSJim Ingham }
9786a4617bbSJim Ingham
GetFilterDescription(Stream * s)979b9c1b51eSKate Stone void Breakpoint::GetFilterDescription(Stream *s) {
9806a4617bbSJim Ingham m_filter_sp->GetDescription(s);
9816a4617bbSJim Ingham }
9826a4617bbSJim Ingham
EvaluatePrecondition(StoppointCallbackContext & context)983b9c1b51eSKate Stone bool Breakpoint::EvaluatePrecondition(StoppointCallbackContext &context) {
984a72b31c7SJim Ingham if (!m_precondition_sp)
985a72b31c7SJim Ingham return true;
986a72b31c7SJim Ingham
987a72b31c7SJim Ingham return m_precondition_sp->EvaluatePrecondition(context);
988a72b31c7SJim Ingham }
989a72b31c7SJim Ingham
SendBreakpointChangedEvent(lldb::BreakpointEventType eventKind)990b9c1b51eSKate Stone void Breakpoint::SendBreakpointChangedEvent(
991b9c1b51eSKate Stone lldb::BreakpointEventType eventKind) {
992b9c1b51eSKate Stone if (!m_being_created && !IsInternal() &&
993b9c1b51eSKate Stone GetTarget().EventTypeHasListeners(
994b9c1b51eSKate Stone Target::eBroadcastBitBreakpointChanged)) {
995b9c1b51eSKate Stone BreakpointEventData *data =
996b9c1b51eSKate Stone new Breakpoint::BreakpointEventData(eventKind, shared_from_this());
9976a4617bbSJim Ingham
9986a4617bbSJim Ingham GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged, data);
9996a4617bbSJim Ingham }
10006a4617bbSJim Ingham }
10016a4617bbSJim Ingham
SendBreakpointChangedEvent(BreakpointEventData * data)1002b9c1b51eSKate Stone void Breakpoint::SendBreakpointChangedEvent(BreakpointEventData *data) {
100316fd7511SEugene Zelenko if (data == nullptr)
10046a4617bbSJim Ingham return;
10056a4617bbSJim Ingham
1006b9c1b51eSKate Stone if (!m_being_created && !IsInternal() &&
1007b9c1b51eSKate Stone GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
10086a4617bbSJim Ingham GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged, data);
10096a4617bbSJim Ingham else
10106a4617bbSJim Ingham delete data;
10116a4617bbSJim Ingham }
10126a4617bbSJim Ingham
BreakpointEventTypeAsCString(BreakpointEventType type)10133f438185SJim Ingham const char *Breakpoint::BreakpointEventTypeAsCString(BreakpointEventType type) {
10143f438185SJim Ingham switch (type) {
10153f438185SJim Ingham case eBreakpointEventTypeInvalidType: return "invalid";
10163f438185SJim Ingham case eBreakpointEventTypeAdded: return "breakpoint added";
10173f438185SJim Ingham case eBreakpointEventTypeRemoved: return "breakpoint removed";
10183f438185SJim Ingham case eBreakpointEventTypeLocationsAdded: return "locations added";
10193f438185SJim Ingham case eBreakpointEventTypeLocationsRemoved: return "locations removed";
10203f438185SJim Ingham case eBreakpointEventTypeLocationsResolved: return "locations resolved";
10213f438185SJim Ingham case eBreakpointEventTypeEnabled: return "breakpoint enabled";
10223f438185SJim Ingham case eBreakpointEventTypeDisabled: return "breakpoint disabled";
10233f438185SJim Ingham case eBreakpointEventTypeCommandChanged: return "command changed";
10243f438185SJim Ingham case eBreakpointEventTypeConditionChanged: return "condition changed";
10253f438185SJim Ingham case eBreakpointEventTypeIgnoreChanged: return "ignore count changed";
10263f438185SJim Ingham case eBreakpointEventTypeThreadChanged: return "thread changed";
10273f438185SJim Ingham case eBreakpointEventTypeAutoContinueChanged: return "autocontinue changed";
10283f438185SJim Ingham };
1029*ae2aa2d2SMartin Storsjö llvm_unreachable("Fully covered switch above!");
10303f438185SJim Ingham }
10313f438185SJim Ingham
GetLogChannel()10323f438185SJim Ingham Log *Breakpoint::BreakpointEventData::GetLogChannel() {
10333f438185SJim Ingham return GetLog(LLDBLog::Breakpoints);
10343f438185SJim Ingham }
10353f438185SJim Ingham
BreakpointEventData(BreakpointEventType sub_type,const BreakpointSP & new_breakpoint_sp)1036b9c1b51eSKate Stone Breakpoint::BreakpointEventData::BreakpointEventData(
1037b9c1b51eSKate Stone BreakpointEventType sub_type, const BreakpointSP &new_breakpoint_sp)
1038ee4b6cf5SKazu Hirata : m_breakpoint_event(sub_type), m_new_breakpoint_sp(new_breakpoint_sp) {}
103930fdc8d8SChris Lattner
104016fd7511SEugene Zelenko Breakpoint::BreakpointEventData::~BreakpointEventData() = default;
104130fdc8d8SChris Lattner
GetFlavorString()10420e4c4821SAdrian Prantl ConstString Breakpoint::BreakpointEventData::GetFlavorString() {
104330fdc8d8SChris Lattner static ConstString g_flavor("Breakpoint::BreakpointEventData");
104430fdc8d8SChris Lattner return g_flavor;
104530fdc8d8SChris Lattner }
104630fdc8d8SChris Lattner
GetFlavor() const10470e4c4821SAdrian Prantl ConstString Breakpoint::BreakpointEventData::GetFlavor() const {
104830fdc8d8SChris Lattner return BreakpointEventData::GetFlavorString();
104930fdc8d8SChris Lattner }
105030fdc8d8SChris Lattner
GetBreakpoint() const10513f438185SJim Ingham BreakpointSP Breakpoint::BreakpointEventData::GetBreakpoint() const {
105230fdc8d8SChris Lattner return m_new_breakpoint_sp;
105330fdc8d8SChris Lattner }
105430fdc8d8SChris Lattner
10559fed0d85SGreg Clayton BreakpointEventType
GetBreakpointEventType() const1056b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetBreakpointEventType() const {
10579fed0d85SGreg Clayton return m_breakpoint_event;
105830fdc8d8SChris Lattner }
105930fdc8d8SChris Lattner
Dump(Stream * s) const10603f438185SJim Ingham void Breakpoint::BreakpointEventData::Dump(Stream *s) const {
10613f438185SJim Ingham if (!s)
10623f438185SJim Ingham return;
10633f438185SJim Ingham BreakpointEventType event_type = GetBreakpointEventType();
10643f438185SJim Ingham break_id_t bkpt_id = GetBreakpoint()->GetID();
10653f438185SJim Ingham s->Format("bkpt: {0} type: {1}", bkpt_id,
10663f438185SJim Ingham BreakpointEventTypeAsCString(event_type));
10673f438185SJim Ingham }
106830fdc8d8SChris Lattner
1069e6bc6cb9SJim Ingham const Breakpoint::BreakpointEventData *
GetEventDataFromEvent(const Event * event)1070b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetEventDataFromEvent(const Event *event) {
1071b9c1b51eSKate Stone if (event) {
1072e6bc6cb9SJim Ingham const EventData *event_data = event->GetData();
1073b9c1b51eSKate Stone if (event_data &&
1074b9c1b51eSKate Stone event_data->GetFlavor() == BreakpointEventData::GetFlavorString())
1075e6bc6cb9SJim Ingham return static_cast<const BreakpointEventData *>(event->GetData());
107630fdc8d8SChris Lattner }
107716fd7511SEugene Zelenko return nullptr;
107830fdc8d8SChris Lattner }
107930fdc8d8SChris Lattner
10809fed0d85SGreg Clayton BreakpointEventType
GetBreakpointEventTypeFromEvent(const EventSP & event_sp)1081b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
1082b9c1b51eSKate Stone const EventSP &event_sp) {
1083e6bc6cb9SJim Ingham const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get());
108430fdc8d8SChris Lattner
108516fd7511SEugene Zelenko if (data == nullptr)
10869fed0d85SGreg Clayton return eBreakpointEventTypeInvalidType;
108730fdc8d8SChris Lattner else
10889fed0d85SGreg Clayton return data->GetBreakpointEventType();
108930fdc8d8SChris Lattner }
109030fdc8d8SChris Lattner
GetBreakpointFromEvent(const EventSP & event_sp)1091b9c1b51eSKate Stone BreakpointSP Breakpoint::BreakpointEventData::GetBreakpointFromEvent(
1092b9c1b51eSKate Stone const EventSP &event_sp) {
10939fed0d85SGreg Clayton BreakpointSP bp_sp;
109430fdc8d8SChris Lattner
1095e6bc6cb9SJim Ingham const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get());
10969fed0d85SGreg Clayton if (data)
1097e6bc6cb9SJim Ingham bp_sp = data->m_new_breakpoint_sp;
10989fed0d85SGreg Clayton
10999fed0d85SGreg Clayton return bp_sp;
110030fdc8d8SChris Lattner }
11019fed0d85SGreg Clayton
GetNumBreakpointLocationsFromEvent(const EventSP & event_sp)1102b9c1b51eSKate Stone size_t Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
1103b9c1b51eSKate Stone const EventSP &event_sp) {
1104e6bc6cb9SJim Ingham const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get());
1105e6bc6cb9SJim Ingham if (data)
1106e6bc6cb9SJim Ingham return data->m_locations.GetSize();
1107e6bc6cb9SJim Ingham
1108e6bc6cb9SJim Ingham return 0;
1109e6bc6cb9SJim Ingham }
1110e6bc6cb9SJim Ingham
11119fed0d85SGreg Clayton lldb::BreakpointLocationSP
GetBreakpointLocationAtIndexFromEvent(const lldb::EventSP & event_sp,uint32_t bp_loc_idx)1112b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent(
1113b9c1b51eSKate Stone const lldb::EventSP &event_sp, uint32_t bp_loc_idx) {
11149fed0d85SGreg Clayton lldb::BreakpointLocationSP bp_loc_sp;
11159fed0d85SGreg Clayton
1116e6bc6cb9SJim Ingham const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get());
1117b9c1b51eSKate Stone if (data) {
1118e6bc6cb9SJim Ingham bp_loc_sp = data->m_locations.GetByIndex(bp_loc_idx);
11199fed0d85SGreg Clayton }
11209fed0d85SGreg Clayton
11219fed0d85SGreg Clayton return bp_loc_sp;
112230fdc8d8SChris Lattner }
1123fb254968SGreg Clayton
GetStatistics()1124fb254968SGreg Clayton json::Value Breakpoint::GetStatistics() {
1125fb254968SGreg Clayton json::Object bp;
1126fb254968SGreg Clayton bp.try_emplace("id", GetID());
11274f89157bSPavel Labath bp.try_emplace("resolveTime", m_resolve_time.get().count());
1128fb254968SGreg Clayton bp.try_emplace("numLocations", (int64_t)GetNumLocations());
1129fb254968SGreg Clayton bp.try_emplace("numResolvedLocations", (int64_t)GetNumResolvedLocations());
1130fb254968SGreg Clayton bp.try_emplace("internal", IsInternal());
1131fb254968SGreg Clayton if (!m_kind_description.empty())
1132fb254968SGreg Clayton bp.try_emplace("kindDescription", m_kind_description);
1133fb254968SGreg Clayton // Put the full structured data for reproducing this breakpoint in a key/value
1134fb254968SGreg Clayton // pair named "details". This allows the breakpoint's details to be visible
1135fb254968SGreg Clayton // in the stats in case we need to reproduce a breakpoint that has long
1136fb254968SGreg Clayton // resolve times
1137fb254968SGreg Clayton StructuredData::ObjectSP bp_data_sp = SerializeToStructuredData();
1138fb254968SGreg Clayton if (bp_data_sp) {
1139fb254968SGreg Clayton std::string buffer;
1140fb254968SGreg Clayton llvm::raw_string_ostream ss(buffer);
1141fb254968SGreg Clayton json::OStream json_os(ss);
1142fb254968SGreg Clayton bp_data_sp->Serialize(json_os);
1143fb254968SGreg Clayton if (auto expected_value = llvm::json::parse(ss.str())) {
1144fb254968SGreg Clayton bp.try_emplace("details", std::move(*expected_value));
1145fb254968SGreg Clayton } else {
1146fb254968SGreg Clayton std::string details_error = toString(expected_value.takeError());
1147fb254968SGreg Clayton json::Object details;
1148fb254968SGreg Clayton details.try_emplace("error", details_error);
1149fb254968SGreg Clayton bp.try_emplace("details", std::move(details));
1150fb254968SGreg Clayton }
1151fb254968SGreg Clayton }
1152fb254968SGreg Clayton return json::Value(std::move(bp));
1153fb254968SGreg Clayton }
1154