1 /**************************************************************************
3 * Copyright 2011 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 **************************************************************************/
35 #include "trace_parser.hpp"
36 #include "retrace.hpp"
44 unsigned long long size;
47 typedef std::map<unsigned long long, Region> RegionMap;
48 static RegionMap regionMap;
52 contains(RegionMap::iterator &it, unsigned long long address) {
53 return it->first <= address && (it->first + it->second.size) > address;
58 intersects(RegionMap::iterator &it, unsigned long long start, unsigned long long size) {
59 unsigned long it_start = it->first;
60 unsigned long it_stop = it->first + it->second.size;
61 unsigned long stop = start + size;
62 return it_start < stop && start < it_stop;
66 // Iterator to the first region that contains the address, or the first after
67 static RegionMap::iterator
68 lowerBound(unsigned long long address) {
69 RegionMap::iterator it = regionMap.lower_bound(address);
71 while (it != regionMap.begin()) {
72 RegionMap::iterator pred = it;
74 if (contains(pred, address)) {
84 // Iterator to the first region that starts after the address
85 static RegionMap::iterator
86 upperBound(unsigned long long address) {
87 RegionMap::iterator it = regionMap.upper_bound(address);
93 addRegion(unsigned long long address, void *buffer, unsigned long long size)
96 // Ignore NULL pointer
102 RegionMap::iterator start = lowerBound(address);
103 RegionMap::iterator stop = upperBound(address + size);
105 // Forget all regions that intersect this new one.
106 regionMap.erase(start, stop);
108 for (RegionMap::iterator it = start; it != stop; ++it) {
109 std::cerr << std::hex << "warning: "
110 "region 0x" << address << "-0x" << (address + size) << " "
111 "intersects existing region 0x" << it->first << "-0x" << (it->first + it->second.size) << "\n" << std::dec;
112 assert(intersects(it, address, size));
120 region.buffer = buffer;
123 regionMap[address] = region;
126 static RegionMap::iterator
127 lookupRegion(unsigned long long address) {
128 RegionMap::iterator it = regionMap.lower_bound(address);
130 if (it == regionMap.end() ||
131 it->first > address) {
132 if (it == regionMap.begin()) {
133 return regionMap.end();
139 assert(contains(it, address));
144 delRegion(unsigned long long address) {
145 RegionMap::iterator it = lookupRegion(address);
146 if (it != regionMap.end()) {
155 delRegionByPointer(void *ptr) {
156 for (RegionMap::iterator it = regionMap.begin(); it != regionMap.end(); ++it) {
157 if (it->second.buffer == ptr) {
166 lookupAddress(unsigned long long address) {
167 RegionMap::iterator it = lookupRegion(address);
168 if (it != regionMap.end()) {
169 unsigned long long offset = address - it->first;
170 assert(offset < it->second.size);
171 return (char *)it->second.buffer + offset;
174 if (address >= 0x00400000) {
175 std::cerr << "warning: could not translate address 0x" << std::hex << address << std::dec << "\n";
178 return (void *)(uintptr_t)address;
182 class Translator : protected trace::Visitor
189 void visit(trace::Null *) {
193 void visit(trace::Blob *blob) {
194 result = blob->toPointer(bind);
197 void visit(trace::Pointer *p) {
198 result = lookupAddress(p->value);
202 Translator(bool _bind) :
207 void * operator() (trace::Value *node) {
215 toPointer(trace::Value &value, bool bind) {
216 return Translator(bind) (&value);
220 static void retrace_malloc(trace::Call &call) {
221 size_t size = call.arg(0).toUInt();
222 unsigned long long address = call.ret->toUIntPtr();
228 void *buffer = malloc(size);
230 std::cerr << "error: failed to allocated " << size << " bytes.";
234 addRegion(address, buffer, size);
238 static void retrace_memcpy(trace::Call &call) {
239 void * dest = toPointer(call.arg(0));
240 void * src = toPointer(call.arg(1));
241 size_t n = call.arg(2).toUInt();
243 if (!dest || !src || !n) {
247 memcpy(dest, src, n);
251 const retrace::Entry stdc_callbacks[] = {
252 {"malloc", &retrace_malloc},
253 {"memcpy", &retrace_memcpy},