/* 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_