Changeset 5679 in vbox
- Timestamp:
- Nov 11, 2007 9:07:18 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/DBGConsole.cpp
r5677 r5679 19 19 /** @page pg_dbgc DBGC - The Debug Console 20 20 * 21 * The debugger console is a first attempt to make some interactive 22 * debugging facilities for the VirtualBox backend (i.e. the VM). At a later 23 * stage we'll make a fancy gui around this, but for the present a telnet (or 24 * serial terminal) will have to suffice. 25 * 26 * The debugger is only built into the VM with debug builds or when 27 * VBOX_WITH_DEBUGGER is defined. There might be need for \#ifdef'ing on this 28 * define to enable special debugger hooks, but the general approach is to 29 * make generic interfaces. The individual components also can register 30 * external commands, and such code must be within \#ifdef. 21 * The debugger console is an early attempt to make some interactive 22 * debugging facilities for the VirtualBox VMM. It was initially only 23 * accessible thru a telnet session on debug builds. Later it was hastily 24 * built into the VBoxDbg module with a very simple Qt wrapper around it. 25 * 26 * The debugger is optional and presently not built into release builds 27 * of VirtualBox. It is therefore necessary to enclose code related to it 28 * in \#ifdef VBOX_WITH_DEBUGGER blocks. This is mandatory for components 29 * that register extenral commands. 31 30 * 32 31 * … … 47 46 * - '0y' - binary. 48 47 * 48 * Some of the prefixes are a bit uncommon, the reason for this that 49 * the typical binary prefix '0b' can also be a hexadecimal value since 50 * no prefix or suffix is required for such values. Ditto for '0d' and 51 * '0' for decimal and octal. 52 * 49 53 * 50 54 * @subsection sec_dbg_op_address Addressing modes … … 55 59 * - The default target for the addressing is the guest context, the '#' 56 60 * will override this and set it to the host. 61 * Note that several operations won't work on host addresses. 62 * 63 * The '%', '%%' and '#' prefixes is implemented as unary operators, while ':' 64 * is a binary operator. Operator precedence takes care of evaluation order. 57 65 * 58 66 * 59 67 * @subsection sec_dbg_op_evalution Evaluation 60 68 * 61 * As time permits support will be implemented support for a subset of the C 62 * binary operators, starting with '+', '-', '*' and '/'. Support for variables 63 * are provided thru commands 'set' and 'unset' and the unary operator '$'. The 64 * unary '@' operator will indicate function calls. The debugger needs a set of 65 * memory read functions, but we might later extend this to allow registration of 66 * external functions too. 67 * 68 * A special command '?' will then be added which evalutates a given expression 69 * and prints it in all the different formats. 69 * Most unary and binary C operators are supported, check the help text for 70 * details. However, some of these are not yet implemented because this is 71 * tiresome and annoying work. So, if something is missing and you need it 72 * you implement it or complain to bird. (Ditto for missing functions.) 73 * 74 * Simple variable support is provided thru the 'set' and 'unset' commands and 75 * the unary '$' operator. 76 * 77 * The unary '@' operator will indicate function calls. Commands and functions 78 * are the same thing, except that functions has a return type. 70 79 * 71 80 * … … 77 86 * prefix the register names with '.'. 78 87 * 79 * 80 * @subsection sec_dbg_op_commands Commands 81 * 82 * The commands are all lowercase, case sensitive, and starting with a letter. We will 83 * later add some special commands ('?' for evaulation) and perhaps command classes ('.', '!') 84 * 85 * 86 * @section sec_dbg_tasks Tasks 87 * 88 * To implement DBGT and instrument VMM for basic state inspection and log 89 * viewing, the follwing task must be executed: 90 * 91 * -# Basic threading layer in RT. 92 * -# Basic tcpip server abstration in RT. 93 * -# Write DBGC. 94 * -# Write DBCTCP. 95 * -# Integrate with VMM and the rest. 96 * -# Start writing DBGF (VMM). 88 * The registers are implemented as built-in symbols. For making gdb guys more at 89 * home it is possible to access them with the '$' operator, i.e. as a variable. 90 * 91 * 92 * @subsection sec_dbg_op_commands Commands and Functions 93 * 94 * Commands and functions are the same thing, except that functions may return a 95 * value. So, functions may be used as commands. The command/function handlers 96 * can detect whether they are invoked as a command or function by checking whether 97 * there is a return variable or not. 98 * 99 * The command/function names are all lowercase, case sensitive, and starting 100 * with a letter. Operator characters are not permitted in the names of course. 101 * Space is allowed, but must be flagged so the parser can check for multiple 102 * spaces and tabs. (This feature is for 'dump xyz' and for emulating the 103 * gdb 'info abc'.) 104 * 105 * The '.' prefix indicates the set of external commands. External commands are 106 * command registered by VMM components. 107 * 108 * 109 * @section sec_dbgc_logging Logging 110 * 111 * The idea is to be able to pass thru debug and release logs to the console 112 * if the user so wishes. This feature requires some kind of hook into the 113 * logger instance and while this was sketched it hasn't yet been implemented 114 * (dbgcProcessLog and DBGC::fLog). 115 * 116 * 117 * 118 * @section sec_dbgc_linking Linking and API 119 * 120 * The DBGC code is linked into the VBoxVMM module. (At present it is also 121 * linked into VBoxDbg, but this is obviously very wrong.) 122 * 123 * A COM object will be created for the DBGC so it can be operated remotely 124 * without using TCP. VBoxDbg is the intended audience for this usage. Some 125 * questions about callbacks (for output) and security (you may wish to 126 * restrict users from debugging a VM) needs to be answered first though. 97 127 */ 98 99 100 128 101 129 … … 135 163 136 164 165 /******************************************************************************* 166 * Internal Functions * 167 *******************************************************************************/ 168 static int dbgcProcessLog(PDBGC pDbgc); 169 170 137 171 138 172 /** … … 157 191 return ASMBitTest(&g_bmOperatorChars[0], (uint8_t)ch); 158 192 } 159 160 161 /**162 * Prints any log lines from the log buffer.163 *164 * The caller must not call function this unless pDbgc->fLog is set.165 *166 * @returns VBox status. (output related)167 * @param pDbgc Debugger console instance data.168 */169 static int dbgcProcessLog(PDBGC pDbgc)170 {171 /** @todo */172 NOREF(pDbgc);173 return 0;174 }175 176 177 178 /**179 * Handle input buffer overflow.180 *181 * Will read any available input looking for a '\n' to reset the buffer on.182 *183 * @returns VBox status.184 * @param pDbgc Debugger console instance data.185 */186 static int dbgcInputOverflow(PDBGC pDbgc)187 {188 /*189 * Assert overflow status and reset the input buffer.190 */191 if (!pDbgc->fInputOverflow)192 {193 pDbgc->fInputOverflow = true;194 pDbgc->iRead = pDbgc->iWrite = 0;195 pDbgc->cInputLines = 0;196 pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Input overflow!!\n");197 }198 199 /*200 * Eat input till no more or there is a '\n'.201 * When finding a '\n' we'll continue normal processing.202 */203 while (pDbgc->pBack->pfnInput(pDbgc->pBack, 0))204 {205 size_t cbRead;206 int rc = pDbgc->pBack->pfnRead(pDbgc->pBack, &pDbgc->achInput[0], sizeof(pDbgc->achInput) - 1, &cbRead);207 if (VBOX_FAILURE(rc))208 return rc;209 char *psz = (char *)memchr(&pDbgc->achInput[0], '\n', cbRead);210 if (psz)211 {212 pDbgc->fInputOverflow = false;213 pDbgc->iRead = psz - &pDbgc->achInput[0] + 1;214 pDbgc->iWrite = (unsigned)cbRead;215 pDbgc->cInputLines = 0;216 break;217 }218 }219 220 return 0;221 }222 223 224 225 /**226 * Read input and do some preprocessing.227 *228 * @returns VBox status.229 * In addition to the iWrite and achInput, cInputLines is maintained.230 * In case of an input overflow the fInputOverflow flag will be set.231 * @param pDbgc Debugger console instance data.232 */233 static int dbgcInputRead(PDBGC pDbgc)234 {235 /*236 * We have ready input.237 * Read it till we don't have any or we have a full input buffer.238 */239 int rc = 0;240 do241 {242 /*243 * More available buffer space?244 */245 size_t cbLeft;246 if (pDbgc->iWrite > pDbgc->iRead)247 cbLeft = sizeof(pDbgc->achInput) - pDbgc->iWrite - (pDbgc->iRead == 0);248 else249 cbLeft = pDbgc->iRead - pDbgc->iWrite - 1;250 if (!cbLeft)251 {252 /* overflow? */253 if (!pDbgc->cInputLines)254 rc = dbgcInputOverflow(pDbgc);255 break;256 }257 258 /*259 * Read one char and interpret it.260 */261 char achRead[128];262 size_t cbRead;263 rc = pDbgc->pBack->pfnRead(pDbgc->pBack, &achRead[0], RT_MIN(cbLeft, sizeof(achRead)), &cbRead);264 if (VBOX_FAILURE(rc))265 return rc;266 char *psz = &achRead[0];267 while (cbRead-- > 0)268 {269 char ch = *psz++;270 switch (ch)271 {272 /*273 * Ignore.274 */275 case '\0':276 case '\r':277 case '\a':278 break;279 280 /*281 * Backspace.282 */283 case '\b':284 Log2(("DBGC: backspace\n"));285 if (pDbgc->iRead != pDbgc->iWrite)286 {287 unsigned iWriteUndo = pDbgc->iWrite;288 if (pDbgc->iWrite)289 pDbgc->iWrite--;290 else291 pDbgc->iWrite = sizeof(pDbgc->achInput) - 1;292 293 if (pDbgc->achInput[pDbgc->iWrite] == '\n')294 pDbgc->iWrite = iWriteUndo;295 }296 break;297 298 /*299 * Add char to buffer.300 */301 case '\t':302 case '\n':303 case ';':304 switch (ch)305 {306 case '\t': ch = ' '; break;307 case '\n': pDbgc->cInputLines++; break;308 }309 default:310 Log2(("DBGC: ch=%02x\n", (unsigned char)ch));311 pDbgc->achInput[pDbgc->iWrite] = ch;312 if (++pDbgc->iWrite >= sizeof(pDbgc->achInput))313 pDbgc->iWrite = 0;314 break;315 }316 }317 318 /* Terminate it to make it easier to read in the debugger. */319 pDbgc->achInput[pDbgc->iWrite] = '\0';320 } while (pDbgc->pBack->pfnInput(pDbgc->pBack, 0));321 322 return rc;323 }324 325 193 326 194 … … 1486 1354 1487 1355 /** 1488 * Process all commands current in the buffer.1356 * Process all commands currently in the buffer. 1489 1357 * 1490 1358 * @returns VBox status code. Any error indicates the termination of the console session. … … 1551 1419 break; 1552 1420 } 1421 1422 return rc; 1423 } 1424 1425 1426 /** 1427 * Handle input buffer overflow. 1428 * 1429 * Will read any available input looking for a '\n' to reset the buffer on. 1430 * 1431 * @returns VBox status. 1432 * @param pDbgc Debugger console instance data. 1433 */ 1434 static int dbgcInputOverflow(PDBGC pDbgc) 1435 { 1436 /* 1437 * Assert overflow status and reset the input buffer. 1438 */ 1439 if (!pDbgc->fInputOverflow) 1440 { 1441 pDbgc->fInputOverflow = true; 1442 pDbgc->iRead = pDbgc->iWrite = 0; 1443 pDbgc->cInputLines = 0; 1444 pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "Input overflow!!\n"); 1445 } 1446 1447 /* 1448 * Eat input till no more or there is a '\n'. 1449 * When finding a '\n' we'll continue normal processing. 1450 */ 1451 while (pDbgc->pBack->pfnInput(pDbgc->pBack, 0)) 1452 { 1453 size_t cbRead; 1454 int rc = pDbgc->pBack->pfnRead(pDbgc->pBack, &pDbgc->achInput[0], sizeof(pDbgc->achInput) - 1, &cbRead); 1455 if (VBOX_FAILURE(rc)) 1456 return rc; 1457 char *psz = (char *)memchr(&pDbgc->achInput[0], '\n', cbRead); 1458 if (psz) 1459 { 1460 pDbgc->fInputOverflow = false; 1461 pDbgc->iRead = psz - &pDbgc->achInput[0] + 1; 1462 pDbgc->iWrite = (unsigned)cbRead; 1463 pDbgc->cInputLines = 0; 1464 break; 1465 } 1466 } 1467 1468 return 0; 1469 } 1470 1471 1472 /** 1473 * Read input and do some preprocessing. 1474 * 1475 * @returns VBox status. 1476 * In addition to the iWrite and achInput, cInputLines is maintained. 1477 * In case of an input overflow the fInputOverflow flag will be set. 1478 * @param pDbgc Debugger console instance data. 1479 */ 1480 static int dbgcInputRead(PDBGC pDbgc) 1481 { 1482 /* 1483 * We have ready input. 1484 * Read it till we don't have any or we have a full input buffer. 1485 */ 1486 int rc = 0; 1487 do 1488 { 1489 /* 1490 * More available buffer space? 1491 */ 1492 size_t cbLeft; 1493 if (pDbgc->iWrite > pDbgc->iRead) 1494 cbLeft = sizeof(pDbgc->achInput) - pDbgc->iWrite - (pDbgc->iRead == 0); 1495 else 1496 cbLeft = pDbgc->iRead - pDbgc->iWrite - 1; 1497 if (!cbLeft) 1498 { 1499 /* overflow? */ 1500 if (!pDbgc->cInputLines) 1501 rc = dbgcInputOverflow(pDbgc); 1502 break; 1503 } 1504 1505 /* 1506 * Read one char and interpret it. 1507 */ 1508 char achRead[128]; 1509 size_t cbRead; 1510 rc = pDbgc->pBack->pfnRead(pDbgc->pBack, &achRead[0], RT_MIN(cbLeft, sizeof(achRead)), &cbRead); 1511 if (VBOX_FAILURE(rc)) 1512 return rc; 1513 char *psz = &achRead[0]; 1514 while (cbRead-- > 0) 1515 { 1516 char ch = *psz++; 1517 switch (ch) 1518 { 1519 /* 1520 * Ignore. 1521 */ 1522 case '\0': 1523 case '\r': 1524 case '\a': 1525 break; 1526 1527 /* 1528 * Backspace. 1529 */ 1530 case '\b': 1531 Log2(("DBGC: backspace\n")); 1532 if (pDbgc->iRead != pDbgc->iWrite) 1533 { 1534 unsigned iWriteUndo = pDbgc->iWrite; 1535 if (pDbgc->iWrite) 1536 pDbgc->iWrite--; 1537 else 1538 pDbgc->iWrite = sizeof(pDbgc->achInput) - 1; 1539 1540 if (pDbgc->achInput[pDbgc->iWrite] == '\n') 1541 pDbgc->iWrite = iWriteUndo; 1542 } 1543 break; 1544 1545 /* 1546 * Add char to buffer. 1547 */ 1548 case '\t': 1549 case '\n': 1550 case ';': 1551 switch (ch) 1552 { 1553 case '\t': ch = ' '; break; 1554 case '\n': pDbgc->cInputLines++; break; 1555 } 1556 default: 1557 Log2(("DBGC: ch=%02x\n", (unsigned char)ch)); 1558 pDbgc->achInput[pDbgc->iWrite] = ch; 1559 if (++pDbgc->iWrite >= sizeof(pDbgc->achInput)) 1560 pDbgc->iWrite = 0; 1561 break; 1562 } 1563 } 1564 1565 /* Terminate it to make it easier to read in the debugger. */ 1566 pDbgc->achInput[pDbgc->iWrite] = '\0'; 1567 } while (pDbgc->pBack->pfnInput(pDbgc->pBack, 0)); 1553 1568 1554 1569 return rc; … … 1745 1760 if (VBOX_SUCCESS(rc) && pEvent->u.Src.pszMessage && *pEvent->u.Src.pszMessage) 1746 1761 rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, 1747 "Message: %s\n",1762 "Message: %s\n", 1748 1763 pEvent->u.Src.pszMessage); 1749 1764 if (VBOX_SUCCESS(rc)) … … 1788 1803 1789 1804 1790 1805 /** 1806 * Prints any log lines from the log buffer. 1807 * 1808 * The caller must not call function this unless pDbgc->fLog is set. 1809 * 1810 * @returns VBox status. (output related) 1811 * @param pDbgc Debugger console instance data. 1812 */ 1813 static int dbgcProcessLog(PDBGC pDbgc) 1814 { 1815 /** @todo */ 1816 NOREF(pDbgc); 1817 return 0; 1818 } 1791 1819 1792 1820 … … 1807 1835 * callbacks to return fatal failures. 1808 1836 */ 1809 DBGDECL(int) 1837 DBGDECL(int) DBGCCreate(PVM pVM, PDBGCBACK pBack, unsigned fFlags) 1810 1838 { 1811 1839 /*
Note:
See TracChangeset
for help on using the changeset viewer.