#include <string.h>
-#include "glproc.hpp"
-
#include "trace_parser.hpp"
typedef std::map<unsigned long long, Region> RegionMap;
static RegionMap regionMap;
-// Iterator to the first region that contains the address
+
+static inline bool
+contains(RegionMap::iterator &it, unsigned long long address) {
+ return it->first <= address && (it->first + it->second.size) > address;
+}
+
+
+static inline bool
+intersects(RegionMap::iterator &it, unsigned long long start, unsigned long long size) {
+ unsigned long it_start = it->first;
+ unsigned long it_stop = it->first + it->second.size;
+ unsigned long stop = start + size;
+ return it_start < stop && start < it_stop;
+}
+
+
+// Iterator to the first region that contains the address, or the first after
static RegionMap::iterator
lowerBound(unsigned long long address) {
RegionMap::iterator it = regionMap.lower_bound(address);
- while (it != regionMap.begin() &&
- it != regionMap.end() &&
- it->first + it->second. size > address) {
- --it;
+ while (it != regionMap.begin()) {
+ RegionMap::iterator pred = it;
+ --pred;
+ if (contains(pred, address)) {
+ it = pred;
+ } else {
+ break;
+ }
}
return it;
}
-// Iterator to the first region that not contains the address
+// Iterator to the first region that starts after the address
static RegionMap::iterator
upperBound(unsigned long long address) {
RegionMap::iterator it = regionMap.upper_bound(address);
- while (it != regionMap.end() &&
- it->first + it->second.size > address) {
- ++it;
- }
-
return it;
}
void
addRegion(unsigned long long address, void *buffer, unsigned long long size)
{
- // Forget all regions that intersect this new one.
+ if (retrace::verbosity >= 2) {
+ std::cout
+ << "region "
+ << std::hex
+ << "0x" << address << "-0x" << (address + size)
+ << " -> "
+ << "0x" << (uintptr_t)buffer << "-0x" << ((uintptr_t)buffer + size)
+ << std::dec
+ << "\n";
+ }
+
+ if (!address) {
+ // Ignore NULL pointer
+ assert(!buffer);
+ return;
+ }
+
+#ifndef NDEBUG
+ RegionMap::iterator start = lowerBound(address);
+ RegionMap::iterator stop = upperBound(address + size);
if (0) {
- RegionMap::iterator start = lowerBound(address);
- if (start != regionMap.end()) {
- RegionMap::iterator stop = upperBound(address + size);
- regionMap.erase(start, stop);
+ // Forget all regions that intersect this new one.
+ regionMap.erase(start, stop);
+ } else {
+ for (RegionMap::iterator it = start; it != stop; ++it) {
+ std::cerr << std::hex << "warning: "
+ "region 0x" << address << "-0x" << (address + size) << " "
+ "intersects existing region 0x" << it->first << "-0x" << (it->first + it->second.size) << "\n" << std::dec;
+ assert(intersects(it, address, size));
}
}
+#endif
assert(buffer);
}
}
- assert(it->first <= address);
- assert(it->first + it->second.size >= address);
+ assert(contains(it, address));
return it;
}
void
delRegionByPointer(void *ptr) {
- RegionMap::iterator it = regionMap.begin();
- while (it != regionMap.end()) {
+ for (RegionMap::iterator it = regionMap.begin(); it != regionMap.end(); ++it) {
if (it->second.buffer == ptr) {
regionMap.erase(it);
return;
if (it != regionMap.end()) {
unsigned long long offset = address - it->first;
assert(offset < it->second.size);
- return (char *)it->second.buffer + offset;
+ void *addr = (char *)it->second.buffer + offset;
+
+ if (retrace::verbosity >= 2) {
+ std::cout
+ << "region "
+ << std::hex
+ << "0x" << address
+ << " <- "
+ << "0x" << (uintptr_t)addr
+ << std::dec
+ << "\n";
+ }
+
+ return addr;
}
if (address >= 0x00400000) {
}
-class Translator : protected Trace::Visitor
+class Translator : protected trace::Visitor
{
protected:
bool bind;
void *result;
- void visit(Trace::Null *) {
+ void visit(trace::Null *) {
result = NULL;
}
- void visit(Trace::Blob *blob) {
+ void visit(trace::Blob *blob) {
result = blob->toPointer(bind);
}
- void visit(Trace::Pointer *p) {
+ void visit(trace::Pointer *p) {
result = lookupAddress(p->value);
}
result(NULL)
{}
- void * operator() (Trace::Value *node) {
+ void * operator() (trace::Value *node) {
_visit(node);
return result;
}
void *
-toPointer(Trace::Value &value, bool bind) {
+toPointer(trace::Value &value, bool bind) {
return Translator(bind) (&value);
}
-static void retrace_malloc(Trace::Call &call) {
+static void retrace_malloc(trace::Call &call) {
size_t size = call.arg(0).toUInt();
unsigned long long address = call.ret->toUIntPtr();
}
-static void retrace_memcpy(Trace::Call &call) {
+static void retrace_memcpy(trace::Call &call) {
void * dest = toPointer(call.arg(0));
void * src = toPointer(call.arg(1));
size_t n = call.arg(2).toUInt();