VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGCCmdHlp.cpp@ 99569

Last change on this file since 99569 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 53.9 KB
Line 
1/* $Id: DBGCCmdHlp.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Command Helpers.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_DBGC
33#include <VBox/dbg.h>
34#include <VBox/vmm/dbgf.h>
35#include <VBox/vmm/pgm.h>
36#include <VBox/param.h>
37#include <VBox/err.h>
38#include <VBox/log.h>
39
40#include <iprt/assert.h>
41#include <iprt/ctype.h>
42#include <iprt/mem.h>
43#include <iprt/string.h>
44
45#include "DBGCInternal.h"
46
47
48
49/**
50 * @interface_method_impl{DBGCCMDHLP,pfnPrintf}
51 */
52static DECLCALLBACK(int) dbgcHlpPrintf(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten, const char *pszFormat, ...)
53{
54 /*
55 * Do the formatting and output.
56 */
57 va_list args;
58 va_start(args, pszFormat);
59 int rc = pCmdHlp->pfnPrintfV(pCmdHlp, pcbWritten, pszFormat, args);
60 va_end(args);
61
62 return rc;
63}
64
65
66/**
67 * Outputs a string in quotes.
68 *
69 * @returns The number of bytes formatted.
70 * @param pfnOutput Pointer to output function.
71 * @param pvArgOutput Argument for the output function.
72 * @param chQuote The quote character.
73 * @param psz The string to quote.
74 * @param cch The string length.
75 */
76static size_t dbgcStringOutputInQuotes(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char chQuote, const char *psz, size_t cch)
77{
78 size_t cchOutput = pfnOutput(pvArgOutput, &chQuote, 1);
79
80 while (cch > 0)
81 {
82 char *pchQuote = (char *)memchr(psz, chQuote, cch);
83 if (!pchQuote)
84 {
85 cchOutput += pfnOutput(pvArgOutput, psz, cch);
86 break;
87 }
88 size_t cchSub = pchQuote - psz + 1;
89 cchOutput += pfnOutput(pvArgOutput, psz, cchSub);
90 cchOutput += pfnOutput(pvArgOutput, &chQuote, 1);
91 cch -= cchSub;
92 psz += cchSub;
93 }
94
95 cchOutput += pfnOutput(pvArgOutput, &chQuote, 1);
96 return cchOutput;
97}
98
99
100/**
101 * Callback to format non-standard format specifiers, employed by dbgcPrintfV
102 * and others.
103 *
104 * @returns The number of bytes formatted.
105 * @param pvArg Formatter argument.
106 * @param pfnOutput Pointer to output function.
107 * @param pvArgOutput Argument for the output function.
108 * @param ppszFormat Pointer to the format string pointer. Advance this till the char
109 * after the format specifier.
110 * @param pArgs Pointer to the argument list. Use this to fetch the arguments.
111 * @param cchWidth Format Width. -1 if not specified.
112 * @param cchPrecision Format Precision. -1 if not specified.
113 * @param fFlags Flags (RTSTR_NTFS_*).
114 * @param chArgSize The argument size specifier, 'l' or 'L'.
115 */
116static DECLCALLBACK(size_t) dbgcStringFormatter(void *pvArg, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
117 const char **ppszFormat, va_list *pArgs, int cchWidth,
118 int cchPrecision, unsigned fFlags, char chArgSize)
119{
120 NOREF(cchWidth); NOREF(cchPrecision); NOREF(fFlags); NOREF(chArgSize); NOREF(pvArg);
121 if (**ppszFormat != 'D')
122 {
123 (*ppszFormat)++;
124 return 0;
125 }
126
127 (*ppszFormat)++;
128 switch (**ppszFormat)
129 {
130 /*
131 * Print variable without range.
132 * The argument is a const pointer to the variable.
133 */
134 case 'V':
135 {
136 (*ppszFormat)++;
137 PCDBGCVAR pVar = va_arg(*pArgs, PCDBGCVAR);
138 switch (pVar->enmType)
139 {
140 case DBGCVAR_TYPE_GC_FLAT:
141 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%RGv", pVar->u.GCFlat);
142 case DBGCVAR_TYPE_GC_FAR:
143 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%04x:%08x", pVar->u.GCFar.sel, pVar->u.GCFar.off);
144 case DBGCVAR_TYPE_GC_PHYS:
145 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%%%RGp", pVar->u.GCPhys);
146 case DBGCVAR_TYPE_HC_FLAT:
147 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%#%RHv", (uintptr_t)pVar->u.pvHCFlat);
148 case DBGCVAR_TYPE_HC_PHYS:
149 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "#%%%%%RHp", pVar->u.HCPhys);
150 case DBGCVAR_TYPE_NUMBER:
151 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%llx", pVar->u.u64Number);
152 case DBGCVAR_TYPE_STRING:
153 return dbgcStringOutputInQuotes(pfnOutput, pvArgOutput, '"', pVar->u.pszString, (size_t)pVar->u64Range);
154 case DBGCVAR_TYPE_SYMBOL:
155 return dbgcStringOutputInQuotes(pfnOutput, pvArgOutput, '\'', pVar->u.pszString, (size_t)pVar->u64Range);
156
157 case DBGCVAR_TYPE_UNKNOWN:
158 default:
159 return pfnOutput(pvArgOutput, "??", 2);
160 }
161 }
162
163 /*
164 * Print variable with range.
165 * The argument is a const pointer to the variable.
166 */
167 case 'v':
168 {
169 (*ppszFormat)++;
170 PCDBGCVAR pVar = va_arg(*pArgs, PCDBGCVAR);
171
172 char szRange[32];
173 switch (pVar->enmRangeType)
174 {
175 case DBGCVAR_RANGE_NONE:
176 szRange[0] = '\0';
177 break;
178 case DBGCVAR_RANGE_ELEMENTS:
179 RTStrPrintf(szRange, sizeof(szRange), " L %llx", pVar->u64Range);
180 break;
181 case DBGCVAR_RANGE_BYTES:
182 RTStrPrintf(szRange, sizeof(szRange), " LB %llx", pVar->u64Range);
183 break;
184 }
185
186 switch (pVar->enmType)
187 {
188 case DBGCVAR_TYPE_GC_FLAT:
189 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%RGv%s", pVar->u.GCFlat, szRange);
190 case DBGCVAR_TYPE_GC_FAR:
191 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%04x:%08x%s", pVar->u.GCFar.sel, pVar->u.GCFar.off, szRange);
192 case DBGCVAR_TYPE_GC_PHYS:
193 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%%%RGp%s", pVar->u.GCPhys, szRange);
194 case DBGCVAR_TYPE_HC_FLAT:
195 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%#%RHv%s", (uintptr_t)pVar->u.pvHCFlat, szRange);
196 case DBGCVAR_TYPE_HC_PHYS:
197 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "#%%%%%RHp%s", pVar->u.HCPhys, szRange);
198 case DBGCVAR_TYPE_NUMBER:
199 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%llx%s", pVar->u.u64Number, szRange);
200 case DBGCVAR_TYPE_STRING:
201 return dbgcStringOutputInQuotes(pfnOutput, pvArgOutput, '"', pVar->u.pszString, (size_t)pVar->u64Range);
202 case DBGCVAR_TYPE_SYMBOL:
203 return dbgcStringOutputInQuotes(pfnOutput, pvArgOutput, '\'', pVar->u.pszString, (size_t)pVar->u64Range);
204
205 case DBGCVAR_TYPE_UNKNOWN:
206 default:
207 return pfnOutput(pvArgOutput, "??", 2);
208 }
209 }
210
211 default:
212 AssertMsgFailed(("Invalid format type '%s'!\n", **ppszFormat));
213 return 0;
214 }
215}
216
217
218/**
219 * Output callback employed by dbgcHlpPrintfV.
220 *
221 * @returns number of bytes written.
222 * @param pvArg User argument.
223 * @param pachChars Pointer to an array of utf-8 characters.
224 * @param cbChars Number of bytes in the character array pointed to by pachChars.
225 */
226static DECLCALLBACK(size_t) dbgcFormatOutput(void *pvArg, const char *pachChars, size_t cbChars)
227{
228 PDBGC pDbgc = (PDBGC)pvArg;
229 if (cbChars)
230 {
231 int rc = pDbgc->pfnOutput(pDbgc->pvOutputUser, pachChars, cbChars);
232 if (RT_SUCCESS(rc))
233 pDbgc->chLastOutput = pachChars[cbChars - 1];
234 else
235 {
236 pDbgc->rcOutput = rc;
237 cbChars = 0;
238 }
239 }
240
241 return cbChars;
242}
243
244
245
246/**
247 * @interface_method_impl{DBGCCMDHLP,pfnPrintfV}
248 */
249static DECLCALLBACK(int) dbgcHlpPrintfV(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten, const char *pszFormat, va_list args)
250{
251 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
252
253 /*
254 * Do the formatting and output.
255 */
256 pDbgc->rcOutput = 0;
257 size_t cb = RTStrFormatV(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, pszFormat, args);
258
259 if (pcbWritten)
260 *pcbWritten = cb;
261
262 return pDbgc->rcOutput;
263}
264
265
266/**
267 * @interface_method_impl{DBGCCMDHLP,pfnStrPrintfV}
268 */
269static DECLCALLBACK(size_t) dbgcHlpStrPrintfV(PDBGCCMDHLP pCmdHlp, char *pszBuf, size_t cbBuf,
270 const char *pszFormat, va_list va)
271{
272 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
273 return RTStrPrintfExV(dbgcStringFormatter, pDbgc, pszBuf, cbBuf, pszFormat, va);
274}
275
276
277/**
278 * @interface_method_impl{DBGCCMDHLP,pfnStrPrintf}
279 */
280static DECLCALLBACK(size_t) dbgcHlpStrPrintf(PDBGCCMDHLP pCmdHlp, char *pszBuf, size_t cbBuf, const char *pszFormat, ...)
281{
282 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
283 va_list va;
284 va_start(va, pszFormat);
285 size_t cch = RTStrPrintfExV(dbgcStringFormatter, pDbgc, pszBuf, cbBuf, pszFormat, va);
286 va_end(va);
287 return cch;
288}
289
290
291/**
292 * @interface_method_impl{DBGCCMDHLP,pfnVBoxErrorV}
293 */
294static DECLCALLBACK(int) dbgcHlpVBoxErrorV(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, va_list args)
295{
296 switch (rc)
297 {
298 case VINF_SUCCESS:
299 break;
300
301 default:
302 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: %Rrc: %s", rc, pszFormat ? " " : "\n");
303 if (RT_SUCCESS(rc) && pszFormat)
304 rc = pCmdHlp->pfnPrintfV(pCmdHlp, NULL, pszFormat, args);
305 if (RT_SUCCESS(rc))
306 rc = VERR_DBGC_COMMAND_FAILED;
307 break;
308 }
309 return rc;
310}
311
312
313/**
314 * @interface_method_impl{DBGCCMDHLP,pfnVBoxError}
315 */
316static DECLCALLBACK(int) dbgcHlpVBoxError(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, ...)
317{
318 va_list args;
319 va_start(args, pszFormat);
320 int rcRet = pCmdHlp->pfnVBoxErrorV(pCmdHlp, rc, pszFormat, args);
321 va_end(args);
322 return rcRet;
323}
324
325
326/**
327 * @interface_method_impl{DBGCCMDHLP,pfnMemRead}
328 */
329static DECLCALLBACK(int) dbgcHlpMemRead(PDBGCCMDHLP pCmdHlp, void *pvBuffer, size_t cbRead, PCDBGCVAR pVarPointer, size_t *pcbRead)
330{
331 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
332 DBGFADDRESS Address;
333 int rc;
334
335 /*
336 * Dummy check.
337 */
338 if (cbRead == 0)
339 {
340 if (*pcbRead)
341 *pcbRead = 0;
342 return VINF_SUCCESS;
343 }
344
345 /*
346 * Convert Far addresses getting size and the correct base address.
347 * Getting and checking the size is what makes this messy and slow.
348 */
349 DBGCVAR Var = *pVarPointer;
350 switch (pVarPointer->enmType)
351 {
352 case DBGCVAR_TYPE_GC_FAR:
353 /* Use DBGFR3AddrFromSelOff for the conversion. */
354 Assert(pDbgc->pUVM);
355 rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, Var.u.GCFar.sel, Var.u.GCFar.off);
356 if (RT_FAILURE(rc))
357 return rc;
358
359 /* don't bother with flat selectors (for now). */
360 if (!DBGFADDRESS_IS_FLAT(&Address))
361 {
362 DBGFSELINFO SelInfo;
363 rc = DBGFR3SelQueryInfo(pDbgc->pUVM, pDbgc->idCpu, Address.Sel,
364 DBGFSELQI_FLAGS_DT_GUEST | DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE, &SelInfo);
365 if (RT_SUCCESS(rc))
366 {
367 RTGCUINTPTR cb; /* -1 byte */
368 if (DBGFSelInfoIsExpandDown(&SelInfo))
369 {
370 if ( !SelInfo.u.Raw.Gen.u1Granularity
371 && Address.off > UINT16_C(0xffff))
372 return VERR_OUT_OF_SELECTOR_BOUNDS;
373 if (Address.off <= SelInfo.cbLimit)
374 return VERR_OUT_OF_SELECTOR_BOUNDS;
375 cb = (SelInfo.u.Raw.Gen.u1Granularity ? UINT32_C(0xffffffff) : UINT32_C(0xffff)) - Address.off;
376 }
377 else
378 {
379 if (Address.off > SelInfo.cbLimit)
380 return VERR_OUT_OF_SELECTOR_BOUNDS;
381 cb = SelInfo.cbLimit - Address.off;
382 }
383 if (cbRead - 1 > cb)
384 {
385 if (!pcbRead)
386 return VERR_OUT_OF_SELECTOR_BOUNDS;
387 cbRead = cb + 1;
388 }
389 }
390 }
391 Var.enmType = DBGCVAR_TYPE_GC_FLAT;
392 Var.u.GCFlat = Address.FlatPtr;
393 break;
394
395 case DBGCVAR_TYPE_GC_FLAT:
396 case DBGCVAR_TYPE_GC_PHYS:
397 case DBGCVAR_TYPE_HC_FLAT:
398 case DBGCVAR_TYPE_HC_PHYS:
399 break;
400
401 default:
402 return VERR_NOT_IMPLEMENTED;
403 }
404
405
406
407 /*
408 * Copy page by page.
409 */
410 size_t cbLeft = cbRead;
411 for (;;)
412 {
413 /*
414 * Calc read size.
415 */
416 size_t cb = RT_MIN(PAGE_SIZE, cbLeft);
417 switch (pVarPointer->enmType)
418 {
419 case DBGCVAR_TYPE_GC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCFlat & PAGE_OFFSET_MASK)); break;
420 case DBGCVAR_TYPE_GC_PHYS: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCPhys & PAGE_OFFSET_MASK)); break;
421 case DBGCVAR_TYPE_HC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - ((uintptr_t)Var.u.pvHCFlat & PAGE_OFFSET_MASK)); break;
422 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! */
423 default: break;
424 }
425
426 /*
427 * Perform read.
428 */
429 switch (Var.enmType)
430 {
431 case DBGCVAR_TYPE_GC_FLAT:
432 rc = DBGFR3MemRead(pDbgc->pUVM, pDbgc->idCpu,
433 DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, Var.u.GCFlat),
434 pvBuffer, cb);
435 break;
436
437 case DBGCVAR_TYPE_GC_PHYS:
438 rc = DBGFR3MemRead(pDbgc->pUVM, pDbgc->idCpu,
439 DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, Var.u.GCPhys),
440 pvBuffer, cb);
441 break;
442
443 case DBGCVAR_TYPE_HC_PHYS:
444 {
445 DBGCVAR Var2;
446 rc = dbgcOpAddrFlat(pDbgc, &Var, DBGCVAR_CAT_ANY, &Var2);
447 if (RT_SUCCESS(rc))
448 {
449 memcpy(pvBuffer, Var2.u.pvHCFlat, cb);
450 rc = VINF_SUCCESS;
451 }
452 else
453 rc = VERR_INVALID_POINTER;
454 break;
455 }
456
457 case DBGCVAR_TYPE_HC_FLAT:
458 rc = VERR_NOT_SUPPORTED;
459 break;
460
461 default:
462 rc = VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
463 }
464
465 /*
466 * Check for failure.
467 */
468 if (RT_FAILURE(rc))
469 {
470 if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0)
471 return VINF_SUCCESS;
472 return rc;
473 }
474
475 /*
476 * Next.
477 */
478 cbLeft -= cb;
479 if (!cbLeft)
480 break;
481 pvBuffer = (char *)pvBuffer + cb;
482 rc = DBGCCmdHlpEval(pCmdHlp, &Var, "%DV + %#zx", &Var, cb);
483 if (RT_FAILURE(rc))
484 {
485 if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0)
486 return VINF_SUCCESS;
487 return rc;
488 }
489 }
490
491 /*
492 * Done
493 */
494 if (pcbRead)
495 *pcbRead = cbRead;
496 return 0;
497}
498
499
500/**
501 * @interface_method_impl{DBGCCMDHLP,pfnMemWrite}
502 */
503static DECLCALLBACK(int) dbgcHlpMemWrite(PDBGCCMDHLP pCmdHlp, const void *pvBuffer, size_t cbWrite, PCDBGCVAR pVarPointer, size_t *pcbWritten)
504{
505 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
506 DBGFADDRESS Address;
507 int rc;
508
509 /*
510 * Dummy check.
511 */
512 if (cbWrite == 0)
513 {
514 if (*pcbWritten)
515 *pcbWritten = 0;
516 return VINF_SUCCESS;
517 }
518
519 /*
520 * Convert Far addresses getting size and the correct base address.
521 * Getting and checking the size is what makes this messy and slow.
522 */
523 DBGCVAR Var = *pVarPointer;
524 switch (pVarPointer->enmType)
525 {
526 case DBGCVAR_TYPE_GC_FAR:
527 {
528 /* Use DBGFR3AddrFromSelOff for the conversion. */
529 Assert(pDbgc->pUVM);
530 rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, Var.u.GCFar.sel, Var.u.GCFar.off);
531 if (RT_FAILURE(rc))
532 return rc;
533
534 /* don't bother with flat selectors (for now). */
535 if (!DBGFADDRESS_IS_FLAT(&Address))
536 {
537 DBGFSELINFO SelInfo;
538 rc = DBGFR3SelQueryInfo(pDbgc->pUVM, pDbgc->idCpu, Address.Sel,
539 DBGFSELQI_FLAGS_DT_GUEST | DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE, &SelInfo);
540 if (RT_SUCCESS(rc))
541 {
542 RTGCUINTPTR cb; /* -1 byte */
543 if (DBGFSelInfoIsExpandDown(&SelInfo))
544 {
545 if ( !SelInfo.u.Raw.Gen.u1Granularity
546 && Address.off > UINT16_C(0xffff))
547 return VERR_OUT_OF_SELECTOR_BOUNDS;
548 if (Address.off <= SelInfo.cbLimit)
549 return VERR_OUT_OF_SELECTOR_BOUNDS;
550 cb = (SelInfo.u.Raw.Gen.u1Granularity ? UINT32_C(0xffffffff) : UINT32_C(0xffff)) - Address.off;
551 }
552 else
553 {
554 if (Address.off > SelInfo.cbLimit)
555 return VERR_OUT_OF_SELECTOR_BOUNDS;
556 cb = SelInfo.cbLimit - Address.off;
557 }
558 if (cbWrite - 1 > cb)
559 {
560 if (!pcbWritten)
561 return VERR_OUT_OF_SELECTOR_BOUNDS;
562 cbWrite = cb + 1;
563 }
564 }
565 }
566 Var.enmType = DBGCVAR_TYPE_GC_FLAT;
567 Var.u.GCFlat = Address.FlatPtr;
568 }
569 RT_FALL_THRU();
570 case DBGCVAR_TYPE_GC_FLAT:
571 rc = DBGFR3MemWrite(pDbgc->pUVM, pDbgc->idCpu,
572 DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, Var.u.GCFlat),
573 pvBuffer, cbWrite);
574 if (pcbWritten && RT_SUCCESS(rc))
575 *pcbWritten = cbWrite;
576 return rc;
577
578 case DBGCVAR_TYPE_GC_PHYS:
579 rc = DBGFR3MemWrite(pDbgc->pUVM, pDbgc->idCpu,
580 DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, Var.u.GCPhys),
581 pvBuffer, cbWrite);
582 if (pcbWritten && RT_SUCCESS(rc))
583 *pcbWritten = cbWrite;
584 return rc;
585
586 case DBGCVAR_TYPE_HC_PHYS:
587 {
588 /*
589 * Copy HC memory page by page.
590 */
591 if (pcbWritten)
592 *pcbWritten = 0;
593 while (cbWrite > 0)
594 {
595 /* convert to flat address */
596 DBGCVAR Var2;
597 rc = dbgcOpAddrFlat(pDbgc, &Var, DBGCVAR_CAT_ANY, &Var2);
598 if (RT_FAILURE(rc))
599 {
600 if (pcbWritten && *pcbWritten)
601 return -VERR_INVALID_POINTER;
602 return VERR_INVALID_POINTER;
603 }
604
605 /* calc size. */
606 size_t cbChunk = PAGE_SIZE;
607 cbChunk -= (uintptr_t)Var.u.pvHCFlat & PAGE_OFFSET_MASK;
608 if (cbChunk > cbWrite)
609 cbChunk = cbWrite;
610
611 memcpy(Var2.u.pvHCFlat, pvBuffer, cbChunk);
612
613 /* advance */
614 if (Var.enmType == DBGCVAR_TYPE_HC_FLAT)
615 Var.u.pvHCFlat = (uint8_t *)Var.u.pvHCFlat + cbChunk;
616 else
617 Var.u.HCPhys += cbChunk;
618 pvBuffer = (uint8_t const *)pvBuffer + cbChunk;
619 if (pcbWritten)
620 *pcbWritten += cbChunk;
621 cbWrite -= cbChunk;
622 }
623
624 return VINF_SUCCESS;
625 }
626
627 case DBGCVAR_TYPE_HC_FLAT:
628 return VERR_NOT_SUPPORTED;
629
630 default:
631 return VERR_NOT_IMPLEMENTED;
632 }
633}
634
635
636/**
637 * @interface_method_impl{DBGCCMDHLP,pfnExec}
638 */
639static DECLCALLBACK(int) dbgcHlpExec(PDBGCCMDHLP pCmdHlp, const char *pszExpr, ...)
640{
641 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
642 /* Save the scratch state. */
643 char *pszScratch = pDbgc->pszScratch;
644 unsigned iArg = pDbgc->iArg;
645
646 /*
647 * Format the expression.
648 */
649 va_list args;
650 va_start(args, pszExpr);
651 size_t cbScratch = sizeof(pDbgc->achScratch) - (pDbgc->pszScratch - &pDbgc->achScratch[0]);
652 size_t cb = RTStrPrintfExV(dbgcStringFormatter, pDbgc, pDbgc->pszScratch, cbScratch, pszExpr, args);
653 va_end(args);
654 if (cb >= cbScratch)
655 return VERR_BUFFER_OVERFLOW;
656
657 /*
658 * Execute the command.
659 * We save and restore the arg index and scratch buffer pointer.
660 */
661 pDbgc->pszScratch = pDbgc->pszScratch + cb + 1;
662 int rc = dbgcEvalCommand(pDbgc, pszScratch, cb, false /* fNoExecute */);
663
664 /* Restore the scratch state. */
665 pDbgc->iArg = iArg;
666 pDbgc->pszScratch = pszScratch;
667
668 return rc;
669}
670
671
672/**
673 * @interface_method_impl{DBGCCMDHLP,pfnEvalV}
674 */
675static DECLCALLBACK(int) dbgcHlpEvalV(PDBGCCMDHLP pCmdHlp, PDBGCVAR pResult, const char *pszExpr, va_list va)
676{
677 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
678
679 /*
680 * Format the expression.
681 */
682 char szExprFormatted[2048];
683 size_t cb = RTStrPrintfExV(dbgcStringFormatter, pDbgc, szExprFormatted, sizeof(szExprFormatted), pszExpr, va);
684 /* ignore overflows. */
685
686 return dbgcEvalSub(pDbgc, &szExprFormatted[0], cb, DBGCVAR_CAT_ANY, pResult);
687}
688
689
690/**
691 * @interface_method_impl{DBGCCMDHLP,pfnFailV}
692 */
693static DECLCALLBACK(int) dbgcHlpFailV(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, const char *pszFormat, va_list va)
694{
695 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
696
697 /*
698 * Do the formatting and output.
699 */
700 pDbgc->rcOutput = VINF_SUCCESS;
701 RTStrFormat(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, "%s: error: ", pCmd->pszCmd);
702 if (RT_FAILURE(pDbgc->rcOutput))
703 return pDbgc->rcOutput;
704 RTStrFormatV(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, pszFormat, va);
705 if (RT_FAILURE(pDbgc->rcOutput))
706 return pDbgc->rcOutput;
707 if (pDbgc->chLastOutput != '\n')
708 dbgcFormatOutput(pDbgc, "\n", 1);
709 return VERR_DBGC_COMMAND_FAILED;
710}
711
712
713/**
714 * @interface_method_impl{DBGCCMDHLP,pfnFailRcV}
715 */
716static DECLCALLBACK(int) dbgcHlpFailRcV(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int rc, const char *pszFormat, va_list va)
717{
718 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
719
720 /*
721 * Do the formatting and output.
722 */
723 pDbgc->rcOutput = VINF_SUCCESS;
724 RTStrFormat(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, "%s: error: ", pCmd->pszCmd);
725 if (RT_FAILURE(pDbgc->rcOutput))
726 return pDbgc->rcOutput;
727 RTStrFormatV(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, pszFormat, va);
728 if (RT_FAILURE(pDbgc->rcOutput))
729 return pDbgc->rcOutput;
730 RTStrFormat(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, ": %Rrc\n", rc);
731 if (RT_FAILURE(pDbgc->rcOutput))
732 return pDbgc->rcOutput;
733
734 return VERR_DBGC_COMMAND_FAILED;
735}
736
737
738/**
739 * @interface_method_impl{DBGCCMDHLP,pfnParserError}
740 */
741static DECLCALLBACK(int) dbgcHlpParserError(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int iArg, const char *pszExpr, unsigned iLine)
742{
743 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
744
745 /*
746 * Do the formatting and output.
747 */
748 pDbgc->rcOutput = VINF_SUCCESS;
749 RTStrFormat(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, "%s: parser error: iArg=%d iLine=%u pszExpr=%s\n",
750 pCmd->pszCmd, iArg, iLine, pszExpr);
751 if (RT_FAILURE(pDbgc->rcOutput))
752 return pDbgc->rcOutput;
753 return VERR_DBGC_COMMAND_FAILED;
754}
755
756
757/**
758 * @interface_method_impl{DBGCCMDHLP,pfnVarToDbgfAddr}
759 */
760static DECLCALLBACK(int) dbgcHlpVarToDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PDBGFADDRESS pAddress)
761{
762 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
763 AssertPtr(pVar);
764 AssertPtr(pAddress);
765
766 switch (pVar->enmType)
767 {
768 case DBGCVAR_TYPE_GC_FLAT:
769 DBGFR3AddrFromFlat(pDbgc->pUVM, pAddress, pVar->u.GCFlat);
770 return VINF_SUCCESS;
771
772 case DBGCVAR_TYPE_NUMBER:
773 DBGFR3AddrFromFlat(pDbgc->pUVM, pAddress, (RTGCUINTPTR)pVar->u.u64Number);
774 return VINF_SUCCESS;
775
776 case DBGCVAR_TYPE_GC_FAR:
777 return DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, pAddress, pVar->u.GCFar.sel, pVar->u.GCFar.off);
778
779 case DBGCVAR_TYPE_GC_PHYS:
780 DBGFR3AddrFromPhys(pDbgc->pUVM, pAddress, pVar->u.GCPhys);
781 return VINF_SUCCESS;
782
783 case DBGCVAR_TYPE_SYMBOL:
784 {
785 DBGCVAR Var;
786 int rc = DBGCCmdHlpEval(&pDbgc->CmdHlp, &Var, "%%(%DV)", pVar);
787 if (RT_FAILURE(rc))
788 return rc;
789 return dbgcHlpVarToDbgfAddr(pCmdHlp, &Var, pAddress);
790 }
791
792 case DBGCVAR_TYPE_STRING:
793 case DBGCVAR_TYPE_HC_FLAT:
794 case DBGCVAR_TYPE_HC_PHYS:
795 default:
796 return VERR_DBGC_PARSE_CONVERSION_FAILED;
797 }
798}
799
800
801/**
802 * @interface_method_impl{DBGCCMDHLP,pfnVarFromDbgfAddr}
803 */
804static DECLCALLBACK(int) dbgcHlpVarFromDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGFADDRESS pAddress, PDBGCVAR pResult)
805{
806 RT_NOREF1(pCmdHlp);
807 AssertPtrReturn(pAddress, VERR_INVALID_POINTER);
808 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
809 AssertPtrReturn(pResult, VERR_INVALID_POINTER);
810
811 switch (pAddress->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK)
812 {
813 case DBGFADDRESS_FLAGS_FAR16:
814 case DBGFADDRESS_FLAGS_FAR32:
815 case DBGFADDRESS_FLAGS_FAR64:
816 DBGCVAR_INIT_GC_FAR(pResult, pAddress->Sel, pAddress->off);
817 break;
818
819 case DBGFADDRESS_FLAGS_FLAT:
820 DBGCVAR_INIT_GC_FLAT(pResult, pAddress->FlatPtr);
821 break;
822
823 case DBGFADDRESS_FLAGS_PHYS:
824 DBGCVAR_INIT_GC_PHYS(pResult, pAddress->FlatPtr);
825 break;
826
827 default:
828 DBGCVAR_INIT(pResult);
829 AssertMsgFailedReturn(("%#x\n", pAddress->fFlags), VERR_INVALID_PARAMETER);
830 break;
831 }
832
833 return VINF_SUCCESS;
834}
835
836
837/**
838 * @interface_method_impl{DBGCCMDHLP,pfnVarToNumber}
839 */
840static DECLCALLBACK(int) dbgcHlpVarToNumber(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t *pu64Number)
841{
842 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
843 NOREF(pDbgc);
844
845 uint64_t u64Number;
846 switch (pVar->enmType)
847 {
848 case DBGCVAR_TYPE_GC_FLAT:
849 u64Number = pVar->u.GCFlat;
850 break;
851 case DBGCVAR_TYPE_GC_PHYS:
852 u64Number = pVar->u.GCPhys;
853 break;
854 case DBGCVAR_TYPE_HC_FLAT:
855 u64Number = (uintptr_t)pVar->u.pvHCFlat;
856 break;
857 case DBGCVAR_TYPE_HC_PHYS:
858 u64Number = (uintptr_t)pVar->u.HCPhys;
859 break;
860 case DBGCVAR_TYPE_NUMBER:
861 u64Number = (uintptr_t)pVar->u.u64Number;
862 break;
863 case DBGCVAR_TYPE_GC_FAR:
864 u64Number = (uintptr_t)pVar->u.GCFar.off;
865 break;
866 case DBGCVAR_TYPE_SYMBOL:
867 /** @todo try convert as symbol? */
868 case DBGCVAR_TYPE_STRING:
869 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; /** @todo better error code! */
870 default:
871 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
872 }
873 *pu64Number = u64Number;
874 return VINF_SUCCESS;
875}
876
877
878/**
879 * @interface_method_impl{DBGCCMDHLP,pfnVarToBool}
880 */
881static DECLCALLBACK(int) dbgcHlpVarToBool(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, bool *pf)
882{
883 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
884 NOREF(pDbgc);
885
886 switch (pVar->enmType)
887 {
888 case DBGCVAR_TYPE_SYMBOL:
889 case DBGCVAR_TYPE_STRING:
890 if ( !RTStrICmp(pVar->u.pszString, "true")
891 || !RTStrICmp(pVar->u.pszString, "on")
892 || !RTStrICmp(pVar->u.pszString, "no")
893 || !RTStrICmp(pVar->u.pszString, "enabled"))
894 {
895 *pf = true;
896 return VINF_SUCCESS;
897 }
898 if ( !RTStrICmp(pVar->u.pszString, "false")
899 || !RTStrICmp(pVar->u.pszString, "off")
900 || !RTStrICmp(pVar->u.pszString, "yes")
901 || !RTStrICmp(pVar->u.pszString, "disabled"))
902 {
903 *pf = false;
904 return VINF_SUCCESS;
905 }
906 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; /** @todo better error code! */
907
908 case DBGCVAR_TYPE_GC_FLAT:
909 case DBGCVAR_TYPE_GC_PHYS:
910 case DBGCVAR_TYPE_HC_FLAT:
911 case DBGCVAR_TYPE_HC_PHYS:
912 case DBGCVAR_TYPE_NUMBER:
913 *pf = pVar->u.u64Number != 0;
914 return VINF_SUCCESS;
915
916 case DBGCVAR_TYPE_GC_FAR:
917 default:
918 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
919 }
920}
921
922
923/**
924 * @interface_method_impl{DBGCCMDHLP,pfnVarGetRange}
925 */
926static DECLCALLBACK(int) dbgcHlpVarGetRange(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t cbElement, uint64_t cbDefault,
927 uint64_t *pcbRange)
928{
929 RT_NOREF1(pCmdHlp);
930/** @todo implement this properly, strings/symbols are not resolved now. */
931 switch (pVar->enmRangeType)
932 {
933 default:
934 case DBGCVAR_RANGE_NONE:
935 *pcbRange = cbDefault;
936 break;
937 case DBGCVAR_RANGE_BYTES:
938 *pcbRange = pVar->u64Range;
939 break;
940 case DBGCVAR_RANGE_ELEMENTS:
941 *pcbRange = pVar->u64Range * cbElement;
942 break;
943 }
944 return VINF_SUCCESS;
945}
946
947
948/**
949 * @interface_method_impl{DBGCCMDHLP,pfnVarConvert}
950 */
951static DECLCALLBACK(int) dbgcHlpVarConvert(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, DBGCVARTYPE enmToType, bool fConvSyms,
952 PDBGCVAR pResult)
953{
954 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
955 DBGCVAR const InVar = *pVar; /* if pVar == pResult */
956 PCDBGCVAR pArg = &InVar; /* lazy bird, clean up later */
957 DBGFADDRESS Address;
958 int rc;
959
960 Assert(pDbgc->pUVM);
961
962 *pResult = InVar;
963 switch (InVar.enmType)
964 {
965 case DBGCVAR_TYPE_GC_FLAT:
966 switch (enmToType)
967 {
968 case DBGCVAR_TYPE_GC_FLAT:
969 return VINF_SUCCESS;
970
971 case DBGCVAR_TYPE_GC_FAR:
972 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
973
974 case DBGCVAR_TYPE_GC_PHYS:
975 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
976 rc = DBGFR3AddrToPhys(pDbgc->pUVM, pDbgc->idCpu,
977 DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat),
978 &pResult->u.GCPhys);
979 if (RT_SUCCESS(rc))
980 return VINF_SUCCESS;
981 return VERR_DBGC_PARSE_CONVERSION_FAILED;
982
983 case DBGCVAR_TYPE_HC_FLAT:
984 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
985 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu,
986 DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat),
987 false /*fReadOnly */,
988 &pResult->u.pvHCFlat);
989 if (RT_SUCCESS(rc))
990 return VINF_SUCCESS;
991 return VERR_DBGC_PARSE_CONVERSION_FAILED;
992
993 case DBGCVAR_TYPE_HC_PHYS:
994 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
995 rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu,
996 DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat),
997 &pResult->u.GCPhys);
998 if (RT_SUCCESS(rc))
999 return VINF_SUCCESS;
1000 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1001
1002 case DBGCVAR_TYPE_NUMBER:
1003 pResult->enmType = enmToType;
1004 pResult->u.u64Number = InVar.u.GCFlat;
1005 return VINF_SUCCESS;
1006
1007 case DBGCVAR_TYPE_STRING:
1008 case DBGCVAR_TYPE_SYMBOL:
1009 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1010
1011 case DBGCVAR_TYPE_UNKNOWN:
1012 case DBGCVAR_TYPE_ANY:
1013 break;
1014 }
1015 break;
1016
1017 case DBGCVAR_TYPE_GC_FAR:
1018 switch (enmToType)
1019 {
1020 case DBGCVAR_TYPE_GC_FLAT:
1021 rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
1022 if (RT_SUCCESS(rc))
1023 {
1024 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
1025 pResult->u.GCFlat = Address.FlatPtr;
1026 return VINF_SUCCESS;
1027 }
1028 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1029
1030 case DBGCVAR_TYPE_GC_FAR:
1031 return VINF_SUCCESS;
1032
1033 case DBGCVAR_TYPE_GC_PHYS:
1034 rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
1035 if (RT_SUCCESS(rc))
1036 {
1037 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1038 rc = DBGFR3AddrToPhys(pDbgc->pUVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
1039 if (RT_SUCCESS(rc))
1040 return VINF_SUCCESS;
1041 }
1042 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1043
1044 case DBGCVAR_TYPE_HC_FLAT:
1045 rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
1046 if (RT_SUCCESS(rc))
1047 {
1048 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
1049 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu, &Address,
1050 false /*fReadOnly*/, &pResult->u.pvHCFlat);
1051 if (RT_SUCCESS(rc))
1052 return VINF_SUCCESS;
1053 }
1054 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1055
1056 case DBGCVAR_TYPE_HC_PHYS:
1057 rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
1058 if (RT_SUCCESS(rc))
1059 {
1060 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1061 rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
1062 if (RT_SUCCESS(rc))
1063 return VINF_SUCCESS;
1064 }
1065 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1066
1067 case DBGCVAR_TYPE_NUMBER:
1068 pResult->enmType = enmToType;
1069 pResult->u.u64Number = InVar.u.GCFar.off;
1070 return VINF_SUCCESS;
1071
1072 case DBGCVAR_TYPE_STRING:
1073 case DBGCVAR_TYPE_SYMBOL:
1074 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1075
1076 case DBGCVAR_TYPE_UNKNOWN:
1077 case DBGCVAR_TYPE_ANY:
1078 break;
1079 }
1080 break;
1081
1082 case DBGCVAR_TYPE_GC_PHYS:
1083 switch (enmToType)
1084 {
1085 case DBGCVAR_TYPE_GC_FLAT:
1086 //rc = MMR3PhysGCPhys2GCVirtEx(pDbgc->pVM, pResult->u.GCPhys, ..., &pResult->u.GCFlat); - yea, sure.
1087 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1088
1089 case DBGCVAR_TYPE_GC_FAR:
1090 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1091
1092 case DBGCVAR_TYPE_GC_PHYS:
1093 return VINF_SUCCESS;
1094
1095 case DBGCVAR_TYPE_HC_FLAT:
1096 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
1097 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu,
1098 DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, pArg->u.GCPhys),
1099 false /*fReadOnly */,
1100 &pResult->u.pvHCFlat);
1101 if (RT_SUCCESS(rc))
1102 return VINF_SUCCESS;
1103 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1104
1105 case DBGCVAR_TYPE_HC_PHYS:
1106 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1107 rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu,
1108 DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, pArg->u.GCPhys),
1109 &pResult->u.HCPhys);
1110 if (RT_SUCCESS(rc))
1111 return VINF_SUCCESS;
1112 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1113
1114 case DBGCVAR_TYPE_NUMBER:
1115 pResult->enmType = enmToType;
1116 pResult->u.u64Number = InVar.u.GCPhys;
1117 return VINF_SUCCESS;
1118
1119 case DBGCVAR_TYPE_STRING:
1120 case DBGCVAR_TYPE_SYMBOL:
1121 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1122
1123 case DBGCVAR_TYPE_UNKNOWN:
1124 case DBGCVAR_TYPE_ANY:
1125 break;
1126 }
1127 break;
1128
1129 case DBGCVAR_TYPE_HC_FLAT:
1130 switch (enmToType)
1131 {
1132 case DBGCVAR_TYPE_GC_FLAT:
1133 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1134
1135 case DBGCVAR_TYPE_GC_FAR:
1136 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1137
1138 case DBGCVAR_TYPE_GC_PHYS:
1139 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1140 rc = PGMR3DbgR3Ptr2GCPhys(pDbgc->pUVM, pArg->u.pvHCFlat, &pResult->u.GCPhys);
1141 if (RT_SUCCESS(rc))
1142 return VINF_SUCCESS;
1143 /** @todo more memory types! */
1144 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1145
1146 case DBGCVAR_TYPE_HC_FLAT:
1147 return VINF_SUCCESS;
1148
1149 case DBGCVAR_TYPE_HC_PHYS:
1150 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1151 rc = PGMR3DbgR3Ptr2HCPhys(pDbgc->pUVM, pArg->u.pvHCFlat, &pResult->u.HCPhys);
1152 if (RT_SUCCESS(rc))
1153 return VINF_SUCCESS;
1154 /** @todo more memory types! */
1155 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1156
1157 case DBGCVAR_TYPE_NUMBER:
1158 pResult->enmType = enmToType;
1159 pResult->u.u64Number = (uintptr_t)InVar.u.pvHCFlat;
1160 return VINF_SUCCESS;
1161
1162 case DBGCVAR_TYPE_STRING:
1163 case DBGCVAR_TYPE_SYMBOL:
1164 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1165
1166 case DBGCVAR_TYPE_UNKNOWN:
1167 case DBGCVAR_TYPE_ANY:
1168 break;
1169 }
1170 break;
1171
1172 case DBGCVAR_TYPE_HC_PHYS:
1173 switch (enmToType)
1174 {
1175 case DBGCVAR_TYPE_GC_FLAT:
1176 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1177
1178 case DBGCVAR_TYPE_GC_FAR:
1179 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1180
1181 case DBGCVAR_TYPE_GC_PHYS:
1182 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1183 rc = PGMR3DbgHCPhys2GCPhys(pDbgc->pUVM, pArg->u.HCPhys, &pResult->u.GCPhys);
1184 if (RT_SUCCESS(rc))
1185 return VINF_SUCCESS;
1186 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1187
1188 case DBGCVAR_TYPE_HC_FLAT:
1189 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1190
1191 case DBGCVAR_TYPE_HC_PHYS:
1192 return VINF_SUCCESS;
1193
1194 case DBGCVAR_TYPE_NUMBER:
1195 pResult->enmType = enmToType;
1196 pResult->u.u64Number = InVar.u.HCPhys;
1197 return VINF_SUCCESS;
1198
1199 case DBGCVAR_TYPE_STRING:
1200 case DBGCVAR_TYPE_SYMBOL:
1201 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1202
1203 case DBGCVAR_TYPE_UNKNOWN:
1204 case DBGCVAR_TYPE_ANY:
1205 break;
1206 }
1207 break;
1208
1209 case DBGCVAR_TYPE_NUMBER:
1210 switch (enmToType)
1211 {
1212 case DBGCVAR_TYPE_GC_FLAT:
1213 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
1214 pResult->u.GCFlat = (RTGCPTR)InVar.u.u64Number;
1215 return VINF_SUCCESS;
1216
1217 case DBGCVAR_TYPE_GC_FAR:
1218 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1219
1220 case DBGCVAR_TYPE_GC_PHYS:
1221 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1222 pResult->u.GCPhys = (RTGCPHYS)InVar.u.u64Number;
1223 return VINF_SUCCESS;
1224
1225 case DBGCVAR_TYPE_HC_FLAT:
1226 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
1227 pResult->u.pvHCFlat = (void *)(uintptr_t)InVar.u.u64Number;
1228 return VINF_SUCCESS;
1229
1230 case DBGCVAR_TYPE_HC_PHYS:
1231 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1232 pResult->u.HCPhys = (RTHCPHYS)InVar.u.u64Number;
1233 return VINF_SUCCESS;
1234
1235 case DBGCVAR_TYPE_NUMBER:
1236 return VINF_SUCCESS;
1237
1238 case DBGCVAR_TYPE_STRING:
1239 case DBGCVAR_TYPE_SYMBOL:
1240 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1241
1242 case DBGCVAR_TYPE_UNKNOWN:
1243 case DBGCVAR_TYPE_ANY:
1244 break;
1245 }
1246 break;
1247
1248 case DBGCVAR_TYPE_SYMBOL:
1249 case DBGCVAR_TYPE_STRING:
1250 switch (enmToType)
1251 {
1252 case DBGCVAR_TYPE_GC_FLAT:
1253 case DBGCVAR_TYPE_GC_FAR:
1254 case DBGCVAR_TYPE_GC_PHYS:
1255 case DBGCVAR_TYPE_HC_FLAT:
1256 case DBGCVAR_TYPE_HC_PHYS:
1257 case DBGCVAR_TYPE_NUMBER:
1258 if (fConvSyms)
1259 {
1260 rc = dbgcSymbolGet(pDbgc, InVar.u.pszString, enmToType, pResult);
1261 if (RT_SUCCESS(rc))
1262 return VINF_SUCCESS;
1263 }
1264 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1265
1266 case DBGCVAR_TYPE_STRING:
1267 case DBGCVAR_TYPE_SYMBOL:
1268 pResult->enmType = enmToType;
1269 return VINF_SUCCESS;
1270
1271 case DBGCVAR_TYPE_UNKNOWN:
1272 case DBGCVAR_TYPE_ANY:
1273 break;
1274 }
1275 break;
1276
1277 case DBGCVAR_TYPE_UNKNOWN:
1278 case DBGCVAR_TYPE_ANY:
1279 break;
1280 }
1281
1282 AssertMsgFailed(("f=%d t=%d\n", InVar.enmType, enmToType));
1283 return VERR_INVALID_PARAMETER;
1284}
1285
1286
1287/**
1288 * @interface_method_impl{DBGFINFOHLP,pfnPrintf}
1289 */
1290static DECLCALLBACK(void) dbgcHlpGetDbgfOutputHlp_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
1291{
1292 PDBGC pDbgc = RT_FROM_MEMBER(pHlp, DBGC, DbgfOutputHlp);
1293 va_list va;
1294 va_start(va, pszFormat);
1295 pDbgc->CmdHlp.pfnPrintfV(&pDbgc->CmdHlp, NULL, pszFormat, va);
1296 va_end(va);
1297}
1298
1299
1300/**
1301 * @interface_method_impl{DBGFINFOHLP,pfnPrintfV}
1302 */
1303static DECLCALLBACK(void) dbgcHlpGetDbgfOutputHlp_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
1304{
1305 PDBGC pDbgc = RT_FROM_MEMBER(pHlp, DBGC, DbgfOutputHlp);
1306 pDbgc->CmdHlp.pfnPrintfV(&pDbgc->CmdHlp, NULL, pszFormat, args);
1307}
1308
1309
1310/**
1311 * @interface_method_impl{DBGCCMDHLP,pfnGetDbgfOutputHlp}
1312 */
1313static DECLCALLBACK(PCDBGFINFOHLP) dbgcHlpGetDbgfOutputHlp(PDBGCCMDHLP pCmdHlp)
1314{
1315 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
1316
1317 /* Lazy init */
1318 if (!pDbgc->DbgfOutputHlp.pfnPrintf)
1319 {
1320 pDbgc->DbgfOutputHlp.pfnPrintf = dbgcHlpGetDbgfOutputHlp_Printf;
1321 pDbgc->DbgfOutputHlp.pfnPrintfV = dbgcHlpGetDbgfOutputHlp_PrintfV;
1322 pDbgc->DbgfOutputHlp.pfnGetOptError = DBGFR3InfoGenericGetOptError;
1323 }
1324
1325 return &pDbgc->DbgfOutputHlp;
1326}
1327
1328
1329/**
1330 * @interface_method_impl{DBGCCMDHLP,pfnGetCurrentCpu}
1331 */
1332static DECLCALLBACK(VMCPUID) dbgcHlpGetCurrentCpu(PDBGCCMDHLP pCmdHlp)
1333{
1334 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
1335 return pDbgc->idCpu;
1336}
1337
1338
1339/**
1340 * @interface_method_impl{DBGCCMDHLP,pfnGetCpuMode}
1341 */
1342static DECLCALLBACK(CPUMMODE) dbgcHlpGetCpuMode(PDBGCCMDHLP pCmdHlp)
1343{
1344 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
1345 CPUMMODE enmMode = CPUMMODE_INVALID;
1346 if (pDbgc->pUVM)
1347 enmMode = DBGFR3CpuGetMode(pDbgc->pUVM, DBGCCmdHlpGetCurrentCpu(pCmdHlp));
1348 if (enmMode == CPUMMODE_INVALID)
1349#if HC_ARCH_BITS == 64
1350 enmMode = CPUMMODE_LONG;
1351#else
1352 enmMode = CPUMMODE_PROTECTED;
1353#endif
1354 return enmMode;
1355}
1356
1357
1358/**
1359 * @interface_method_impl{DBGCCMDHLP,pfnRegPrintf}
1360 */
1361static DECLCALLBACK(int) dbgcHlpRegPrintf(PDBGCCMDHLP pCmdHlp, VMCPUID idCpu, int f64BitMode, bool fTerse)
1362{
1363 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
1364 char szDisAndRegs[8192];
1365 int rc;
1366
1367 if (f64BitMode < 0)
1368 f64BitMode = DBGFR3CpuIsIn64BitCode(pDbgc->pUVM, idCpu);
1369
1370 if (fTerse)
1371 {
1372 if (f64BitMode)
1373 rc = DBGFR3RegPrintf(pDbgc->pUVM, idCpu, &szDisAndRegs[0], sizeof(szDisAndRegs),
1374 "u %016VR{rip} L 0\n"
1375 "rax=%016VR{rax} rbx=%016VR{rbx} rcx=%016VR{rcx} rdx=%016VR{rdx}\n"
1376 "rsi=%016VR{rsi} rdi=%016VR{rdi} r8 =%016VR{r8} r9 =%016VR{r9}\n"
1377 "r10=%016VR{r10} r11=%016VR{r11} r12=%016VR{r12} r13=%016VR{r13}\n"
1378 "r14=%016VR{r14} r15=%016VR{r15} %VRF{rflags}\n"
1379 "rip=%016VR{rip} rsp=%016VR{rsp} rbp=%016VR{rbp}\n"
1380 "cs=%04VR{cs} ds=%04VR{ds} es=%04VR{es} fs=%04VR{fs} gs=%04VR{gs} ss=%04VR{ss} rflags=%08VR{rflags}\n");
1381 else
1382 rc = DBGFR3RegPrintf(pDbgc->pUVM, idCpu, szDisAndRegs, sizeof(szDisAndRegs),
1383 "u %04VR{cs}:%08VR{eip} L 0\n"
1384 "eax=%08VR{eax} ebx=%08VR{ebx} ecx=%08VR{ecx} edx=%08VR{edx} esi=%08VR{esi} edi=%08VR{edi}\n"
1385 "eip=%08VR{eip} esp=%08VR{esp} ebp=%08VR{ebp} %VRF{eflags}\n"
1386 "cs=%04VR{cs} ds=%04VR{ds} es=%04VR{es} fs=%04VR{fs} gs=%04VR{gs} ss=%04VR{ss} eflags=%08VR{eflags}\n");
1387 }
1388 else
1389 {
1390 if (f64BitMode)
1391 rc = DBGFR3RegPrintf(pDbgc->pUVM, idCpu, &szDisAndRegs[0], sizeof(szDisAndRegs),
1392 "u %016VR{rip} L 0\n"
1393 "rax=%016VR{rax} rbx=%016VR{rbx} rcx=%016VR{rcx} rdx=%016VR{rdx}\n"
1394 "rsi=%016VR{rsi} rdi=%016VR{rdi} r8 =%016VR{r8} r9 =%016VR{r9}\n"
1395 "r10=%016VR{r10} r11=%016VR{r11} r12=%016VR{r12} r13=%016VR{r13}\n"
1396 "r14=%016VR{r14} r15=%016VR{r15} %VRF{rflags}\n"
1397 "rip=%016VR{rip} rsp=%016VR{rsp} rbp=%016VR{rbp}\n"
1398 "cs={%04VR{cs} base=%016VR{cs_base} limit=%08VR{cs_lim} flags=%04VR{cs_attr}} cr0=%016VR{cr0}\n"
1399 "ds={%04VR{ds} base=%016VR{ds_base} limit=%08VR{ds_lim} flags=%04VR{ds_attr}} cr2=%016VR{cr2}\n"
1400 "es={%04VR{es} base=%016VR{es_base} limit=%08VR{es_lim} flags=%04VR{es_attr}} cr3=%016VR{cr3}\n"
1401 "fs={%04VR{fs} base=%016VR{fs_base} limit=%08VR{fs_lim} flags=%04VR{fs_attr}} cr4=%016VR{cr4}\n"
1402 "gs={%04VR{gs} base=%016VR{gs_base} limit=%08VR{gs_lim} flags=%04VR{gs_attr}} cr8=%016VR{cr8}\n"
1403 "ss={%04VR{ss} base=%016VR{ss_base} limit=%08VR{ss_lim} flags=%04VR{ss_attr}}\n"
1404 "dr0=%016VR{dr0} dr1=%016VR{dr1} dr2=%016VR{dr2} dr3=%016VR{dr3}\n"
1405 "dr6=%016VR{dr6} dr7=%016VR{dr7}\n"
1406 "gdtr=%016VR{gdtr_base}:%04VR{gdtr_lim} idtr=%016VR{idtr_base}:%04VR{idtr_lim} rflags=%08VR{rflags}\n"
1407 "ldtr={%04VR{ldtr} base=%016VR{ldtr_base} limit=%08VR{ldtr_lim} flags=%08VR{ldtr_attr}}\n"
1408 "tr ={%04VR{tr} base=%016VR{tr_base} limit=%08VR{tr_lim} flags=%08VR{tr_attr}}\n"
1409 " sysenter={cs=%04VR{sysenter_cs} eip=%08VR{sysenter_eip} esp=%08VR{sysenter_esp}}\n"
1410 " efer=%016VR{efer}\n"
1411 " pat=%016VR{pat}\n"
1412 " sf_mask=%016VR{sf_mask}\n"
1413 "krnl_gs_base=%016VR{krnl_gs_base}\n"
1414 " lstar=%016VR{lstar}\n"
1415 " star=%016VR{star} cstar=%016VR{cstar}\n"
1416 "fcw=%04VR{fcw} fsw=%04VR{fsw} ftw=%04VR{ftw} mxcsr=%04VR{mxcsr} mxcsr_mask=%04VR{mxcsr_mask}\n"
1417 );
1418 else
1419 rc = DBGFR3RegPrintf(pDbgc->pUVM, idCpu, szDisAndRegs, sizeof(szDisAndRegs),
1420 "u %04VR{cs}:%08VR{eip} L 0\n"
1421 "eax=%08VR{eax} ebx=%08VR{ebx} ecx=%08VR{ecx} edx=%08VR{edx} esi=%08VR{esi} edi=%08VR{edi}\n"
1422 "eip=%08VR{eip} esp=%08VR{esp} ebp=%08VR{ebp} %VRF{eflags}\n"
1423 "cs={%04VR{cs} base=%08VR{cs_base} limit=%08VR{cs_lim} flags=%04VR{cs_attr}} dr0=%08VR{dr0} dr1=%08VR{dr1}\n"
1424 "ds={%04VR{ds} base=%08VR{ds_base} limit=%08VR{ds_lim} flags=%04VR{ds_attr}} dr2=%08VR{dr2} dr3=%08VR{dr3}\n"
1425 "es={%04VR{es} base=%08VR{es_base} limit=%08VR{es_lim} flags=%04VR{es_attr}} dr6=%08VR{dr6} dr7=%08VR{dr7}\n"
1426 "fs={%04VR{fs} base=%08VR{fs_base} limit=%08VR{fs_lim} flags=%04VR{fs_attr}} cr0=%08VR{cr0} cr2=%08VR{cr2}\n"
1427 "gs={%04VR{gs} base=%08VR{gs_base} limit=%08VR{gs_lim} flags=%04VR{gs_attr}} cr3=%08VR{cr3} cr4=%08VR{cr4}\n"
1428 "ss={%04VR{ss} base=%08VR{ss_base} limit=%08VR{ss_lim} flags=%04VR{ss_attr}} cr8=%08VR{cr8}\n"
1429 "gdtr=%08VR{gdtr_base}:%04VR{gdtr_lim} idtr=%08VR{idtr_base}:%04VR{idtr_lim} eflags=%08VR{eflags}\n"
1430 "ldtr={%04VR{ldtr} base=%08VR{ldtr_base} limit=%08VR{ldtr_lim} flags=%04VR{ldtr_attr}}\n"
1431 "tr ={%04VR{tr} base=%08VR{tr_base} limit=%08VR{tr_lim} flags=%04VR{tr_attr}}\n"
1432 "sysenter={cs=%04VR{sysenter_cs} eip=%08VR{sysenter_eip} esp=%08VR{sysenter_esp}}\n"
1433 "fcw=%04VR{fcw} fsw=%04VR{fsw} ftw=%04VR{ftw} mxcsr=%04VR{mxcsr} mxcsr_mask=%04VR{mxcsr_mask}\n"
1434 );
1435 }
1436 if (RT_FAILURE(rc))
1437 return DBGCCmdHlpVBoxError(pCmdHlp, rc, "DBGFR3RegPrintf failed");
1438 char *pszRegs = strchr(szDisAndRegs, '\n');
1439 *pszRegs++ = '\0';
1440 rc = DBGCCmdHlpPrintf(pCmdHlp, "%s", pszRegs);
1441
1442 /*
1443 * Disassemble one instruction at cs:[r|e]ip.
1444 */
1445 if (!f64BitMode && strstr(pszRegs, " vm ")) /* a bit ugly... */
1446 return pCmdHlp->pfnExec(pCmdHlp, "uv86 %s", szDisAndRegs + 2);
1447 return pCmdHlp->pfnExec(pCmdHlp, "%s", szDisAndRegs);
1448}
1449
1450
1451/**
1452 * Initializes the Command Helpers for a DBGC instance.
1453 *
1454 * @param pDbgc Pointer to the DBGC instance.
1455 */
1456void dbgcInitCmdHlp(PDBGC pDbgc)
1457{
1458 pDbgc->CmdHlp.u32Magic = DBGCCMDHLP_MAGIC;
1459 pDbgc->CmdHlp.pfnPrintfV = dbgcHlpPrintfV;
1460 pDbgc->CmdHlp.pfnPrintf = dbgcHlpPrintf;
1461 pDbgc->CmdHlp.pfnStrPrintf = dbgcHlpStrPrintf;
1462 pDbgc->CmdHlp.pfnStrPrintfV = dbgcHlpStrPrintfV;
1463 pDbgc->CmdHlp.pfnVBoxErrorV = dbgcHlpVBoxErrorV;
1464 pDbgc->CmdHlp.pfnVBoxError = dbgcHlpVBoxError;
1465 pDbgc->CmdHlp.pfnMemRead = dbgcHlpMemRead;
1466 pDbgc->CmdHlp.pfnMemWrite = dbgcHlpMemWrite;
1467 pDbgc->CmdHlp.pfnEvalV = dbgcHlpEvalV;
1468 pDbgc->CmdHlp.pfnExec = dbgcHlpExec;
1469 pDbgc->CmdHlp.pfnFailV = dbgcHlpFailV;
1470 pDbgc->CmdHlp.pfnFailRcV = dbgcHlpFailRcV;
1471 pDbgc->CmdHlp.pfnParserError = dbgcHlpParserError;
1472 pDbgc->CmdHlp.pfnVarToDbgfAddr = dbgcHlpVarToDbgfAddr;
1473 pDbgc->CmdHlp.pfnVarFromDbgfAddr = dbgcHlpVarFromDbgfAddr;
1474 pDbgc->CmdHlp.pfnVarToNumber = dbgcHlpVarToNumber;
1475 pDbgc->CmdHlp.pfnVarToBool = dbgcHlpVarToBool;
1476 pDbgc->CmdHlp.pfnVarGetRange = dbgcHlpVarGetRange;
1477 pDbgc->CmdHlp.pfnVarConvert = dbgcHlpVarConvert;
1478 pDbgc->CmdHlp.pfnGetDbgfOutputHlp = dbgcHlpGetDbgfOutputHlp;
1479 pDbgc->CmdHlp.pfnGetCurrentCpu = dbgcHlpGetCurrentCpu;
1480 pDbgc->CmdHlp.pfnGetCpuMode = dbgcHlpGetCpuMode;
1481 pDbgc->CmdHlp.pfnRegPrintf = dbgcHlpRegPrintf;
1482 pDbgc->CmdHlp.u32EndMarker = DBGCCMDHLP_MAGIC;
1483}
1484
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette