1*9712c20fSFrederick Mayle // Copyright 2006 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.h: Range maps. 30*9712c20fSFrederick Mayle // 31*9712c20fSFrederick Mayle // A range map associates a range of addresses with a specific object. This 32*9712c20fSFrederick Mayle // is useful when certain objects of variable size are located within an 33*9712c20fSFrederick Mayle // address space. The range map makes it simple to determine which object is 34*9712c20fSFrederick Mayle // associated with a specific address, which may be any address within the 35*9712c20fSFrederick Mayle // range associated with an object. 36*9712c20fSFrederick Mayle // 37*9712c20fSFrederick Mayle // Author: Mark Mentovai 38*9712c20fSFrederick Mayle 39*9712c20fSFrederick Mayle #ifndef PROCESSOR_RANGE_MAP_H__ 40*9712c20fSFrederick Mayle #define PROCESSOR_RANGE_MAP_H__ 41*9712c20fSFrederick Mayle 42*9712c20fSFrederick Mayle 43*9712c20fSFrederick Mayle #include <map> 44*9712c20fSFrederick Mayle 45*9712c20fSFrederick Mayle 46*9712c20fSFrederick Mayle namespace google_breakpad { 47*9712c20fSFrederick Mayle 48*9712c20fSFrederick Mayle // Forward declarations (for later friend declarations of specialized template). 49*9712c20fSFrederick Mayle template<class, class> class RangeMapSerializer; 50*9712c20fSFrederick Mayle 51*9712c20fSFrederick Mayle // Determines what happens when two ranges overlap. 52*9712c20fSFrederick Mayle enum class MergeRangeStrategy { 53*9712c20fSFrederick Mayle // When two ranges overlap, the new range fails to be inserted. The default 54*9712c20fSFrederick Mayle // strategy. 55*9712c20fSFrederick Mayle kExclusiveRanges, 56*9712c20fSFrederick Mayle 57*9712c20fSFrederick Mayle // The range with the lower base address will be truncated such that it's 58*9712c20fSFrederick Mayle // high address is one less than the range above it. 59*9712c20fSFrederick Mayle kTruncateLower, 60*9712c20fSFrederick Mayle 61*9712c20fSFrederick Mayle // The range with the greater high address has its range truncated such that 62*9712c20fSFrederick Mayle // its base address is one higher than the range below it. 63*9712c20fSFrederick Mayle kTruncateUpper 64*9712c20fSFrederick Mayle }; 65*9712c20fSFrederick Mayle 66*9712c20fSFrederick Mayle template<typename AddressType, typename EntryType> 67*9712c20fSFrederick Mayle class RangeMap { 68*9712c20fSFrederick Mayle public: RangeMap()69*9712c20fSFrederick Mayle RangeMap() : merge_strategy_(MergeRangeStrategy::kExclusiveRanges), map_() {} 70*9712c20fSFrederick Mayle SetMergeStrategy(MergeRangeStrategy strat)71*9712c20fSFrederick Mayle void SetMergeStrategy(MergeRangeStrategy strat) { merge_strategy_ = strat; } 72*9712c20fSFrederick Mayle GetMergeStrategy()73*9712c20fSFrederick Mayle MergeRangeStrategy GetMergeStrategy() const { return merge_strategy_; } 74*9712c20fSFrederick Mayle 75*9712c20fSFrederick Mayle // Inserts a range into the map. Returns false for a parameter error, 76*9712c20fSFrederick Mayle // or if the location of the range would conflict with a range already 77*9712c20fSFrederick Mayle // stored in the map. If enable_shrink_down is true and there is an overlap 78*9712c20fSFrederick Mayle // between the current range and some other range (already in the map), 79*9712c20fSFrederick Mayle // shrink down the range which ends at a higher address. 80*9712c20fSFrederick Mayle bool StoreRange(const AddressType& base, const AddressType& size, 81*9712c20fSFrederick Mayle const EntryType& entry); 82*9712c20fSFrederick Mayle 83*9712c20fSFrederick Mayle // Locates the range encompassing the supplied address. If there is no such 84*9712c20fSFrederick Mayle // range, returns false. entry_base, entry_delta, and entry_size, if 85*9712c20fSFrederick Mayle // non-NULL, are set to the base, delta, and size of the entry's range. 86*9712c20fSFrederick Mayle // A positive entry delta (> 0) indicates that there was an overlap and the 87*9712c20fSFrederick Mayle // entry was shrunk down (original start address was increased by delta). 88*9712c20fSFrederick Mayle bool RetrieveRange(const AddressType& address, EntryType* entry, 89*9712c20fSFrederick Mayle AddressType* entry_base, AddressType* entry_delta, 90*9712c20fSFrederick Mayle AddressType* entry_size) const; 91*9712c20fSFrederick Mayle 92*9712c20fSFrederick Mayle // Locates the range encompassing the supplied address, if one exists. 93*9712c20fSFrederick Mayle // If no range encompasses the supplied address, locates the nearest range 94*9712c20fSFrederick Mayle // to the supplied address that is lower than the address. Returns false 95*9712c20fSFrederick Mayle // if no range meets these criteria. entry_base, entry_delta, and entry_size, 96*9712c20fSFrederick Mayle // if non-NULL, are set to the base, delta, and size of the entry's range. 97*9712c20fSFrederick Mayle // A positive entry delta (> 0) indicates that there was an overlap and the 98*9712c20fSFrederick Mayle // entry was shrunk down (original start address was increased by delta). 99*9712c20fSFrederick Mayle bool RetrieveNearestRange(const AddressType& address, EntryType* entry, 100*9712c20fSFrederick Mayle AddressType* entry_base, AddressType* entry_delta, 101*9712c20fSFrederick Mayle AddressType* entry_size) const; 102*9712c20fSFrederick Mayle 103*9712c20fSFrederick Mayle // Treating all ranges as a list ordered by the address spaces that they 104*9712c20fSFrederick Mayle // occupy, locates the range at the index specified by index. Returns 105*9712c20fSFrederick Mayle // false if index is larger than the number of ranges stored. entry_base, 106*9712c20fSFrederick Mayle // entry_delta, and entry_size, if non-NULL, are set to the base, delta, and 107*9712c20fSFrederick Mayle // size of the entry's range. 108*9712c20fSFrederick Mayle // A positive entry delta (> 0) indicates that there was an overlap and the 109*9712c20fSFrederick Mayle // entry was shrunk down (original start address was increased by delta). 110*9712c20fSFrederick Mayle // 111*9712c20fSFrederick Mayle // RetrieveRangeAtIndex is not optimized for speedy operation. 112*9712c20fSFrederick Mayle bool RetrieveRangeAtIndex(int index, EntryType* entry, 113*9712c20fSFrederick Mayle AddressType* entry_base, AddressType* entry_delta, 114*9712c20fSFrederick Mayle AddressType* entry_size) const; 115*9712c20fSFrederick Mayle 116*9712c20fSFrederick Mayle // Returns the number of ranges stored in the RangeMap. 117*9712c20fSFrederick Mayle int GetCount() const; 118*9712c20fSFrederick Mayle 119*9712c20fSFrederick Mayle // Empties the range map, restoring it to the state it was when it was 120*9712c20fSFrederick Mayle // initially created. 121*9712c20fSFrederick Mayle void Clear(); 122*9712c20fSFrederick Mayle 123*9712c20fSFrederick Mayle private: 124*9712c20fSFrederick Mayle // Friend declarations. 125*9712c20fSFrederick Mayle friend class ModuleComparer; 126*9712c20fSFrederick Mayle friend class RangeMapSerializer<AddressType, EntryType>; 127*9712c20fSFrederick Mayle 128*9712c20fSFrederick Mayle // Same a StoreRange() with the only exception that the |delta| can be 129*9712c20fSFrederick Mayle // passed in. 130*9712c20fSFrederick Mayle bool StoreRangeInternal(const AddressType& base, const AddressType& delta, 131*9712c20fSFrederick Mayle const AddressType& size, const EntryType& entry); 132*9712c20fSFrederick Mayle 133*9712c20fSFrederick Mayle class Range { 134*9712c20fSFrederick Mayle public: Range(const AddressType & base,const AddressType & delta,const EntryType & entry)135*9712c20fSFrederick Mayle Range(const AddressType& base, const AddressType& delta, 136*9712c20fSFrederick Mayle const EntryType& entry) 137*9712c20fSFrederick Mayle : base_(base), delta_(delta), entry_(entry) {} 138*9712c20fSFrederick Mayle base()139*9712c20fSFrederick Mayle AddressType base() const { return base_; } delta()140*9712c20fSFrederick Mayle AddressType delta() const { return delta_; } entry()141*9712c20fSFrederick Mayle EntryType entry() const { return entry_; } 142*9712c20fSFrederick Mayle 143*9712c20fSFrederick Mayle private: 144*9712c20fSFrederick Mayle // The base address of the range. The high address does not need to 145*9712c20fSFrederick Mayle // be stored, because RangeMap uses it as the key to the map. 146*9712c20fSFrederick Mayle const AddressType base_; 147*9712c20fSFrederick Mayle 148*9712c20fSFrederick Mayle // The delta when the range is shrunk down. 149*9712c20fSFrederick Mayle const AddressType delta_; 150*9712c20fSFrederick Mayle 151*9712c20fSFrederick Mayle // The entry corresponding to a range. 152*9712c20fSFrederick Mayle const EntryType entry_; 153*9712c20fSFrederick Mayle }; 154*9712c20fSFrederick Mayle 155*9712c20fSFrederick Mayle // Convenience types. 156*9712c20fSFrederick Mayle typedef std::map<AddressType, Range> AddressToRangeMap; 157*9712c20fSFrederick Mayle typedef typename AddressToRangeMap::const_iterator MapConstIterator; 158*9712c20fSFrederick Mayle typedef typename AddressToRangeMap::value_type MapValue; 159*9712c20fSFrederick Mayle 160*9712c20fSFrederick Mayle MergeRangeStrategy merge_strategy_; 161*9712c20fSFrederick Mayle 162*9712c20fSFrederick Mayle // Maps the high address of each range to a EntryType. 163*9712c20fSFrederick Mayle AddressToRangeMap map_; 164*9712c20fSFrederick Mayle }; 165*9712c20fSFrederick Mayle 166*9712c20fSFrederick Mayle 167*9712c20fSFrederick Mayle } // namespace google_breakpad 168*9712c20fSFrederick Mayle 169*9712c20fSFrederick Mayle 170*9712c20fSFrederick Mayle #endif // PROCESSOR_RANGE_MAP_H__ 171