xref: /aosp_15_r20/external/google-breakpad/src/processor/range_map-inl.h (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle // Copyright 2010 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle //     * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle //     * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle //     * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle 
29*9712c20fSFrederick Mayle // range_map-inl.h: Range map implementation.
30*9712c20fSFrederick Mayle //
31*9712c20fSFrederick Mayle // See range_map.h for documentation.
32*9712c20fSFrederick Mayle //
33*9712c20fSFrederick Mayle // Author: Mark Mentovai
34*9712c20fSFrederick Mayle 
35*9712c20fSFrederick Mayle #ifndef PROCESSOR_RANGE_MAP_INL_H__
36*9712c20fSFrederick Mayle #define PROCESSOR_RANGE_MAP_INL_H__
37*9712c20fSFrederick Mayle 
38*9712c20fSFrederick Mayle 
39*9712c20fSFrederick Mayle #include <assert.h>
40*9712c20fSFrederick Mayle 
41*9712c20fSFrederick Mayle #include "common/safe_math.h"
42*9712c20fSFrederick Mayle #include "processor/range_map.h"
43*9712c20fSFrederick Mayle #include "processor/linked_ptr.h"
44*9712c20fSFrederick Mayle #include "processor/logging.h"
45*9712c20fSFrederick Mayle 
46*9712c20fSFrederick Mayle 
47*9712c20fSFrederick Mayle namespace google_breakpad {
48*9712c20fSFrederick Mayle 
49*9712c20fSFrederick Mayle template<typename AddressType, typename EntryType>
StoreRange(const AddressType & base,const AddressType & size,const EntryType & entry)50*9712c20fSFrederick Mayle bool RangeMap<AddressType, EntryType>::StoreRange(const AddressType& base,
51*9712c20fSFrederick Mayle                                                   const AddressType& size,
52*9712c20fSFrederick Mayle                                                   const EntryType& entry) {
53*9712c20fSFrederick Mayle   return StoreRangeInternal(base, 0 /* delta */, size, entry);
54*9712c20fSFrederick Mayle }
55*9712c20fSFrederick Mayle 
56*9712c20fSFrederick Mayle template<typename AddressType, typename EntryType>
StoreRangeInternal(const AddressType & base,const AddressType & delta,const AddressType & size,const EntryType & entry)57*9712c20fSFrederick Mayle bool RangeMap<AddressType, EntryType>::StoreRangeInternal(
58*9712c20fSFrederick Mayle     const AddressType& base, const AddressType& delta,
59*9712c20fSFrederick Mayle     const AddressType& size, const EntryType& entry) {
60*9712c20fSFrederick Mayle   AddressType high;
61*9712c20fSFrederick Mayle   bool high_ok = false;
62*9712c20fSFrederick Mayle   if (size > 0) {
63*9712c20fSFrederick Mayle     std::pair<AddressType, bool> result = AddWithOverflowCheck(base, size - 1);
64*9712c20fSFrederick Mayle     high = result.first;
65*9712c20fSFrederick Mayle     high_ok = !result.second;
66*9712c20fSFrederick Mayle   }
67*9712c20fSFrederick Mayle   // Check for undersize or overflow.
68*9712c20fSFrederick Mayle   if (!high_ok) {
69*9712c20fSFrederick Mayle     // The processor will hit this case too frequently with common symbol
70*9712c20fSFrederick Mayle     // files in the size == 0 case, which is more suited to a DEBUG channel.
71*9712c20fSFrederick Mayle     // Filter those out since there's no DEBUG channel at the moment.
72*9712c20fSFrederick Mayle     BPLOG_IF(INFO, size != 0) << "StoreRangeInternal failed, "
73*9712c20fSFrederick Mayle                               << HexString(base) << "+" << HexString(size)
74*9712c20fSFrederick Mayle                               << ", " << HexString(high)
75*9712c20fSFrederick Mayle                               << ", delta: " << HexString(delta);
76*9712c20fSFrederick Mayle     return false;
77*9712c20fSFrederick Mayle   }
78*9712c20fSFrederick Mayle 
79*9712c20fSFrederick Mayle   // Ensure that this range does not overlap with another one already in the
80*9712c20fSFrederick Mayle   // map.
81*9712c20fSFrederick Mayle   MapConstIterator iterator_base = map_.lower_bound(base);
82*9712c20fSFrederick Mayle   MapConstIterator iterator_high = map_.lower_bound(high);
83*9712c20fSFrederick Mayle 
84*9712c20fSFrederick Mayle   if (iterator_base != iterator_high) {
85*9712c20fSFrederick Mayle     // Some other range ends in the space used by this range.  It may be
86*9712c20fSFrederick Mayle     // contained within the space used by this range, or it may extend lower.
87*9712c20fSFrederick Mayle     if (merge_strategy_ == MergeRangeStrategy::kTruncateLower) {
88*9712c20fSFrederick Mayle       // kTruncate the range with the lower base address.
89*9712c20fSFrederick Mayle       AddressType other_base = iterator_base->second.base();
90*9712c20fSFrederick Mayle       if (base < other_base) {
91*9712c20fSFrederick Mayle         return StoreRangeInternal(base, delta, other_base - base, entry);
92*9712c20fSFrederick Mayle       } else if (other_base < base) {
93*9712c20fSFrederick Mayle         EntryType other_entry;
94*9712c20fSFrederick Mayle         AddressType other_high, other_size, other_delta;
95*9712c20fSFrederick Mayle         other_high = iterator_base->first;
96*9712c20fSFrederick Mayle         RetrieveRange(other_high, &other_entry, &other_base, &other_delta,
97*9712c20fSFrederick Mayle                       &other_size);
98*9712c20fSFrederick Mayle         map_.erase(iterator_base);
99*9712c20fSFrederick Mayle         map_.insert(
100*9712c20fSFrederick Mayle             MapValue(base - 1, Range(other_base, other_delta, other_entry)));
101*9712c20fSFrederick Mayle         return StoreRangeInternal(base, delta, size, entry);
102*9712c20fSFrederick Mayle       } else {
103*9712c20fSFrederick Mayle         return false;
104*9712c20fSFrederick Mayle       }
105*9712c20fSFrederick Mayle     } else if (merge_strategy_ == MergeRangeStrategy::kTruncateUpper) {
106*9712c20fSFrederick Mayle       // Truncate the lower portion of this range.
107*9712c20fSFrederick Mayle       AddressType additional_delta = iterator_base->first - base + 1;
108*9712c20fSFrederick Mayle       return StoreRangeInternal(base + additional_delta,
109*9712c20fSFrederick Mayle                                 delta + additional_delta,
110*9712c20fSFrederick Mayle                                 size - additional_delta, entry);
111*9712c20fSFrederick Mayle     } else {
112*9712c20fSFrederick Mayle       // The processor hits this case too frequently with common symbol files.
113*9712c20fSFrederick Mayle       // This is most appropriate for a DEBUG channel, but since none exists
114*9712c20fSFrederick Mayle       // now simply comment out this logging.
115*9712c20fSFrederick Mayle       // AddressType other_base = iterator_base->second.base();
116*9712c20fSFrederick Mayle       // AddressType other_size = iterator_base->first - other_base + 1;
117*9712c20fSFrederick Mayle       // BPLOG(INFO) << "StoreRangeInternal failed, an existing range is "
118*9712c20fSFrederick Mayle       //             << "overlapping with the new range: new "
119*9712c20fSFrederick Mayle       //             << HexString(base) << "+" << HexString(size)
120*9712c20fSFrederick Mayle       //             << ", existing " << HexString(other_base) << "+"
121*9712c20fSFrederick Mayle       //             << HexString(other_size);
122*9712c20fSFrederick Mayle       return false;
123*9712c20fSFrederick Mayle     }
124*9712c20fSFrederick Mayle   }
125*9712c20fSFrederick Mayle 
126*9712c20fSFrederick Mayle   if (iterator_high != map_.end() && iterator_high->second.base() <= high) {
127*9712c20fSFrederick Mayle     // The range above this one overlaps with this one.  It may fully
128*9712c20fSFrederick Mayle     // contain this range, or it may begin within this range and extend
129*9712c20fSFrederick Mayle     // higher.
130*9712c20fSFrederick Mayle     if (merge_strategy_ == MergeRangeStrategy::kTruncateLower) {
131*9712c20fSFrederick Mayle       AddressType other_base = iterator_high->second.base();
132*9712c20fSFrederick Mayle       if (base < other_base) {
133*9712c20fSFrederick Mayle         return StoreRangeInternal(base, delta, other_base - base, entry);
134*9712c20fSFrederick Mayle       } else if (other_base < base) {
135*9712c20fSFrederick Mayle         EntryType other_entry;
136*9712c20fSFrederick Mayle         AddressType other_high, other_size, other_delta;
137*9712c20fSFrederick Mayle         other_high = iterator_high->first;
138*9712c20fSFrederick Mayle         RetrieveRange(other_high, &other_entry, &other_base, &other_delta,
139*9712c20fSFrederick Mayle                       &other_size);
140*9712c20fSFrederick Mayle         map_.erase(iterator_high);
141*9712c20fSFrederick Mayle         map_.insert(
142*9712c20fSFrederick Mayle             MapValue(base - 1, Range(other_base, other_delta, other_entry)));
143*9712c20fSFrederick Mayle         return StoreRangeInternal(base, delta, size, entry);
144*9712c20fSFrederick Mayle       } else {
145*9712c20fSFrederick Mayle         return false;
146*9712c20fSFrederick Mayle       }
147*9712c20fSFrederick Mayle     } else if (merge_strategy_ == MergeRangeStrategy::kTruncateUpper &&
148*9712c20fSFrederick Mayle                iterator_high->first > high) {
149*9712c20fSFrederick Mayle       // Shrink the other range down.
150*9712c20fSFrederick Mayle       AddressType other_high = iterator_high->first;
151*9712c20fSFrederick Mayle       AddressType additional_delta = high - iterator_high->second.base() + 1;
152*9712c20fSFrederick Mayle       EntryType other_entry;
153*9712c20fSFrederick Mayle       AddressType other_base = AddressType();
154*9712c20fSFrederick Mayle       AddressType other_size = AddressType();
155*9712c20fSFrederick Mayle       AddressType other_delta = AddressType();
156*9712c20fSFrederick Mayle       RetrieveRange(other_high, &other_entry, &other_base, &other_delta,
157*9712c20fSFrederick Mayle                     &other_size);
158*9712c20fSFrederick Mayle       map_.erase(iterator_high);
159*9712c20fSFrederick Mayle       map_.insert(MapValue(other_high,
160*9712c20fSFrederick Mayle                            Range(other_base + additional_delta,
161*9712c20fSFrederick Mayle                                  other_delta + additional_delta, other_entry)));
162*9712c20fSFrederick Mayle       // Retry to store this range.
163*9712c20fSFrederick Mayle       return StoreRangeInternal(base, delta, size, entry);
164*9712c20fSFrederick Mayle     } else {
165*9712c20fSFrederick Mayle       // The processor hits this case too frequently with common symbol files.
166*9712c20fSFrederick Mayle       // This is most appropriate for a DEBUG channel, but since none exists
167*9712c20fSFrederick Mayle       // now simply comment out this logging.
168*9712c20fSFrederick Mayle       //
169*9712c20fSFrederick Mayle       // AddressType other_base = iterator_high->second.base();
170*9712c20fSFrederick Mayle       // AddressType other_size = iterator_high->first - other_base + 1;
171*9712c20fSFrederick Mayle       // BPLOG(INFO) << "StoreRangeInternal failed, an existing range "
172*9712c20fSFrederick Mayle       //             << "contains or extends higher than the new range: new "
173*9712c20fSFrederick Mayle       //             << HexString(base) << "+" << HexString(size)
174*9712c20fSFrederick Mayle       //             << ", existing " << HexString(other_base) << "+"
175*9712c20fSFrederick Mayle       //             << HexString(other_size);
176*9712c20fSFrederick Mayle       return false;
177*9712c20fSFrederick Mayle     }
178*9712c20fSFrederick Mayle   }
179*9712c20fSFrederick Mayle 
180*9712c20fSFrederick Mayle   // Store the range in the map by its high address, so that lower_bound can
181*9712c20fSFrederick Mayle   // be used to quickly locate a range by address.
182*9712c20fSFrederick Mayle   map_.insert(MapValue(high, Range(base, delta, entry)));
183*9712c20fSFrederick Mayle   return true;
184*9712c20fSFrederick Mayle }
185*9712c20fSFrederick Mayle 
186*9712c20fSFrederick Mayle 
187*9712c20fSFrederick Mayle template<typename AddressType, typename EntryType>
RetrieveRange(const AddressType & address,EntryType * entry,AddressType * entry_base,AddressType * entry_delta,AddressType * entry_size)188*9712c20fSFrederick Mayle bool RangeMap<AddressType, EntryType>::RetrieveRange(
189*9712c20fSFrederick Mayle     const AddressType& address, EntryType* entry, AddressType* entry_base,
190*9712c20fSFrederick Mayle     AddressType* entry_delta, AddressType* entry_size) const {
191*9712c20fSFrederick Mayle   BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRange requires |entry|";
192*9712c20fSFrederick Mayle   assert(entry);
193*9712c20fSFrederick Mayle 
194*9712c20fSFrederick Mayle   MapConstIterator iterator = map_.lower_bound(address);
195*9712c20fSFrederick Mayle   if (iterator == map_.end())
196*9712c20fSFrederick Mayle     return false;
197*9712c20fSFrederick Mayle 
198*9712c20fSFrederick Mayle   // The map is keyed by the high address of each range, so |address| is
199*9712c20fSFrederick Mayle   // guaranteed to be lower than the range's high address.  If |range| is
200*9712c20fSFrederick Mayle   // not directly preceded by another range, it's possible for address to
201*9712c20fSFrederick Mayle   // be below the range's low address, though.  When that happens, address
202*9712c20fSFrederick Mayle   // references something not within any range, so return false.
203*9712c20fSFrederick Mayle   if (address < iterator->second.base())
204*9712c20fSFrederick Mayle     return false;
205*9712c20fSFrederick Mayle 
206*9712c20fSFrederick Mayle   *entry = iterator->second.entry();
207*9712c20fSFrederick Mayle   if (entry_base)
208*9712c20fSFrederick Mayle     *entry_base = iterator->second.base();
209*9712c20fSFrederick Mayle   if (entry_delta)
210*9712c20fSFrederick Mayle     *entry_delta = iterator->second.delta();
211*9712c20fSFrederick Mayle   if (entry_size)
212*9712c20fSFrederick Mayle     *entry_size = iterator->first - iterator->second.base() + 1;
213*9712c20fSFrederick Mayle 
214*9712c20fSFrederick Mayle   return true;
215*9712c20fSFrederick Mayle }
216*9712c20fSFrederick Mayle 
217*9712c20fSFrederick Mayle 
218*9712c20fSFrederick Mayle template<typename AddressType, typename EntryType>
RetrieveNearestRange(const AddressType & address,EntryType * entry,AddressType * entry_base,AddressType * entry_delta,AddressType * entry_size)219*9712c20fSFrederick Mayle bool RangeMap<AddressType, EntryType>::RetrieveNearestRange(
220*9712c20fSFrederick Mayle     const AddressType& address, EntryType* entry, AddressType* entry_base,
221*9712c20fSFrederick Mayle     AddressType* entry_delta, AddressType* entry_size) const {
222*9712c20fSFrederick Mayle   BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveNearestRange requires |entry|";
223*9712c20fSFrederick Mayle   assert(entry);
224*9712c20fSFrederick Mayle 
225*9712c20fSFrederick Mayle   // If address is within a range, RetrieveRange can handle it.
226*9712c20fSFrederick Mayle   if (RetrieveRange(address, entry, entry_base, entry_delta, entry_size))
227*9712c20fSFrederick Mayle     return true;
228*9712c20fSFrederick Mayle 
229*9712c20fSFrederick Mayle   // upper_bound gives the first element whose key is greater than address,
230*9712c20fSFrederick Mayle   // but we want the first element whose key is less than or equal to address.
231*9712c20fSFrederick Mayle   // Decrement the iterator to get there, but not if the upper_bound already
232*9712c20fSFrederick Mayle   // points to the beginning of the map - in that case, address is lower than
233*9712c20fSFrederick Mayle   // the lowest stored key, so return false.
234*9712c20fSFrederick Mayle   MapConstIterator iterator = map_.upper_bound(address);
235*9712c20fSFrederick Mayle   if (iterator == map_.begin())
236*9712c20fSFrederick Mayle     return false;
237*9712c20fSFrederick Mayle   --iterator;
238*9712c20fSFrederick Mayle 
239*9712c20fSFrederick Mayle   *entry = iterator->second.entry();
240*9712c20fSFrederick Mayle   if (entry_base)
241*9712c20fSFrederick Mayle     *entry_base = iterator->second.base();
242*9712c20fSFrederick Mayle   if (entry_delta)
243*9712c20fSFrederick Mayle     *entry_delta = iterator->second.delta();
244*9712c20fSFrederick Mayle   if (entry_size)
245*9712c20fSFrederick Mayle     *entry_size = iterator->first - iterator->second.base() + 1;
246*9712c20fSFrederick Mayle 
247*9712c20fSFrederick Mayle   return true;
248*9712c20fSFrederick Mayle }
249*9712c20fSFrederick Mayle 
250*9712c20fSFrederick Mayle 
251*9712c20fSFrederick Mayle template<typename AddressType, typename EntryType>
RetrieveRangeAtIndex(int index,EntryType * entry,AddressType * entry_base,AddressType * entry_delta,AddressType * entry_size)252*9712c20fSFrederick Mayle bool RangeMap<AddressType, EntryType>::RetrieveRangeAtIndex(
253*9712c20fSFrederick Mayle     int index, EntryType* entry, AddressType* entry_base,
254*9712c20fSFrederick Mayle     AddressType* entry_delta, AddressType* entry_size) const {
255*9712c20fSFrederick Mayle   BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRangeAtIndex requires |entry|";
256*9712c20fSFrederick Mayle   assert(entry);
257*9712c20fSFrederick Mayle 
258*9712c20fSFrederick Mayle   if (index >= GetCount()) {
259*9712c20fSFrederick Mayle     BPLOG(ERROR) << "Index out of range: " << index << "/" << GetCount();
260*9712c20fSFrederick Mayle     return false;
261*9712c20fSFrederick Mayle   }
262*9712c20fSFrederick Mayle 
263*9712c20fSFrederick Mayle   // Walk through the map.  Although it's ordered, it's not a vector, so it
264*9712c20fSFrederick Mayle   // can't be addressed directly by index.
265*9712c20fSFrederick Mayle   MapConstIterator iterator = map_.begin();
266*9712c20fSFrederick Mayle   for (int this_index = 0; this_index < index; ++this_index)
267*9712c20fSFrederick Mayle     ++iterator;
268*9712c20fSFrederick Mayle 
269*9712c20fSFrederick Mayle   *entry = iterator->second.entry();
270*9712c20fSFrederick Mayle   if (entry_base)
271*9712c20fSFrederick Mayle     *entry_base = iterator->second.base();
272*9712c20fSFrederick Mayle   if (entry_delta)
273*9712c20fSFrederick Mayle     *entry_delta = iterator->second.delta();
274*9712c20fSFrederick Mayle   if (entry_size)
275*9712c20fSFrederick Mayle     *entry_size = iterator->first - iterator->second.base() + 1;
276*9712c20fSFrederick Mayle 
277*9712c20fSFrederick Mayle   return true;
278*9712c20fSFrederick Mayle }
279*9712c20fSFrederick Mayle 
280*9712c20fSFrederick Mayle 
281*9712c20fSFrederick Mayle template<typename AddressType, typename EntryType>
GetCount()282*9712c20fSFrederick Mayle int RangeMap<AddressType, EntryType>::GetCount() const {
283*9712c20fSFrederick Mayle   return static_cast<int>(map_.size());
284*9712c20fSFrederick Mayle }
285*9712c20fSFrederick Mayle 
286*9712c20fSFrederick Mayle 
287*9712c20fSFrederick Mayle template<typename AddressType, typename EntryType>
Clear()288*9712c20fSFrederick Mayle void RangeMap<AddressType, EntryType>::Clear() {
289*9712c20fSFrederick Mayle   map_.clear();
290*9712c20fSFrederick Mayle }
291*9712c20fSFrederick Mayle 
292*9712c20fSFrederick Mayle 
293*9712c20fSFrederick Mayle }  // namespace google_breakpad
294*9712c20fSFrederick Mayle 
295*9712c20fSFrederick Mayle 
296*9712c20fSFrederick Mayle #endif  // PROCESSOR_RANGE_MAP_INL_H__
297