gdb: add all_bp_locations_at_addr function
Add the all_bp_locations_at_addr function, which returns a range of all
breakpoint locations at exactly the given address. This lets us
replace:
bp_location *loc, **loc2p, *locp;
ALL_BP_LOCATIONS_AT_ADDR (loc2p, locp, address)
{
loc = *loc2p;
// use loc
}
with
for (bp_location *loc : all_bp_locations_at_addr (address))
{
// use loc
}
The all_bp_locations_at_addr returns a bp_locations_at_addr_range
object, which is really just a wrapper around two std::vector iterators
representing the beginning and end of the interesting range. These
iterators are found when constructing the bp_locations_at_addr_range
object using std::equal_range, which seems a perfect fit for this use
case.
One thing I noticed about the current ALL_BP_LOCATIONS_AT_ADDR is that
if you call it with a NULL start variable, that variable gets filled in
and can be re-used for subsequent iterations. This avoids the cost of
finding the start of the interesting range again for the subsequent
iterations. This happens in build_target_command_list, for example.
The same effect can be achieved by storing the range in a local
variable, it can be iterated on multiple times.
Note that the original comment over ALL_BP_LOCATIONS_AT_ADDR says:
Iterates through locations with address ADDRESS for the currently
selected program space.
I don't see anything restricting the iteration to a given program space,
as we iterate over all bp_locations, which as far as I know contains all
breakpoint locations, regardless of the program space. So I just
dropped that part of the comment.
gdb/ChangeLog:
* breakpoint.c (get_first_locp_gte_addr): Remove.
(ALL_BP_LOCATIONS_AT_ADDR): Remove. Replace all uses with
all_bp_locations_at_addr.
(struct bp_locations_at_addr_range): New.
(all_bp_locations_at_addr): New.
(bp_locations_compare_addrs): New.
Change-Id: Icc8c92302045c47a48f507b7f1872bdd31d4ba59