From ab8142ff4ab07a92565676ead5b0ad4607492cbc Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Sun, 13 May 2012 10:04:19 +0100 Subject: [PATCH] Split retrace swizlling helpers. --- retrace/CMakeLists.txt | 3 +- retrace/retrace.hpp | 52 -------- retrace/retrace.py | 1 + retrace/retrace_stdc.cpp | 224 ++------------------------------- retrace/retrace_swizzle.cpp | 242 ++++++++++++++++++++++++++++++++++++ retrace/retrace_swizzle.hpp | 92 ++++++++++++++ 6 files changed, 343 insertions(+), 271 deletions(-) create mode 100644 retrace/retrace_swizzle.cpp create mode 100644 retrace/retrace_swizzle.hpp diff --git a/retrace/CMakeLists.txt b/retrace/CMakeLists.txt index 00cef67..63fbed6 100644 --- a/retrace/CMakeLists.txt +++ b/retrace/CMakeLists.txt @@ -35,6 +35,7 @@ add_library (retrace_common retrace.cpp retrace_main.cpp retrace_stdc.cpp + retrace_swizzle.cpp ) target_link_libraries (retrace_common @@ -145,8 +146,6 @@ if (WIN32 AND DirectX_D3DX9_INCLUDE_DIR) include_directories (SYSTEM ${DirectX_D3DX9_INCLUDE_DIR}) add_executable (d3dretrace - retrace.cpp - retrace_stdc.cpp d3dretrace_main.cpp d3dretrace_d3d9.cpp d3dretrace_ws.cpp diff --git a/retrace/retrace.hpp b/retrace/retrace.hpp index 9a1d5cc..a019de7 100644 --- a/retrace/retrace.hpp +++ b/retrace/retrace.hpp @@ -49,48 +49,6 @@ namespace retrace { extern trace::Parser parser; -/** - * Handle map. - * - * It is just like a regular std::map container, but lookups of missing - * keys return the key instead of default constructor. - * - * This is necessary for several GL named objects, where one can either request - * the implementation to generate an unique name, or pick a value never used - * before. - * - * XXX: In some cases, instead of returning the key, it would make more sense - * to return an unused data value (e.g., container count). - */ -template -class map -{ -private: - typedef std::map base_type; - base_type base; - -public: - - T & operator[] (const T &key) { - typename base_type::iterator it; - it = base.find(key); - if (it == base.end()) { - return (base[key] = key); - } - return it->second; - } - - const T & operator[] (const T &key) const { - typename base_type::const_iterator it; - it = base.find(key); - if (it == base.end()) { - return (base[key] = key); - } - return it->second; - } -}; - - /** * Similar to alloca(), but implemented with malloc. */ @@ -174,16 +132,6 @@ public: }; -void -addRegion(unsigned long long address, void *buffer, unsigned long long size); - -void -delRegionByPointer(void *ptr); - -void * -toPointer(trace::Value &value, bool bind = false); - - /** * Output verbosity when retracing files. */ diff --git a/retrace/retrace.py b/retrace/retrace.py index 8291021..7ee4a06 100644 --- a/retrace/retrace.py +++ b/retrace/retrace.py @@ -470,6 +470,7 @@ class Retracer: print '#include "os_time.hpp"' print '#include "trace_parser.hpp"' print '#include "retrace.hpp"' + print '#include "retrace_swizzle.hpp"' print types = api.getAllTypes() diff --git a/retrace/retrace_stdc.cpp b/retrace/retrace_stdc.cpp index df3e0c3..dd4d0f4 100644 --- a/retrace/retrace_stdc.cpp +++ b/retrace/retrace_stdc.cpp @@ -25,219 +25,12 @@ #include - #include +#include - -#include "trace_parser.hpp" #include "retrace.hpp" - - -namespace retrace { - -struct Region -{ - void *buffer; - unsigned long long size; -}; - -typedef std::map 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; - } - } - - 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); - - 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); - 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); -} +#include "retrace_swizzle.hpp" static void retrace_malloc(trace::Call &call) { @@ -250,17 +43,17 @@ static void retrace_malloc(trace::Call &call) { void *buffer = malloc(size); if (!buffer) { - std::cerr << "error: failed to allocated " << size << " bytes."; + std::cerr << "error: failed to allocate " << size << " bytes."; return; } - addRegion(address, buffer, size); + retrace::addRegion(address, buffer, size); } static void retrace_memcpy(trace::Call &call) { - void * dest = toPointer(call.arg(0)); - void * src = toPointer(call.arg(1)); + void * dest = retrace::toPointer(call.arg(0)); + void * src = retrace::toPointer(call.arg(1)); size_t n = call.arg(2).toUInt(); if (!dest || !src || !n) { @@ -271,11 +64,8 @@ static void retrace_memcpy(trace::Call &call) { } -const retrace::Entry stdc_callbacks[] = { +const retrace::Entry retrace::stdc_callbacks[] = { {"malloc", &retrace_malloc}, {"memcpy", &retrace_memcpy}, {NULL, NULL} }; - - -} /* retrace */ diff --git a/retrace/retrace_swizzle.cpp b/retrace/retrace_swizzle.cpp new file mode 100644 index 0000000..52dfad2 --- /dev/null +++ b/retrace/retrace_swizzle.cpp @@ -0,0 +1,242 @@ +/************************************************************************** + * + * Copyright 2011-2012 Jose Fonseca + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +#include + +#include + +#include "retrace.hpp" +#include "retrace_swizzle.hpp" + + +namespace retrace { + + +struct Region +{ + void *buffer; + unsigned long long size; +}; + +typedef std::map 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; + } + } + + 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); + + 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); + 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); +} + + +} /* retrace */ diff --git a/retrace/retrace_swizzle.hpp b/retrace/retrace_swizzle.hpp new file mode 100644 index 0000000..fa5e008 --- /dev/null +++ b/retrace/retrace_swizzle.hpp @@ -0,0 +1,92 @@ +/************************************************************************** + * + * Copyright 2011-2012 Jose Fonseca + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + +#ifndef _RETRACE_SWIZZLE_HPP_ +#define _RETRACE_SWIZZLE_HPP_ + + +#include + +#include "trace_model.hpp" + + +namespace retrace { + + +/** + * Handle map. + * + * It is just like a regular std::map container, but lookups of missing + * keys return the key instead of default constructor. + * + * This is necessary for several GL named objects, where one can either request + * the implementation to generate an unique name, or pick a value never used + * before. + * + * XXX: In some cases, instead of returning the key, it would make more sense + * to return an unused data value (e.g., container count). + */ +template +class map +{ +private: + typedef std::map base_type; + base_type base; + +public: + + T & operator[] (const T &key) { + typename base_type::iterator it; + it = base.find(key); + if (it == base.end()) { + return (base[key] = key); + } + return it->second; + } + + const T & operator[] (const T &key) const { + typename base_type::const_iterator it; + it = base.find(key); + if (it == base.end()) { + return (base[key] = key); + } + return it->second; + } +}; + + +void +addRegion(unsigned long long address, void *buffer, unsigned long long size); + +void +delRegionByPointer(void *ptr); + +void * +toPointer(trace::Value &value, bool bind = false); + + +} /* namespace retrace */ + +#endif /* _RETRACE_SWIZZLE_HPP_ */ -- 2.45.2