/* Handle the "qXfer" command used by gdb to transfer data to and from the stub for special functionality. Command Format: qXfer:object:read:annex:offset,length Where supported objects are currently: memory-map */ static uint32_t handleQueryTransferCommand(void) { Buffer* pBuffer =GetBuffer(); static const char memoryMapObject[] = "memory-map"; static const char featureObject[] = "features"; if (!Buffer_IsNextCharEqualTo(pBuffer, ':')) { PrepareStringResponse(MRI_ERROR_INVALID_ARGUMENT); return 0; } if (Buffer_MatchesString(pBuffer, memoryMapObject, sizeof(memoryMapObject)-1)) { return handleQueryTransferMemoryMapCommand(); } else if (Buffer_MatchesString(pBuffer, featureObject, sizeof(featureObject)-1)) { return handleQueryTransferFeaturesCommand(); } else { PrepareEmptyResponseForUnknownCommand(); return 0; } }
/* Handle the 'q' command used by gdb to communicate state to debug monitor and vice versa. Command Format: qSSS Where SSS is a variable length string indicating which query command is being sent to the stub. */ uint32_t HandleQueryCommand(void) { Buffer* pBuffer = GetBuffer(); static const char qSupportedCommand[] = "Supported"; static const char qXferCommand[] = "Xfer"; if (Buffer_MatchesString(pBuffer, qSupportedCommand, sizeof(qSupportedCommand)-1)) { return handleQuerySupportedCommand(); } else if (Buffer_MatchesString(pBuffer, qXferCommand, sizeof(qXferCommand)-1)) { return handleQueryTransferCommand(); } else { PrepareEmptyResponseForUnknownCommand(); return 0; } }
static const char* readQueryTransferAnnexArgument(Buffer* pBuffer) { static const char targetXmlAnnex[] = "target.xml"; const char* pReturn = NULL; if (Buffer_MatchesString(pBuffer, targetXmlAnnex, sizeof(targetXmlAnnex)-1)) pReturn = targetXmlAnnex; if (pReturn && !Buffer_IsNextCharEqualTo(pBuffer, ':')) __throw_and_return(invalidArgumentException, NULL); else if (!pReturn && Buffer_IsNextCharEqualTo(pBuffer, ':')) return NULL; else if (!pReturn) __throw_and_return(invalidArgumentException, NULL); else return pReturn; }
/* Handle the 'F' command which is sent from gdb in response to a previously sent File I/O command from mri. Command Format: Frr[,ee[,C]] Where rr is the hexadecimal representation of the return code from the last requested file I/O command. ee is the optional hexadecimal value for the errorno associated with the call if rr indicates error. C is the optional 'C' character sent by gdb to indicate that CTRL+C was pressed by user while gdb was processing the current file I/O request. */ uint32_t HandleFileIOCommand(void) { static const char controlCFlag[] = ",C"; Buffer* pBuffer = GetBuffer(); int returnCode = -1; int errNo = 0; int controlC = 0; returnCode = Buffer_ReadIntegerAsHex(pBuffer); if (Buffer_IsNextCharEqualTo(pBuffer, ',')) { errNo = Buffer_ReadIntegerAsHex(pBuffer); controlC = Buffer_MatchesString(pBuffer, controlCFlag, sizeof(controlCFlag)-1); } SetSemihostReturnValues(returnCode, errNo); RecordControlCFlagSentFromGdb(controlC); return (HANDLER_RETURN_RESUME_PROGRAM | HANDLER_RETURN_RETURN_IMMEDIATELY); }
static void readQueryTransferReadArguments(Buffer* pBuffer, AnnexOffsetLength* pAnnexOffsetLength) { static const char readCommand[] = "read"; memset(pAnnexOffsetLength, 0, sizeof(*pAnnexOffsetLength)); if (!Buffer_IsNextCharEqualTo(pBuffer, ':') || !Buffer_MatchesString(pBuffer, readCommand, sizeof(readCommand)-1) || !Buffer_IsNextCharEqualTo(pBuffer, ':') ) { __throw(invalidArgumentException); } __try { __throwing_func( pAnnexOffsetLength->pAnnex = readQueryTransferAnnexArgument(pBuffer) ); __throwing_func( readQueryTransferOffsetLengthArguments(pBuffer, pAnnexOffsetLength) ); } __catch { __rethrow; } }
void validateBufferMatches(const char* pExpectedOutput) { CHECK_TRUE( Buffer_MatchesString(&m_buffer, pExpectedOutput, strlen(pExpectedOutput)) ); }