Example #1
0
/* Handle the 'M' command which is to write to the specified address range in memory.

    Command Format:     MAAAAAAAA,LLLLLLLL:xx...
    Response Format:    OK
    
    Where AAAAAAAA is the hexadecimal representation of the address where the write is to start.
          LLLLLLLL is the hexadecimal representation of the length (in bytes) of the write to be conducted.
          xx is the hexadecimal representation of the first byte to be written to the specified location.
          ... continue returning the rest of LLLLLLLL-1 bytes in hexadecimal format.
*/
uint32_t HandleMemoryWriteCommand(void)
{
    Buffer*         pBuffer = GetBuffer();
    AddressLength   addressLength;

    __try
    {
        ReadAddressAndLengthArgumentsWithColon(pBuffer, &addressLength);
    }
    __catch
    {
        PrepareStringResponse(MRI_ERROR_INVALID_ARGUMENT);
        return 0;
    }
    
    if (WriteHexBufferToMemory(pBuffer, ADDR32_TO_POINTER(addressLength.address), addressLength.length))
    {
        PrepareStringResponse("OK");
    }
    else
    {
        if (Buffer_OverrunDetected(pBuffer))
            PrepareStringResponse( MRI_ERROR_BUFFER_OVERRUN);
        else
            PrepareStringResponse(MRI_ERROR_MEMORY_ACCESS_FAILURE);
    }

    return 0;
}
Example #2
0
/* Handle the 'G' command which is to receive the new contents of the registers from gdb for the program to use when
   it resumes execution.
   
   Command Format:      Gxxxxxxxxyyyyyyyy...
   Response Format:     OK
   
    Where xxxxxxxx is the hexadecimal representation of the 32-bit R0 register.
          yyyyyyyy is the hexadecimal representation of the 32-bit R1 register.
          ... and so on through the members of the SContext structure.
*/
uint32_t HandleRegisterWriteCommand(void)
{
    Buffer*     pBuffer = GetBuffer();
    
    Platform_CopyContextFromBuffer(pBuffer);

    if (Buffer_OverrunDetected(pBuffer))
        PrepareStringResponse(MRI_ERROR_BUFFER_OVERRUN);
    else
        PrepareStringResponse("OK");

    return 0;
}
Example #3
0
/* Handle the '"Z*" commands used by gdb to set hardware breakpoints/watchpoints.

    Command Format:     Z*,AAAAAAAA,K
    Response Format:    OK
    Where * is 1 for hardware breakpoint.
               2 for write watchpoint.
               3 for read watchpoint.
               4 for read/write watchpoint.
          AAAAAAAA is the hexadecimal representation of the address on which the breakpoint should be set.
          K is either 2: 16-bit Thumb instruction.
                      3: 32-bit Thumb2 instruction.
                      4: 32-bit ARM insruction.
                      value: byte size for data watchpoint.
*/
uint32_t HandleBreakpointWatchpointSetCommand(void)
{
    BreakpointWatchpointArguments  arguments;
    
    __try
    {
        parseBreakpointWatchpointCommandArguments(&arguments);
    }
    __catch
    {
        PrepareStringResponse(MRI_ERROR_INVALID_ARGUMENT);
        return 0;
    }
    
    switch(arguments.type)
    {
    case '1':
        handleHardwareBreakpointSetCommand(&arguments);
        break;
    case '2':
        handleWatchpointSetCommand(MRI_PLATFORM_WRITE_WATCHPOINT, &arguments);
        break;
    case '3':
        handleWatchpointSetCommand(MRI_PLATFORM_READ_WATCHPOINT, &arguments);
        break;
    case '4':
        handleWatchpointSetCommand(MRI_PLATFORM_READWRITE_WATCHPOINT, &arguments);
        break;
    default:
        PrepareEmptyResponseForUnknownCommand();
        break;
    }
    
    return 0;
}
Example #4
0
/* Handle the 'C' command which is sent from gdb to tell the debugger to continue execution of the currently halted
   program. It is similar to the 'c' command but it also provides a signal level, which MRI ignores.
   
    Command Format:     cAA;BBBBBBBB
    Response Format:    Blank until the next exception, at which time a 'T' stop response packet will be sent.

    Where AA is the signal to be set, and
          BBBBBBBB is an optional value to be used for the Program Counter when restarting the program.
*/
uint32_t HandleContinueWithSignalCommand(void)
{
    Buffer*     pBuffer = GetBuffer();
    uint32_t    returnValue = 0;
    uint32_t    newPC;

    returnValue |= skipHardcodedBreakpoint();
    __try
    {
        /* Fetch signal value but ignore it. */
        __throwing_func( ReadUIntegerArgument(pBuffer) );
        if (Buffer_BytesLeft(pBuffer) && Buffer_IsNextCharEqualTo(pBuffer, ';'))
        {
            __throwing_func( newPC = ReadUIntegerArgument(pBuffer) );
            Platform_SetProgramCounter(newPC);
        }
    }
    __catch
    {
        PrepareStringResponse(MRI_ERROR_INVALID_ARGUMENT);
        return 0;
    }

    return (returnValue | HANDLER_RETURN_RESUME_PROGRAM | HANDLER_RETURN_RETURN_IMMEDIATELY);
}
Example #5
0
/* 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;
    }
}
Example #6
0
/* Handle the 'm' command which is to read the specified address range from memory.

    Command Format:     mAAAAAAAA,LLLLLLLL
    Response Format:    xx...
    
    Where AAAAAAAA is the hexadecimal representation of the address where the read is to start.
          LLLLLLLL is the hexadecimal representation of the length (in bytes) of the read to be conducted.
          xx is the hexadecimal representation of the first byte read from the specified location.
          ... continue returning the rest of LLLLLLLL-1 bytes in hexadecimal format.
*/
uint32_t HandleMemoryReadCommand(void)
{
    Buffer*       pBuffer = GetBuffer();
    AddressLength addressLength;

    __try
    {
        ReadAddressAndLengthArguments(pBuffer, &addressLength);
    }
    __catch
    {
        PrepareStringResponse(MRI_ERROR_INVALID_ARGUMENT);
        return 0;
    }

    InitBuffer();
    ReadMemoryIntoHexBuffer(pBuffer, ADDR32_TO_POINTER(addressLength.address), addressLength.length);

    return 0;
}
Example #7
0
/* Handle the "qXfer:features" command used by gdb to read the target XML from the stub.

    Command Format: qXfer:features:read:target.xml:offset,length
*/
static uint32_t handleQueryTransferFeaturesCommand(void)
{
    Buffer*             pBuffer = GetBuffer();
    AnnexOffsetLength   arguments;
    
    __try
    {
        __throwing_func( readQueryTransferReadArguments(pBuffer, &arguments) );
        __throwing_func( validateAnnexIs(arguments.pAnnex, "target.xml") );
    }
    __catch
    {
        PrepareStringResponse(MRI_ERROR_INVALID_ARGUMENT);
        return 0;
    }

    arguments.pAnnex = Platform_GetTargetXml();
    arguments.annexSize = Platform_GetTargetXmlSize();
    handleQueryTransferReadCommand(&arguments);
    
    return 0;
}