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.

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

mercurial