SimpleCharBuffer GdbSrvControllerImpl::ExecuteExdiGdbSrvMonitor()

in Exdi/exdigdbsrv/GdbSrvControllerLib/GdbSrvControllerLib.cpp [137:243]


    SimpleCharBuffer GdbSrvControllerImpl::ExecuteExdiGdbSrvMonitor(_In_ unsigned core, _In_ LPCWSTR pCmdToExecute)
    {
        assert(pCmdToExecute != nullptr);

        //  Check if this is an internal exdicmd function.
        std::map<wstring, InternalGdbClientFunctions>::const_iterator itFunction =
            m_InternalGdbFunctions.find(TargetArchitectureHelpers::WMakeLowerCase(pCmdToExecute));
        if (itFunction != m_InternalGdbFunctions.end())
        {
            return itFunction->second();
        }

        HRESULT gdbServerError = S_OK;
        //  Are we connected to the GdbServer on this core?
        if (m_pRspClient->GetRspSessionStatus(gdbServerError, core))
        {
            if (gdbServerError != ERROR_SUCCESS)
            {
                //  We are not connected, so open a RSP channel and connect to it.
                if (!AttachGdbSrv(GetCoreConnectionString(core), core))
                {
                    throw _com_error(E_FAIL);
                }
            }
        }

        SimpleCharBuffer monitorResult;
        if (!monitorResult.TryEnsureCapacity(C_MAX_MONITOR_CMD_BUFFER))
        {
            throw _com_error(E_OUTOFMEMORY);
        }

        if (core != C_ALLCORES && core > GetNumberOfRspConnections())
        {
            throw _com_error(E_INVALIDARG);
        }

        size_t cmdToExecMaxLength = (wcslen(pCmdToExecute) + 1) * sizeof(WCHAR);
        unique_ptr<char> pCommand(new (nothrow) char[cmdToExecMaxLength]);
        if (WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, pCmdToExecute, -1, pCommand.get(), static_cast<int>(cmdToExecMaxLength), nullptr, nullptr) == 0)
        {
            throw _com_error(E_INVALIDARG);
        }

        char * pMonitorCmd = pCommand.get();
        size_t commandLength = strlen(pMonitorCmd);
        std::string dataBuffer;
        for (size_t idx = 0; idx < commandLength; ++idx)
        {
            dataBuffer.insert(dataBuffer.end(), 1, NumberToAciiHex(((pMonitorCmd[idx] >> 4) & 0xf)));
            dataBuffer.insert(dataBuffer.end(), 1, NumberToAciiHex((pMonitorCmd[idx] & 0xf)));
        }

        std::string commandMonitor("qRcmd,");
        commandMonitor += dataBuffer.c_str();

        std::string reply = ExecuteCommandOnProcessor(commandMonitor.c_str(), true, 0, core);
        size_t messageLength = reply.length();

        //  Is an empty response or an error response 'E NN'?
        if (messageLength == 0 || IsReplyError(reply))
        {
            throw _com_error(E_FAIL);
        }

        messageLength = min(messageLength, C_MAX_MONITOR_CMD_BUFFER);
        bool replyDone = false;
        do
        {
            if (IsReplyOK(reply))
            {
                monitorResult.SetLength(monitorResult.GetLength() + messageLength);
                memcpy(&monitorResult[monitorResult.GetLength() - messageLength], reply.c_str(), messageLength);
                replyDone = true;
            }
            else
            {
                if (messageLength >= (monitorResult.GetCapacity() - (monitorResult.GetLength() + 1)) ) 
                {
                    if (!monitorResult.TryEnsureCapacity((monitorResult.GetLength() + 1) + (4 * C_MAX_MONITOR_CMD_BUFFER)))
                    {
                        throw _com_error(E_OUTOFMEMORY);
                    }
                }
                size_t pos = (reply[0] == 'O') ? 1 : 0;
                for (; pos < messageLength; pos += 2)
                {
                    monitorResult.SetLength(monitorResult.GetLength() + 1);
                    unsigned char highByte = ((AciiHexToNumber(reply[pos]) << 4) & 0xf0);
                    monitorResult[monitorResult.GetLength() - 1] = highByte | (AciiHexToNumber(reply[pos + 1]) & 0x0f);
                }
                //  Try to read more packets
                bool IsPollingChannelMode = false;
                if (m_pRspClient->ReceiveRspPacketEx(reply, core, true, IsPollingChannelMode, false))
                {
                    messageLength = reply.length();
                }
                else
                {
                    replyDone = true;
                }
            }
        }
        while (!replyDone);

        return monitorResult;
    }