diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:09:23 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:09:23 +0000 |
| commit | f73363f1dd94996356cefbf24388f561891acf0b (patch) | |
| tree | e3c31248bdb36eaec5fd833490d4278162dba2a0 /source/Breakpoint | |
| parent | 160ee69dd7ae18978f4068116777639ea98dc951 (diff) | |
Notes
Diffstat (limited to 'source/Breakpoint')
| -rw-r--r-- | source/Breakpoint/Breakpoint.cpp | 133 | ||||
| -rw-r--r-- | source/Breakpoint/BreakpointID.cpp | 7 | ||||
| -rw-r--r-- | source/Breakpoint/BreakpointIDList.cpp | 23 | ||||
| -rw-r--r-- | source/Breakpoint/BreakpointList.cpp | 12 | ||||
| -rw-r--r-- | source/Breakpoint/BreakpointLocation.cpp | 38 | ||||
| -rw-r--r-- | source/Breakpoint/BreakpointLocationList.cpp | 33 | ||||
| -rw-r--r-- | source/Breakpoint/BreakpointOptions.cpp | 30 | ||||
| -rw-r--r-- | source/Breakpoint/BreakpointResolver.cpp | 10 | ||||
| -rw-r--r-- | source/Breakpoint/BreakpointResolverAddress.cpp | 15 | ||||
| -rw-r--r-- | source/Breakpoint/BreakpointResolverFileLine.cpp | 67 | ||||
| -rw-r--r-- | source/Breakpoint/BreakpointResolverName.cpp | 17 | ||||
| -rw-r--r-- | source/Breakpoint/BreakpointSiteList.cpp | 17 | ||||
| -rw-r--r-- | source/Breakpoint/Watchpoint.cpp | 16 | ||||
| -rw-r--r-- | source/Breakpoint/WatchpointList.cpp | 6 | ||||
| -rw-r--r-- | source/Breakpoint/WatchpointOptions.cpp | 3 |
15 files changed, 237 insertions, 190 deletions
diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp index 3f6c63e1e5ba1..1dc029654bfc5 100644 --- a/source/Breakpoint/Breakpoint.cpp +++ b/source/Breakpoint/Breakpoint.cpp @@ -23,6 +23,7 @@ #include "lldb/Core/ModuleList.h" #include "lldb/Core/SearchFilter.h" #include "lldb/Core/Section.h" +#include "lldb/Target/SectionLoadList.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" @@ -284,13 +285,13 @@ void Breakpoint::RemoveInvalidLocations(const ArchSpec &arch) { m_locations.RemoveInvalidLocations(arch); } -// For each of the overall options we need to decide how they propagate to -// the location options. This will determine the precedence of options on -// the breakpoint vs. its locations. +// For each of the overall options we need to decide how they propagate to the +// location options. This will determine the precedence of options on the +// breakpoint vs. its locations. -// Disable at the breakpoint level should override the location settings. -// That way you can conveniently turn off a whole breakpoint without messing -// up the individual settings. +// Disable at the breakpoint level should override the location settings. That +// way you can conveniently turn off a whole breakpoint without messing up the +// individual settings. void Breakpoint::SetEnabled(bool enable) { if (enable == m_options_up->IsEnabled()) @@ -330,10 +331,8 @@ bool Breakpoint::IgnoreCountShouldStop() { uint32_t ignore = GetIgnoreCount(); if (ignore != 0) { // When we get here we know the location that caused the stop doesn't have - // an ignore count, - // since by contract we call it first... So we don't have to find & - // decrement it, we only have - // to decrement our own ignore count. + // an ignore count, since by contract we call it first... So we don't have + // to find & decrement it, we only have to decrement our own ignore count. DecrementIgnoreCount(); return false; } else @@ -430,8 +429,8 @@ const char *Breakpoint::GetConditionText() const { // This function is used when "baton" doesn't need to be freed void Breakpoint::SetCallback(BreakpointHitCallback callback, void *baton, bool is_synchronous) { - // The default "Baton" class will keep a copy of "baton" and won't free - // or delete it when it goes goes out of scope. + // The default "Baton" class will keep a copy of "baton" and won't free or + // delete it when it goes goes out of scope. m_options_up->SetCallback(callback, std::make_shared<UntypedBaton>(baton), is_synchronous); @@ -477,8 +476,7 @@ void Breakpoint::ResolveBreakpointInModules(ModuleList &module_list, bool send_event) { if (m_resolver_sp) { // If this is not an internal breakpoint, set up to record the new - // locations, then dispatch - // an event with the new locations. + // locations, then dispatch an event with the new locations. if (!IsInternal() && send_event) { BreakpointEventData *new_locations_event = new BreakpointEventData( eBreakpointEventTypeLocationsAdded, shared_from_this()); @@ -516,8 +514,8 @@ void Breakpoint::ModulesChanged(ModuleList &module_list, bool load, std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex()); if (load) { // The logic for handling new modules is: - // 1) If the filter rejects this module, then skip it. - // 2) Run through the current location list and if there are any locations + // 1) If the filter rejects this module, then skip it. 2) Run through the + // current location list and if there are any locations // for that module, we mark the module as "seen" and we don't try to // re-resolve // breakpoint locations for that module. @@ -527,20 +525,37 @@ void Breakpoint::ModulesChanged(ModuleList &module_list, bool load, ModuleList new_modules; // We'll stuff the "unseen" modules in this list, // and then resolve - // them after the locations pass. Have to do it this way because - // resolving breakpoints will add new locations potentially. + // them after the locations pass. Have to do it this way because resolving + // breakpoints will add new locations potentially. for (ModuleSP module_sp : module_list.ModulesNoLocking()) { bool seen = false; if (!m_filter_sp->ModulePasses(module_sp)) continue; + BreakpointLocationCollection locations_with_no_section; for (BreakpointLocationSP break_loc_sp : m_locations.BreakpointLocations()) { + + // If the section for this location was deleted, that means it's Module + // has gone away but somebody forgot to tell us. Let's clean it up + // here. + Address section_addr(break_loc_sp->GetAddress()); + if (section_addr.SectionWasDeleted()) { + locations_with_no_section.Add(break_loc_sp); + continue; + } + if (!break_loc_sp->IsEnabled()) continue; - SectionSP section_sp(break_loc_sp->GetAddress().GetSection()); - if (!section_sp || section_sp->GetModule() == module_sp) { + + SectionSP section_sp(section_addr.GetSection()); + + // If we don't have a Section, that means this location is a raw + // address that we haven't resolved to a section yet. So we'll have to + // look in all the new modules to resolve this location. Otherwise, if + // it was set in this module, re-resolve it here. + if (section_sp && section_sp->GetModule() == module_sp) { if (!seen) seen = true; @@ -552,6 +567,11 @@ void Breakpoint::ModulesChanged(ModuleList &module_list, bool load, } } } + + size_t num_to_delete = locations_with_no_section.GetSize(); + + for (size_t i = 0; i < num_to_delete; i++) + m_locations.RemoveLocation(locations_with_no_section.GetByIndex(i)); if (!seen) new_modules.AppendIfNeeded(module_sp); @@ -583,10 +603,9 @@ void Breakpoint::ModulesChanged(ModuleList &module_list, bool load, BreakpointLocationSP break_loc_sp(m_locations.GetByIndex(loc_idx)); SectionSP section_sp(break_loc_sp->GetAddress().GetSection()); if (section_sp && section_sp->GetModule() == module_sp) { - // Remove this breakpoint since the shared library is - // unloaded, but keep the breakpoint location around - // so we always get complete hit count and breakpoint - // lifetime info + // Remove this breakpoint since the shared library is unloaded, but + // keep the breakpoint location around so we always get complete + // hit count and breakpoint lifetime info break_loc_sp->ClearBreakpointSite(); if (removed_locations_event) { removed_locations_event->GetBreakpointLocationCollection().Add( @@ -614,7 +633,8 @@ static bool SymbolContextsMightBeEquivalent(SymbolContext &old_sc, bool equivalent_scs = false; if (old_sc.module_sp.get() == new_sc.module_sp.get()) { - // If these come from the same module, we can directly compare the pointers: + // If these come from the same module, we can directly compare the + // pointers: if (old_sc.comp_unit && new_sc.comp_unit && (old_sc.comp_unit == new_sc.comp_unit)) { if (old_sc.function && new_sc.function && @@ -671,15 +691,13 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp, temp_list.Append(new_module_sp); ResolveBreakpointInModules(temp_list); } else { - // First search the new module for locations. - // Then compare this with the old list, copy over locations that "look the - // same" - // Then delete the old locations. - // Finally remember to post the creation event. + // First search the new module for locations. Then compare this with the + // old list, copy over locations that "look the same" Then delete the old + // locations. Finally remember to post the creation event. // - // Two locations are the same if they have the same comp unit & function (by - // name) and there are the same number - // of locations in the old function as in the new one. + // Two locations are the same if they have the same comp unit & function + // (by name) and there are the same number of locations in the old function + // as in the new one. ModuleList temp_list; temp_list.Append(new_module_sp); @@ -692,8 +710,8 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp, if (num_new_locations > 0) { // Break out the case of one location -> one location since that's the - // most common one, and there's no need - // to build up the structures needed for the merge in that case. + // most common one, and there's no need to build up the structures needed + // for the merge in that case. if (num_new_locations == 1 && num_old_locations == 1) { bool equivalent_locations = false; SymbolContext old_sc, new_sc; @@ -716,8 +734,7 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp, } } else { // We don't want to have to keep computing the SymbolContexts for these - // addresses over and over, - // so lets get them up front: + // addresses over and over, so lets get them up front: typedef std::map<lldb::break_id_t, SymbolContext> IDToSCMap; IDToSCMap old_sc_map; @@ -740,7 +757,8 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp, lldb::break_id_t old_id = old_sc_map.begin()->first; SymbolContext &old_sc = old_sc_map.begin()->second; - // Count the number of entries equivalent to this SC for the old list: + // Count the number of entries equivalent to this SC for the old + // list: std::vector<lldb::break_id_t> old_id_vec; old_id_vec.push_back(old_id); @@ -760,17 +778,15 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp, } // Alright, if we have the same number of potentially equivalent - // locations in the old - // and new modules, we'll just map them one to one in ascending ID - // order (assuming the - // resolver's order would match the equivalent ones. - // Otherwise, we'll dump all the old ones, and just take the new ones, - // erasing the elements - // from both maps as we go. + // locations in the old and new modules, we'll just map them one to + // one in ascending ID order (assuming the resolver's order would + // match the equivalent ones. Otherwise, we'll dump all the old ones, + // and just take the new ones, erasing the elements from both maps as + // we go. if (old_id_vec.size() == new_id_vec.size()) { - sort(old_id_vec.begin(), old_id_vec.end()); - sort(new_id_vec.begin(), new_id_vec.end()); + llvm::sort(old_id_vec.begin(), old_id_vec.end()); + llvm::sort(new_id_vec.begin(), new_id_vec.end()); size_t num_elements = old_id_vec.size(); for (size_t idx = 0; idx < num_elements; idx++) { BreakpointLocationSP old_loc_sp = @@ -798,11 +814,9 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp, } // Now remove the remaining old locations, and cons up a removed locations - // event. - // Note, we don't put the new locations that were swapped with an old - // location on the locations_to_remove - // list, so we don't need to worry about telling the world about removing a - // location we didn't tell them + // event. Note, we don't put the new locations that were swapped with an + // old location on the locations_to_remove list, so we don't need to worry + // about telling the world about removing a location we didn't tell them // about adding. BreakpointEventData *locations_event; @@ -838,8 +852,8 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp, void Breakpoint::Dump(Stream *) {} size_t Breakpoint::GetNumResolvedLocations() const { - // Return the number of breakpoints that are actually resolved and set - // down in the inferior process. + // Return the number of breakpoints that are actually resolved and set down + // in the inferior process. return m_locations.GetNumResolvedLocations(); } @@ -866,9 +880,8 @@ void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level, const size_t num_resolved_locations = GetNumResolvedLocations(); // They just made the breakpoint, they don't need to be told HOW they made - // it... - // Also, we'll print the breakpoint number differently depending on whether - // there is 1 or more locations. + // it... Also, we'll print the breakpoint number differently depending on + // whether there is 1 or more locations. if (level != eDescriptionLevelInitial) { s->Printf("%i: ", GetID()); GetResolverDescription(s); @@ -885,8 +898,7 @@ void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level, (uint64_t)num_resolved_locations, GetHitCount()); } else { // Don't print the pending notification for exception resolvers since we - // don't generally - // know how to set them until the target is run. + // don't generally know how to set them until the target is run. if (m_resolver_sp->getResolverID() != BreakpointResolver::ExceptionResolver) s->Printf(", locations = 0 (pending)"); @@ -942,8 +954,7 @@ void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level, } // The brief description is just the location name (1.2 or whatever). That's - // pointless to - // show in the breakpoint's description, so suppress it. + // pointless to show in the breakpoint's description, so suppress it. if (show_locations && level != lldb::eDescriptionLevelBrief) { s->IndentMore(); for (size_t i = 0; i < num_locations; ++i) { diff --git a/source/Breakpoint/BreakpointID.cpp b/source/Breakpoint/BreakpointID.cpp index b801065468221..3f72f2052b52c 100644 --- a/source/Breakpoint/BreakpointID.cpp +++ b/source/Breakpoint/BreakpointID.cpp @@ -29,10 +29,9 @@ BreakpointID::~BreakpointID() = default; static llvm::StringRef g_range_specifiers[] = {"-", "to", "To", "TO"}; // Tells whether or not STR is valid to use between two strings representing -// breakpoint IDs, to -// indicate a range of breakpoint IDs. This is broken out into a separate -// function so that we can -// easily change or add to the format for specifying ID ranges at a later date. +// breakpoint IDs, to indicate a range of breakpoint IDs. This is broken out +// into a separate function so that we can easily change or add to the format +// for specifying ID ranges at a later date. bool BreakpointID::IsRangeIdentifier(llvm::StringRef str) { for (auto spec : g_range_specifiers) { diff --git a/source/Breakpoint/BreakpointIDList.cpp b/source/Breakpoint/BreakpointIDList.cpp index 6d610d512f3b8..bc4c2a111fd41 100644 --- a/source/Breakpoint/BreakpointIDList.cpp +++ b/source/Breakpoint/BreakpointIDList.cpp @@ -16,9 +16,9 @@ #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/Args.h" using namespace lldb; using namespace lldb_private; @@ -89,14 +89,13 @@ bool BreakpointIDList::FindBreakpointID(const char *bp_id_str, return FindBreakpointID(*bp_id, position); } -void BreakpointIDList::InsertStringArray(const char **string_array, - size_t array_size, - CommandReturnObject &result) { - if (string_array == nullptr) +void BreakpointIDList::InsertStringArray( + llvm::ArrayRef<const char *> string_array, CommandReturnObject &result) { + if(string_array.empty()) return; - for (uint32_t i = 0; i < array_size; ++i) { - auto bp_id = BreakpointID::ParseCanonicalReference(string_array[i]); + for (const char *str : string_array) { + auto bp_id = BreakpointID::ParseCanonicalReference(str); if (bp_id.hasValue()) m_breakpoint_ids.push_back(*bp_id); } @@ -237,13 +236,13 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target, } // We have valid range starting & ending breakpoint IDs. Go through all - // the breakpoints in the target and find all the breakpoints that fit - // into this range, and add them to new_args. + // the breakpoints in the target and find all the breakpoints that fit into + // this range, and add them to new_args. // Next check to see if we have location id's. If so, make sure the - // start_bp_id and end_bp_id are for the same breakpoint; otherwise we - // have an illegal range: breakpoint id ranges that specify bp locations - // are NOT allowed to cross major bp id numbers. + // start_bp_id and end_bp_id are for the same breakpoint; otherwise we have + // an illegal range: breakpoint id ranges that specify bp locations are NOT + // allowed to cross major bp id numbers. if ((start_loc_id != LLDB_INVALID_BREAK_ID) || (end_loc_id != LLDB_INVALID_BREAK_ID)) { diff --git a/source/Breakpoint/BreakpointList.cpp b/source/Breakpoint/BreakpointList.cpp index 01ac59f0a903e..4a49b1e105ab5 100644 --- a/source/Breakpoint/BreakpointList.cpp +++ b/source/Breakpoint/BreakpointList.cpp @@ -99,7 +99,7 @@ void BreakpointList::RemoveAll(bool notify) { 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) { @@ -116,10 +116,12 @@ void BreakpointList::RemoveAllowed(bool notify) { } pos = m_breakpoints.begin(); while ( pos != end) { - if((*pos)->AllowDelete()) - pos = m_breakpoints.erase(pos); - else - pos++; + auto bp = *pos; + if (bp->AllowDelete()) { + bp->ClearAllBreakpointSites(); + pos = m_breakpoints.erase(pos); + } else + pos++; } } diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp index f59c334fe5c8a..932147703304d 100644 --- a/source/Breakpoint/BreakpointLocation.cpp +++ b/source/Breakpoint/BreakpointLocation.cpp @@ -110,8 +110,8 @@ void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) { if (thread_id != LLDB_INVALID_THREAD_ID) GetLocationOptions()->SetThreadID(thread_id); else { - // If we're resetting this to an invalid thread id, then - // don't make an options pointer just to do that. + // If we're resetting this to an invalid thread id, then don't make an + // options pointer just to do that. if (m_options_ap.get() != nullptr) m_options_ap->SetThreadID(thread_id); } @@ -132,8 +132,8 @@ void BreakpointLocation::SetThreadIndex(uint32_t index) { if (index != 0) GetLocationOptions()->GetThreadSpec()->SetIndex(index); else { - // If we're resetting this to an invalid thread id, then - // don't make an options pointer just to do that. + // If we're resetting this to an invalid thread id, then don't make an + // options pointer just to do that. if (m_options_ap.get() != nullptr) m_options_ap->GetThreadSpec()->SetIndex(index); } @@ -154,8 +154,8 @@ void BreakpointLocation::SetThreadName(const char *thread_name) { if (thread_name != nullptr) GetLocationOptions()->GetThreadSpec()->SetName(thread_name); else { - // If we're resetting this to an invalid thread id, then - // don't make an options pointer just to do that. + // If we're resetting this to an invalid thread id, then don't make an + // options pointer just to do that. if (m_options_ap.get() != nullptr) m_options_ap->GetThreadSpec()->SetName(thread_name); } @@ -176,8 +176,8 @@ void BreakpointLocation::SetQueueName(const char *queue_name) { if (queue_name != nullptr) GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name); else { - // If we're resetting this to an invalid thread id, then - // don't make an options pointer just to do that. + // If we're resetting this to an invalid thread id, then don't make an + // options pointer just to do that. if (m_options_ap.get() != nullptr) m_options_ap->GetThreadSpec()->SetQueueName(queue_name); } @@ -203,8 +203,8 @@ bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) { void BreakpointLocation::SetCallback(BreakpointHitCallback callback, void *baton, bool is_synchronous) { - // The default "Baton" class will keep a copy of "baton" and won't free - // or delete it when it goes goes out of scope. + // The default "Baton" class will keep a copy of "baton" and won't free or + // delete it when it goes goes out of scope. GetLocationOptions()->SetCallback( callback, std::make_shared<UntypedBaton>(baton), is_synchronous); SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged); @@ -283,8 +283,7 @@ bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx, } // We need to make sure the user sees any parse errors in their condition, so - // we'll hook the - // constructor errors up to the debugger's Async I/O. + // we'll hook the constructor errors up to the debugger's Async I/O. ValueObjectSP result_value_sp; @@ -372,9 +371,9 @@ bool BreakpointLocation::IgnoreCountShouldStop() { } 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 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( new BreakpointOptions(false)); @@ -479,9 +478,8 @@ bool BreakpointLocation::ClearBreakpointSite() { if (m_bp_site_sp.get()) { ProcessSP process_sp(m_owner.GetTarget().GetProcessSP()); // If the process exists, get it to remove the owner, it will remove the - // physical implementation - // of the breakpoint as well if there are no more owners. Otherwise just - // remove this owner. + // physical implementation of the breakpoint as well if there are no more + // owners. Otherwise just remove this owner. if (process_sp) process_sp->RemoveOwnerFromBreakpointSite(GetBreakpoint().GetID(), GetID(), m_bp_site_sp); @@ -499,8 +497,8 @@ void BreakpointLocation::GetDescription(Stream *s, SymbolContext sc; // If the description level is "initial" then the breakpoint is printing out - // our initial state, - // and we should let it decide how it wants to print our label. + // our initial state, and we should let it decide how it wants to print our + // label. if (level != eDescriptionLevelInitial) { s->Indent(); BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID()); diff --git a/source/Breakpoint/BreakpointLocationList.cpp b/source/Breakpoint/BreakpointLocationList.cpp index 1e4b4412a427b..23ca89da6ce1a 100644 --- a/source/Breakpoint/BreakpointLocationList.cpp +++ b/source/Breakpoint/BreakpointLocationList.cpp @@ -49,12 +49,12 @@ bool BreakpointLocationList::ShouldStop(StoppointCallbackContext *context, BreakpointLocationSP bp = FindByID(break_id); if (bp) { // Let the BreakpointLocation decide if it should stop here (could not have - // reached it's target hit count yet, or it could have a callback - // that decided it shouldn't stop (shared library loads/unloads). + // reached it's target hit count yet, or it could have a callback that + // decided it shouldn't stop (shared library loads/unloads). return bp->ShouldStop(context); } - // We should stop here since this BreakpointLocation isn't valid anymore or it - // doesn't exist. + // We should stop here since this BreakpointLocation isn't valid anymore or + // it doesn't exist. return true; } @@ -246,10 +246,10 @@ bool BreakpointLocationList::RemoveLocation( m_address_to_location.erase(bp_loc_sp->GetAddress()); - collection::iterator pos, end = m_locations.end(); - for (pos = m_locations.begin(); pos != end; ++pos) { - if ((*pos).get() == bp_loc_sp.get()) { - m_locations.erase(pos); + size_t num_locations = m_locations.size(); + for (size_t idx = 0; idx < num_locations; idx++) { + if (m_locations[idx].get() == bp_loc_sp.get()) { + RemoveLocationByIndex(idx); return true; } } @@ -257,17 +257,23 @@ bool BreakpointLocationList::RemoveLocation( return false; } +void BreakpointLocationList::RemoveLocationByIndex(size_t idx) { + assert (idx < m_locations.size()); + m_address_to_location.erase(m_locations[idx]->GetAddress()); + m_locations.erase(m_locations.begin() + idx); +} + void BreakpointLocationList::RemoveInvalidLocations(const ArchSpec &arch) { std::lock_guard<std::recursive_mutex> guard(m_mutex); size_t idx = 0; - // Don't cache m_location.size() as it will change since we might - // remove locations from our vector... + // Don't cache m_location.size() as it will change since we might remove + // locations from our vector... while (idx < m_locations.size()) { BreakpointLocation *bp_loc = m_locations[idx].get(); if (bp_loc->GetAddress().SectionWasDeleted()) { // Section was deleted which means this breakpoint comes from a module // that is no longer valid, so we should remove it. - m_locations.erase(m_locations.begin() + idx); + RemoveLocationByIndex(idx); continue; } if (arch.IsValid()) { @@ -276,12 +282,13 @@ void BreakpointLocationList::RemoveInvalidLocations(const ArchSpec &arch) { if (!arch.IsCompatibleMatch(module_sp->GetArchitecture())) { // The breakpoint was in a module whose architecture is no longer // compatible with "arch", so we need to remove it - m_locations.erase(m_locations.begin() + idx); + RemoveLocationByIndex(idx); continue; } } } - // Only increment the index if we didn't remove the locations at index "idx" + // Only increment the index if we didn't remove the locations at index + // "idx" ++idx; } } diff --git a/source/Breakpoint/BreakpointOptions.cpp b/source/Breakpoint/BreakpointOptions.cpp index 662b288794d3a..b5869fc34dfc3 100644 --- a/source/Breakpoint/BreakpointOptions.cpp +++ b/source/Breakpoint/BreakpointOptions.cpp @@ -425,10 +425,9 @@ void BreakpointOptions::SetCallback(BreakpointHitCallback callback, const lldb::BatonSP &callback_baton_sp, bool callback_is_synchronous) { // FIXME: This seems unsafe. If BatonSP actually *is* a CommandBaton, but - // in a shared_ptr<Baton> instead of a shared_ptr<CommandBaton>, then we - // will set m_baton_is_command_baton to false, which is incorrect. - // One possible solution is to make the base Baton class provide a method - // such as: + // in a shared_ptr<Baton> instead of a shared_ptr<CommandBaton>, then we will + // set m_baton_is_command_baton to false, which is incorrect. One possible + // solution is to make the base Baton class provide a method such as: // virtual StringRef getBatonId() const { return ""; } // and have CommandBaton override this to return something unique, and then // check for it here. Another option might be to make Baton using the llvm @@ -470,12 +469,18 @@ const Baton *BreakpointOptions::GetBaton() const { bool BreakpointOptions::InvokeCallback(StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id) { - if (m_callback && context->is_synchronous == IsCallbackSynchronous()) { - return m_callback(m_callback_baton_sp ? m_callback_baton_sp->data() + if (m_callback) { + if (context->is_synchronous == IsCallbackSynchronous()) { + return m_callback(m_callback_baton_sp ? m_callback_baton_sp->data() : nullptr, context, break_id, break_loc_id); - } else - return true; + } else if (IsCallbackSynchronous()) { + // If a synchronous callback is called at async time, it should not say + // to stop. + return false; + } + } + return true; } bool BreakpointOptions::HasCallback() const { @@ -526,7 +531,10 @@ const ThreadSpec *BreakpointOptions::GetThreadSpecNoCreate() const { ThreadSpec *BreakpointOptions::GetThreadSpec() { if (m_thread_spec_ap.get() == nullptr) + { + m_set_flags.Set(eThreadSpec); m_thread_spec_ap.reset(new ThreadSpec()); + } return m_thread_spec_ap.get(); } @@ -545,8 +553,7 @@ void BreakpointOptions::SetThreadSpec( void BreakpointOptions::GetDescription(Stream *s, lldb::DescriptionLevel level) const { // Figure out if there are any options not at their default value, and only - // print - // anything if there are: + // print anything if there are: if (m_ignore_count != 0 || !m_enabled || m_one_shot || m_auto_continue || (GetThreadSpecNoCreate() != nullptr && @@ -651,8 +658,7 @@ bool BreakpointOptions::BreakpointOptionsCallbackFunction( CommandReturnObject result; Debugger &debugger = target->GetDebugger(); // Rig up the results secondary output stream to the debugger's, so the - // output will come out synchronously - // if the debugger is set up that way. + // output will come out synchronously if the debugger is set up that way. StreamSP output_stream(debugger.GetAsyncOutputStream()); StreamSP error_stream(debugger.GetAsyncErrorStream()); diff --git a/source/Breakpoint/BreakpointResolver.cpp b/source/Breakpoint/BreakpointResolver.cpp index 31aefb08f9769..6ab578dd85760 100644 --- a/source/Breakpoint/BreakpointResolver.cpp +++ b/source/Breakpoint/BreakpointResolver.cpp @@ -15,8 +15,8 @@ // Project includes #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" -// Have to include the other breakpoint resolver types here so the static create -// from StructuredData can call them. +// Have to include the other breakpoint resolver types here so the static +// create from StructuredData can call them. #include "lldb/Breakpoint/BreakpointResolverAddress.h" #include "lldb/Breakpoint/BreakpointResolverFileLine.h" #include "lldb/Breakpoint/BreakpointResolverFileRegex.h" @@ -212,8 +212,7 @@ void BreakpointResolver::SetSCMatchesByLine(SearchFilter &filter, sc_list.RemoveContextAtIndex(current_idx); // ResolveSymbolContext will always return a number that is >= the line - // number you pass in. - // So the smaller line number is always better. + // number you pass in. So the smaller line number is always better. if (sc.line_entry.line < closest_line_number) closest_line_number = sc.line_entry.line; } else @@ -234,8 +233,7 @@ void BreakpointResolver::SetSCMatchesByLine(SearchFilter &filter, } // Next go through and see if there are line table entries that are - // contiguous, and if so keep only the - // first of the contiguous range: + // contiguous, and if so keep only the first of the contiguous range: current_idx = 0; std::map<Block *, lldb::addr_t> blocks_with_breakpoints; diff --git a/source/Breakpoint/BreakpointResolverAddress.cpp b/source/Breakpoint/BreakpointResolverAddress.cpp index 32f2045ed59a1..d4647e2c589d4 100644 --- a/source/Breakpoint/BreakpointResolverAddress.cpp +++ b/source/Breakpoint/BreakpointResolverAddress.cpp @@ -66,7 +66,7 @@ BreakpointResolver *BreakpointResolverAddress::CreateFromStructuredData( error.SetErrorString("BRA::CFSD: Couldn't read module name entry."); return nullptr; } - module_filespec.SetFile(module_name, false); + module_filespec.SetFile(module_name, false, FileSpec::Style::native); } return new BreakpointResolverAddress(bkpt, address, module_filespec); } @@ -100,11 +100,10 @@ BreakpointResolverAddress::SerializeToStructuredData() { } void BreakpointResolverAddress::ResolveBreakpoint(SearchFilter &filter) { - // If the address is not section relative, then we should not try to - // re-resolve it, it is just some - // random address and we wouldn't know what to do on reload. But if it is - // section relative, we need to - // re-resolve it since the section it's in may have shifted on re-run. + // If the address is not section relative, then we should not try to re- + // resolve it, it is just some random address and we wouldn't know what to do + // on reload. But if it is section relative, we need to re-resolve it since + // the section it's in may have shifted on re-run. bool re_resolve = false; if (m_addr.GetSection() || m_module_filespec) re_resolve = true; @@ -137,8 +136,8 @@ BreakpointResolverAddress::SearchCallback(SearchFilter &filter, if (filter.AddressPasses(m_addr)) { if (m_breakpoint->GetNumLocations() == 0) { // If the address is just an offset, and we're given a module, see if we - // can find the appropriate module - // loaded in the binary, and fix up m_addr to use that. + // can find the appropriate module loaded in the binary, and fix up + // m_addr to use that. if (!m_addr.IsSectionOffset() && m_module_filespec) { Target &target = m_breakpoint->GetTarget(); ModuleSpec module_spec(m_module_filespec); diff --git a/source/Breakpoint/BreakpointResolverFileLine.cpp b/source/Breakpoint/BreakpointResolverFileLine.cpp index 780d25db9ccb8..ecef88eb99894 100644 --- a/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -110,20 +110,40 @@ BreakpointResolverFileLine::SerializeToStructuredData() { // Filter the symbol context list to remove contexts where the line number was // moved into a new function. We do this conservatively, so if e.g. we cannot -// resolve the function in the context (which can happen in case of -// line-table-only debug info), we leave the context as is. The trickiest part -// here is handling inlined functions -- in this case we need to make sure we -// look at the declaration line of the inlined function, NOT the function it was +// resolve the function in the context (which can happen in case of line-table- +// only debug info), we leave the context as is. The trickiest part here is +// handling inlined functions -- in this case we need to make sure we look at +// the declaration line of the inlined function, NOT the function it was // inlined into. -void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list) { +void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list, + bool is_relative) { if (m_exact_match) return; // Nothing to do. Contexts are precise. + llvm::StringRef relative_path; + if (is_relative) + relative_path = m_file_spec.GetDirectory().GetStringRef(); + Log * log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS); for(uint32_t i = 0; i < sc_list.GetSize(); ++i) { SymbolContext sc; sc_list.GetContextAtIndex(i, sc); - if (! sc.block) + if (is_relative) { + // If the path was relative, make sure any matches match as long as the + // relative parts of the path match the path from support files + auto sc_dir = sc.line_entry.file.GetDirectory().GetStringRef(); + if (!sc_dir.endswith(relative_path)) { + // We had a relative path specified and the relative directory doesn't + // match so remove this one + LLDB_LOG(log, "removing not matching relative path {0} since it " + "doesn't end with {1}", sc_dir, relative_path); + sc_list.RemoveContextAtIndex(i); + --i; + continue; + } + } + + if (!sc.block) continue; FileSpec file; @@ -179,33 +199,38 @@ BreakpointResolverFileLine::SearchCallback(SearchFilter &filter, assert(m_breakpoint != NULL); // There is a tricky bit here. You can have two compilation units that - // #include the same file, and in one of them the function at m_line_number is - // used (and so code and a line entry for it is generated) but in the other it - // isn't. If we considered the CU's independently, then in the second - // inclusion, we'd move the breakpoint to the next function that actually - // generated code in the header file. That would end up being confusing. So - // instead, we do the CU iterations by hand here, then scan through the - // complete list of matches, and figure out the closest line number match, and - // only set breakpoints on that match. + // #include the same file, and in one of them the function at m_line_number + // is used (and so code and a line entry for it is generated) but in the + // other it isn't. If we considered the CU's independently, then in the + // second inclusion, we'd move the breakpoint to the next function that + // actually generated code in the header file. That would end up being + // confusing. So instead, we do the CU iterations by hand here, then scan + // through the complete list of matches, and figure out the closest line + // number match, and only set breakpoints on that match. + + // Note also that if file_spec only had a file name and not a directory, + // there may be many different file spec's in the resultant list. The + // closest line match for one will not be right for some totally different + // file. So we go through the match list and pull out the sets that have the + // same file spec in their line_entry and treat each set separately. - // Note also that if file_spec only had a file name and not a directory, there - // may be many different file spec's in the resultant list. The closest line - // match for one will not be right for some totally different file. So we go - // through the match list and pull out the sets that have the same file spec - // in their line_entry and treat each set separately. + FileSpec search_file_spec = m_file_spec; + const bool is_relative = m_file_spec.IsRelative(); + if (is_relative) + search_file_spec.GetDirectory().Clear(); const size_t num_comp_units = context.module_sp->GetNumCompileUnits(); for (size_t i = 0; i < num_comp_units; i++) { CompUnitSP cu_sp(context.module_sp->GetCompileUnitAtIndex(i)); if (cu_sp) { if (filter.CompUnitPasses(*cu_sp)) - cu_sp->ResolveSymbolContext(m_file_spec, m_line_number, m_inlines, + cu_sp->ResolveSymbolContext(search_file_spec, m_line_number, m_inlines, m_exact_match, eSymbolContextEverything, sc_list); } } - FilterContexts(sc_list); + FilterContexts(sc_list, is_relative); StreamString s; s.Printf("for %s:%d ", m_file_spec.GetFilename().AsCString("<Unknown>"), diff --git a/source/Breakpoint/BreakpointResolverName.cpp b/source/Breakpoint/BreakpointResolverName.cpp index 468de35db0ee7..ba277ae2655e2 100644 --- a/source/Breakpoint/BreakpointResolverName.cpp +++ b/source/Breakpoint/BreakpointResolverName.cpp @@ -16,11 +16,13 @@ #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" #include "Plugins/Language/ObjC/ObjCLanguage.h" #include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/Architecture.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/Target.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" @@ -239,9 +241,8 @@ void BreakpointResolverName::AddNameLookup(const ConstString &name, // FIXME: Right now we look at the module level, and call the module's // "FindFunctions". // Greg says he will add function tables, maybe at the CompileUnit level to -// accelerate function -// lookup. At that point, we should switch the depth to CompileUnit, and look -// in these tables. +// accelerate function lookup. At that point, we should switch the depth to +// CompileUnit, and look in these tables. Searcher::CallbackReturn BreakpointResolverName::SearchCallback(SearchFilter &filter, @@ -299,8 +300,8 @@ BreakpointResolverName::SearchCallback(SearchFilter &filter, break; } - // If the filter specifies a Compilation Unit, remove the ones that don't pass - // at this point. + // If the filter specifies a Compilation Unit, remove the ones that don't + // pass at this point. if (filter_by_cu || filter_by_language) { uint32_t num_functions = func_list.GetSize(); @@ -365,6 +366,12 @@ BreakpointResolverName::SearchCallback(SearchFilter &filter, sc.symbol->GetPrologueByteSize(); if (prologue_byte_size) break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); + else { + const Architecture *arch = + m_breakpoint->GetTarget().GetArchitecturePlugin(); + if (arch) + arch->AdjustBreakpointAddress(*sc.symbol, break_addr); + } } } diff --git a/source/Breakpoint/BreakpointSiteList.cpp b/source/Breakpoint/BreakpointSiteList.cpp index 87ce292feb8e9..9bb9aa3661061 100644 --- a/source/Breakpoint/BreakpointSiteList.cpp +++ b/source/Breakpoint/BreakpointSiteList.cpp @@ -24,8 +24,7 @@ BreakpointSiteList::BreakpointSiteList() : m_mutex(), m_bp_site_list() {} BreakpointSiteList::~BreakpointSiteList() {} // Add breakpoint site to the list. However, if the element already exists in -// the -// list, then we don't add it, and return LLDB_INVALID_BREAK_ID. +// the list, then we don't add it, and return LLDB_INVALID_BREAK_ID. lldb::break_id_t BreakpointSiteList::Add(const BreakpointSiteSP &bp) { lldb::addr_t bp_site_load_addr = bp->GetLoadAddress(); @@ -45,8 +44,8 @@ bool BreakpointSiteList::ShouldStop(StoppointCallbackContext *context, BreakpointSiteSP site_sp(FindByID(site_id)); if (site_sp) { // Let the BreakpointSite decide if it should stop here (could not have - // reached it's target hit count yet, or it could have a callback - // that decided it shouldn't stop (shared library loads/unloads). + // reached it's target hit count yet, or it could have a callback that + // decided it shouldn't stop (shared library loads/unloads). return site_sp->ShouldStop(context); } // We should stop here since this BreakpointSite isn't valid anymore or it @@ -60,7 +59,8 @@ lldb::break_id_t BreakpointSiteList::FindIDByAddress(lldb::addr_t addr) { // PRIx64 " ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID()); return bp.get()->GetID(); } - // DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" PRIx64 + // DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" + // PRIx64 // " ) => NONE", __FUNCTION__, (uint64_t)addr); return LLDB_INVALID_BREAK_ID; } @@ -185,10 +185,9 @@ bool BreakpointSiteList::FindInRange(lldb::addr_t lower_bound, if (lower == m_bp_site_list.end() || (*lower).first >= upper_bound) return false; - // This is one tricky bit. The breakpoint might overlap the bottom end of the - // range. So we grab the - // breakpoint prior to the lower bound, and check that that + its byte size - // isn't in our range. + // This is one tricky bit. The breakpoint might overlap the bottom end of + // the range. So we grab the breakpoint prior to the lower bound, and check + // that that + its byte size isn't in our range. if (lower != m_bp_site_list.begin()) { collection::const_iterator prev_pos = lower; prev_pos--; diff --git a/source/Breakpoint/Watchpoint.cpp b/source/Breakpoint/Watchpoint.cpp index a141a6b5c2f97..7a936d1fb130e 100644 --- a/source/Breakpoint/Watchpoint.cpp +++ b/source/Breakpoint/Watchpoint.cpp @@ -59,8 +59,8 @@ Watchpoint::~Watchpoint() = default; // This function is used when "baton" doesn't need to be freed void Watchpoint::SetCallback(WatchpointHitCallback callback, void *baton, bool is_synchronous) { - // The default "Baton" class will keep a copy of "baton" and won't free - // or delete it when it goes goes out of scope. + // The default "Baton" class will keep a copy of "baton" and won't free or + // delete it when it goes goes out of scope. m_options.SetCallback(callback, std::make_shared<UntypedBaton>(baton), is_synchronous); @@ -103,8 +103,8 @@ bool Watchpoint::CaptureWatchedValue(const ExecutionContext &exe_ctx) { Address watch_address(GetLoadAddress()); if (!m_type.IsValid()) { // Don't know how to report new & old values, since we couldn't make a - // scalar type for this watchpoint. - // This works around an assert in ValueObjectMemory::Create. + // scalar type for this watchpoint. This works around an assert in + // ValueObjectMemory::Create. // FIXME: This should not happen, but if it does in some case we care about, // we can go grab the value raw and print it as unsigned. return false; @@ -217,11 +217,9 @@ void Watchpoint::DumpWithLevel(Stream *s, bool Watchpoint::IsEnabled() const { return m_enabled; } // Within StopInfo.cpp, we purposely turn on the ephemeral mode right before -// temporarily disable the watchpoint -// in order to perform possible watchpoint actions without triggering further -// watchpoint events. -// After the temporary disabled watchpoint is enabled, we then turn off the -// ephemeral mode. +// temporarily disable the watchpoint in order to perform possible watchpoint +// actions without triggering further watchpoint events. After the temporary +// disabled watchpoint is enabled, we then turn off the ephemeral mode. void Watchpoint::TurnOnEphemeralMode() { m_is_ephemeral = true; } diff --git a/source/Breakpoint/WatchpointList.cpp b/source/Breakpoint/WatchpointList.cpp index 6ec3bd09c1429..6497780084d96 100644 --- a/source/Breakpoint/WatchpointList.cpp +++ b/source/Breakpoint/WatchpointList.cpp @@ -203,9 +203,9 @@ bool WatchpointList::ShouldStop(StoppointCallbackContext *context, WatchpointSP wp_sp = FindByID(watch_id); if (wp_sp) { - // Let the Watchpoint decide if it should stop here (could not have - // reached it's target hit count yet, or it could have a callback - // that decided it shouldn't stop. + // Let the Watchpoint decide if it should stop here (could not have reached + // it's target hit count yet, or it could have a callback that decided it + // shouldn't stop. return wp_sp->ShouldStop(context); } // We should stop here since this Watchpoint isn't valid anymore or it diff --git a/source/Breakpoint/WatchpointOptions.cpp b/source/Breakpoint/WatchpointOptions.cpp index 558ebc51008c0..402fee943a023 100644 --- a/source/Breakpoint/WatchpointOptions.cpp +++ b/source/Breakpoint/WatchpointOptions.cpp @@ -143,8 +143,7 @@ void WatchpointOptions::GetCallbackDescription( void WatchpointOptions::GetDescription(Stream *s, lldb::DescriptionLevel level) const { // Figure out if there are any options not at their default value, and only - // print - // anything if there are: + // print anything if there are: if ((GetThreadSpecNoCreate() != nullptr && GetThreadSpecNoCreate()->HasSpecification())) { |
