summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose Fonseca <jfonseca@vmware.com>2016-05-05 17:01:12 +0100
committerJose Fonseca <jfonseca@vmware.com>2016-05-05 20:32:27 +0100
commit5057d100cfc3763c422a15023dbdb6778502d552 (patch)
tree4a1a68e462662c10f04553ee1ce600f1a0be609b
parent1ee7c4cfceb11c667da9327bdb61a1921fff384e (diff)
dxgitrace: Try to detect non-overlapping buffer writes.
-rw-r--r--wrappers/dxgitrace.hpp129
-rw-r--r--wrappers/dxgitrace.py34
2 files changed, 154 insertions, 9 deletions
diff --git a/wrappers/dxgitrace.hpp b/wrappers/dxgitrace.hpp
new file mode 100644
index 00000000..526ac609
--- /dev/null
+++ b/wrappers/dxgitrace.hpp
@@ -0,0 +1,129 @@
+/**************************************************************************
+ *
+ * Copyright 2014 VMware, Inc.
+ * 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.
+ *
+ **************************************************************************/
+
+
+/*
+ * Helper functions for C++ code generated by dxgitrace.py.
+ *
+ */
+
+#pragma once
+
+
+#include <assert.h>
+
+#include "d3dcommonshader.hpp"
+
+#include "d3d10imports.hpp"
+#include "d3d10size.hpp"
+#include "d3d11imports.hpp"
+#include "d3d11size.hpp"
+#include "dcompimports.hpp"
+#include "d2dimports.hpp" // WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
+#include "d3d9imports.hpp" // D3DPERF_*
+#include "memtrace.hpp"
+
+
+/*
+ * Overloaded function to determine whether a given resource be have maps
+ * shadowed or not.
+ */
+
+inline bool
+_shouldShadowMap(IDXGISurface *pSurface)
+{
+ return false;
+}
+
+inline bool
+_shouldShadowMap(ID3D10Resource *pResource)
+{
+ D3D10_RESOURCE_DIMENSION Type = D3D10_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&Type);
+ return Type == D3D10_RESOURCE_DIMENSION_BUFFER;
+}
+
+inline bool
+_shouldShadowMap(ID3D11Resource *pResource)
+{
+ D3D11_RESOURCE_DIMENSION Type = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&Type);
+ return Type == D3D11_RESOURCE_DIMENSION_BUFFER;
+}
+
+
+/*
+ * Overloaded function to initialize buffer resources upon creation time.
+ */
+
+inline void
+_initializeBuffer(ID3D10Device *pDevice, const D3D10_BUFFER_DESC *pDesc, ID3D10Buffer *pBuffer)
+{
+ HRESULT hr;
+
+ if (!(pDesc->CPUAccessFlags & D3D10_CPU_ACCESS_WRITE)) {
+ return;
+ }
+
+ assert(pBuffer);
+
+ D3D10_MAP MapType = pDesc->Usage == D3D10_USAGE_DYNAMIC ? D3D10_MAP_WRITE_DISCARD : D3D10_MAP_WRITE;
+ VOID *pData;
+ hr = pBuffer->Map(MapType, 0, &pData);
+ assert(SUCCEEDED(hr));
+ if (FAILED(hr)) {
+ return;
+ }
+
+ MemoryShadow::zero(pData, pDesc->ByteWidth);
+ pBuffer->Unmap();
+}
+
+inline void
+_initializeBuffer(ID3D11Device *pDevice, const D3D11_BUFFER_DESC *pDesc, ID3D11Buffer *pBuffer)
+{
+ HRESULT hr;
+
+ if (!(pDesc->CPUAccessFlags & D3D11_CPU_ACCESS_WRITE)) {
+ return;
+ }
+
+ assert(pBuffer);
+
+ com_ptr<ID3D11DeviceContext> pImmediateContext;
+ pDevice->GetImmediateContext(&pImmediateContext);
+ assert(pImmediateContext);
+
+ D3D11_MAP MapType = pDesc->Usage == D3D11_USAGE_DYNAMIC ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE;
+ D3D11_MAPPED_SUBRESOURCE MappedResource;
+ hr = pImmediateContext->Map(pBuffer, 0, MapType, 0, &MappedResource);
+ assert(SUCCEEDED(hr));
+ if (FAILED(hr)) {
+ return;
+ }
+
+ MemoryShadow::zero(MappedResource.pData, pDesc->ByteWidth);
+ pImmediateContext->Unmap(pBuffer, 0);
+}
diff --git a/wrappers/dxgitrace.py b/wrappers/dxgitrace.py
index fd1275d3..f3ea82d2 100644
--- a/wrappers/dxgitrace.py
+++ b/wrappers/dxgitrace.py
@@ -99,10 +99,12 @@ class D3DCommonTracer(DllTracer):
if interface.hasBase(*self.mapInterfaces):
variables += [
('_MAP_DESC', 'm_MapDesc', None),
+ ('MemoryShadow', 'm_MapShadow', None),
]
if interface.hasBase(d3d11.ID3D11DeviceContext):
variables += [
('std::map< std::pair<ID3D11Resource *, UINT>, _MAP_DESC >', 'm_MapDescs', None),
+ ('std::map< std::pair<ID3D11Resource *, UINT>, MemoryShadow >', 'm_MapShadows', None),
]
return variables
@@ -118,12 +120,20 @@ class D3DCommonTracer(DllTracer):
resourceArg = method.getArgByName('pResource')
if resourceArg is None:
print ' _MAP_DESC & _MapDesc = m_MapDesc;'
+ print ' MemoryShadow & _MapShadow = m_MapShadow;'
+ print ' %s *pResourceInstance = m_pInstance;' % interface.name
else:
print ' _MAP_DESC & _MapDesc = m_MapDescs[std::pair<%s, UINT>(pResource, Subresource)];' % resourceArg.type
+ print ' MemoryShadow & _MapShadow = m_MapShadows[std::pair<%s, UINT>(pResource, Subresource)];' % resourceArg.type
+ print ' Wrap%spResourceInstance = static_cast<Wrap%s>(%s);' % (resourceArg.type, resourceArg.type, resourceArg.name)
if method.name == 'Unmap':
print ' if (_MapDesc.Size && _MapDesc.pData) {'
+ print ' if (_shouldShadowMap(pResourceInstance)) {'
+ print ' _MapShadow.update(trace::fakeMemcpy);'
+ print ' } else {'
self.emit_memcpy('_MapDesc.pData', '_MapDesc.Size')
+ print ' }'
print ' }'
DllTracer.implementWrapperInterfaceMethodBody(self, interface, base, method)
@@ -132,6 +142,13 @@ class D3DCommonTracer(DllTracer):
# NOTE: recursive locks are explicitely forbidden
print ' if (SUCCEEDED(_result)) {'
print ' _getMapDesc(_this, %s, _MapDesc);' % ', '.join(method.argNames())
+ print ' if (_MapDesc.pData && _shouldShadowMap(pResourceInstance)) {'
+ if interface.name.startswith('IDXGI'):
+ print ' (void)_MapShadow;'
+ else:
+ print ' bool _discard = MapType == 4 /* D3D1[01]_MAP_WRITE_DISCARD */;'
+ print ' _MapShadow.cover(_MapDesc.pData, _MapDesc.Size, _discard);'
+ print ' }'
print ' } else {'
print ' _MapDesc.pData = NULL;'
print ' _MapDesc.Size = 0;'
@@ -156,6 +173,13 @@ class D3DCommonTracer(DllTracer):
print r' os::log("apitrace: warning: hiding IWarpPrivateAPI interface\n");'
print r' }'
+ # Ensure buffers are initialized, otherwise we can fail to detect
+ # changes when unititialized data matches what the app wrote.
+ if method.name == 'CreateBuffer':
+ print r' if (SUCCEEDED(_result) && !pInitialData) {'
+ print r' _initializeBuffer(_this, pDesc, *ppBuffer);'
+ print r' }'
+
if __name__ == '__main__':
print r'#include "guids_defs.hpp"'
@@ -163,15 +187,7 @@ if __name__ == '__main__':
print r'#include "trace_writer_local.hpp"'
print r'#include "os.hpp"'
print
- print r'#include "d3dcommonshader.hpp"'
- print
- print r'#include "d3d10imports.hpp"'
- print r'#include "d3d10size.hpp"'
- print r'#include "d3d11imports.hpp"'
- print r'#include "d3d11size.hpp"'
- print r'#include "dcompimports.hpp"'
- print r'#include "d2dimports.hpp" // WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT'
- print r'#include "d3d9imports.hpp" // D3DPERF_*'
+ print r'#include "dxgitrace.hpp"'
print
api = API()