in Exdi/exdigdbsrv/GdbSrvControllerLib/GdbSrvControllerLib.cpp [1524:1619]
SimpleCharBuffer GdbSrvControllerImpl::ReadMemory(_In_ AddressType address, _In_ size_t maxSize,
_In_ const memoryAccessType memType)
{
SimpleCharBuffer result;
// The response is an Ascii hex string, so ensure some extra capacity
// in case that GdbServer replies with an unexpected stop reply packet.
size_t maxReplyLength = (maxSize * 2) + 256;
if (!result.TryEnsureCapacity(maxReplyLength))
{
throw _com_error(E_OUTOFMEMORY);
}
ConfigExdiGdbServerHelper & cfgData = ConfigExdiGdbServerHelper::GetInstanceCfgExdiGdbServer(nullptr);
size_t maxPacketLength = cfgData.GetMaxServerPacketLength();
if (maxPacketLength != 0)
{
maxPacketLength = (maxPacketLength < maxSize) ? maxPacketLength : maxSize;
}
else
{
maxPacketLength = maxSize;
}
// We need to support local configuration maximum packet size and packetsize that
// the GdbServer dynamically supports by sending chunk of data until we reach the maximum requested size.
while (maxSize != 0)
{
size_t recvLength = 0;
bool fError = false;
size_t size = maxPacketLength;
// We will send a sequence of �m addr,length� request packets
// until we obtain the requested data length from the GdbServer.
for (;;)
{
char memoryCmd[256] = {0};
PCSTR pFormat = GetReadMemoryCmd(memType);
sprintf_s(memoryCmd, _countof(memoryCmd), pFormat, address, size);
std::string reply = ExecuteCommandEx(memoryCmd, true, maxReplyLength);
size_t messageLength = reply.length();
// Is an empty response?
if (messageLength == 0 && result.GetLength() == 0)
{
if (GetThrowExceptionEnabled())
{
// Yes, it is unacceptable
throw _com_error(E_FAIL);
}
fError = true;
break;
}
// Is an error response 'E NN'?
if (IsReplyError(reply))
{
// Yes, return the current stored length
// and let the caller's handles the returned data.
fError = true;
// unless we didn't read anything, in which case fail
if (recvLength == 0 && GetThrowExceptionEnabled())
{
throw _com_error(E_FAIL);
}
break;
}
// Handle the received memory data
for (size_t pos = 0; pos < messageLength ; pos += 2)
{
std::string oneByteMemory = reply.substr(pos, 2);
int value = 0;
if (sscanf_s(oneByteMemory.c_str(), "%x", &value) != 1)
{
throw _com_error(E_FAIL);
}
result.SetLength(result.GetLength() + 1);
result[result.GetLength() - 1] = static_cast<char>(value);
recvLength++;
}
// Update the parameters for the next packet.
address += recvLength;
size -= recvLength;
// Are we done with the requested data?
if (size == 0 || messageLength == 0)
{
break;
}
}
if (fError)
{
break;
}
maxSize -= maxPacketLength;
maxPacketLength = (maxPacketLength >= maxSize) ? maxSize : maxPacketLength;
}
return result;
}