1 /**************************************************************************
3 * Copyright 2011-2012 Jose Fonseca
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
31 #include "retrace.hpp"
32 #include "retrace_swizzle.hpp"
41 unsigned long long size;
44 typedef std::map<unsigned long long, Region> RegionMap;
45 static RegionMap regionMap;
49 contains(RegionMap::iterator &it, unsigned long long address) {
50 return it->first <= address && (it->first + it->second.size) > address;
55 intersects(RegionMap::iterator &it, unsigned long long start, unsigned long long size) {
56 unsigned long it_start = it->first;
57 unsigned long it_stop = it->first + it->second.size;
58 unsigned long stop = start + size;
59 return it_start < stop && start < it_stop;
63 // Iterator to the first region that contains the address, or the first after
64 static RegionMap::iterator
65 lowerBound(unsigned long long address) {
66 RegionMap::iterator it = regionMap.lower_bound(address);
68 while (it != regionMap.begin()) {
69 RegionMap::iterator pred = it;
71 if (contains(pred, address)) {
79 if (it != regionMap.end()) {
80 assert(contains(it, address) || it->first > address);
87 // Iterator to the first region that starts after the address
88 static RegionMap::iterator
89 upperBound(unsigned long long address) {
90 RegionMap::iterator it = regionMap.upper_bound(address);
93 if (it != regionMap.end()) {
94 assert(it->first >= address);
102 addRegion(unsigned long long address, void *buffer, unsigned long long size)
104 if (retrace::verbosity >= 2) {
108 << "0x" << address << "-0x" << (address + size)
110 << "0x" << (uintptr_t)buffer << "-0x" << ((uintptr_t)buffer + size)
116 // Ignore NULL pointer
122 RegionMap::iterator start = lowerBound(address);
123 RegionMap::iterator stop = upperBound(address + size - 1);
125 // Forget all regions that intersect this new one.
126 regionMap.erase(start, stop);
128 for (RegionMap::iterator it = start; it != stop; ++it) {
129 std::cerr << std::hex << "warning: "
130 "region 0x" << address << "-0x" << (address + size) << " "
131 "intersects existing region 0x" << it->first << "-0x" << (it->first + it->second.size) << "\n" << std::dec;
132 assert(intersects(it, address, size));
140 region.buffer = buffer;
143 regionMap[address] = region;
146 static RegionMap::iterator
147 lookupRegion(unsigned long long address) {
148 RegionMap::iterator it = regionMap.lower_bound(address);
150 if (it == regionMap.end() ||
151 it->first > address) {
152 if (it == regionMap.begin()) {
153 return regionMap.end();
159 assert(contains(it, address));
164 delRegion(unsigned long long address) {
165 RegionMap::iterator it = lookupRegion(address);
166 if (it != regionMap.end()) {
175 delRegionByPointer(void *ptr) {
176 for (RegionMap::iterator it = regionMap.begin(); it != regionMap.end(); ++it) {
177 if (it->second.buffer == ptr) {
186 lookupAddress(unsigned long long address) {
187 RegionMap::iterator it = lookupRegion(address);
188 if (it != regionMap.end()) {
189 unsigned long long offset = address - it->first;
190 assert(offset < it->second.size);
191 void *addr = (char *)it->second.buffer + offset;
193 if (retrace::verbosity >= 2) {
199 << "0x" << (uintptr_t)addr
207 if (retrace::debug && address >= 64 * 1024 * 1024) {
208 /* Likely not an offset, but an address that should had been swizzled */
209 std::cerr << "warning: passing high address 0x" << std::hex << address << std::dec << " as uintptr_t\n";
212 return (void *)(uintptr_t)address;
216 class Translator : protected trace::Visitor
223 void visit(trace::Null *) {
227 void visit(trace::Blob *blob) {
228 result = blob->toPointer(bind);
231 void visit(trace::Pointer *p) {
232 result = lookupAddress(p->value);
236 Translator(bool _bind) :
241 void * operator() (trace::Value *node) {
249 toPointer(trace::Value &value, bool bind) {
250 return Translator(bind) (&value);
255 static std::map<unsigned long long, void *> _obj_map;
258 addObj(trace::Value &value, void *obj) {
259 unsigned long long address = value.toUIntPtr();
260 _obj_map[address] = obj;
262 if (retrace::verbosity >= 2) {
263 std::cout << std::hex << "obj 0x" << address << " -> 0x" << size_t(obj) << std::dec << "\n";
268 delObj(trace::Value &value) {
269 unsigned long long address = value.toUIntPtr();
270 _obj_map.erase(address);
274 toObjPointer(trace::Value &value) {
275 unsigned long long address = value.toUIntPtr();
276 void *obj = address ? _obj_map[address] : NULL;
278 if (retrace::verbosity >= 2) {
279 std::cout << std::hex << "obj 0x" << address << " <- 0x" << size_t(obj) << std::dec << "\n";