SimpleCharBuffer GdbSrvControllerImpl::ReadMemory()

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;
    }