- Timestamp:
- Jun 5, 2020 6:12:41 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/DBGCGdbRemoteStub.cpp
r84694 r84707 154 154 * Means we have to track all registration so we can remove them later on. */ 155 155 RTLISTANCHOR LstTps; 156 /** Flag whether a ThreadInfo query was started. */ 157 bool fInThrdInfoQuery; 158 /** Next ID to return in the current ThreadInfo query. */ 159 VMCPUID idCpuNextThrdInfoQuery; 156 160 } GDBSTUBCTX; 157 161 /** Pointer to the GDB stub context data. */ … … 582 586 static int dbgcGdbStubCtxReplySendSigTrap(PGDBSTUBCTX pThis) 583 587 { 584 uint8_t achSigTrap[3] = { 'S', '0', '5' }; 585 return dbgcGdbStubCtxReplySend(pThis, &achSigTrap[0], sizeof(achSigTrap)); 588 char achReply[32]; 589 ssize_t cchStr = RTStrPrintf2(&achReply[0], sizeof(achReply), "T05thread:%02x;", pThis->Dbgc.idCpu + 1); 590 return dbgcGdbStubCtxReplySend(pThis, &achReply[0], cchStr); 586 591 } 587 592 … … 793 798 /** @todo Enhance. */ 794 799 if (pThis->fFeatures & GDBSTUBCTX_FEATURES_F_TGT_DESC) 795 return dbgcGdbStubCtxReplySend(pThis, "qXfer:features:read+ ", sizeof("qXfer:features:read+") - 1);800 return dbgcGdbStubCtxReplySend(pThis, "qXfer:features:read+;vContSupported+", sizeof("qXfer:features:read+;vContSupported+") - 1); 796 801 797 802 return dbgcGdbStubCtxReplySend(pThis, NULL, 0); … … 1128 1133 1129 1134 /** 1135 * Processes the 'C' query (query current thread ID). 1136 * 1137 * @returns Status code. 1138 * @param pThis The GDB stub context. 1139 * @param pbArgs Pointer to the start of the arguments in the packet. 1140 * @param cbArgs Size of arguments in bytes. 1141 */ 1142 static int dbgcGdbStubCtxPktProcessQueryThreadId(PGDBSTUBCTX pThis, const uint8_t *pbArgs, size_t cbArgs) 1143 { 1144 RT_NOREF(pbArgs, cbArgs); 1145 1146 int rc = VERR_BUFFER_OVERFLOW; 1147 char achReply[32]; 1148 ssize_t cchStr = RTStrPrintf(&achReply[0], sizeof(achReply), "QC %02x", pThis->Dbgc.idCpu + 1); 1149 if (cchStr > 0) 1150 rc = dbgcGdbStubCtxReplySend(pThis, &achReply[0], cchStr); 1151 1152 return rc; 1153 } 1154 1155 1156 /** 1157 * Processes the 'Attached' query. 1158 * 1159 * @returns Status code. 1160 * @param pThis The GDB stub context. 1161 * @param pbArgs Pointer to the start of the arguments in the packet. 1162 * @param cbArgs Size of arguments in bytes. 1163 */ 1164 static int dbgcGdbStubCtxPktProcessQueryAttached(PGDBSTUBCTX pThis, const uint8_t *pbArgs, size_t cbArgs) 1165 { 1166 RT_NOREF(pbArgs, cbArgs); 1167 1168 /* We always report attached so that the VM doesn't get killed when GDB quits. */ 1169 uint8_t bAttached = '1'; 1170 return dbgcGdbStubCtxReplySend(pThis, &bAttached, sizeof(bAttached)); 1171 } 1172 1173 1174 /** 1130 1175 * Processes the 'Xfer:features:read' query. 1131 1176 * … … 1234 1279 1235 1280 /** 1281 * Worker for both 'qfThreadInfo' and 'qsThreadInfo'. 1282 * 1283 * @returns VBox status code. 1284 * @param pThis The GDB stub context. 1285 */ 1286 static int dbgcGdbStubCtxPktProcessQueryThreadInfoWorker(PGDBSTUBCTX pThis) 1287 { 1288 int rc = dbgcGdbStubCtxReplySendBegin(pThis); 1289 if (RT_SUCCESS(rc)) 1290 { 1291 uint8_t bReplyStart = { 'm' }; 1292 rc = dbgcGdbStubCtxReplySendData(pThis, &bReplyStart, sizeof(bReplyStart)); 1293 if (RT_SUCCESS(rc)) 1294 { 1295 char achReply[32]; 1296 ssize_t cchStr = RTStrPrintf(&achReply[0], sizeof(achReply), "%02x", pThis->idCpuNextThrdInfoQuery + 1); 1297 if (cchStr <= 0) 1298 rc = VERR_BUFFER_OVERFLOW; 1299 1300 if (RT_SUCCESS(rc)) 1301 rc = dbgcGdbStubCtxReplySendData(pThis, &achReply[0], cchStr); 1302 pThis->idCpuNextThrdInfoQuery++; 1303 } 1304 1305 rc = dbgcGdbStubCtxReplySendEnd(pThis); 1306 } 1307 1308 return rc; 1309 } 1310 1311 1312 /** 1313 * Processes the 'fThreadInfo' query. 1314 * 1315 * @returns Status code. 1316 * @param pThis The GDB stub context. 1317 * @param pbArgs Pointer to the start of the arguments in the packet. 1318 * @param cbArgs Size of arguments in bytes. 1319 */ 1320 static int dbgcGdbStubCtxPktProcessQueryThreadInfoStart(PGDBSTUBCTX pThis, const uint8_t *pbArgs, size_t cbArgs) 1321 { 1322 RT_NOREF(pbArgs, cbArgs); 1323 1324 pThis->idCpuNextThrdInfoQuery = 0; 1325 pThis->fInThrdInfoQuery = true; 1326 return dbgcGdbStubCtxPktProcessQueryThreadInfoWorker(pThis); 1327 } 1328 1329 1330 /** 1331 * Processes the 'fThreadInfo' query. 1332 * 1333 * @returns Status code. 1334 * @param pThis The GDB stub context. 1335 * @param pbArgs Pointer to the start of the arguments in the packet. 1336 * @param cbArgs Size of arguments in bytes. 1337 */ 1338 static int dbgcGdbStubCtxPktProcessQueryThreadInfoCont(PGDBSTUBCTX pThis, const uint8_t *pbArgs, size_t cbArgs) 1339 { 1340 RT_NOREF(pbArgs, cbArgs); 1341 1342 /* If we are in a thread info query we just send the end of list specifier (all thread IDs where sent previously already). */ 1343 if (!pThis->fInThrdInfoQuery) 1344 return dbgcGdbStubCtxReplySendErrSts(pThis, VERR_NET_PROTOCOL_ERROR); 1345 1346 VMCPUID cCpus = DBGFR3CpuGetCount(pThis->Dbgc.pUVM); 1347 if (pThis->idCpuNextThrdInfoQuery == cCpus) 1348 { 1349 pThis->fInThrdInfoQuery = false; 1350 uint8_t bEoL = 'l'; 1351 return dbgcGdbStubCtxReplySend(pThis, &bEoL, sizeof(bEoL)); 1352 } 1353 1354 return dbgcGdbStubCtxPktProcessQueryThreadInfoWorker(pThis); 1355 } 1356 1357 1358 /** 1359 * Processes the 'ThreadExtraInfo' query. 1360 * 1361 * @returns Status code. 1362 * @param pThis The GDB stub context. 1363 * @param pbArgs Pointer to the start of the arguments in the packet. 1364 * @param cbArgs Size of arguments in bytes. 1365 */ 1366 static int dbgcGdbStubCtxPktProcessQueryThreadExtraInfo(PGDBSTUBCTX pThis, const uint8_t *pbArgs, size_t cbArgs) 1367 { 1368 /* Skip the , following the qThreadExtraInfo start. */ 1369 if ( cbArgs < 1 1370 || pbArgs[0] != ',') 1371 return VERR_NET_PROTOCOL_ERROR; 1372 1373 cbArgs--; 1374 pbArgs++; 1375 1376 /* We know there is an # character denoting the end so the following must return with VWRN_TRAILING_CHARS. */ 1377 VMCPUID idCpu; 1378 int rc = RTStrToUInt32Ex((const char *)pbArgs, NULL /*ppszNext*/, 16, &idCpu); 1379 if ( rc == VWRN_TRAILING_CHARS 1380 && idCpu > 0) 1381 { 1382 idCpu--; 1383 1384 VMCPUID cCpus = DBGFR3CpuGetCount(pThis->Dbgc.pUVM); 1385 if (idCpu < cCpus) 1386 { 1387 const char *pszCpuState = DBGFR3CpuGetState(pThis->Dbgc.pUVM, idCpu); 1388 size_t cchCpuState = strlen(pszCpuState); 1389 1390 if (!pszCpuState) 1391 pszCpuState = "DBGFR3CpuGetState() -> NULL"; 1392 1393 rc = dbgcGdbStubCtxReplySendBegin(pThis); 1394 if (RT_SUCCESS(rc)) 1395 { 1396 /* Convert the characters to hex. */ 1397 const char *pachCur = pszCpuState; 1398 1399 while ( cchCpuState 1400 && RT_SUCCESS(rc)) 1401 { 1402 uint8_t achHex[512 + 1]; 1403 size_t cbThisSend = RT_MIN((sizeof(achHex) - 1) / 2, cchCpuState); /* Each character needs two bytes. */ 1404 1405 rc = dbgcGdbStubCtxEncodeBinaryAsHex(&achHex[0], cbThisSend * 2 + 1, pachCur, cbThisSend); 1406 if (RT_SUCCESS(rc)) 1407 rc = dbgcGdbStubCtxReplySendData(pThis, &achHex[0], cbThisSend * 2); 1408 1409 pachCur += cbThisSend; 1410 cchCpuState -= cbThisSend; 1411 } 1412 1413 dbgcGdbStubCtxReplySendEnd(pThis); 1414 } 1415 } 1416 else 1417 rc = dbgcGdbStubCtxReplySendErrSts(pThis, VERR_NET_PROTOCOL_ERROR); 1418 } 1419 else if ( RT_SUCCESS(rc) 1420 || !idCpu) 1421 rc = dbgcGdbStubCtxReplySendErrSts(pThis, VERR_NET_PROTOCOL_ERROR); 1422 1423 return rc; 1424 } 1425 1426 1427 /** 1236 1428 * List of supported query packets. 1237 1429 */ … … 1239 1431 { 1240 1432 #define GDBSTUBQPKTPROC_INIT(a_Name, a_pfnProc) { a_Name, sizeof(a_Name) - 1, a_pfnProc } 1433 GDBSTUBQPKTPROC_INIT("C", dbgcGdbStubCtxPktProcessQueryThreadId), 1434 GDBSTUBQPKTPROC_INIT("Attached", dbgcGdbStubCtxPktProcessQueryAttached), 1241 1435 GDBSTUBQPKTPROC_INIT("TStatus", dbgcGdbStubCtxPktProcessQueryTStatus), 1242 1436 GDBSTUBQPKTPROC_INIT("Supported", dbgcGdbStubCtxPktProcessQuerySupported), 1243 1437 GDBSTUBQPKTPROC_INIT("Xfer:features:read", dbgcGdbStubCtxPktProcessQueryXferFeatRead), 1244 1438 GDBSTUBQPKTPROC_INIT("Rcmd", dbgcGdbStubCtxPktProcessQueryRcmd), 1439 GDBSTUBQPKTPROC_INIT("fThreadInfo", dbgcGdbStubCtxPktProcessQueryThreadInfoStart), 1440 GDBSTUBQPKTPROC_INIT("sThreadInfo", dbgcGdbStubCtxPktProcessQueryThreadInfoCont), 1441 GDBSTUBQPKTPROC_INIT("ThreadExtraInfo", dbgcGdbStubCtxPktProcessQueryThreadExtraInfo), 1245 1442 #undef GDBSTUBQPKTPROC_INIT 1246 1443 }; … … 1381 1578 1382 1579 /** 1580 * Processes a 'H<op><thread-id>' packet, sending the appropriate reply. 1581 * 1582 * @returns Status code. 1583 * @param pThis The GDB stub context. 1584 * @param pbPktRem The remaining packet data (without the 'H'). 1585 * @param cbPktRem Size of the remaining packet in bytes. 1586 */ 1587 static int dbgcGdbStubCtxPktProcessH(PGDBSTUBCTX pThis, const uint8_t *pbPktRem, size_t cbPktRem) 1588 { 1589 int rc = VINF_SUCCESS; 1590 1591 if (*pbPktRem == 'g') 1592 { 1593 cbPktRem--; 1594 pbPktRem++; 1595 1596 /* We know there is an # character denoting the end so the following must return with VWRN_TRAILING_CHARS. */ 1597 VMCPUID idCpu; 1598 rc = RTStrToUInt32Ex((const char *)pbPktRem, NULL /*ppszNext*/, 16, &idCpu); 1599 if ( rc == VWRN_TRAILING_CHARS 1600 && idCpu > 0) 1601 { 1602 idCpu--; 1603 1604 VMCPUID cCpus = DBGFR3CpuGetCount(pThis->Dbgc.pUVM); 1605 if (idCpu < cCpus) 1606 { 1607 pThis->Dbgc.idCpu = idCpu; 1608 rc = dbgcGdbStubCtxReplySendOk(pThis); 1609 } 1610 else 1611 rc = dbgcGdbStubCtxReplySendErrSts(pThis, VERR_NET_PROTOCOL_ERROR); 1612 } 1613 else 1614 rc = dbgcGdbStubCtxReplySendErrSts(pThis, VERR_NET_PROTOCOL_ERROR); 1615 } 1616 else /* Do not support the 'c' operation for now (will be handled through vCont later on anyway). */ 1617 rc = dbgcGdbStubCtxReplySend(pThis, NULL, 0); 1618 1619 return rc; 1620 } 1621 1622 1623 /** 1383 1624 * Processes a completely received packet. 1384 1625 * … … 1420 1661 if (DBGFR3IsHalted(pThis->Dbgc.pUVM)) 1421 1662 DBGFR3Resume(pThis->Dbgc.pUVM); 1663 break; 1664 } 1665 case 'H': 1666 { 1667 rc = dbgcGdbStubCtxPktProcessH(pThis, &pThis->pbPktBuf[2], pThis->cbPkt - 1); 1668 break; 1669 } 1670 case 'T': 1671 { 1672 rc = dbgcGdbStubCtxReplySendOk(pThis); 1422 1673 break; 1423 1674 } … … 2151 2402 } 2152 2403 2153 #if 02154 2404 default: 2155 2405 { … … 2212 2462 } 2213 2463 2214 /*2215 * Prompt, anyone?2216 */2217 if (fPrintPrompt && RT_SUCCESS(rc))2218 {2219 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "VBoxDbg> ");2220 pDbgc->fReady = true;2221 if (RT_SUCCESS(rc))2222 pDbgc->pBack->pfnSetReady(pDbgc->pBack, true);2223 pDbgc->cMultiStepsLeft = 0;2224 }2225 #else2226 default:2227 break;2228 }2229 #endif2230 2231 2464 return rc; 2232 2465 } … … 2425 2658 2426 2659 /* Init the GDB stub specific parts. */ 2427 pThis->cbPktBufMax = 0; 2428 pThis->pbPktBuf = NULL; 2429 pThis->fFeatures = GDBSTUBCTX_FEATURES_F_TGT_DESC; 2430 pThis->pachTgtXmlDesc = NULL; 2431 pThis->cbTgtXmlDesc = 0; 2432 pThis->fExtendedMode = false; 2433 pThis->fOutput = false; 2660 pThis->cbPktBufMax = 0; 2661 pThis->pbPktBuf = NULL; 2662 pThis->fFeatures = GDBSTUBCTX_FEATURES_F_TGT_DESC; 2663 pThis->pachTgtXmlDesc = NULL; 2664 pThis->cbTgtXmlDesc = 0; 2665 pThis->fExtendedMode = false; 2666 pThis->fOutput = false; 2667 pThis->fInThrdInfoQuery = false; 2434 2668 RTListInit(&pThis->LstTps); 2435 2669 dbgcGdbStubCtxReset(pThis); … … 2501 2735 pThis->Dbgc.pUVM = pUVM; 2502 2736 pThis->Dbgc.idCpu = 0; 2503 rc = pThis->Dbgc.CmdHlp.pfnPrintf(&pThis->Dbgc.CmdHlp, NULL,2504 "Current VM is %08x, CPU #%u\n" /** @todo get and print the VM name! */2505 , pThis->Dbgc.pVM, pThis->Dbgc.idCpu);2506 2737 } 2507 2738 else
Note:
See TracChangeset
for help on using the changeset viewer.