1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5
6#include "stdafx.h"
7#include "datatargetreader.h"
8
9
10DataTargetReader::DataTargetReader(CORDB_ADDRESS remoteAddressCursor, ICorDebugDataTarget* pDataTarget, DWORD targetDefines, DWORD mdStructuresVersion)
11: m_remotePointerSize(0),
12m_currentStructureAlign(1),
13m_targetDefines(targetDefines),
14m_mdStructuresVersion(mdStructuresVersion)
15{
16 m_remoteAddressCursor = remoteAddressCursor;
17 m_pDataTarget = pDataTarget;
18 m_pDataTarget->AddRef();
19}
20DataTargetReader::DataTargetReader(const DataTargetReader & otherReader)
21{
22 m_pDataTarget = otherReader.m_pDataTarget;
23 m_pDataTarget->AddRef();
24 m_remotePointerSize = otherReader.m_remotePointerSize;
25 m_remoteAddressCursor = otherReader.m_remoteAddressCursor;
26 m_targetDefines = otherReader.m_targetDefines;
27 m_mdStructuresVersion = otherReader.m_mdStructuresVersion;
28}
29DataTargetReader & DataTargetReader::operator=(const DataTargetReader & otherReader)
30{
31 if (this != &otherReader)
32 {
33 m_pDataTarget = otherReader.m_pDataTarget;
34 m_pDataTarget->AddRef();
35 m_remotePointerSize = otherReader.m_remotePointerSize;
36 m_remoteAddressCursor = otherReader.m_remoteAddressCursor;
37 m_targetDefines = otherReader.m_targetDefines;
38 m_mdStructuresVersion = otherReader.m_mdStructuresVersion;
39 }
40 return *this;
41}
42DataTargetReader::~DataTargetReader()
43{
44 m_pDataTarget->Release();
45 m_pDataTarget = NULL;
46}
47
48HRESULT DataTargetReader::ReadPointer(CORDB_ADDRESS* pPointerValue)
49{
50 HRESULT hr = S_OK;
51 if (m_remotePointerSize == 0)
52 {
53 IfFailRet(GetRemotePointerSize(&m_remotePointerSize));
54 }
55 _ASSERTE(m_remotePointerSize == 4 || m_remotePointerSize == 8);
56 *pPointerValue = 0;
57 if (m_remotePointerSize == 4)
58 return Read32((ULONG32*)pPointerValue);
59 else
60 return Read64((ULONG64*)pPointerValue);
61}
62HRESULT DataTargetReader::SkipPointer()
63{
64 HRESULT hr = S_OK;
65 if (m_remotePointerSize == 0)
66 {
67 IfFailRet(GetRemotePointerSize(&m_remotePointerSize));
68 }
69 _ASSERTE(m_remotePointerSize == 4 || m_remotePointerSize == 8);
70 Align(m_remotePointerSize);
71 return SkipBytes(m_remotePointerSize);
72}
73HRESULT DataTargetReader::Read8(BYTE* pByteValue)
74{
75 return ReadBytes(pByteValue, 1);
76}
77HRESULT DataTargetReader::Skip8()
78{
79 return SkipBytes(1);
80}
81HRESULT DataTargetReader::Read32(ULONG32* pUlong32Value)
82{
83 Align(4);
84 return ReadBytes((BYTE*)pUlong32Value, sizeof(ULONG32));
85}
86HRESULT DataTargetReader::Skip32()
87{
88 Align(4);
89 return SkipBytes(sizeof(ULONG32));
90}
91HRESULT DataTargetReader::Read64(ULONG64* pUlong64Value)
92{
93 Align(8);
94 return ReadBytes((BYTE*)pUlong64Value, sizeof(ULONG64));
95}
96HRESULT DataTargetReader::Skip64()
97{
98 Align(8);
99 return SkipBytes(sizeof(ULONG64));
100}
101
102HRESULT DataTargetReader::ReadBytes(BYTE* pBuffer, DWORD cbBuffer)
103{
104 HRESULT hr = S_OK;
105 ULONG32 cbTotalRead = 0;
106 CORDB_ADDRESS m_tempRemoteAddressCursor = m_remoteAddressCursor;
107 while (cbTotalRead < cbBuffer)
108 {
109 ULONG32 cbRead = 0;
110 if(FAILED(m_pDataTarget->ReadVirtual(m_remoteAddressCursor + cbTotalRead,
111 pBuffer + cbTotalRead,
112 cbBuffer - cbTotalRead,
113 &cbRead)))
114 return CORDBG_E_READVIRTUAL_FAILURE;
115 if (cbRead == 0)
116 return CORDBG_E_READVIRTUAL_FAILURE;
117 cbTotalRead += cbRead;
118 }
119
120 // on success only, move the cursor
121 m_remoteAddressCursor += cbTotalRead;
122 return S_OK;
123}
124HRESULT DataTargetReader::SkipBytes(DWORD cbRead)
125{
126 m_remoteAddressCursor += cbRead;
127 return S_OK;
128}
129
130#ifndef MAX
131#define MAX(a,b) ((a)>(b) ? (a) : (b))
132#endif
133
134HRESULT DataTargetReader::Read(TargetObject* pTargetObject)
135{
136 ULONG32 previousAlign = m_currentStructureAlign;
137 m_currentStructureAlign = 1;
138 HRESULT hr = pTargetObject->ReadFrom(*this);
139 if (SUCCEEDED(hr))
140 {
141 // increase the structure size to a multiple of the maximum alignment of any of its members
142 Align(m_currentStructureAlign);
143 }
144 m_currentStructureAlign = MAX(previousAlign, m_currentStructureAlign);
145 return hr;
146}
147
148HRESULT DataTargetReader::ReadPointer(TargetObject* pTargetObject)
149{
150 HRESULT hr = S_OK;
151 CORDB_ADDRESS pointerValue;
152 IfFailRet(ReadPointer(&pointerValue));
153
154 DataTargetReader reader = CreateReaderAt(pointerValue);
155 return pTargetObject->ReadFrom(reader);
156}
157
158void DataTargetReader::Align(DWORD alignmentBytes)
159{
160 m_remoteAddressCursor = AlignUp(m_remoteAddressCursor, alignmentBytes);
161 m_currentStructureAlign = MAX(m_currentStructureAlign, alignmentBytes);
162}
163
164void DataTargetReader::AlignBase()
165{
166#ifdef _MSC_VER
167 // Windows MSVC compiler aligns structs based on the largest field size
168 Align(m_currentStructureAlign);
169#else
170 // clang (on all platforms) aligns structs always on 4 byte boundaries
171 Align(4);
172#endif
173}
174
175HRESULT DataTargetReader::GetRemotePointerSize(ULONG32* pPointerSize)
176{
177 HRESULT hr = S_OK;
178 CorDebugPlatform platform;
179 IfFailRet(m_pDataTarget->GetPlatform(&platform));
180 if ((platform == CORDB_PLATFORM_WINDOWS_X86) || (platform == CORDB_PLATFORM_POSIX_X86) || (platform == CORDB_PLATFORM_MAC_X86))
181 *pPointerSize = 4;
182 else if ((platform == CORDB_PLATFORM_WINDOWS_AMD64) || (platform == CORDB_PLATFORM_POSIX_AMD64) || (platform == CORDB_PLATFORM_MAC_AMD64))
183 *pPointerSize = 8;
184 else if ((platform == CORDB_PLATFORM_WINDOWS_ARM) || (platform == CORDB_PLATFORM_POSIX_ARM))
185 *pPointerSize = 4;
186 else if ((platform == CORDB_PLATFORM_WINDOWS_ARM64) || (platform == CORDB_PLATFORM_POSIX_ARM64))
187 *pPointerSize = 8;
188 else
189 return CORDBG_E_UNSUPPORTED;
190 return S_OK;
191}
192
193DWORD DataTargetReader::GetMDStructuresVersion()
194{
195 return m_mdStructuresVersion;
196}
197
198BOOL DataTargetReader::IsDefined(DWORD define)
199{
200 return (m_targetDefines & define) == define;
201}
202
203DataTargetReader DataTargetReader::CreateReaderAt(CORDB_ADDRESS remoteAddressCursor)
204{
205 DataTargetReader newReader(remoteAddressCursor, m_pDataTarget, m_targetDefines, m_mdStructuresVersion);
206 return newReader;
207}
208