toolkit/crashreporter/google-breakpad/src/processor/range_map-inl.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 // Copyright (c) 2010 Google Inc.
michael@0 2 // All rights reserved.
michael@0 3 //
michael@0 4 // Redistribution and use in source and binary forms, with or without
michael@0 5 // modification, are permitted provided that the following conditions are
michael@0 6 // met:
michael@0 7 //
michael@0 8 // * Redistributions of source code must retain the above copyright
michael@0 9 // notice, this list of conditions and the following disclaimer.
michael@0 10 // * Redistributions in binary form must reproduce the above
michael@0 11 // copyright notice, this list of conditions and the following disclaimer
michael@0 12 // in the documentation and/or other materials provided with the
michael@0 13 // distribution.
michael@0 14 // * Neither the name of Google Inc. nor the names of its
michael@0 15 // contributors may be used to endorse or promote products derived from
michael@0 16 // this software without specific prior written permission.
michael@0 17 //
michael@0 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
michael@0 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
michael@0 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
michael@0 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
michael@0 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
michael@0 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
michael@0 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
michael@0 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
michael@0 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
michael@0 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 29
michael@0 30 // range_map-inl.h: Range map implementation.
michael@0 31 //
michael@0 32 // See range_map.h for documentation.
michael@0 33 //
michael@0 34 // Author: Mark Mentovai
michael@0 35
michael@0 36 #ifndef PROCESSOR_RANGE_MAP_INL_H__
michael@0 37 #define PROCESSOR_RANGE_MAP_INL_H__
michael@0 38
michael@0 39
michael@0 40 #include <assert.h>
michael@0 41
michael@0 42 #include "processor/range_map.h"
michael@0 43 #include "common/logging.h"
michael@0 44
michael@0 45
michael@0 46 namespace google_breakpad {
michael@0 47
michael@0 48
michael@0 49 template<typename AddressType, typename EntryType>
michael@0 50 bool RangeMap<AddressType, EntryType>::StoreRange(const AddressType &base,
michael@0 51 const AddressType &size,
michael@0 52 const EntryType &entry) {
michael@0 53 AddressType high = base + size - 1;
michael@0 54
michael@0 55 // Check for undersize or overflow.
michael@0 56 if (size <= 0 || high < base) {
michael@0 57 // The processor will hit this case too frequently with common symbol
michael@0 58 // files in the size == 0 case, which is more suited to a DEBUG channel.
michael@0 59 // Filter those out since there's no DEBUG channel at the moment.
michael@0 60 BPLOG_IF(INFO, size != 0) << "StoreRange failed, " << HexString(base) <<
michael@0 61 "+" << HexString(size) << ", " <<
michael@0 62 HexString(high);
michael@0 63 return false;
michael@0 64 }
michael@0 65
michael@0 66 // Ensure that this range does not overlap with another one already in the
michael@0 67 // map.
michael@0 68 MapConstIterator iterator_base = map_.lower_bound(base);
michael@0 69 MapConstIterator iterator_high = map_.lower_bound(high);
michael@0 70
michael@0 71 if (iterator_base != iterator_high) {
michael@0 72 // Some other range begins in the space used by this range. It may be
michael@0 73 // contained within the space used by this range, or it may extend lower.
michael@0 74 // Regardless, it is an error.
michael@0 75 AddressType other_base = iterator_base->second.base();
michael@0 76 AddressType other_size = iterator_base->first - other_base + 1;
michael@0 77 BPLOG(INFO) << "StoreRange failed, an existing range is contained by or "
michael@0 78 "extends lower than the new range: new " <<
michael@0 79 HexString(base) << "+" << HexString(size) << ", existing " <<
michael@0 80 HexString(other_base) << "+" << HexString(other_size);
michael@0 81 return false;
michael@0 82 }
michael@0 83
michael@0 84 if (iterator_high != map_.end()) {
michael@0 85 if (iterator_high->second.base() <= high) {
michael@0 86 // The range above this one overlaps with this one. It may fully
michael@0 87 // contain this range, or it may begin within this range and extend
michael@0 88 // higher. Regardless, it's an error.
michael@0 89 AddressType other_base = iterator_high->second.base();
michael@0 90 AddressType other_size = iterator_high->first - other_base + 1;
michael@0 91 BPLOG(INFO) << "StoreRange failed, an existing range contains or "
michael@0 92 "extends higher than the new range: new " <<
michael@0 93 HexString(base) << "+" << HexString(size) <<
michael@0 94 ", existing " <<
michael@0 95 HexString(other_base) << "+" << HexString(other_size);
michael@0 96 return false;
michael@0 97 }
michael@0 98 }
michael@0 99
michael@0 100 // Store the range in the map by its high address, so that lower_bound can
michael@0 101 // be used to quickly locate a range by address.
michael@0 102 map_.insert(MapValue(high, Range(base, entry)));
michael@0 103 return true;
michael@0 104 }
michael@0 105
michael@0 106
michael@0 107 template<typename AddressType, typename EntryType>
michael@0 108 bool RangeMap<AddressType, EntryType>::RetrieveRange(
michael@0 109 const AddressType &address, EntryType *entry,
michael@0 110 AddressType *entry_base, AddressType *entry_size) const {
michael@0 111 BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRange requires |entry|";
michael@0 112 assert(entry);
michael@0 113
michael@0 114 MapConstIterator iterator = map_.lower_bound(address);
michael@0 115 if (iterator == map_.end())
michael@0 116 return false;
michael@0 117
michael@0 118 // The map is keyed by the high address of each range, so |address| is
michael@0 119 // guaranteed to be lower than the range's high address. If |range| is
michael@0 120 // not directly preceded by another range, it's possible for address to
michael@0 121 // be below the range's low address, though. When that happens, address
michael@0 122 // references something not within any range, so return false.
michael@0 123 if (address < iterator->second.base())
michael@0 124 return false;
michael@0 125
michael@0 126 *entry = iterator->second.entry();
michael@0 127 if (entry_base)
michael@0 128 *entry_base = iterator->second.base();
michael@0 129 if (entry_size)
michael@0 130 *entry_size = iterator->first - iterator->second.base() + 1;
michael@0 131
michael@0 132 return true;
michael@0 133 }
michael@0 134
michael@0 135
michael@0 136 template<typename AddressType, typename EntryType>
michael@0 137 bool RangeMap<AddressType, EntryType>::RetrieveNearestRange(
michael@0 138 const AddressType &address, EntryType *entry,
michael@0 139 AddressType *entry_base, AddressType *entry_size) const {
michael@0 140 BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveNearestRange requires |entry|";
michael@0 141 assert(entry);
michael@0 142
michael@0 143 // If address is within a range, RetrieveRange can handle it.
michael@0 144 if (RetrieveRange(address, entry, entry_base, entry_size))
michael@0 145 return true;
michael@0 146
michael@0 147 // upper_bound gives the first element whose key is greater than address,
michael@0 148 // but we want the first element whose key is less than or equal to address.
michael@0 149 // Decrement the iterator to get there, but not if the upper_bound already
michael@0 150 // points to the beginning of the map - in that case, address is lower than
michael@0 151 // the lowest stored key, so return false.
michael@0 152 MapConstIterator iterator = map_.upper_bound(address);
michael@0 153 if (iterator == map_.begin())
michael@0 154 return false;
michael@0 155 --iterator;
michael@0 156
michael@0 157 *entry = iterator->second.entry();
michael@0 158 if (entry_base)
michael@0 159 *entry_base = iterator->second.base();
michael@0 160 if (entry_size)
michael@0 161 *entry_size = iterator->first - iterator->second.base() + 1;
michael@0 162
michael@0 163 return true;
michael@0 164 }
michael@0 165
michael@0 166
michael@0 167 template<typename AddressType, typename EntryType>
michael@0 168 bool RangeMap<AddressType, EntryType>::RetrieveRangeAtIndex(
michael@0 169 int index, EntryType *entry,
michael@0 170 AddressType *entry_base, AddressType *entry_size) const {
michael@0 171 BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRangeAtIndex requires |entry|";
michael@0 172 assert(entry);
michael@0 173
michael@0 174 if (index >= GetCount()) {
michael@0 175 BPLOG(ERROR) << "Index out of range: " << index << "/" << GetCount();
michael@0 176 return false;
michael@0 177 }
michael@0 178
michael@0 179 // Walk through the map. Although it's ordered, it's not a vector, so it
michael@0 180 // can't be addressed directly by index.
michael@0 181 MapConstIterator iterator = map_.begin();
michael@0 182 for (int this_index = 0; this_index < index; ++this_index)
michael@0 183 ++iterator;
michael@0 184
michael@0 185 *entry = iterator->second.entry();
michael@0 186 if (entry_base)
michael@0 187 *entry_base = iterator->second.base();
michael@0 188 if (entry_size)
michael@0 189 *entry_size = iterator->first - iterator->second.base() + 1;
michael@0 190
michael@0 191 return true;
michael@0 192 }
michael@0 193
michael@0 194
michael@0 195 template<typename AddressType, typename EntryType>
michael@0 196 int RangeMap<AddressType, EntryType>::GetCount() const {
michael@0 197 return map_.size();
michael@0 198 }
michael@0 199
michael@0 200
michael@0 201 template<typename AddressType, typename EntryType>
michael@0 202 void RangeMap<AddressType, EntryType>::Clear() {
michael@0 203 map_.clear();
michael@0 204 }
michael@0 205
michael@0 206
michael@0 207 } // namespace google_breakpad
michael@0 208
michael@0 209
michael@0 210 #endif // PROCESSOR_RANGE_MAP_INL_H__

mercurial