1*9712c20fSFrederick Mayle // Copyright 2011 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 // memory_range.h: Define the google_breakpad::MemoryRange class, which 30*9712c20fSFrederick Mayle // is a lightweight wrapper with a pointer and a length to encapsulate 31*9712c20fSFrederick Mayle // a contiguous range of memory. 32*9712c20fSFrederick Mayle 33*9712c20fSFrederick Mayle #ifndef COMMON_MEMORY_RANGE_H_ 34*9712c20fSFrederick Mayle #define COMMON_MEMORY_RANGE_H_ 35*9712c20fSFrederick Mayle 36*9712c20fSFrederick Mayle #include <stddef.h> 37*9712c20fSFrederick Mayle 38*9712c20fSFrederick Mayle #include "google_breakpad/common/breakpad_types.h" 39*9712c20fSFrederick Mayle 40*9712c20fSFrederick Mayle namespace google_breakpad { 41*9712c20fSFrederick Mayle 42*9712c20fSFrederick Mayle // A lightweight wrapper with a pointer and a length to encapsulate a 43*9712c20fSFrederick Mayle // contiguous range of memory. It provides helper methods for checked 44*9712c20fSFrederick Mayle // access of a subrange of the memory. Its implemementation does not 45*9712c20fSFrederick Mayle // allocate memory or call into libc functions, and is thus safer to use 46*9712c20fSFrederick Mayle // in a crashed environment. 47*9712c20fSFrederick Mayle class MemoryRange { 48*9712c20fSFrederick Mayle public: MemoryRange()49*9712c20fSFrederick Mayle MemoryRange() : data_(NULL), length_(0) {} 50*9712c20fSFrederick Mayle MemoryRange(const void * data,size_t length)51*9712c20fSFrederick Mayle MemoryRange(const void* data, size_t length) { 52*9712c20fSFrederick Mayle Set(data, length); 53*9712c20fSFrederick Mayle } 54*9712c20fSFrederick Mayle 55*9712c20fSFrederick Mayle // Returns true if this memory range contains no data. IsEmpty()56*9712c20fSFrederick Mayle bool IsEmpty() const { 57*9712c20fSFrederick Mayle // Set() guarantees that |length_| is zero if |data_| is NULL. 58*9712c20fSFrederick Mayle return length_ == 0; 59*9712c20fSFrederick Mayle } 60*9712c20fSFrederick Mayle 61*9712c20fSFrederick Mayle // Resets to an empty range. Reset()62*9712c20fSFrederick Mayle void Reset() { 63*9712c20fSFrederick Mayle data_ = NULL; 64*9712c20fSFrederick Mayle length_ = 0; 65*9712c20fSFrederick Mayle } 66*9712c20fSFrederick Mayle 67*9712c20fSFrederick Mayle // Sets this memory range to point to |data| and its length to |length|. Set(const void * data,size_t length)68*9712c20fSFrederick Mayle void Set(const void* data, size_t length) { 69*9712c20fSFrederick Mayle data_ = reinterpret_cast<const uint8_t*>(data); 70*9712c20fSFrederick Mayle // Always set |length_| to zero if |data_| is NULL. 71*9712c20fSFrederick Mayle length_ = data ? length : 0; 72*9712c20fSFrederick Mayle } 73*9712c20fSFrederick Mayle 74*9712c20fSFrederick Mayle // Returns true if this range covers a subrange of |sub_length| bytes 75*9712c20fSFrederick Mayle // at |sub_offset| bytes of this memory range, or false otherwise. Covers(size_t sub_offset,size_t sub_length)76*9712c20fSFrederick Mayle bool Covers(size_t sub_offset, size_t sub_length) const { 77*9712c20fSFrederick Mayle // The following checks verify that: 78*9712c20fSFrederick Mayle // 1. sub_offset is within [ 0 .. length_ - 1 ] 79*9712c20fSFrederick Mayle // 2. sub_offset + sub_length is within 80*9712c20fSFrederick Mayle // [ sub_offset .. length_ ] 81*9712c20fSFrederick Mayle return sub_offset < length_ && 82*9712c20fSFrederick Mayle sub_offset + sub_length >= sub_offset && 83*9712c20fSFrederick Mayle sub_offset + sub_length <= length_; 84*9712c20fSFrederick Mayle } 85*9712c20fSFrederick Mayle 86*9712c20fSFrederick Mayle // Returns a raw data pointer to a subrange of |sub_length| bytes at 87*9712c20fSFrederick Mayle // |sub_offset| bytes of this memory range, or NULL if the subrange 88*9712c20fSFrederick Mayle // is out of bounds. GetData(size_t sub_offset,size_t sub_length)89*9712c20fSFrederick Mayle const void* GetData(size_t sub_offset, size_t sub_length) const { 90*9712c20fSFrederick Mayle return Covers(sub_offset, sub_length) ? (data_ + sub_offset) : NULL; 91*9712c20fSFrederick Mayle } 92*9712c20fSFrederick Mayle 93*9712c20fSFrederick Mayle // Same as the two-argument version of GetData() but uses sizeof(DataType) 94*9712c20fSFrederick Mayle // as the subrange length and returns an |DataType| pointer for convenience. 95*9712c20fSFrederick Mayle template <typename DataType> GetData(size_t sub_offset)96*9712c20fSFrederick Mayle const DataType* GetData(size_t sub_offset) const { 97*9712c20fSFrederick Mayle return reinterpret_cast<const DataType*>( 98*9712c20fSFrederick Mayle GetData(sub_offset, sizeof(DataType))); 99*9712c20fSFrederick Mayle } 100*9712c20fSFrederick Mayle 101*9712c20fSFrederick Mayle // Returns a raw pointer to the |element_index|-th element of an array 102*9712c20fSFrederick Mayle // of elements of length |element_size| starting at |sub_offset| bytes 103*9712c20fSFrederick Mayle // of this memory range, or NULL if the element is out of bounds. GetArrayElement(size_t element_offset,size_t element_size,unsigned element_index)104*9712c20fSFrederick Mayle const void* GetArrayElement(size_t element_offset, 105*9712c20fSFrederick Mayle size_t element_size, 106*9712c20fSFrederick Mayle unsigned element_index) const { 107*9712c20fSFrederick Mayle size_t sub_offset = element_offset + element_index * element_size; 108*9712c20fSFrederick Mayle return GetData(sub_offset, element_size); 109*9712c20fSFrederick Mayle } 110*9712c20fSFrederick Mayle 111*9712c20fSFrederick Mayle // Same as the three-argument version of GetArrayElement() but deduces 112*9712c20fSFrederick Mayle // the element size using sizeof(ElementType) and returns an |ElementType| 113*9712c20fSFrederick Mayle // pointer for convenience. 114*9712c20fSFrederick Mayle template <typename ElementType> GetArrayElement(size_t element_offset,unsigned element_index)115*9712c20fSFrederick Mayle const ElementType* GetArrayElement(size_t element_offset, 116*9712c20fSFrederick Mayle unsigned element_index) const { 117*9712c20fSFrederick Mayle return reinterpret_cast<const ElementType*>( 118*9712c20fSFrederick Mayle GetArrayElement(element_offset, sizeof(ElementType), element_index)); 119*9712c20fSFrederick Mayle } 120*9712c20fSFrederick Mayle 121*9712c20fSFrederick Mayle // Returns a subrange of |sub_length| bytes at |sub_offset| bytes of 122*9712c20fSFrederick Mayle // this memory range, or an empty range if the subrange is out of bounds. Subrange(size_t sub_offset,size_t sub_length)123*9712c20fSFrederick Mayle MemoryRange Subrange(size_t sub_offset, size_t sub_length) const { 124*9712c20fSFrederick Mayle return Covers(sub_offset, sub_length) ? 125*9712c20fSFrederick Mayle MemoryRange(data_ + sub_offset, sub_length) : MemoryRange(); 126*9712c20fSFrederick Mayle } 127*9712c20fSFrederick Mayle 128*9712c20fSFrederick Mayle // Returns a pointer to the beginning of this memory range. data()129*9712c20fSFrederick Mayle const uint8_t* data() const { return data_; } 130*9712c20fSFrederick Mayle 131*9712c20fSFrederick Mayle // Returns the length, in bytes, of this memory range. length()132*9712c20fSFrederick Mayle size_t length() const { return length_; } 133*9712c20fSFrederick Mayle 134*9712c20fSFrederick Mayle private: 135*9712c20fSFrederick Mayle // Pointer to the beginning of this memory range. 136*9712c20fSFrederick Mayle const uint8_t* data_; 137*9712c20fSFrederick Mayle 138*9712c20fSFrederick Mayle // Length, in bytes, of this memory range. 139*9712c20fSFrederick Mayle size_t length_; 140*9712c20fSFrederick Mayle }; 141*9712c20fSFrederick Mayle 142*9712c20fSFrederick Mayle } // namespace google_breakpad 143*9712c20fSFrederick Mayle 144*9712c20fSFrederick Mayle #endif // COMMON_MEMORY_RANGE_H_ 145