VirtualBox

Changeset 84653 in vbox for trunk/src/VBox/Debugger


Ignore:
Timestamp:
Jun 3, 2020 9:22:18 AM (5 years ago)
Author:
vboxsync
Message:

Debugger: Add support for the Rcmd/monitor packet to access the native VBox debugger

Location:
trunk/src/VBox/Debugger
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Debugger/DBGCCmdHlp.cpp

    r82968 r84653  
    219219    if (cbChars)
    220220    {
    221         int rc = pDbgc->pBack->pfnWrite(pDbgc->pBack, pachChars, cbChars, NULL);
     221        int rc = pDbgc->pfnOutput(pDbgc->pvOutputUser, pachChars, cbChars);
    222222        if (RT_SUCCESS(rc))
    223223            pDbgc->chLastOutput = pachChars[cbChars - 1];
  • trunk/src/VBox/Debugger/DBGCGdbRemoteStub.cpp

    r84630 r84653  
    126126    /** Flag whether the stub is in extended mode. */
    127127    bool                        fExtendedMode;
     128    /** Flag whether was something was output using the 'O' packet since it was reset last. */
     129    bool                        fOutput;
    128130} GDBSTUBCTX;
    129131/** Pointer to the GDB stub context data. */
     
    356358 * @param   cbSrc               Number of bytes to encode.
    357359 */
    358 DECLINLINE(int) dbgcGdbStubCtxEncodeBinaryAsHex(uint8_t *pbDst, size_t cbDst, void *pvSrc, size_t cbSrc)
     360DECLINLINE(int) dbgcGdbStubCtxEncodeBinaryAsHex(uint8_t *pbDst, size_t cbDst, const void *pvSrc, size_t cbSrc)
    359361{
    360362    return RTStrPrintHexBytes((char *)pbDst, cbDst, pvSrc, cbSrc, RTSTRPRINTHEXBYTES_F_UPPER);
     
    10891091
    10901092
    1091 #if 0
    1092 /**
    1093  * Calls the given command handler and processes the reply.
    1094  *
    1095  * @returns Status code.
    1096  * @param   pThis               The GDB stub context.
    1097  * @param   pCmd                The command to call - NULL if using the generic monitor command received callback in the
    1098  *                              interface callback table.
    1099  * @param   pszArgs             Argument string to call the command with.
    1100  */
    1101 static int gdbStubCtxCmdProcess(PGDBSTUBCTXINT pThis, PCGDBSTUBCMD pCmd, const char *pszArgs)
    1102 {
    1103     int rc = gdbStubCtxReplySendBegin(pThis);
    1104     if (rc == GDBSTUB_INF_SUCCESS)
    1105     {
    1106         gdbStubOutCtxReset(&pThis->OutCtx);
    1107         int rcCmd = GDBSTUB_INF_SUCCESS;
    1108         if (pCmd)
    1109             rcCmd = pCmd->pfnCmd(pThis, &pThis->OutCtx.Hlp, pszArgs, pThis->pvUser);
    1110         else
    1111             rcCmd = pThis->pIf->pfnMonCmd(pThis, &pThis->OutCtx.Hlp, pszArgs, pThis->pvUser);
    1112         if (rcCmd == GDBSTUB_INF_SUCCESS)
    1113         {
    1114             if (!pThis->OutCtx.offScratch) /* No output, just send OK reply. */
    1115                 rc = gdbStubCtxReplySendOkData(pThis);
    1116             else
    1117                 rc = gdbStubCtxReplySendData(pThis, &pThis->OutCtx.abScratch[0], pThis->OutCtx.offScratch);
    1118 
    1119             /* Try to finish the reply in case of an error anyway (but we might be completely screwed at this point anyway). */
    1120             gdbStubCtxReplySendEnd(pThis);
    1121         }
    1122         else
    1123             rc = gdbStubCtxReplySendErrStsData(pThis, rcCmd);
    1124     }
    1125 
    1126     return rc;
    1127 }
    1128 
    1129 
    11301093/**
    11311094 * Processes the 'Rcmd' query.
     
    11361099 * @param   cbArgs              Size of arguments in bytes.
    11371100 */
    1138 static int gdbStubCtxPktProcessQueryRcmd(PGDBSTUBCTXINT pThis, const uint8_t *pbArgs, size_t cbArgs)
    1139 {
    1140     int rc = GDBSTUB_INF_SUCCESS;
    1141 
     1101static int dbgcGdbStubCtxPktProcessQueryRcmd(PGDBSTUBCTX pThis, const uint8_t *pbArgs, size_t cbArgs)
     1102{
    11421103    /* Skip the , following the qRcmd start. */
    11431104    if (   cbArgs < 1
    11441105        || pbArgs[0] != ',')
    1145         return GDBSTUB_ERR_PROTOCOL_VIOLATION;
    1146 
    1147     if (!pThis->pIf->paCmds)
    1148         return GDBSTUB_ERR_NOT_FOUND;
     1106        return VERR_NET_PROTOCOL_ERROR;
    11491107
    11501108    cbArgs--;
     
    11531111    /* Decode the command. */
    11541112    /** @todo Make this dynamic. */
    1155     char szCmd[4096];
     1113    char szCmd[_4K];
     1114    RT_ZERO(szCmd);
     1115
    11561116    if (cbArgs / 2 >= sizeof(szCmd))
    1157         return GDBSTUB_ERR_BUFFER_OVERFLOW;
     1117        return VERR_NET_PROTOCOL_ERROR;
    11581118
    11591119    size_t cbDecoded = 0;
    1160     rc = gdbStubCtxParseHexStringAsByteBuf(pbArgs, cbArgs - 1, &szCmd[0], sizeof(szCmd), &cbDecoded);
    1161     if (rc == GDBSTUB_INF_SUCCESS)
    1162     {
    1163         const char *pszArgs = NULL;
    1164 
    1165         cbDecoded /= 2;
     1120    int rc = RTStrConvertHexBytesEx((const char *)pbArgs, &szCmd[0], sizeof(szCmd), 0 /*fFlags*/,
     1121                                    NULL /* ppszNext */, &cbDecoded);
     1122    if (rc == VWRN_TRAILING_CHARS)
     1123        rc = VINF_SUCCESS;
     1124    if (RT_SUCCESS(rc))
     1125    {
    11661126        szCmd[cbDecoded] = '\0'; /* Ensure zero termination. */
    11671127
    1168         /** @todo Sanitize string. */
    1169 
    1170         /* Look for the first space and take that as the separator between command identifier. */
    1171         uint8_t *pbDelim = gdbStubCtxMemchr(&szCmd[0], ' ', cbDecoded);
    1172         if (pbDelim)
    1173         {
    1174             *pbDelim = '\0';
    1175             pszArgs = pbDelim + 1;
    1176         }
    1177 
    1178         /* Search for the command. */
    1179         PCGDBSTUBCMD pCmd = &pThis->pIf->paCmds[0];
    1180         rc = GDBSTUB_ERR_NOT_FOUND;
    1181         while (pCmd->pszCmd)
    1182         {
    1183             if (!gdbStubStrcmp(pCmd->pszCmd, &szCmd[0]))
    1184             {
    1185                 rc = gdbStubCtxCmdProcess(pThis, pCmd, pszArgs);
    1186                 break;
    1187             }
    1188             pCmd++;
    1189         }
    1190 
    1191         if (   rc == GDBSTUB_ERR_NOT_FOUND
    1192             && pThis->pIf->pfnMonCmd)
    1193         {
    1194             /* Restore delimiter. */
    1195             if (pbDelim)
    1196                 *pbDelim = ' ';
    1197             rc = gdbStubCtxCmdProcess(pThis, NULL, &szCmd[0]);
    1198         }
    1199         else
    1200             rc = gdbStubCtxReplySendErrSts(pThis, rc); /** @todo Send string. */
     1128        pThis->fOutput = false;
     1129        rc = dbgcEvalCommand(&pThis->Dbgc, &szCmd[0], cbDecoded, false /*fNoExecute*/);
     1130        dbgcGdbStubCtxReplySendOk(pThis);
     1131        if (   rc != VERR_DBGC_QUIT
     1132            && rc != VWRN_DBGC_CMD_PENDING)
     1133            rc = VINF_SUCCESS; /* ignore other statuses */
    12011134    }
    12021135
    12031136    return rc;
    12041137}
    1205 #endif
    12061138
    12071139
     
    12151147    GDBSTUBQPKTPROC_INIT("Supported",          dbgcGdbStubCtxPktProcessQuerySupported),
    12161148    GDBSTUBQPKTPROC_INIT("Xfer:features:read", dbgcGdbStubCtxPktProcessQueryXferFeatRead),
    1217     //GDBSTUBQPKTPROC_INIT("Rcmd",               dbgcGdbStubCtxPktProcessQueryRcmd),
     1149    GDBSTUBQPKTPROC_INIT("Rcmd",               dbgcGdbStubCtxPktProcessQueryRcmd),
    12181150#undef GDBSTUBQPKTPROC_INIT
    12191151};
     
    19811913     * Process the event.
    19821914     */
     1915    PDBGC pDbgc = &pThis->Dbgc;
    19831916    pThis->Dbgc.pszScratch = &pThis->Dbgc.achInput[0];
    19841917    pThis->Dbgc.iArg       = 0;
     
    19961929
    19971930
    1998 #if 0
    19991931        /*
    20001932         * The second part is events which can occur at any time.
     
    20081940            break;
    20091941        }
    2010 #endif
    20111942
    20121943        case DBGFEVENT_BREAKPOINT:
     
    20261957        }
    20271958
    2028 #if 0
    20291959        case DBGFEVENT_ASSERTION_HYPER:
    20301960        {
     
    20691999            break;
    20702000        }
    2071 #endif
    20722001
    20732002        case DBGFEVENT_POWERING_OFF:
     
    22362165
    22372166/**
     2167 * @copdoc{DBGC,pfnOutput}
     2168 */
     2169static DECLCALLBACK(int) dbgcOutputGdb(void *pvUser, const char *pachChars, size_t cbChars)
     2170{
     2171    PGDBSTUBCTX pThis = (PGDBSTUBCTX)pvUser;
     2172
     2173    pThis->fOutput = true;
     2174    int rc = dbgcGdbStubCtxReplySendBegin(pThis);
     2175    if (RT_SUCCESS(rc))
     2176    {
     2177        uint8_t chConOut = 'O';
     2178        rc = dbgcGdbStubCtxReplySendData(pThis, &chConOut, sizeof(chConOut));
     2179        if (RT_SUCCESS(rc))
     2180        {
     2181            /* Convert the characters to hex. */
     2182            const char *pachCur = pachChars;
     2183
     2184            while (   cbChars
     2185                   && RT_SUCCESS(rc))
     2186            {
     2187                uint8_t achHex[512 + 1];
     2188                size_t cbThisSend = RT_MIN((sizeof(achHex) - 1) / 2, cbChars); /* Each character needs two bytes. */
     2189
     2190                rc = dbgcGdbStubCtxEncodeBinaryAsHex(&achHex[0], cbThisSend * 2 + 1, pachCur, cbThisSend);
     2191                if (RT_SUCCESS(rc))
     2192                    rc = dbgcGdbStubCtxReplySendData(pThis, &achHex[0], cbThisSend * 2);
     2193
     2194                pachCur += cbThisSend;
     2195                cbChars -= cbThisSend;
     2196            }
     2197        }
     2198
     2199        dbgcGdbStubCtxReplySendEnd(pThis);
     2200    }
     2201
     2202    return rc;
     2203}
     2204
     2205
     2206/**
    22382207 * Creates a GDB stub context instance with the given backend.
    22392208 *
     
    22642233     */
    22652234    pThis->Dbgc.pBack            = pBack;
     2235    pThis->Dbgc.pfnOutput        = dbgcOutputGdb;
     2236    pThis->Dbgc.pvOutputUser     = pThis;
    22662237    pThis->Dbgc.pVM              = NULL;
    22672238    pThis->Dbgc.pUVM             = NULL;
     
    23172288    pThis->cbTgtXmlDesc    = 0;
    23182289    pThis->fExtendedMode   = false;
     2290    pThis->fOutput         = false;
    23192291    dbgcGdbStubCtxReset(pThis);
    23202292
     
    23852357            pThis->Dbgc.pUVM  = pUVM;
    23862358            pThis->Dbgc.idCpu = 0;
     2359            rc = pThis->Dbgc.CmdHlp.pfnPrintf(&pThis->Dbgc.CmdHlp, NULL,
     2360                                              "Current VM is %08x, CPU #%u\n" /** @todo get and print the VM name! */
     2361                                              , pThis->Dbgc.pVM, pThis->Dbgc.idCpu);
    23872362        }
    23882363        else
  • trunk/src/VBox/Debugger/DBGCInternal.h

    r84627 r84653  
    116116    /** Pointer to backend callback structure. */
    117117    PDBGCBACK           pBack;
     118
     119    /**
     120     * Output a bunch of characters.
     121     *
     122     * @returns VBox status code.
     123     * @param   pvUser      Opaque user data from DBGC::pvOutputUser.
     124     * @param   pachChars   Pointer to an array of utf-8 characters.
     125     * @param   cbChars     Number of bytes in the character array pointed to by pachChars.
     126     */
     127    DECLR3CALLBACKMEMBER(int, pfnOutput, (void *pvUser, const char *pachChars, size_t cbChars));
     128    /** Opqaue user data passed to DBGC::pfnOutput. */
     129    void                *pvOutputUser;
    118130
    119131    /** Pointer to the current VM. */
     
    587599void    dbgcDestroy(PDBGC pDbgc);
    588600
     601const char *dbgcGetEventCtx(DBGFEVENTCTX enmCtx);
    589602
    590603DECLHIDDEN(int) dbgcGdbStubCreate(PUVM pUVM, PDBGCBACK pBack, unsigned fFlags);
  • trunk/src/VBox/Debugger/DBGConsole.cpp

    r84627 r84653  
    588588 * @param   enmCtx          The context.
    589589 */
    590 static const char *dbgcGetEventCtx(DBGFEVENTCTX enmCtx)
     590const char *dbgcGetEventCtx(DBGFEVENTCTX enmCtx)
    591591{
    592592    switch (enmCtx)
     
    10891089
    10901090
     1091/**
     1092 * @copdoc{DBGC,pfnOutput}
     1093 */
     1094static DECLCALLBACK(int) dbgcOutputNative(void *pvUser, const char *pachChars, size_t cbChars)
     1095{
     1096    PDBGC pDbgc = (PDBGC)pvUser;
     1097    return pDbgc->pBack->pfnWrite(pDbgc->pBack, pachChars, cbChars, NULL /*pcbWritten*/);
     1098}
     1099
    10911100
    10921101/**
     
    11151124    dbgcInitCmdHlp(pDbgc);
    11161125    pDbgc->pBack            = pBack;
     1126    pDbgc->pfnOutput        = dbgcOutputNative;
     1127    pDbgc->pvOutputUser     = pDbgc;
    11171128    pDbgc->pVM              = NULL;
    11181129    pDbgc->pUVM             = NULL;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette