3 * DBGC - Debugger Console, Command Helpers.
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 /*******************************************************************************
20 *******************************************************************************/
21 #define LOG_GROUP LOG_GROUP_DBGC
23 #include <VBox/vmm/dbgf.h>
24 #include <VBox/vmm/pgm.h>
25 #include <VBox/param.h>
29 #include <iprt/assert.h>
30 #include <iprt/ctype.h>
32 #include <iprt/string.h>
34 #include "DBGCInternal.h"
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.
47 va_start(args
, pszFormat
);
48 int rc
= pCmdHlp
->pfnPrintfV(pCmdHlp
, pcbWritten
, pszFormat
, args
);
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);
71 char *pchQuote
= (char *)memchr(psz
, chQuote
, cch
);
74 cchOutput
+= pfnOutput(pvArgOutput
, psz
, cch
);
77 size_t cchSub
= pchQuote
- psz
+ 1;
78 cchOutput
+= pfnOutput(pvArgOutput
, psz
, cchSub
);
79 cchOutput
+= pfnOutput(pvArgOutput
, &chQuote
, 1);
84 cchOutput
+= pfnOutput(pvArgOutput
, &chQuote
, 1);
90 * Callback to format non-standard format specifiers, employed by dbgcPrintfV
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')
117 switch (**ppszFormat
)
120 * Print variable without range.
121 * The argument is a const pointer to the variable.
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
:
148 return pfnOutput(pvArgOutput
, "??", 2);
153 * Print variable with range.
154 * The argument is a const pointer to the variable.
159 PCDBGCVAR pVar
= va_arg(*pArgs
, PCDBGCVAR
);
162 switch (pVar
->enmRangeType
)
164 case DBGCVAR_RANGE_NONE
:
167 case DBGCVAR_RANGE_ELEMENTS
:
168 RTStrPrintf(szRange
, sizeof(szRange
), " L %llx", pVar
->u64Range
);
170 case DBGCVAR_RANGE_BYTES
:
171 RTStrPrintf(szRange
, sizeof(szRange
), " LB %llx", pVar
->u64Range
);
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
:
196 return pfnOutput(pvArgOutput
, "??", 2);
201 AssertMsgFailed(("Invalid format type '%s'!\n", **ppszFormat
));
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
;
220 int rc
= pDbgc
->pBack
->pfnWrite(pDbgc
->pBack
, pachChars
, cbChars
, NULL
);
222 pDbgc
->chLastOutput
= pachChars
[cbChars
- 1];
225 pDbgc
->rcOutput
= rc
;
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.
246 size_t cb
= RTStrFormatV(dbgcFormatOutput
, pDbgc
, dbgcStringFormatter
, pDbgc
, pszFormat
, args
);
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
);
273 va_start(va
, pszFormat
);
274 size_t cch
= RTStrPrintfExV(dbgcStringFormatter
, pDbgc
, pszBuf
, cbBuf
, pszFormat
, va
);
281 * @interface_method_impl{DBGCCMDHLP,pfnVBoxErrorV}
283 static DECLCALLBACK(int) dbgcHlpVBoxErrorV(PDBGCCMDHLP pCmdHlp
, int rc
, const char *pszFormat
, va_list args
)
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
);
295 rc
= VERR_DBGC_COMMAND_FAILED
;
303 * @interface_method_impl{DBGCCMDHLP,pfnVBoxError}
305 static DECLCALLBACK(int) dbgcHlpVBoxError(PDBGCCMDHLP pCmdHlp
, int rc
, const char *pszFormat
, ...)
308 va_start(args
, pszFormat
);
309 int rcRet
= pCmdHlp
->pfnVBoxErrorV(pCmdHlp
, rc
, pszFormat
, args
);
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
);
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. */
344 rc
= DBGFR3AddrFromSelOff(pDbgc
->pVM
, pDbgc
->idCpu
, &Address
, Var
.u
.GCFar
.sel
, Var
.u
.GCFar
.off
);
348 /* don't bother with flat selectors (for now). */
349 if (!DBGFADDRESS_IS_FLAT(&Address
))
352 rc
= DBGFR3SelQueryInfo(pDbgc
->pVM
, pDbgc
->idCpu
, Address
.Sel
,
353 DBGFSELQI_FLAGS_DT_GUEST
| DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE
, &SelInfo
);
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
;
368 if (Address
.off
> SelInfo
.cbLimit
)
369 return VERR_OUT_OF_SELECTOR_BOUNDS
;
370 cb
= SelInfo
.cbLimit
- Address
.off
;
375 return VERR_OUT_OF_SELECTOR_BOUNDS
;
380 Var
.enmType
= DBGCVAR_TYPE_GC_FLAT
;
381 Var
.u
.GCFlat
= Address
.FlatPtr
;
384 case DBGCVAR_TYPE_GC_FLAT
:
385 case DBGCVAR_TYPE_GC_PHYS
:
386 case DBGCVAR_TYPE_HC_FLAT
:
387 case DBGCVAR_TYPE_HC_PHYS
:
391 return VERR_NOT_IMPLEMENTED
;
399 size_t cbLeft
= cbRead
;
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! */
420 case DBGCVAR_TYPE_GC_FLAT
:
421 rc
= DBGFR3MemRead(pDbgc
->pVM
, pDbgc
->idCpu
,
422 DBGFR3AddrFromFlat(pVM
, &Address
, Var
.u
.GCFlat
),
426 case DBGCVAR_TYPE_GC_PHYS
:
427 rc
= DBGFR3MemRead(pDbgc
->pVM
, pDbgc
->idCpu
,
428 DBGFR3AddrFromPhys(pVM
, &Address
, Var
.u
.GCPhys
),
432 case DBGCVAR_TYPE_HC_PHYS
:
433 case DBGCVAR_TYPE_HC_FLAT
:
436 rc
= dbgcOpAddrFlat(pDbgc
, &Var
, DBGCVAR_CAT_ANY
, &Var2
);
439 /** @todo protect this!!! */
440 memcpy(pvBuffer
, Var2
.u
.pvHCFlat
, cb
);
444 rc
= VERR_INVALID_POINTER
;
449 rc
= VERR_DBGC_PARSE_INCORRECT_ARG_TYPE
;
457 if (pcbRead
&& (*pcbRead
= cbRead
- cbLeft
) > 0)
468 pvBuffer
= (char *)pvBuffer
+ cb
;
469 rc
= DBGCCmdHlpEval(pCmdHlp
, &Var
, "%DV + %d", &Var
, cb
);
472 if (pcbRead
&& (*pcbRead
= cbRead
- cbLeft
) > 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
);
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. */
517 rc
= DBGFR3AddrFromSelOff(pDbgc
->pVM
, pDbgc
->idCpu
, &Address
, Var
.u
.GCFar
.sel
, Var
.u
.GCFar
.off
);
521 /* don't bother with flat selectors (for now). */
522 if (!DBGFADDRESS_IS_FLAT(&Address
))
525 rc
= DBGFR3SelQueryInfo(pDbgc
->pVM
, pDbgc
->idCpu
, Address
.Sel
,
526 DBGFSELQI_FLAGS_DT_GUEST
| DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE
, &SelInfo
);
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
;
541 if (Address
.off
> SelInfo
.cbLimit
)
542 return VERR_OUT_OF_SELECTOR_BOUNDS
;
543 cb
= SelInfo
.cbLimit
- Address
.off
;
545 if (cbWrite
- 1 > cb
)
548 return VERR_OUT_OF_SELECTOR_BOUNDS
;
553 Var
.enmType
= DBGCVAR_TYPE_GC_FLAT
;
554 Var
.u
.GCFlat
= Address
.FlatPtr
;
557 case DBGCVAR_TYPE_GC_FLAT
:
558 rc
= DBGFR3MemWrite(pVM
, pDbgc
->idCpu
,
559 DBGFR3AddrFromFlat(pVM
, &Address
, Var
.u
.GCFlat
),
561 if (pcbWritten
&& RT_SUCCESS(rc
))
562 *pcbWritten
= cbWrite
;
565 case DBGCVAR_TYPE_GC_PHYS
:
566 rc
= DBGFR3MemWrite(pVM
, pDbgc
->idCpu
,
567 DBGFR3AddrFromPhys(pVM
, &Address
, Var
.u
.GCPhys
),
569 if (pcbWritten
&& RT_SUCCESS(rc
))
570 *pcbWritten
= cbWrite
;
573 case DBGCVAR_TYPE_HC_FLAT
:
574 case DBGCVAR_TYPE_HC_PHYS
:
577 * Copy HC memory page by page.
583 /* convert to flat address */
585 rc
= dbgcOpAddrFlat(pDbgc
, &Var
, DBGCVAR_CAT_ANY
, &Var2
);
588 if (pcbWritten
&& *pcbWritten
)
589 return -VERR_INVALID_POINTER
;
590 return VERR_INVALID_POINTER
;
594 size_t cbChunk
= PAGE_SIZE
;
595 cbChunk
-= (uintptr_t)Var
.u
.pvHCFlat
& PAGE_OFFSET_MASK
;
596 if (cbChunk
> cbWrite
)
599 /** @todo protect this!!! */
600 memcpy(Var2
.u
.pvHCFlat
, pvBuffer
, cbChunk
);
603 if (Var
.enmType
== DBGCVAR_TYPE_HC_FLAT
)
604 Var
.u
.pvHCFlat
= (uint8_t *)Var
.u
.pvHCFlat
+ cbChunk
;
606 Var
.u
.HCPhys
+= cbChunk
;
607 pvBuffer
= (uint8_t const *)pvBuffer
+ cbChunk
;
609 *pcbWritten
+= cbChunk
;
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.
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
);
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. */
652 pDbgc
->pszScratch
= pszScratch
;
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
);
733 switch (pVar
->enmType
)
735 case DBGCVAR_TYPE_GC_FLAT
:
736 DBGFR3AddrFromFlat(pDbgc
->pVM
, pAddress
, pVar
->u
.GCFlat
);
739 case DBGCVAR_TYPE_NUMBER
:
740 DBGFR3AddrFromFlat(pDbgc
->pVM
, pAddress
, (RTGCUINTPTR
)pVar
->u
.u64Number
);
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
);
750 case DBGCVAR_TYPE_SYMBOL
:
753 int rc
= DBGCCmdHlpEval(&pDbgc
->CmdHlp
, &Var
, "%%(%DV)", pVar
);
756 return dbgcHlpVarToDbgfAddr(pCmdHlp
, &Var
, pAddress
);
759 case DBGCVAR_TYPE_STRING
:
760 case DBGCVAR_TYPE_HC_FLAT
:
761 case DBGCVAR_TYPE_HC_PHYS
:
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
);
785 case DBGFADDRESS_FLAGS_FLAT
:
786 DBGCVAR_INIT_GC_FLAT(pResult
, pAddress
->FlatPtr
);
789 case DBGFADDRESS_FLAGS_PHYS
:
790 DBGCVAR_INIT_GC_PHYS(pResult
, pAddress
->FlatPtr
);
794 DBGCVAR_INIT(pResult
);
795 AssertMsgFailedReturn(("%#x\n", pAddress
->fFlags
), VERR_INVALID_PARAMETER
);
804 * @interface_method_impl{DBGCCMDHLP,pfnVarToNumber}
806 static DECLCALLBACK(int) dbgcHlpVarToNumber(PDBGCCMDHLP pCmdHlp
, PCDBGCVAR pVar
, uint64_t *pu64Number
)
808 PDBGC pDbgc
= DBGC_CMDHLP2DBGC(pCmdHlp
);
812 switch (pVar
->enmType
)
814 case DBGCVAR_TYPE_GC_FLAT
:
815 u64Number
= pVar
->u
.GCFlat
;
817 case DBGCVAR_TYPE_GC_PHYS
:
818 u64Number
= pVar
->u
.GCPhys
;
820 case DBGCVAR_TYPE_HC_FLAT
:
821 u64Number
= (uintptr_t)pVar
->u
.pvHCFlat
;
823 case DBGCVAR_TYPE_HC_PHYS
:
824 u64Number
= (uintptr_t)pVar
->u
.HCPhys
;
826 case DBGCVAR_TYPE_NUMBER
:
827 u64Number
= (uintptr_t)pVar
->u
.u64Number
;
829 case DBGCVAR_TYPE_GC_FAR
:
830 u64Number
= (uintptr_t)pVar
->u
.GCFar
.off
;
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! */
837 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE
;
839 *pu64Number
= u64Number
;
845 * @interface_method_impl{DBGCCMDHLP,pfnVarToBool}
847 static DECLCALLBACK(int) dbgcHlpVarToBool(PDBGCCMDHLP pCmdHlp
, PCDBGCVAR pVar
, bool *pf
)
849 PDBGC pDbgc
= DBGC_CMDHLP2DBGC(pCmdHlp
);
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"))
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"))
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;
882 case DBGCVAR_TYPE_GC_FAR
:
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
,
895 /** @todo implement this properly, strings/symbols are not resolved now. */
896 switch (pVar
->enmRangeType
)
899 case DBGCVAR_RANGE_NONE
:
900 *pcbRange
= cbDefault
;
902 case DBGCVAR_RANGE_BYTES
:
903 *pcbRange
= pVar
->u64Range
;
905 case DBGCVAR_RANGE_ELEMENTS
:
906 *pcbRange
= pVar
->u64Range
* cbElement
;
914 * @interface_method_impl{DBGCCMDHLP,pfnVarConvert}
916 static DECLCALLBACK(int) dbgcHlpVarConvert(PDBGCCMDHLP pCmdHlp
, PCDBGCVAR pInVar
, DBGCVARTYPE enmToType
, bool fConvSyms
,
919 PDBGC pDbgc
= DBGC_CMDHLP2DBGC(pCmdHlp
);
920 DBGCVAR
const InVar
= *pInVar
; /* if pInVar == pResult */
921 PCDBGCVAR pArg
= &InVar
; /* lazy bird, clean up later */
928 switch (InVar
.enmType
)
930 case DBGCVAR_TYPE_GC_FLAT
:
933 case DBGCVAR_TYPE_GC_FLAT
:
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
),
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
);
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
),
965 return VERR_DBGC_PARSE_CONVERSION_FAILED
;
967 case DBGCVAR_TYPE_NUMBER
:
968 pResult
->enmType
= enmToType
;
969 pResult
->u
.u64Number
= InVar
.u
.GCFlat
;
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
:
982 case DBGCVAR_TYPE_GC_FAR
:
985 case DBGCVAR_TYPE_GC_FLAT
:
986 rc
= DBGFR3AddrFromSelOff(pDbgc
->pVM
, pDbgc
->idCpu
, &Address
, pArg
->u
.GCFar
.sel
, pArg
->u
.GCFar
.off
);
989 pResult
->enmType
= DBGCVAR_TYPE_GC_FLAT
;
990 pResult
->u
.GCFlat
= Address
.FlatPtr
;
993 return VERR_DBGC_PARSE_CONVERSION_FAILED
;
995 case DBGCVAR_TYPE_GC_FAR
:
998 case DBGCVAR_TYPE_GC_PHYS
:
999 rc
= DBGFR3AddrFromSelOff(pDbgc
->pVM
, pDbgc
->idCpu
, &Address
, pArg
->u
.GCFar
.sel
, pArg
->u
.GCFar
.off
);
1002 pResult
->enmType
= DBGCVAR_TYPE_GC_PHYS
;
1003 rc
= DBGFR3AddrToPhys(pDbgc
->pVM
, pDbgc
->idCpu
, &Address
, &pResult
->u
.GCPhys
);
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
);
1013 pResult
->enmType
= DBGCVAR_TYPE_HC_FLAT
;
1014 rc
= DBGFR3AddrToVolatileR3Ptr(pDbgc
->pVM
, pDbgc
->idCpu
, &Address
,
1015 false /*fReadOnly*/, &pResult
->u
.pvHCFlat
);
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
);
1025 pResult
->enmType
= DBGCVAR_TYPE_HC_PHYS
;
1026 rc
= DBGFR3AddrToHostPhys(pDbgc
->pVM
, pDbgc
->idCpu
, &Address
, &pResult
->u
.GCPhys
);
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
:
1047 case DBGCVAR_TYPE_GC_PHYS
:
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
);
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
);
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
:
1094 case DBGCVAR_TYPE_HC_FLAT
:
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
);
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
);
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
:
1137 case DBGCVAR_TYPE_HC_PHYS
:
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
);
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
:
1174 case DBGCVAR_TYPE_NUMBER
:
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
:
1213 case DBGCVAR_TYPE_SYMBOL
:
1214 case DBGCVAR_TYPE_STRING
:
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
:
1225 rc
= dbgcSymbolGet(pDbgc
, InVar
.u
.pszString
, enmToType
, pResult
);
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
:
1242 case DBGCVAR_TYPE_UNKNOWN
:
1243 case DBGCVAR_TYPE_ANY
:
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
);
1259 va_start(va
, pszFormat
);
1260 pDbgc
->CmdHlp
.pfnPrintfV(&pDbgc
->CmdHlp
, NULL
, pszFormat
, 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
);
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
)
1313 enmMode
= DBGFR3CpuGetMode(pDbgc
->pVM
, DBGCCmdHlpGetCurrentCpu(pCmdHlp
));
1314 if (enmMode
== CPUMMODE_INVALID
)
1315 #if HC_ARCH_BITS == 64
1316 enmMode
= CPUMMODE_LONG
;
1318 enmMode
= CPUMMODE_PROTECTED
;
1322 enmMode
= CPUMMODE_PROTECTED
;
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
;