Changeset 41571 in vbox
- Timestamp:
- Jun 4, 2012 7:49:03 PM (13 years ago)
- Location:
- trunk/src/VBox/Debugger
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/DBGCCmdHlp.cpp
r41565 r41571 5 5 6 6 /* 7 * Copyright (C) 2006-201 1Oracle Corporation7 * Copyright (C) 2006-2012 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 1198 1198 rc = dbgcSymbolGet(pDbgc, InVar.u.pszString, enmToType, pResult); 1199 1199 if (RT_SUCCESS(rc)) 1200 {1201 if (InVar.enmRangeType != DBGCVAR_RANGE_NONE)1202 {1203 pResult->enmRangeType = InVar.enmRangeType;1204 pResult->u64Range = InVar.u64Range;1205 }1206 1200 return VINF_SUCCESS; 1207 }1208 1201 } 1209 1202 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; -
trunk/src/VBox/Debugger/DBGCCommands.cpp
r41561 r41571 1064 1064 break; 1065 1065 1066 case DBGCVAR_TYPE_SYMBOL: 1067 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, 1068 "Symbol, %lld bytes long: %s\n", 1069 paArgs[iArg].u64Range, 1070 paArgs[iArg].u.pszString); 1071 break; 1072 1066 1073 case DBGCVAR_TYPE_NUMBER: 1067 1074 if (paArgs[iArg].enmRangeType != DBGCVAR_RANGE_NONE) -
trunk/src/VBox/Debugger/DBGCEval.cpp
r41561 r41571 76 76 77 77 78 79 static int dbgcEvalSubString(PDBGC pDbgc, char *pszExpr, size_t cchExpr, PDBGCVAR pArg) 78 /** 79 * Returns the amount of free scratch space. 80 * 81 * @returns Number of unallocated bytes. 82 * @param pDbgc The DBGC instance. 83 */ 84 size_t dbgcGetFreeScratchSpace(PDBGC pDbgc) 80 85 { 81 Log2(("dbgcEvalSubString: cchExpr=%d pszExpr=%s\n", cchExpr, pszExpr)); 86 return sizeof(pDbgc->achScratch) - (pDbgc->pszScratch - &pDbgc->achScratch[0]); 87 } 88 89 90 /** 91 * Allocates a string from the scratch space. 92 * 93 * @returns Pointer to the allocated string buffer, NULL if out of space. 94 * @param pDbgc The DBGC instance. 95 * @param cbRequested The number of bytes to allocate. 96 */ 97 char *dbgcAllocStringScatch(PDBGC pDbgc, size_t cbRequested) 98 { 99 if (cbRequested > dbgcGetFreeScratchSpace(pDbgc)) 100 return NULL; 101 char *psz = pDbgc->pszScratch; 102 pDbgc->pszScratch += cbRequested; 103 return psz; 104 } 105 106 107 /** 108 * Evals an expression into a string or symbol (single quotes). 109 * 110 * The string memory is allocated from the scratch buffer. 111 * 112 * @returns VBox status code. 113 * @param pDbgc The DBGC instance. 114 * @param pachExpr The string/symbol expression. 115 * @param cchExpr The length of the expression. 116 * @param pArg Where to return the string. 117 */ 118 static int dbgcEvalSubString(PDBGC pDbgc, const char *pachExpr, size_t cchExpr, PDBGCVAR pArg) 119 { 120 Log2(("dbgcEvalSubString: cchExpr=%d pachExpr=%.*s\n", cchExpr, cchExpr, pachExpr)); 121 122 /* 123 * Allocate scratch space for the string. 124 */ 125 char *pszCopy = dbgcAllocStringScatch(pDbgc, cchExpr + 1); 126 if (!pszCopy) 127 return VERR_DBGC_PARSE_NO_SCRATCH; 82 128 83 129 /* 84 130 * Removing any quoting and escapings. 85 131 */ 86 char c h = *pszExpr;87 if (ch == '"' || ch== '\'')88 { 89 if (p szExpr[--cchExpr] != ch)132 char const chQuote = *pachExpr; 133 if (chQuote == '"' || chQuote == '\'') 134 { 135 if (pachExpr[--cchExpr] != chQuote) 90 136 return VERR_DBGC_PARSE_UNBALANCED_QUOTE; 137 91 138 cchExpr--; 92 pszExpr++; 93 94 /** @todo string unescaping. */ 95 } 96 pszExpr[cchExpr] = '\0'; 139 pachExpr++; 140 if (!memchr(pachExpr, chQuote, cchExpr)) 141 memcpy(pszCopy, pachExpr, cchExpr); 142 else 143 { 144 size_t offSrc = 0; 145 size_t offDst = 0; 146 while (offSrc < cchExpr) 147 { 148 char const ch = pachExpr[offSrc++]; 149 if (ch == chQuote) 150 { 151 if (pachExpr[offSrc] != ch) 152 return VERR_DBGC_PARSE_EXPECTED_BINARY_OP; 153 offSrc++; 154 } 155 pszCopy[offDst++] = ch; 156 } 157 } 158 } 159 else 160 memcpy(pszCopy, pachExpr, cchExpr); 161 pszCopy[cchExpr] = '\0'; 97 162 98 163 /* … … 101 166 pArg->pDesc = NULL; 102 167 pArg->pNext = NULL; 103 pArg->enmType = DBGCVAR_TYPE_STRING;104 pArg->u.pszString = psz Expr;168 pArg->enmType = chQuote == '\'' ? DBGCVAR_TYPE_SYMBOL : DBGCVAR_TYPE_STRING; 169 pArg->u.pszString = pszCopy; 105 170 pArg->enmRangeType = DBGCVAR_RANGE_BYTES; 106 171 pArg->u64Range = cchExpr; … … 111 176 112 177 113 static int dbgcEvalSubNum(c har *pszExpr, unsigned uBase, PDBGCVAR pArg)178 static int dbgcEvalSubNum(const char *pachExpr, size_t cchExpr, unsigned uBase, PDBGCVAR pArg) 114 179 { 115 Log2(("dbgcEvalSubNum: uBase=%d pszExpr=%s\n", uBase, pszExpr)); 180 Log2(("dbgcEvalSubNum: uBase=%d pachExpr=%.*s\n", uBase, cchExpr, pachExpr)); 181 182 /* 183 * Empty expressions cannot be valid numbers. 184 */ 185 if (!cchExpr) 186 return VERR_DBGC_PARSE_INVALID_NUMBER; 187 116 188 /* 117 189 * Convert to number. 118 190 */ 119 191 uint64_t u64 = 0; 120 char ch;121 while ((ch = *pszExpr) != '\0')122 {192 while (cchExpr-- > 0) 193 { 194 char const ch = *pachExpr; 123 195 uint64_t u64Prev = u64; 124 196 unsigned u = ch - '0'; … … 137 209 138 210 /* next */ 139 p szExpr++;211 pachExpr++; 140 212 } 141 213 … … 172 244 /* 0x<hex digits> */ 173 245 if (ch == '0' && (ch2 == 'x' || ch2 == 'X')) 174 return dbgcEvalSubNum(pszExpr + 2, 16, pResult);246 return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 16, pResult); 175 247 176 248 /* <hex digits>h */ … … 178 250 { 179 251 pszExpr[cchExpr] = '\0'; 180 return dbgcEvalSubNum(pszExpr, 16, pResult);252 return dbgcEvalSubNum(pszExpr, cchExpr - 1, 16, pResult); 181 253 } 182 254 183 255 /* 0i<decimal digits> */ 184 256 if (ch == '0' && ch2 == 'i') 185 return dbgcEvalSubNum(pszExpr + 2, 10, pResult);257 return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 10, pResult); 186 258 187 259 /* 0t<octal digits> */ 188 260 if (ch == '0' && ch2 == 't') 189 return dbgcEvalSubNum(pszExpr + 2, 8, pResult);261 return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 8, pResult); 190 262 191 263 /* 0y<binary digits> */ 192 264 if (ch == '0' && ch2 == 'y') 193 return dbgcEvalSubNum(pszExpr + 2, 10, pResult);265 return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 10, pResult); 194 266 195 267 /* Hex number? */ 196 268 unsigned off = 0; 197 while ( RT_C_IS_XDIGIT(pszExpr[off]) || pszExpr[off] == '`')269 while (off < cchExpr && (RT_C_IS_XDIGIT(pszExpr[off]) || pszExpr[off] == '`')) 198 270 off++; 199 271 if (off == cchExpr) 200 return dbgcEvalSubNum(pszExpr, 16, pResult); 201 202 /* 203 * Some kind of symbol? 272 return dbgcEvalSubNum(pszExpr, cchExpr, 16, pResult); 273 274 /* 275 * Some kind of symbol? Rejected double quoted strings, only unquoted 276 * and single quoted strings will be considered as symbols. 204 277 */ 205 278 DBGCVARTYPE enmType; … … 219 292 } 220 293 221 if ( (*pszExpr == '"' || *pszExpr == '\'') 222 && pszExpr[cchExpr - 1] == *pszExpr) 223 { 294 char const chQuote = *pszExpr; 295 if (chQuote == '"') 296 return VERR_DBGC_PARSE_INVALID_NUMBER; 297 298 if (chQuote == '\'') 299 { 300 if (pszExpr[cchExpr - 1] != chQuote) 301 return VERR_DBGC_PARSE_UNBALANCED_QUOTE; 224 302 pszExpr[cchExpr - 1] = '\0'; 225 303 pszExpr++; … … 262 340 off++; 263 341 if (off == cchExpr) 264 return dbgcEvalSubNum(pszExpr + 2, 16, pResult);342 return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 16, pResult); 265 343 return dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult); 266 344 } … … 275 353 { 276 354 pszExpr[cchExpr] = '\0'; 277 return dbgcEvalSubNum(pszExpr, 16, pResult);355 return dbgcEvalSubNum(pszExpr, cchExpr, 16, pResult); 278 356 } 279 357 return dbgcEvalSubString(pDbgc, pszExpr, cchExpr + 1, pResult); 280 358 } 281 359 282 /* 0 i<decimal digits> */283 if (ch == '0' && ch2 == 'i')360 /* 0n<decimal digits> or 0i<decimal digits> */ 361 if (ch == '0' && (ch2 == 'n' || ch2 == 'i')) 284 362 { 285 363 while (RT_C_IS_DIGIT(pszExpr[off]) || pszExpr[off] == '`') 286 364 off++; 287 365 if (off == cchExpr) 288 return dbgcEvalSubNum(pszExpr + 2, 10, pResult);366 return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 10, pResult); 289 367 return dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult); 290 368 } … … 296 374 off++; 297 375 if (off == cchExpr) 298 return dbgcEvalSubNum(pszExpr + 2, 8, pResult);376 return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 8, pResult); 299 377 return dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult); 300 378 } … … 306 384 off++; 307 385 if (off == cchExpr) 308 return dbgcEvalSubNum(pszExpr + 2, 10, pResult);386 return dbgcEvalSubNum(pszExpr + 2, cchExpr - 2, 10, pResult); 309 387 return dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult); 310 388 } … … 316 394 off++; 317 395 if (off == cchExpr) 318 return dbgcEvalSubNum(pszExpr, 16, pResult);396 return dbgcEvalSubNum(pszExpr, cchExpr, 16, pResult); 319 397 return dbgcEvalSubString(pDbgc, pszExpr, cchExpr, pResult); 320 398 } … … 537 615 } while (pszExpr[0] == '(' && pszExpr[cchExpr - 1] == ')'); 538 616 } 539 540 #if 0 /* why was this needed? It'll screw up strings. */541 /* tabs to spaces */542 char *psz = pszExpr;543 while ((psz = strchr(psz, '\t')) != NULL)544 *psz = ' ';545 #endif546 617 547 618 /* -
trunk/src/VBox/Debugger/DBGConsole.cpp
r41561 r41571 20 20 * 21 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. 30 * 31 * 32 * @section sec_dbgc_op Operation (intentions) 33 * 34 * The console will process commands in a manner similar to the OS/2 and 35 * windows kernel debuggers. This means ';' is a command separator and 36 * that when possible we'll use the same command names as these two uses. 22 * debugging facilities for the VirtualBox VMM. It was initially only 23 * accessible thru a telnet session in debug builds. Later it was hastily built 24 * into the VBoxDbg module with a very simple Qt wrapper around it. 25 * 26 * The current state is that it's by default shipped with all standard 27 * VirtualBox builds. The GUI component is by default accessible in all 28 * non-release builds, while release builds require extra data, environment or 29 * command line options to make it visible. 30 * 31 * Now, even if we ship it with all standard builds we would like it to remain 32 * an optional feature that can be omitted when building VirtualBox. Therefore, 33 * all external code interfacing DBGC need to be enclosed in 34 * \#ifdef VBOX_WITH_DEBUGGER blocks. This is mandatory for components that 35 * register external commands. 36 * 37 * 38 * @section sec_dbgc_op Operation 39 * 40 * The console will process commands in a manner similar to the OS/2 and Windows 41 * kernel debuggers. This means ';' is a command separator and that when 42 * possible we'll use the same command names as these two uses. As an 43 * alternative we intent to provide a set of gdb-like commands as well and let 44 * the user decide which should take precedence. 37 45 * 38 46 * … … 42 50 * elsewise. Prefixes: 43 51 * - '0x' - hexadecimal. 44 * - '0 i' - decimal52 * - '0n' - decimal 45 53 * - '0t' - octal. 46 54 * - '0y' - binary. 47 55 * 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. 56 * Some of the prefixes are a bit uncommon, the reason for this that the 57 * typical binary prefix '0b' can also be a hexadecimal value since no prefix or 58 * suffix is required for such values. Ditto for '0n' and '0' for decimal and 59 * octal. 60 * 61 * The '`' can be used in the numeric value to separate parts as the user 62 * wishes. Generally, though the debugger may use it in output as thousand 63 * separator in decimal numbers and 32-bit separator in hex numbers. 64 * 65 * For historical reasons, a 'h' suffix is suffered on hex numbers. Unlike most 66 * assemblers, a leading 0 before a-f is not required with the 'h' suffix. 67 * 68 * The prefix '0i' can be used instead of '0n', as it was the early decimal 69 * prefix employed by DBGC. It's being deprecated and may be removed later. 70 * 71 * 72 * @subsection sec_dbg_op_strings Strings and Symbols 73 * 74 * The debugger will try to guess, convert or promote what the type of an 75 * argument to a command, function or operator based on the input description of 76 * the receiver. If the user wants to make it clear to the debugger that 77 * something is a string, put it inside double quotes. Symbols should use 78 * single quotes, though we're current still a bit flexible on this point. 79 * 80 * If you need to put a quote character inside the quoted text, you escape it by 81 * repating it once: echo "printf(""hello world"");" 52 82 * 53 83 * … … 62 92 * 63 93 * The '%', '%%' and '#' prefixes is implemented as unary operators, while ':' 64 * is a binary operator. Operator precedence takes care of evaluation order. 65 * 66 * 67 * @subsection sec_dbg_op_evalution Evaluation 68 * 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. 94 * is a binary operator. Operator precedence takes care of evaluation order. 95 * 96 * 97 * @subsection sec_dbg_op_c_operators C/C++ Operators 98 * 99 * Most unary and binary arithmetic, comparison, logical and bitwise C/C++ 100 * operators are supported by the debugger, with the same precedence rules of 101 * course. There is one notable change made due to the unary '%' and '%%' 102 * operators, and that is that the modulo (remainder) operator is called 'mod' 103 * instead of '%'. This saves a lot of trouble separating argument. 104 * 105 * There are no assignment operators. Instead some simple global variable space 106 * is provided thru the 'set' and 'unset' commands and the unary '$' operator. 79 107 * 80 108 * 81 109 * @subsection sec_dbg_op_registers Registers 82 110 * 83 * Registers are addressed using their name. Some registers which have several fields 84 * (like gdtr) will have separate names indicating the different fields. The default 85 * register set is the guest one. To access the hypervisor register one have to 86 * prefix the register names with '.'. 87 * 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'.) 111 * All registers and their sub-fields exposed by the DBGF API are accessible via 112 * the '\@' operator. A few CPU register are accessible directly (as symbols) 113 * without using the '\@' operator. Hypervisor registers are accessible by 114 * prefixing the register name with a dot ('.'). 115 * 116 * 117 * @subsection sec_dbg_op_commands Commands 118 * 119 * Commands names are case sensitive. By convention they are lower cased, starts 120 * with a letter but may contain digits and underscores afterwards. Operators 121 * are not allowed in the name (not even part of it), as we would risk 122 * misunderstanding it otherwise. 123 * 124 * Commands returns a status code. 104 125 * 105 126 * The '.' prefix indicates the set of external commands. External commands are 106 127 * command registered by VMM components. 128 * 129 * 130 * @subsection sec_dbg_op_functions Functions 131 * 132 * Functions are similar to commands, but return a variable and can only be used 133 * as part of an expression making up the argument of a command, function, 134 * operator or language statement (if we get around to implement that). 107 135 * 108 136 * … … 114 142 * (dbgcProcessLog and DBGC::fLog). 115 143 * 144 * This feature has not materialized and probably never will. 116 145 * 117 146 * 118 147 * @section sec_dbgc_linking Linking and API 119 148 * 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. 149 * The DBGC code is linked into the VBoxVMM module. 150 * 151 * IMachineDebugger may one day be extended with a DBGC interface so we can work 152 * with DBGC remotely without requiring TCP. Some questions about callbacks 153 * (for output) and security (you may wish to restrict users from debugging a 154 * VM) needs to be answered first though. 127 155 */ 128 156 … … 218 246 rc = dbgcOpRegister(pDbgc, &Var, DBGCVAR_CAT_ANY, pResult); 219 247 if (RT_SUCCESS(rc)) 220 return DBGCCmdHlpConvert(&pDbgc->CmdHlp, &Var, enmType, false /*fConvSyms*/, pResult);248 return DBGCCmdHlpConvert(&pDbgc->CmdHlp, pResult, enmType, false /*fConvSyms*/, pResult); 221 249 } 222 250 } -
trunk/src/VBox/Debugger/testcase/tstDBGCParser.cpp
r41561 r41571 1140 1140 tstTry(pDbgc, "format nosuchfunction()\n", VERR_DBGC_PARSE_FUNCTION_NOT_FOUND); 1141 1141 tstTry(pDbgc, "format randu32()\n", VINF_SUCCESS); 1142 tstTryEx(pDbgc, "format %0\n", VINF_SUCCESS, false, "Guest flat address: %00000000", -1); 1143 tstTryEx(pDbgc, "format %eax\n", VINF_SUCCESS, false, "Guest flat address: %cafebabe", -1); 1142 1144 tstTry(pDbgc, "sa 3 23 4 'q' \"21123123\" 'b' \n", VINF_SUCCESS); 1143 1145 tstTry(pDbgc, "sa 3,23, 4,'q' ,\"21123123\" , 'b' \n", VINF_SUCCESS);
Note:
See TracChangeset
for help on using the changeset viewer.