VirtualBox

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

Last change on this file since 69564 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use