tools/*: remove bcc and as86 as they are no longer required to compile the system...
[virtualbox.git] / src / VBox / Debugger / DBGCCmdHlp.cpp
blob9fd753cba11ec326f75a2b89086b5348c221ec47
1 /* $Id$ */
2 /** @file
3 * DBGC - Debugger Console, Command Helpers.
4 */
6 /*
7 * Copyright (C) 2006-2012 Oracle Corporation
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 /*******************************************************************************
19 * Header Files *
20 *******************************************************************************/
21 #define LOG_GROUP LOG_GROUP_DBGC
22 #include <VBox/dbg.h>
23 #include <VBox/vmm/dbgf.h>
24 #include <VBox/vmm/pgm.h>
25 #include <VBox/param.h>
26 #include <VBox/err.h>
27 #include <VBox/log.h>
29 #include <iprt/assert.h>
30 #include <iprt/ctype.h>
31 #include <iprt/mem.h>
32 #include <iprt/string.h>
34 #include "DBGCInternal.h"
38 /**
39 * @interface_method_impl{DBGCCMDHLP,pfnPrintf}
41 static DECLCALLBACK(int) dbgcHlpPrintf(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten, const char *pszFormat, ...)
44 * Do the formatting and output.
46 va_list args;
47 va_start(args, pszFormat);
48 int rc = pCmdHlp->pfnPrintfV(pCmdHlp, pcbWritten, pszFormat, args);
49 va_end(args);
51 return rc;
55 /**
56 * Outputs a string in quotes.
58 * @returns The number of bytes formatted.
59 * @param pfnOutput Pointer to output function.
60 * @param pvArgOutput Argument for the output function.
61 * @param chQuote The quote character.
62 * @param psz The string to quote.
63 * @param cch The string length.
65 static size_t dbgcStringOutputInQuotes(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char chQuote, const char *psz, size_t cch)
67 size_t cchOutput = pfnOutput(pvArgOutput, &chQuote, 1);
69 while (cch > 0)
71 char *pchQuote = (char *)memchr(psz, chQuote, cch);
72 if (!pchQuote)
74 cchOutput += pfnOutput(pvArgOutput, psz, cch);
75 break;
77 size_t cchSub = pchQuote - psz + 1;
78 cchOutput += pfnOutput(pvArgOutput, psz, cchSub);
79 cchOutput += pfnOutput(pvArgOutput, &chQuote, 1);
80 cchSub -= cchSub;
81 psz += cchSub;
84 cchOutput += pfnOutput(pvArgOutput, &chQuote, 1);
85 return cchOutput;
89 /**
90 * Callback to format non-standard format specifiers, employed by dbgcPrintfV
91 * and others.
93 * @returns The number of bytes formatted.
94 * @param pvArg Formatter argument.
95 * @param pfnOutput Pointer to output function.
96 * @param pvArgOutput Argument for the output function.
97 * @param ppszFormat Pointer to the format string pointer. Advance this till the char
98 * after the format specifier.
99 * @param pArgs Pointer to the argument list. Use this to fetch the arguments.
100 * @param cchWidth Format Width. -1 if not specified.
101 * @param cchPrecision Format Precision. -1 if not specified.
102 * @param fFlags Flags (RTSTR_NTFS_*).
103 * @param chArgSize The argument size specifier, 'l' or 'L'.
105 static DECLCALLBACK(size_t) dbgcStringFormatter(void *pvArg, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
106 const char **ppszFormat, va_list *pArgs, int cchWidth,
107 int cchPrecision, unsigned fFlags, char chArgSize)
109 NOREF(cchWidth); NOREF(cchPrecision); NOREF(fFlags); NOREF(chArgSize); NOREF(pvArg);
110 if (**ppszFormat != 'D')
112 (*ppszFormat)++;
113 return 0;
116 (*ppszFormat)++;
117 switch (**ppszFormat)
120 * Print variable without range.
121 * The argument is a const pointer to the variable.
123 case 'V':
125 (*ppszFormat)++;
126 PCDBGCVAR pVar = va_arg(*pArgs, PCDBGCVAR);
127 switch (pVar->enmType)
129 case DBGCVAR_TYPE_GC_FLAT:
130 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%RGv", pVar->u.GCFlat);
131 case DBGCVAR_TYPE_GC_FAR:
132 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%04x:%08x", pVar->u.GCFar.sel, pVar->u.GCFar.off);
133 case DBGCVAR_TYPE_GC_PHYS:
134 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%%%RGp", pVar->u.GCPhys);
135 case DBGCVAR_TYPE_HC_FLAT:
136 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%#%RHv", (uintptr_t)pVar->u.pvHCFlat);
137 case DBGCVAR_TYPE_HC_PHYS:
138 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "#%%%%%RHp", pVar->u.HCPhys);
139 case DBGCVAR_TYPE_NUMBER:
140 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%llx", pVar->u.u64Number);
141 case DBGCVAR_TYPE_STRING:
142 return dbgcStringOutputInQuotes(pfnOutput, pvArgOutput, '"', pVar->u.pszString, (size_t)pVar->u64Range);
143 case DBGCVAR_TYPE_SYMBOL:
144 return dbgcStringOutputInQuotes(pfnOutput, pvArgOutput, '\'', pVar->u.pszString, (size_t)pVar->u64Range);
146 case DBGCVAR_TYPE_UNKNOWN:
147 default:
148 return pfnOutput(pvArgOutput, "??", 2);
153 * Print variable with range.
154 * The argument is a const pointer to the variable.
156 case 'v':
158 (*ppszFormat)++;
159 PCDBGCVAR pVar = va_arg(*pArgs, PCDBGCVAR);
161 char szRange[32];
162 switch (pVar->enmRangeType)
164 case DBGCVAR_RANGE_NONE:
165 szRange[0] = '\0';
166 break;
167 case DBGCVAR_RANGE_ELEMENTS:
168 RTStrPrintf(szRange, sizeof(szRange), " L %llx", pVar->u64Range);
169 break;
170 case DBGCVAR_RANGE_BYTES:
171 RTStrPrintf(szRange, sizeof(szRange), " LB %llx", pVar->u64Range);
172 break;
175 switch (pVar->enmType)
177 case DBGCVAR_TYPE_GC_FLAT:
178 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%RGv%s", pVar->u.GCFlat, szRange);
179 case DBGCVAR_TYPE_GC_FAR:
180 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%04x:%08x%s", pVar->u.GCFar.sel, pVar->u.GCFar.off, szRange);
181 case DBGCVAR_TYPE_GC_PHYS:
182 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%%%RGp%s", pVar->u.GCPhys, szRange);
183 case DBGCVAR_TYPE_HC_FLAT:
184 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%#%RHv%s", (uintptr_t)pVar->u.pvHCFlat, szRange);
185 case DBGCVAR_TYPE_HC_PHYS:
186 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "#%%%%%RHp%s", pVar->u.HCPhys, szRange);
187 case DBGCVAR_TYPE_NUMBER:
188 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%llx%s", pVar->u.u64Number, szRange);
189 case DBGCVAR_TYPE_STRING:
190 return dbgcStringOutputInQuotes(pfnOutput, pvArgOutput, '"', pVar->u.pszString, (size_t)pVar->u64Range);
191 case DBGCVAR_TYPE_SYMBOL:
192 return dbgcStringOutputInQuotes(pfnOutput, pvArgOutput, '\'', pVar->u.pszString, (size_t)pVar->u64Range);
194 case DBGCVAR_TYPE_UNKNOWN:
195 default:
196 return pfnOutput(pvArgOutput, "??", 2);
200 default:
201 AssertMsgFailed(("Invalid format type '%s'!\n", **ppszFormat));
202 return 0;
208 * Output callback employed by dbgcHlpPrintfV.
210 * @returns number of bytes written.
211 * @param pvArg User argument.
212 * @param pachChars Pointer to an array of utf-8 characters.
213 * @param cbChars Number of bytes in the character array pointed to by pachChars.
215 static DECLCALLBACK(size_t) dbgcFormatOutput(void *pvArg, const char *pachChars, size_t cbChars)
217 PDBGC pDbgc = (PDBGC)pvArg;
218 if (cbChars)
220 int rc = pDbgc->pBack->pfnWrite(pDbgc->pBack, pachChars, cbChars, NULL);
221 if (RT_SUCCESS(rc))
222 pDbgc->chLastOutput = pachChars[cbChars - 1];
223 else
225 pDbgc->rcOutput = rc;
226 cbChars = 0;
230 return cbChars;
236 * @interface_method_impl{DBGCCMDHLP,pfnPrintfV}
238 static DECLCALLBACK(int) dbgcHlpPrintfV(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten, const char *pszFormat, va_list args)
240 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
243 * Do the formatting and output.
245 pDbgc->rcOutput = 0;
246 size_t cb = RTStrFormatV(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, pszFormat, args);
248 if (pcbWritten)
249 *pcbWritten = cb;
251 return pDbgc->rcOutput;
256 * @interface_method_impl{DBGCCMDHLP,pfnStrPrintf}
258 static DECLCALLBACK(size_t) dbgcHlpStrPrintfV(PDBGCCMDHLP pCmdHlp, char *pszBuf, size_t cbBuf,
259 const char *pszFormat, va_list va)
261 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
262 return RTStrPrintfExV(dbgcStringFormatter, pDbgc, pszBuf, cbBuf, pszFormat, va);
267 * @interface_method_impl{DBGCCMDHLP,pfnStrPrintf}
269 static DECLCALLBACK(size_t) dbgcHlpStrPrintf(PDBGCCMDHLP pCmdHlp, char *pszBuf, size_t cbBuf, const char *pszFormat, ...)
271 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
272 va_list va;
273 va_start(va, pszFormat);
274 size_t cch = RTStrPrintfExV(dbgcStringFormatter, pDbgc, pszBuf, cbBuf, pszFormat, va);
275 va_end(va);
276 return cch;
281 * @interface_method_impl{DBGCCMDHLP,pfnVBoxErrorV}
283 static DECLCALLBACK(int) dbgcHlpVBoxErrorV(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, va_list args)
285 switch (rc)
287 case VINF_SUCCESS:
288 break;
290 default:
291 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: %Rrc: %s", rc, pszFormat ? " " : "\n");
292 if (RT_SUCCESS(rc) && pszFormat)
293 rc = pCmdHlp->pfnPrintfV(pCmdHlp, NULL, pszFormat, args);
294 if (RT_SUCCESS(rc))
295 rc = VERR_DBGC_COMMAND_FAILED;
296 break;
298 return rc;
303 * @interface_method_impl{DBGCCMDHLP,pfnVBoxError}
305 static DECLCALLBACK(int) dbgcHlpVBoxError(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, ...)
307 va_list args;
308 va_start(args, pszFormat);
309 int rcRet = pCmdHlp->pfnVBoxErrorV(pCmdHlp, rc, pszFormat, args);
310 va_end(args);
311 return rcRet;
316 * @interface_method_impl{DBGCCMDHLP,pfnMemRead}
318 static DECLCALLBACK(int) dbgcHlpMemRead(PDBGCCMDHLP pCmdHlp, PVM pVM, void *pvBuffer, size_t cbRead, PCDBGCVAR pVarPointer, size_t *pcbRead)
320 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
321 DBGFADDRESS Address;
322 int rc;
325 * Dummy check.
327 if (cbRead == 0)
329 if (*pcbRead)
330 *pcbRead = 0;
331 return VINF_SUCCESS;
335 * Convert Far addresses getting size and the correct base address.
336 * Getting and checking the size is what makes this messy and slow.
338 DBGCVAR Var = *pVarPointer;
339 switch (pVarPointer->enmType)
341 case DBGCVAR_TYPE_GC_FAR:
342 /* Use DBGFR3AddrFromSelOff for the conversion. */
343 Assert(pDbgc->pVM);
344 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, Var.u.GCFar.sel, Var.u.GCFar.off);
345 if (RT_FAILURE(rc))
346 return rc;
348 /* don't bother with flat selectors (for now). */
349 if (!DBGFADDRESS_IS_FLAT(&Address))
351 DBGFSELINFO SelInfo;
352 rc = DBGFR3SelQueryInfo(pDbgc->pVM, pDbgc->idCpu, Address.Sel,
353 DBGFSELQI_FLAGS_DT_GUEST | DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE, &SelInfo);
354 if (RT_SUCCESS(rc))
356 RTGCUINTPTR cb; /* -1 byte */
357 if (DBGFSelInfoIsExpandDown(&SelInfo))
359 if ( !SelInfo.u.Raw.Gen.u1Granularity
360 && Address.off > UINT16_C(0xffff))
361 return VERR_OUT_OF_SELECTOR_BOUNDS;
362 if (Address.off <= SelInfo.cbLimit)
363 return VERR_OUT_OF_SELECTOR_BOUNDS;
364 cb = (SelInfo.u.Raw.Gen.u1Granularity ? UINT32_C(0xffffffff) : UINT32_C(0xffff)) - Address.off;
366 else
368 if (Address.off > SelInfo.cbLimit)
369 return VERR_OUT_OF_SELECTOR_BOUNDS;
370 cb = SelInfo.cbLimit - Address.off;
372 if (cbRead - 1 > cb)
374 if (!pcbRead)
375 return VERR_OUT_OF_SELECTOR_BOUNDS;
376 cbRead = cb + 1;
380 Var.enmType = DBGCVAR_TYPE_GC_FLAT;
381 Var.u.GCFlat = Address.FlatPtr;
382 break;
384 case DBGCVAR_TYPE_GC_FLAT:
385 case DBGCVAR_TYPE_GC_PHYS:
386 case DBGCVAR_TYPE_HC_FLAT:
387 case DBGCVAR_TYPE_HC_PHYS:
388 break;
390 default:
391 return VERR_NOT_IMPLEMENTED;
397 * Copy page by page.
399 size_t cbLeft = cbRead;
400 for (;;)
403 * Calc read size.
405 size_t cb = RT_MIN(PAGE_SIZE, cbLeft);
406 switch (pVarPointer->enmType)
408 case DBGCVAR_TYPE_GC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCFlat & PAGE_OFFSET_MASK)); break;
409 case DBGCVAR_TYPE_GC_PHYS: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCPhys & PAGE_OFFSET_MASK)); break;
410 case DBGCVAR_TYPE_HC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - ((uintptr_t)Var.u.pvHCFlat & PAGE_OFFSET_MASK)); break;
411 case DBGCVAR_TYPE_HC_PHYS: cb = RT_MIN(cb, PAGE_SIZE - ((size_t)Var.u.HCPhys & PAGE_OFFSET_MASK)); break; /* size_t: MSC has braindead loss of data warnings! */
412 default: break;
416 * Perform read.
418 switch (Var.enmType)
420 case DBGCVAR_TYPE_GC_FLAT:
421 rc = DBGFR3MemRead(pDbgc->pVM, pDbgc->idCpu,
422 DBGFR3AddrFromFlat(pVM, &Address, Var.u.GCFlat),
423 pvBuffer, cb);
424 break;
426 case DBGCVAR_TYPE_GC_PHYS:
427 rc = DBGFR3MemRead(pDbgc->pVM, pDbgc->idCpu,
428 DBGFR3AddrFromPhys(pVM, &Address, Var.u.GCPhys),
429 pvBuffer, cb);
430 break;
432 case DBGCVAR_TYPE_HC_PHYS:
433 case DBGCVAR_TYPE_HC_FLAT:
435 DBGCVAR Var2;
436 rc = dbgcOpAddrFlat(pDbgc, &Var, DBGCVAR_CAT_ANY, &Var2);
437 if (RT_SUCCESS(rc))
439 /** @todo protect this!!! */
440 memcpy(pvBuffer, Var2.u.pvHCFlat, cb);
441 rc = 0;
443 else
444 rc = VERR_INVALID_POINTER;
445 break;
448 default:
449 rc = VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
453 * Check for failure.
455 if (RT_FAILURE(rc))
457 if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0)
458 return VINF_SUCCESS;
459 return rc;
463 * Next.
465 cbLeft -= cb;
466 if (!cbLeft)
467 break;
468 pvBuffer = (char *)pvBuffer + cb;
469 rc = DBGCCmdHlpEval(pCmdHlp, &Var, "%DV + %d", &Var, cb);
470 if (RT_FAILURE(rc))
472 if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0)
473 return VINF_SUCCESS;
474 return rc;
479 * Done
481 if (pcbRead)
482 *pcbRead = cbRead;
483 return 0;
488 * @interface_method_impl{DBGCCMDHLP,pfnMemWrite}
490 static DECLCALLBACK(int) dbgcHlpMemWrite(PDBGCCMDHLP pCmdHlp, PVM pVM, const void *pvBuffer, size_t cbWrite, PCDBGCVAR pVarPointer, size_t *pcbWritten)
492 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
493 DBGFADDRESS Address;
494 int rc;
497 * Dummy check.
499 if (cbWrite == 0)
501 if (*pcbWritten)
502 *pcbWritten = 0;
503 return VINF_SUCCESS;
507 * Convert Far addresses getting size and the correct base address.
508 * Getting and checking the size is what makes this messy and slow.
510 DBGCVAR Var = *pVarPointer;
511 switch (pVarPointer->enmType)
513 case DBGCVAR_TYPE_GC_FAR:
515 /* Use DBGFR3AddrFromSelOff for the conversion. */
516 Assert(pDbgc->pVM);
517 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, Var.u.GCFar.sel, Var.u.GCFar.off);
518 if (RT_FAILURE(rc))
519 return rc;
521 /* don't bother with flat selectors (for now). */
522 if (!DBGFADDRESS_IS_FLAT(&Address))
524 DBGFSELINFO SelInfo;
525 rc = DBGFR3SelQueryInfo(pDbgc->pVM, pDbgc->idCpu, Address.Sel,
526 DBGFSELQI_FLAGS_DT_GUEST | DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE, &SelInfo);
527 if (RT_SUCCESS(rc))
529 RTGCUINTPTR cb; /* -1 byte */
530 if (DBGFSelInfoIsExpandDown(&SelInfo))
532 if ( !SelInfo.u.Raw.Gen.u1Granularity
533 && Address.off > UINT16_C(0xffff))
534 return VERR_OUT_OF_SELECTOR_BOUNDS;
535 if (Address.off <= SelInfo.cbLimit)
536 return VERR_OUT_OF_SELECTOR_BOUNDS;
537 cb = (SelInfo.u.Raw.Gen.u1Granularity ? UINT32_C(0xffffffff) : UINT32_C(0xffff)) - Address.off;
539 else
541 if (Address.off > SelInfo.cbLimit)
542 return VERR_OUT_OF_SELECTOR_BOUNDS;
543 cb = SelInfo.cbLimit - Address.off;
545 if (cbWrite - 1 > cb)
547 if (!pcbWritten)
548 return VERR_OUT_OF_SELECTOR_BOUNDS;
549 cbWrite = cb + 1;
553 Var.enmType = DBGCVAR_TYPE_GC_FLAT;
554 Var.u.GCFlat = Address.FlatPtr;
556 /* fall thru */
557 case DBGCVAR_TYPE_GC_FLAT:
558 rc = DBGFR3MemWrite(pVM, pDbgc->idCpu,
559 DBGFR3AddrFromFlat(pVM, &Address, Var.u.GCFlat),
560 pvBuffer, cbWrite);
561 if (pcbWritten && RT_SUCCESS(rc))
562 *pcbWritten = cbWrite;
563 return rc;
565 case DBGCVAR_TYPE_GC_PHYS:
566 rc = DBGFR3MemWrite(pVM, pDbgc->idCpu,
567 DBGFR3AddrFromPhys(pVM, &Address, Var.u.GCPhys),
568 pvBuffer, cbWrite);
569 if (pcbWritten && RT_SUCCESS(rc))
570 *pcbWritten = cbWrite;
571 return rc;
573 case DBGCVAR_TYPE_HC_FLAT:
574 case DBGCVAR_TYPE_HC_PHYS:
577 * Copy HC memory page by page.
579 if (pcbWritten)
580 *pcbWritten = 0;
581 while (cbWrite > 0)
583 /* convert to flat address */
584 DBGCVAR Var2;
585 rc = dbgcOpAddrFlat(pDbgc, &Var, DBGCVAR_CAT_ANY, &Var2);
586 if (RT_FAILURE(rc))
588 if (pcbWritten && *pcbWritten)
589 return -VERR_INVALID_POINTER;
590 return VERR_INVALID_POINTER;
593 /* calc size. */
594 size_t cbChunk = PAGE_SIZE;
595 cbChunk -= (uintptr_t)Var.u.pvHCFlat & PAGE_OFFSET_MASK;
596 if (cbChunk > cbWrite)
597 cbChunk = cbWrite;
599 /** @todo protect this!!! */
600 memcpy(Var2.u.pvHCFlat, pvBuffer, cbChunk);
602 /* advance */
603 if (Var.enmType == DBGCVAR_TYPE_HC_FLAT)
604 Var.u.pvHCFlat = (uint8_t *)Var.u.pvHCFlat + cbChunk;
605 else
606 Var.u.HCPhys += cbChunk;
607 pvBuffer = (uint8_t const *)pvBuffer + cbChunk;
608 if (pcbWritten)
609 *pcbWritten += cbChunk;
610 cbWrite -= cbChunk;
613 return VINF_SUCCESS;
616 default:
617 return VERR_NOT_IMPLEMENTED;
623 * @interface_method_impl{DBGCCMDHLP,pfnHlpExec}
625 static DECLCALLBACK(int) dbgcHlpExec(PDBGCCMDHLP pCmdHlp, const char *pszExpr, ...)
627 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
628 /* Save the scratch state. */
629 char *pszScratch = pDbgc->pszScratch;
630 unsigned iArg = pDbgc->iArg;
633 * Format the expression.
635 va_list args;
636 va_start(args, pszExpr);
637 size_t cbScratch = sizeof(pDbgc->achScratch) - (pDbgc->pszScratch - &pDbgc->achScratch[0]);
638 size_t cb = RTStrPrintfExV(dbgcStringFormatter, pDbgc, pDbgc->pszScratch, cbScratch, pszExpr, args);
639 va_end(args);
640 if (cb >= cbScratch)
641 return VERR_BUFFER_OVERFLOW;
644 * Execute the command.
645 * We save and restore the arg index and scratch buffer pointer.
647 pDbgc->pszScratch = pDbgc->pszScratch + cb + 1;
648 int rc = dbgcEvalCommand(pDbgc, pszScratch, cb, false /* fNoExecute */);
650 /* Restore the scratch state. */
651 pDbgc->iArg = iArg;
652 pDbgc->pszScratch = pszScratch;
654 return rc;
659 * @copydoc DBGCCMDHLP::pfnEvalV
661 static DECLCALLBACK(int) dbgcHlpEvalV(PDBGCCMDHLP pCmdHlp, PDBGCVAR pResult, const char *pszExpr, va_list va)
663 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
666 * Format the expression.
668 char szExprFormatted[2048];
669 size_t cb = RTStrPrintfExV(dbgcStringFormatter, pDbgc, szExprFormatted, sizeof(szExprFormatted), pszExpr, va);
670 /* ignore overflows. */
672 return dbgcEvalSub(pDbgc, &szExprFormatted[0], cb, DBGCVAR_CAT_ANY, pResult);
677 * @copydoc DBGCCMDHLP::pfnFailV
679 static DECLCALLBACK(int) dbgcHlpFailV(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, const char *pszFormat, va_list va)
681 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
684 * Do the formatting and output.
686 pDbgc->rcOutput = VINF_SUCCESS;
687 RTStrFormat(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, "%s: error: ", pCmd->pszCmd);
688 if (RT_FAILURE(pDbgc->rcOutput))
689 return pDbgc->rcOutput;
690 RTStrFormatV(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, pszFormat, va);
691 if (RT_FAILURE(pDbgc->rcOutput))
692 return pDbgc->rcOutput;
693 if (pDbgc->chLastOutput != '\n')
694 dbgcFormatOutput(pDbgc, "\n", 1);
695 return VERR_DBGC_COMMAND_FAILED;
700 * @copydoc DBGCCMDHLP::pfnFailV
702 static DECLCALLBACK(int) dbgcHlpFailRcV(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int rc, const char *pszFormat, va_list va)
704 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
707 * Do the formatting and output.
709 pDbgc->rcOutput = VINF_SUCCESS;
710 RTStrFormat(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, "%s: error: ", pCmd->pszCmd);
711 if (RT_FAILURE(pDbgc->rcOutput))
712 return pDbgc->rcOutput;
713 RTStrFormatV(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, pszFormat, va);
714 if (RT_FAILURE(pDbgc->rcOutput))
715 return pDbgc->rcOutput;
716 RTStrFormat(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, ": %Rrc\n", rc);
717 if (RT_FAILURE(pDbgc->rcOutput))
718 return pDbgc->rcOutput;
720 return VERR_DBGC_COMMAND_FAILED;
725 * @interface_method_impl{DBGCCMDHLP,pfnVarToDbgfAddr}
727 static DECLCALLBACK(int) dbgcHlpVarToDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PDBGFADDRESS pAddress)
729 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
730 AssertPtr(pVar);
731 AssertPtr(pAddress);
733 switch (pVar->enmType)
735 case DBGCVAR_TYPE_GC_FLAT:
736 DBGFR3AddrFromFlat(pDbgc->pVM, pAddress, pVar->u.GCFlat);
737 return VINF_SUCCESS;
739 case DBGCVAR_TYPE_NUMBER:
740 DBGFR3AddrFromFlat(pDbgc->pVM, pAddress, (RTGCUINTPTR)pVar->u.u64Number);
741 return VINF_SUCCESS;
743 case DBGCVAR_TYPE_GC_FAR:
744 return DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, pAddress, pVar->u.GCFar.sel, pVar->u.GCFar.off);
746 case DBGCVAR_TYPE_GC_PHYS:
747 DBGFR3AddrFromPhys(pDbgc->pVM, pAddress, pVar->u.GCPhys);
748 return VINF_SUCCESS;
750 case DBGCVAR_TYPE_SYMBOL:
752 DBGCVAR Var;
753 int rc = DBGCCmdHlpEval(&pDbgc->CmdHlp, &Var, "%%(%DV)", pVar);
754 if (RT_FAILURE(rc))
755 return rc;
756 return dbgcHlpVarToDbgfAddr(pCmdHlp, &Var, pAddress);
759 case DBGCVAR_TYPE_STRING:
760 case DBGCVAR_TYPE_HC_FLAT:
761 case DBGCVAR_TYPE_HC_PHYS:
762 default:
763 return VERR_DBGC_PARSE_CONVERSION_FAILED;
769 * @interface_method_impl{DBGCCMDHLP,pfnVarFromDbgfAddr}
771 static DECLCALLBACK(int) dbgcHlpVarFromDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGFADDRESS pAddress, PDBGCVAR pResult)
773 AssertPtrReturn(pAddress, VERR_INVALID_POINTER);
774 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
775 AssertPtrReturn(pResult, VERR_INVALID_POINTER);
777 switch (pAddress->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK)
779 case DBGFADDRESS_FLAGS_FAR16:
780 case DBGFADDRESS_FLAGS_FAR32:
781 case DBGFADDRESS_FLAGS_FAR64:
782 DBGCVAR_INIT_GC_FAR(pResult, pAddress->Sel, pAddress->off);
783 break;
785 case DBGFADDRESS_FLAGS_FLAT:
786 DBGCVAR_INIT_GC_FLAT(pResult, pAddress->FlatPtr);
787 break;
789 case DBGFADDRESS_FLAGS_PHYS:
790 DBGCVAR_INIT_GC_PHYS(pResult, pAddress->FlatPtr);
791 break;
793 default:
794 DBGCVAR_INIT(pResult);
795 AssertMsgFailedReturn(("%#x\n", pAddress->fFlags), VERR_INVALID_PARAMETER);
796 break;
799 return VINF_SUCCESS;
804 * @interface_method_impl{DBGCCMDHLP,pfnVarToNumber}
806 static DECLCALLBACK(int) dbgcHlpVarToNumber(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t *pu64Number)
808 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
809 NOREF(pDbgc);
811 uint64_t u64Number;
812 switch (pVar->enmType)
814 case DBGCVAR_TYPE_GC_FLAT:
815 u64Number = pVar->u.GCFlat;
816 break;
817 case DBGCVAR_TYPE_GC_PHYS:
818 u64Number = pVar->u.GCPhys;
819 break;
820 case DBGCVAR_TYPE_HC_FLAT:
821 u64Number = (uintptr_t)pVar->u.pvHCFlat;
822 break;
823 case DBGCVAR_TYPE_HC_PHYS:
824 u64Number = (uintptr_t)pVar->u.HCPhys;
825 break;
826 case DBGCVAR_TYPE_NUMBER:
827 u64Number = (uintptr_t)pVar->u.u64Number;
828 break;
829 case DBGCVAR_TYPE_GC_FAR:
830 u64Number = (uintptr_t)pVar->u.GCFar.off;
831 break;
832 case DBGCVAR_TYPE_SYMBOL:
833 /** @todo try convert as symbol? */
834 case DBGCVAR_TYPE_STRING:
835 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; /** @todo better error code! */
836 default:
837 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
839 *pu64Number = u64Number;
840 return VINF_SUCCESS;
845 * @interface_method_impl{DBGCCMDHLP,pfnVarToBool}
847 static DECLCALLBACK(int) dbgcHlpVarToBool(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, bool *pf)
849 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
850 NOREF(pDbgc);
852 switch (pVar->enmType)
854 case DBGCVAR_TYPE_SYMBOL:
855 case DBGCVAR_TYPE_STRING:
856 if ( !RTStrICmp(pVar->u.pszString, "true")
857 || !RTStrICmp(pVar->u.pszString, "on")
858 || !RTStrICmp(pVar->u.pszString, "no")
859 || !RTStrICmp(pVar->u.pszString, "enabled"))
861 *pf = true;
862 return VINF_SUCCESS;
864 if ( !RTStrICmp(pVar->u.pszString, "false")
865 || !RTStrICmp(pVar->u.pszString, "off")
866 || !RTStrICmp(pVar->u.pszString, "yes")
867 || !RTStrICmp(pVar->u.pszString, "disabled"))
869 *pf = false;
870 return VINF_SUCCESS;
872 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; /** @todo better error code! */
874 case DBGCVAR_TYPE_GC_FLAT:
875 case DBGCVAR_TYPE_GC_PHYS:
876 case DBGCVAR_TYPE_HC_FLAT:
877 case DBGCVAR_TYPE_HC_PHYS:
878 case DBGCVAR_TYPE_NUMBER:
879 *pf = pVar->u.u64Number != 0;
880 return VINF_SUCCESS;
882 case DBGCVAR_TYPE_GC_FAR:
883 default:
884 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
890 * @interface_method_impl{DBGCCMDHLP,pfnVarGetRange}
892 static DECLCALLBACK(int) dbgcHlpVarGetRange(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t cbElement, uint64_t cbDefault,
893 uint64_t *pcbRange)
895 /** @todo implement this properly, strings/symbols are not resolved now. */
896 switch (pVar->enmRangeType)
898 default:
899 case DBGCVAR_RANGE_NONE:
900 *pcbRange = cbDefault;
901 break;
902 case DBGCVAR_RANGE_BYTES:
903 *pcbRange = pVar->u64Range;
904 break;
905 case DBGCVAR_RANGE_ELEMENTS:
906 *pcbRange = pVar->u64Range * cbElement;
907 break;
909 return VINF_SUCCESS;
914 * @interface_method_impl{DBGCCMDHLP,pfnVarConvert}
916 static DECLCALLBACK(int) dbgcHlpVarConvert(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pInVar, DBGCVARTYPE enmToType, bool fConvSyms,
917 PDBGCVAR pResult)
919 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
920 DBGCVAR const InVar = *pInVar; /* if pInVar == pResult */
921 PCDBGCVAR pArg = &InVar; /* lazy bird, clean up later */
922 DBGFADDRESS Address;
923 int rc;
925 Assert(pDbgc->pVM);
927 *pResult = InVar;
928 switch (InVar.enmType)
930 case DBGCVAR_TYPE_GC_FLAT:
931 switch (enmToType)
933 case DBGCVAR_TYPE_GC_FLAT:
934 return VINF_SUCCESS;
936 case DBGCVAR_TYPE_GC_FAR:
937 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
939 case DBGCVAR_TYPE_GC_PHYS:
940 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
941 rc = DBGFR3AddrToPhys(pDbgc->pVM, pDbgc->idCpu,
942 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
943 &pResult->u.GCPhys);
944 if (RT_SUCCESS(rc))
945 return VINF_SUCCESS;
946 return VERR_DBGC_PARSE_CONVERSION_FAILED;
948 case DBGCVAR_TYPE_HC_FLAT:
949 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
950 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu,
951 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
952 false /*fReadOnly */,
953 &pResult->u.pvHCFlat);
954 if (RT_SUCCESS(rc))
955 return VINF_SUCCESS;
956 return VERR_DBGC_PARSE_CONVERSION_FAILED;
958 case DBGCVAR_TYPE_HC_PHYS:
959 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
960 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu,
961 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
962 &pResult->u.GCPhys);
963 if (RT_SUCCESS(rc))
964 return VINF_SUCCESS;
965 return VERR_DBGC_PARSE_CONVERSION_FAILED;
967 case DBGCVAR_TYPE_NUMBER:
968 pResult->enmType = enmToType;
969 pResult->u.u64Number = InVar.u.GCFlat;
970 return VINF_SUCCESS;
972 case DBGCVAR_TYPE_STRING:
973 case DBGCVAR_TYPE_SYMBOL:
974 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
976 case DBGCVAR_TYPE_UNKNOWN:
977 case DBGCVAR_TYPE_ANY:
978 break;
980 break;
982 case DBGCVAR_TYPE_GC_FAR:
983 switch (enmToType)
985 case DBGCVAR_TYPE_GC_FLAT:
986 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
987 if (RT_SUCCESS(rc))
989 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
990 pResult->u.GCFlat = Address.FlatPtr;
991 return VINF_SUCCESS;
993 return VERR_DBGC_PARSE_CONVERSION_FAILED;
995 case DBGCVAR_TYPE_GC_FAR:
996 return VINF_SUCCESS;
998 case DBGCVAR_TYPE_GC_PHYS:
999 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
1000 if (RT_SUCCESS(rc))
1002 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1003 rc = DBGFR3AddrToPhys(pDbgc->pVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
1004 if (RT_SUCCESS(rc))
1005 return VINF_SUCCESS;
1007 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1009 case DBGCVAR_TYPE_HC_FLAT:
1010 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
1011 if (RT_SUCCESS(rc))
1013 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
1014 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu, &Address,
1015 false /*fReadOnly*/, &pResult->u.pvHCFlat);
1016 if (RT_SUCCESS(rc))
1017 return VINF_SUCCESS;
1019 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1021 case DBGCVAR_TYPE_HC_PHYS:
1022 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
1023 if (RT_SUCCESS(rc))
1025 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1026 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
1027 if (RT_SUCCESS(rc))
1028 return VINF_SUCCESS;
1030 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1032 case DBGCVAR_TYPE_NUMBER:
1033 pResult->enmType = enmToType;
1034 pResult->u.u64Number = InVar.u.GCFar.off;
1035 return VINF_SUCCESS;
1037 case DBGCVAR_TYPE_STRING:
1038 case DBGCVAR_TYPE_SYMBOL:
1039 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1041 case DBGCVAR_TYPE_UNKNOWN:
1042 case DBGCVAR_TYPE_ANY:
1043 break;
1045 break;
1047 case DBGCVAR_TYPE_GC_PHYS:
1048 switch (enmToType)
1050 case DBGCVAR_TYPE_GC_FLAT:
1051 //rc = MMR3PhysGCPhys2GCVirtEx(pDbgc->pVM, pResult->u.GCPhys, ..., &pResult->u.GCFlat); - yea, sure.
1052 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1054 case DBGCVAR_TYPE_GC_FAR:
1055 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1057 case DBGCVAR_TYPE_GC_PHYS:
1058 return VINF_SUCCESS;
1060 case DBGCVAR_TYPE_HC_FLAT:
1061 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
1062 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu,
1063 DBGFR3AddrFromPhys(pDbgc->pVM, &Address, pArg->u.GCPhys),
1064 false /*fReadOnly */,
1065 &pResult->u.pvHCFlat);
1066 if (RT_SUCCESS(rc))
1067 return VINF_SUCCESS;
1068 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1070 case DBGCVAR_TYPE_HC_PHYS:
1071 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1072 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu,
1073 DBGFR3AddrFromPhys(pDbgc->pVM, &Address, pArg->u.GCPhys),
1074 &pResult->u.HCPhys);
1075 if (RT_SUCCESS(rc))
1076 return VINF_SUCCESS;
1077 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1079 case DBGCVAR_TYPE_NUMBER:
1080 pResult->enmType = enmToType;
1081 pResult->u.u64Number = InVar.u.GCPhys;
1082 return VINF_SUCCESS;
1084 case DBGCVAR_TYPE_STRING:
1085 case DBGCVAR_TYPE_SYMBOL:
1086 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1088 case DBGCVAR_TYPE_UNKNOWN:
1089 case DBGCVAR_TYPE_ANY:
1090 break;
1092 break;
1094 case DBGCVAR_TYPE_HC_FLAT:
1095 switch (enmToType)
1097 case DBGCVAR_TYPE_GC_FLAT:
1098 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1100 case DBGCVAR_TYPE_GC_FAR:
1101 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1103 case DBGCVAR_TYPE_GC_PHYS:
1104 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1105 rc = PGMR3DbgR3Ptr2GCPhys(pDbgc->pVM, pArg->u.pvHCFlat, &pResult->u.GCPhys);
1106 if (RT_SUCCESS(rc))
1107 return VINF_SUCCESS;
1108 /** @todo more memory types! */
1109 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1111 case DBGCVAR_TYPE_HC_FLAT:
1112 return VINF_SUCCESS;
1114 case DBGCVAR_TYPE_HC_PHYS:
1115 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1116 rc = PGMR3DbgR3Ptr2HCPhys(pDbgc->pVM, pArg->u.pvHCFlat, &pResult->u.HCPhys);
1117 if (RT_SUCCESS(rc))
1118 return VINF_SUCCESS;
1119 /** @todo more memory types! */
1120 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1122 case DBGCVAR_TYPE_NUMBER:
1123 pResult->enmType = enmToType;
1124 pResult->u.u64Number = (uintptr_t)InVar.u.pvHCFlat;
1125 return VINF_SUCCESS;
1127 case DBGCVAR_TYPE_STRING:
1128 case DBGCVAR_TYPE_SYMBOL:
1129 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1131 case DBGCVAR_TYPE_UNKNOWN:
1132 case DBGCVAR_TYPE_ANY:
1133 break;
1135 break;
1137 case DBGCVAR_TYPE_HC_PHYS:
1138 switch (enmToType)
1140 case DBGCVAR_TYPE_GC_FLAT:
1141 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1143 case DBGCVAR_TYPE_GC_FAR:
1144 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1146 case DBGCVAR_TYPE_GC_PHYS:
1147 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1148 rc = PGMR3DbgHCPhys2GCPhys(pDbgc->pVM, pArg->u.HCPhys, &pResult->u.GCPhys);
1149 if (RT_SUCCESS(rc))
1150 return VINF_SUCCESS;
1151 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1153 case DBGCVAR_TYPE_HC_FLAT:
1154 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1156 case DBGCVAR_TYPE_HC_PHYS:
1157 return VINF_SUCCESS;
1159 case DBGCVAR_TYPE_NUMBER:
1160 pResult->enmType = enmToType;
1161 pResult->u.u64Number = InVar.u.HCPhys;
1162 return VINF_SUCCESS;
1164 case DBGCVAR_TYPE_STRING:
1165 case DBGCVAR_TYPE_SYMBOL:
1166 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1168 case DBGCVAR_TYPE_UNKNOWN:
1169 case DBGCVAR_TYPE_ANY:
1170 break;
1172 break;
1174 case DBGCVAR_TYPE_NUMBER:
1175 switch (enmToType)
1177 case DBGCVAR_TYPE_GC_FLAT:
1178 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
1179 pResult->u.GCFlat = (RTGCPTR)InVar.u.u64Number;
1180 return VINF_SUCCESS;
1182 case DBGCVAR_TYPE_GC_FAR:
1183 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1185 case DBGCVAR_TYPE_GC_PHYS:
1186 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1187 pResult->u.GCPhys = (RTGCPHYS)InVar.u.u64Number;
1188 return VINF_SUCCESS;
1190 case DBGCVAR_TYPE_HC_FLAT:
1191 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
1192 pResult->u.pvHCFlat = (void *)(uintptr_t)InVar.u.u64Number;
1193 return VINF_SUCCESS;
1195 case DBGCVAR_TYPE_HC_PHYS:
1196 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1197 pResult->u.HCPhys = (RTHCPHYS)InVar.u.u64Number;
1198 return VINF_SUCCESS;
1200 case DBGCVAR_TYPE_NUMBER:
1201 return VINF_SUCCESS;
1203 case DBGCVAR_TYPE_STRING:
1204 case DBGCVAR_TYPE_SYMBOL:
1205 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1207 case DBGCVAR_TYPE_UNKNOWN:
1208 case DBGCVAR_TYPE_ANY:
1209 break;
1211 break;
1213 case DBGCVAR_TYPE_SYMBOL:
1214 case DBGCVAR_TYPE_STRING:
1215 switch (enmToType)
1217 case DBGCVAR_TYPE_GC_FLAT:
1218 case DBGCVAR_TYPE_GC_FAR:
1219 case DBGCVAR_TYPE_GC_PHYS:
1220 case DBGCVAR_TYPE_HC_FLAT:
1221 case DBGCVAR_TYPE_HC_PHYS:
1222 case DBGCVAR_TYPE_NUMBER:
1223 if (fConvSyms)
1225 rc = dbgcSymbolGet(pDbgc, InVar.u.pszString, enmToType, pResult);
1226 if (RT_SUCCESS(rc))
1227 return VINF_SUCCESS;
1229 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1231 case DBGCVAR_TYPE_STRING:
1232 case DBGCVAR_TYPE_SYMBOL:
1233 pResult->enmType = enmToType;
1234 return VINF_SUCCESS;
1236 case DBGCVAR_TYPE_UNKNOWN:
1237 case DBGCVAR_TYPE_ANY:
1238 break;
1240 break;
1242 case DBGCVAR_TYPE_UNKNOWN:
1243 case DBGCVAR_TYPE_ANY:
1244 break;
1247 AssertMsgFailed(("f=%d t=%d\n", InVar.enmType, enmToType));
1248 return VERR_INVALID_PARAMETER;
1253 * @interface_method_impl{DBGFINFOHLP,pfnPrintf}
1255 static DECLCALLBACK(void) dbgcHlpGetDbgfOutputHlp_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
1257 PDBGC pDbgc = RT_FROM_MEMBER(pHlp, DBGC, DbgfOutputHlp);
1258 va_list va;
1259 va_start(va, pszFormat);
1260 pDbgc->CmdHlp.pfnPrintfV(&pDbgc->CmdHlp, NULL, pszFormat, va);
1261 va_end(va);
1266 * @interface_method_impl{DBGFINFOHLP,pfnPrintfV}
1268 static DECLCALLBACK(void) dbgcHlpGetDbgfOutputHlp_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
1270 PDBGC pDbgc = RT_FROM_MEMBER(pHlp, DBGC, DbgfOutputHlp);
1271 pDbgc->CmdHlp.pfnPrintfV(&pDbgc->CmdHlp, NULL, pszFormat, args);
1276 * @interface_method_impl{DBGCCMDHLP,pfnGetDbgfOutputHlp}
1278 static DECLCALLBACK(PCDBGFINFOHLP) dbgcHlpGetDbgfOutputHlp(PDBGCCMDHLP pCmdHlp)
1280 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
1282 /* Lazy init */
1283 if (!pDbgc->DbgfOutputHlp.pfnPrintf)
1285 pDbgc->DbgfOutputHlp.pfnPrintf = dbgcHlpGetDbgfOutputHlp_Printf;
1286 pDbgc->DbgfOutputHlp.pfnPrintfV = dbgcHlpGetDbgfOutputHlp_PrintfV;
1289 return &pDbgc->DbgfOutputHlp;
1294 * @interface_method_impl{DBGCCMDHLP,pfnGetCurrentCpu}
1296 static DECLCALLBACK(VMCPUID) dbgcHlpGetCurrentCpu(PDBGCCMDHLP pCmdHlp)
1298 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
1299 return pDbgc->idCpu;
1304 * @interface_method_impl{DBGCCMDHLP,pfnGetCpuMode}
1306 static DECLCALLBACK(CPUMMODE) dbgcHlpGetCpuMode(PDBGCCMDHLP pCmdHlp)
1308 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
1309 CPUMMODE enmMode = CPUMMODE_INVALID;
1310 if (pDbgc->fRegCtxGuest)
1312 if (pDbgc->pVM)
1313 enmMode = DBGFR3CpuGetMode(pDbgc->pVM, DBGCCmdHlpGetCurrentCpu(pCmdHlp));
1314 if (enmMode == CPUMMODE_INVALID)
1315 #if HC_ARCH_BITS == 64
1316 enmMode = CPUMMODE_LONG;
1317 #else
1318 enmMode = CPUMMODE_PROTECTED;
1319 #endif
1321 else
1322 enmMode = CPUMMODE_PROTECTED;
1323 return enmMode;
1328 * Initializes the Command Helpers for a DBGC instance.
1330 * @param pDbgc Pointer to the DBGC instance.
1332 void dbgcInitCmdHlp(PDBGC pDbgc)
1334 pDbgc->CmdHlp.u32Magic = DBGCCMDHLP_MAGIC;
1335 pDbgc->CmdHlp.pfnPrintfV = dbgcHlpPrintfV;
1336 pDbgc->CmdHlp.pfnPrintf = dbgcHlpPrintf;
1337 pDbgc->CmdHlp.pfnStrPrintf = dbgcHlpStrPrintf;
1338 pDbgc->CmdHlp.pfnStrPrintfV = dbgcHlpStrPrintfV;
1339 pDbgc->CmdHlp.pfnVBoxErrorV = dbgcHlpVBoxErrorV;
1340 pDbgc->CmdHlp.pfnVBoxError = dbgcHlpVBoxError;
1341 pDbgc->CmdHlp.pfnMemRead = dbgcHlpMemRead;
1342 pDbgc->CmdHlp.pfnMemWrite = dbgcHlpMemWrite;
1343 pDbgc->CmdHlp.pfnEvalV = dbgcHlpEvalV;
1344 pDbgc->CmdHlp.pfnExec = dbgcHlpExec;
1345 pDbgc->CmdHlp.pfnFailV = dbgcHlpFailV;
1346 pDbgc->CmdHlp.pfnFailRcV = dbgcHlpFailRcV;
1347 pDbgc->CmdHlp.pfnVarToDbgfAddr = dbgcHlpVarToDbgfAddr;
1348 pDbgc->CmdHlp.pfnVarFromDbgfAddr = dbgcHlpVarFromDbgfAddr;
1349 pDbgc->CmdHlp.pfnVarToNumber = dbgcHlpVarToNumber;
1350 pDbgc->CmdHlp.pfnVarToBool = dbgcHlpVarToBool;
1351 pDbgc->CmdHlp.pfnVarGetRange = dbgcHlpVarGetRange;
1352 pDbgc->CmdHlp.pfnVarConvert = dbgcHlpVarConvert;
1353 pDbgc->CmdHlp.pfnGetDbgfOutputHlp = dbgcHlpGetDbgfOutputHlp;
1354 pDbgc->CmdHlp.pfnGetCurrentCpu = dbgcHlpGetCurrentCpu;
1355 pDbgc->CmdHlp.pfnGetCpuMode = dbgcHlpGetCpuMode;
1356 pDbgc->CmdHlp.u32EndMarker = DBGCCMDHLP_MAGIC;