void delRegion(unsigned long long address) { RegionMap::iterator it = lookupRegion(address); if (it != regionMap.end()) { regionMap.erase(it); } else { assert(0); } }
void delRegionByPointer(void *ptr) { for (RegionMap::iterator it = regionMap.begin(); it != regionMap.end(); ++it) { if (it->second.buffer == ptr) { regionMap.erase(it); return; } } assert(0); }
// Iterator to the first region that not contains 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; }
// 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); #ifndef NDEBUG if (it != regionMap.end()) { assert(it->first >= address); } #endif return it; }
Void Planet::DestroyMoonRegion( MoonID iMoonID, const RegionCoords & vRegionCoords ) { Assert( iMoonID < m_iMoonCount ); RegionMap * pMap = m_arrMoons[iMoonID]; if ( pMap->Contains(vRegionCoords) ) { Region * pRegion = (*pMap)[vRegionCoords]; BlockWorldFn->SelectMemory( TEXT("Regions") ); Delete( pRegion ); BlockWorldFn->UnSelectMemory(); Bool bRemoved = pMap->Remove( vRegionCoords ); Assert( bRemoved ); } }
void * lookupAddress(unsigned long long address) { RegionMap::iterator it = lookupRegion(address); if (it != regionMap.end()) { unsigned long long offset = address - it->first; assert(offset < it->second.size); 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 (retrace::debug && address >= 64 * 1024 * 1024) { /* Likely not an offset, but an address that should had been swizzled */ std::cerr << "warning: passing high address 0x" << std::hex << address << std::dec << " as uintptr_t\n"; } return (void *)(uintptr_t)address; }
static RegionMap::iterator lookupRegion(unsigned long long address) { RegionMap::iterator it = regionMap.lower_bound(address); if (it == regionMap.end() || it->first > address) { if (it == regionMap.begin()) { return regionMap.end(); } else { --it; } } assert(contains(it, address)); return it; }
Region * Planet::CreateMoonRegion( MoonID iMoonID, const RegionCoords & vRegionCoords ) { Assert( iMoonID < m_iMoonCount ); RegionMap * pMap = m_arrMoons[iMoonID]; if ( pMap->Contains(vRegionCoords) ) return (*pMap)[vRegionCoords]; BlockWorldFn->SelectMemory( TEXT("Regions") ); Region * pRegion = New Region( this, iMoonID, vRegionCoords ); BlockWorldFn->UnSelectMemory(); Bool bInserted = pMap->Insert( vRegionCoords, pRegion ); Assert( bInserted ); return pRegion; }
void addRegion(unsigned long long address, void *buffer, unsigned long long size) { // Forget all regions that intersect this new one. if (0) { RegionMap::iterator start = lowerBound(address); if (start != regionMap.end()) { RegionMap::iterator stop = upperBound(address + size); regionMap.erase(start, stop); } } assert(buffer); Region region; region.buffer = buffer; region.size = size; regionMap[address] = region; }
Void Planet::DestroyRegion( RegionLayer iRegionLayer, const RegionCoords & vRegionCoords ) { RegionMap * pMap = NULL; switch( iRegionLayer ) { case REGION_LAYER_UNDERGROUND: pMap = &m_mapUndergroundRegions; break; case REGION_LAYER_SURFACE: pMap = &m_mapSurfaceRegions; break; case REGION_LAYER_ATMOSPHERE: pMap = &m_mapAtmosphereRegions; break; default: Assert( false ); break; } if ( pMap->Contains(vRegionCoords) ) { Region * pRegion = (*pMap)[vRegionCoords]; BlockWorldFn->SelectMemory( TEXT("Regions") ); Delete( pRegion ); BlockWorldFn->UnSelectMemory(); Bool bRemoved = pMap->Remove( vRegionCoords ); Assert( bRemoved ); } }
void setRegionPitch(unsigned long long address, unsigned dimensions, int tracePitch, int realPitch) { RegionMap::iterator it = lookupRegion(address); if (it != regionMap.end()) { Region ®ion = it->second; region.dimensions = dimensions; region.tracePitch = tracePitch; region.realPitch = realPitch; } else { assert(0); } }
// 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()) { RegionMap::iterator pred = it; --pred; if (contains(pred, address)) { it = pred; } else { break; } } #ifndef NDEBUG if (it != regionMap.end()) { assert(contains(it, address) || it->first > address); } #endif return it; }
Region * Planet::CreateRegion( RegionLayer iRegionLayer, const RegionCoords & vRegionCoords ) { RegionMap * pMap = NULL; switch( iRegionLayer ) { case REGION_LAYER_UNDERGROUND: pMap = &m_mapUndergroundRegions; break; case REGION_LAYER_SURFACE: pMap = &m_mapSurfaceRegions; break; case REGION_LAYER_ATMOSPHERE: pMap = &m_mapAtmosphereRegions; break; default: Assert( false ); break; } if ( pMap->Contains(vRegionCoords) ) return (*pMap)[vRegionCoords]; BlockWorldFn->SelectMemory( TEXT("Regions") ); Region * pRegion = New Region( this, iRegionLayer, vRegionCoords ); BlockWorldFn->UnSelectMemory(); Bool bInserted = pMap->Insert( vRegionCoords, pRegion ); Assert( bInserted ); return pRegion; }
void addRegion(trace::Call &call, unsigned long long address, void *buffer, unsigned long long size) { 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 == nullptr); return; } const bool debug = #ifdef NDEBUG false #else true #endif ; if (debug) { RegionMap::iterator start = lowerBound(address); RegionMap::iterator stop = upperBound(address + size - 1); if (0) { // Forget all regions that intersect this new one. regionMap.erase(start, stop); } else { for (RegionMap::iterator it = start; it != stop; ++it) { warning(call) << std::hex << "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)); } } } assert(buffer); Region region; region.buffer = buffer; region.size = size; regionMap[address] = region; }
void * lookupAddress(unsigned long long address) { RegionMap::iterator it = lookupRegion(address); if (it != regionMap.end()) { unsigned long long offset = address - it->first; assert(offset < it->second.size); return (char *)it->second.buffer + offset; } if (address >= 0x00400000) { std::cerr << "warning: could not translate address 0x" << std::hex << address << std::dec << "\n"; } return (void *)(uintptr_t)address; }
static void lookupAddress(unsigned long long address, Range &range) { RegionMap::const_iterator it = lookupRegion(address); if (it != regionMap.end()) { const Region & region = it->second; unsigned long long offset = address - it->first; assert(offset < region.size); range.ptr = (char *)region.buffer + offset; range.len = region.size - offset; range.dims = region.dimensions; range.tracePitch = region.tracePitch; range.realPitch = region.realPitch; if (retrace::verbosity >= 2) { std::cout << "region " << std::hex << "0x" << address << " <- " << "0x" << (uintptr_t)range.ptr << std::dec << "\n"; } return; } if (retrace::debug > 0 && address >= 64 * 1024 * 1024) { /* Likely not an offset, but an address that should had been swizzled */ std::cerr << "warning: passing high address 0x" << std::hex << address << std::dec << " as uintptr_t\n"; } range.ptr = (void *)(uintptr_t)address; range.len = 0; }
namespace retrace { struct Region { void *buffer; unsigned long long size; }; typedef std::map<unsigned long long, Region> RegionMap; static RegionMap regionMap; 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()) { RegionMap::iterator pred = it; --pred; if (contains(pred, address)) { it = pred; } else { break; } } #ifndef NDEBUG if (it != regionMap.end()) { assert(contains(it, address) || it->first > address); } #endif return it; } // 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); #ifndef NDEBUG if (it != regionMap.end()) { assert(it->first >= address); } #endif return it; } void addRegion(unsigned long long address, void *buffer, unsigned long long size) { 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 - 1); if (0) { // 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); Region region; region.buffer = buffer; region.size = size; regionMap[address] = region; } static RegionMap::iterator lookupRegion(unsigned long long address) { RegionMap::iterator it = regionMap.lower_bound(address); if (it == regionMap.end() || it->first > address) { if (it == regionMap.begin()) { return regionMap.end(); } else { --it; } } assert(contains(it, address)); return it; } void delRegion(unsigned long long address) { RegionMap::iterator it = lookupRegion(address); if (it != regionMap.end()) { regionMap.erase(it); } else { assert(0); } } void delRegionByPointer(void *ptr) { for (RegionMap::iterator it = regionMap.begin(); it != regionMap.end(); ++it) { if (it->second.buffer == ptr) { regionMap.erase(it); return; } } assert(0); } void * lookupAddress(unsigned long long address) { RegionMap::iterator it = lookupRegion(address); if (it != regionMap.end()) { unsigned long long offset = address - it->first; assert(offset < it->second.size); 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 (retrace::debug && address >= 64 * 1024 * 1024) { /* Likely not an offset, but an address that should had been swizzled */ std::cerr << "warning: passing high address 0x" << std::hex << address << std::dec << " as uintptr_t\n"; } return (void *)(uintptr_t)address; } class Translator : protected trace::Visitor { protected: bool bind; void *result; void visit(trace::Null *) { result = NULL; } void visit(trace::Blob *blob) { result = blob->toPointer(bind); } void visit(trace::Pointer *p) { result = lookupAddress(p->value); } public: Translator(bool _bind) : bind(_bind), result(NULL) {} void * operator() (trace::Value *node) { _visit(node); return result; } }; void * toPointer(trace::Value &value, bool bind) { return Translator(bind) (&value); } static std::map<unsigned long long, void *> _obj_map; void addObj(trace::Call &call, trace::Value &value, void *obj) { unsigned long long address = value.toUIntPtr(); if (!address) { if (obj) { warning(call) << "unexpected non-null object\n"; } return; } if (!obj) { warning(call) << "got null for object 0x" << std::hex << address << std::dec << "\n"; } _obj_map[address] = obj; if (retrace::verbosity >= 2) { std::cout << std::hex << "obj 0x" << address << " -> 0x" << size_t(obj) << std::dec << "\n"; } } void delObj(trace::Value &value) { unsigned long long address = value.toUIntPtr(); _obj_map.erase(address); if (retrace::verbosity >= 2) { std::cout << std::hex << "obj 0x" << address << " del\n"; } } void * toObjPointer(trace::Call &call, trace::Value &value) { unsigned long long address = value.toUIntPtr(); void *obj; if (address) { obj = _obj_map[address]; if (!obj) { warning(call) << "unknown object 0x" << std::hex << address << std::dec << "\n"; } } else { obj = NULL; } if (retrace::verbosity >= 2) { std::cout << std::hex << "obj 0x" << address << " <- 0x" << size_t(obj) << std::dec << "\n"; } return obj; } } /* retrace */
namespace retrace { struct Region { void *buffer; unsigned long long size; }; typedef std::map<unsigned long long, Region> RegionMap; static RegionMap regionMap; // Iterator to the first region that contains the address 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; } return it; } // Iterator to the first region that not contains 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 (0) { RegionMap::iterator start = lowerBound(address); if (start != regionMap.end()) { RegionMap::iterator stop = upperBound(address + size); regionMap.erase(start, stop); } } assert(buffer); Region region; region.buffer = buffer; region.size = size; regionMap[address] = region; } static RegionMap::iterator lookupRegion(unsigned long long address) { RegionMap::iterator it = regionMap.lower_bound(address); if (it == regionMap.end() || it->first > address) { if (it == regionMap.begin()) { return regionMap.end(); } else { --it; } } assert(it->first <= address); assert(it->first + it->second.size >= address); return it; } void delRegion(unsigned long long address) { RegionMap::iterator it = lookupRegion(address); if (it != regionMap.end()) { regionMap.erase(it); } else { assert(0); } } void delRegionByPointer(void *ptr) { RegionMap::iterator it = regionMap.begin(); while (it != regionMap.end()) { if (it->second.buffer == ptr) { regionMap.erase(it); return; } } assert(0); } void * lookupAddress(unsigned long long address) { RegionMap::iterator it = lookupRegion(address); if (it != regionMap.end()) { unsigned long long offset = address - it->first; assert(offset < it->second.size); return (char *)it->second.buffer + offset; } if (address >= 0x00400000) { std::cerr << "warning: could not translate address 0x" << std::hex << address << std::dec << "\n"; } return (void *)(uintptr_t)address; } class Translator : protected trace::Visitor { protected: bool bind; void *result; void visit(trace::Null *) { result = NULL; } void visit(trace::Blob *blob) { result = blob->toPointer(bind); } void visit(trace::Pointer *p) { result = lookupAddress(p->value); } public: Translator(bool _bind) : bind(_bind), result(NULL) {} void * operator() (trace::Value *node) { _visit(node); return result; } }; void * toPointer(trace::Value &value, bool bind) { return Translator(bind) (&value); } static void retrace_malloc(trace::Call &call) { size_t size = call.arg(0).toUInt(); unsigned long long address = call.ret->toUIntPtr(); if (!address) { return; } void *buffer = malloc(size); if (!buffer) { std::cerr << "error: failed to allocated " << size << " bytes."; return; } addRegion(address, buffer, size); } 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(); if (!dest || !src || !n) { return; } memcpy(dest, src, n); } const retrace::Entry stdc_callbacks[] = { {"malloc", &retrace_malloc}, {"memcpy", &retrace_memcpy}, {NULL, NULL} }; } /* retrace */