| /* Copyright (c) 2008-2010, Google Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| // This file is part of ThreadSanitizer, a dynamic data race detector. |
| // Author: Konstantin Serebryany. |
| // Author: Timur Iskhodzhanov. |
| #ifndef TS_HEAP_INFO_ |
| #define TS_HEAP_INFO_ |
| |
| #include "ts_util.h" |
| |
| // Information about heap memory. |
| // For each heap allocation we create a struct HeapInfo. |
| // This struct should have fields 'uintptr_t ptr' and 'uintptr_t size', |
| // a default CTOR and a copy CTOR. |
| |
| template<class HeapInfo> |
| class HeapMap { |
| public: |
| typedef map<uintptr_t, HeapInfo> map_t; |
| typedef typename map_t::iterator iterator; |
| |
| HeapMap() { Reset(); } |
| |
| iterator begin() { return ++map_.begin(); } |
| iterator end() { return --map_.end(); } |
| |
| size_t size() { return map_.size() - 2; } |
| |
| void InsertInfo(uintptr_t a, HeapInfo info) { |
| CHECK(IsValidPtr(a)); |
| CHECK(info.ptr == a); |
| map_[a] = info; |
| } |
| |
| void EraseInfo(uintptr_t a) { |
| CHECK(IsValidPtr(a)); |
| map_.erase(a); |
| } |
| |
| void EraseRange(uintptr_t start, uintptr_t end) { |
| CHECK(IsValidPtr(start)); |
| CHECK(IsValidPtr(end)); |
| // TODO(glider): the [start, end) range may cover several map_ records. |
| EraseInfo(start); |
| } |
| |
| HeapInfo *GetInfo(uintptr_t a) { |
| CHECK(this); |
| CHECK(IsValidPtr(a)); |
| typename map_t::iterator it = map_.lower_bound(a); |
| CHECK(it != map_.end()); |
| if (it->second.ptr == a) { |
| // Exact match. 'a' is the beginning of a heap-allocated address. |
| return &it->second; |
| } |
| CHECK(a < it->second.ptr); |
| CHECK(it != map_.begin()); |
| // not an exact match, try the previous iterator. |
| --it; |
| HeapInfo *info = &it->second; |
| CHECK(info->ptr < a); |
| if (info->ptr + info->size > a) { |
| // within the range. |
| return info; |
| } |
| return NULL; |
| } |
| |
| void Clear() { |
| map_.clear(); |
| Reset(); |
| } |
| |
| private: |
| bool IsValidPtr(uintptr_t a) { |
| return a != 0 && a != (uintptr_t) -1; |
| } |
| void Reset() { |
| // Insert a maximal and minimal possible values to make GetInfo simpler. |
| HeapInfo max_info; |
| memset(&max_info, 0, sizeof(HeapInfo)); |
| max_info.ptr = (uintptr_t)-1; |
| map_[max_info.ptr] = max_info; |
| |
| HeapInfo min_info; |
| memset(&min_info, 0, sizeof(HeapInfo)); |
| map_[min_info.ptr] = min_info; |
| } |
| map_t map_; |
| }; |
| |
| #endif // TS_HEAP_INFO_ |