VirtualBox

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

Last change on this file since 62481 was 62480, checked in by vboxsync, 8 years ago

(C) 2016

  • 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 62480 2016-07-22 18:29:41Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Command Helpers.
4 */
5
6/*
7 * Copyright (C) 2006-2016 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,pfnStrPrintf}
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 /* 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,pfnFailV}
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 AssertPtrReturn(pAddress, VERR_INVALID_POINTER);
794 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
795 AssertPtrReturn(pResult, VERR_INVALID_POINTER);
796
797 switch (pAddress->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK)
798 {
799 case DBGFADDRESS_FLAGS_FAR16:
800 case DBGFADDRESS_FLAGS_FAR32:
801 case DBGFADDRESS_FLAGS_FAR64:
802 DBGCVAR_INIT_GC_FAR(pResult, pAddress->Sel, pAddress->off);
803 break;
804
805 case DBGFADDRESS_FLAGS_FLAT:
806 DBGCVAR_INIT_GC_FLAT(pResult, pAddress->FlatPtr);
807 break;
808
809 case DBGFADDRESS_FLAGS_PHYS:
810 DBGCVAR_INIT_GC_PHYS(pResult, pAddress->FlatPtr);
811 break;
812
813 default:
814 DBGCVAR_INIT(pResult);
815 AssertMsgFailedReturn(("%#x\n", pAddress->fFlags), VERR_INVALID_PARAMETER);
816 break;
817 }
818
819 return VINF_SUCCESS;
820}
821
822
823/**
824 * @interface_method_impl{DBGCCMDHLP,pfnVarToNumber}
825 */
826static DECLCALLBACK(int) dbgcHlpVarToNumber(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t *pu64Number)
827{
828 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
829 NOREF(pDbgc);
830
831 uint64_t u64Number;
832 switch (pVar->enmType)
833 {
834 case DBGCVAR_TYPE_GC_FLAT:
835 u64Number = pVar->u.GCFlat;
836 break;
837 case DBGCVAR_TYPE_GC_PHYS:
838 u64Number = pVar->u.GCPhys;
839 break;
840 case DBGCVAR_TYPE_HC_FLAT:
841 u64Number = (uintptr_t)pVar->u.pvHCFlat;
842 break;
843 case DBGCVAR_TYPE_HC_PHYS:
844 u64Number = (uintptr_t)pVar->u.HCPhys;
845 break;
846 case DBGCVAR_TYPE_NUMBER:
847 u64Number = (uintptr_t)pVar->u.u64Number;
848 break;
849 case DBGCVAR_TYPE_GC_FAR:
850 u64Number = (uintptr_t)pVar->u.GCFar.off;
851 break;
852 case DBGCVAR_TYPE_SYMBOL:
853 /** @todo try convert as symbol? */
854 case DBGCVAR_TYPE_STRING:
855 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; /** @todo better error code! */
856 default:
857 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
858 }
859 *pu64Number = u64Number;
860 return VINF_SUCCESS;
861}
862
863
864/**
865 * @interface_method_impl{DBGCCMDHLP,pfnVarToBool}
866 */
867static DECLCALLBACK(int) dbgcHlpVarToBool(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, bool *pf)
868{
869 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
870 NOREF(pDbgc);
871
872 switch (pVar->enmType)
873 {
874 case DBGCVAR_TYPE_SYMBOL:
875 case DBGCVAR_TYPE_STRING:
876 if ( !RTStrICmp(pVar->u.pszString, "true")
877 || !RTStrICmp(pVar->u.pszString, "on")
878 || !RTStrICmp(pVar->u.pszString, "no")
879 || !RTStrICmp(pVar->u.pszString, "enabled"))
880 {
881 *pf = true;
882 return VINF_SUCCESS;
883 }
884 if ( !RTStrICmp(pVar->u.pszString, "false")
885 || !RTStrICmp(pVar->u.pszString, "off")
886 || !RTStrICmp(pVar->u.pszString, "yes")
887 || !RTStrICmp(pVar->u.pszString, "disabled"))
888 {
889 *pf = false;
890 return VINF_SUCCESS;
891 }
892 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; /** @todo better error code! */
893
894 case DBGCVAR_TYPE_GC_FLAT:
895 case DBGCVAR_TYPE_GC_PHYS:
896 case DBGCVAR_TYPE_HC_FLAT:
897 case DBGCVAR_TYPE_HC_PHYS:
898 case DBGCVAR_TYPE_NUMBER:
899 *pf = pVar->u.u64Number != 0;
900 return VINF_SUCCESS;
901
902 case DBGCVAR_TYPE_GC_FAR:
903 default:
904 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
905 }
906}
907
908
909/**
910 * @interface_method_impl{DBGCCMDHLP,pfnVarGetRange}
911 */
912static DECLCALLBACK(int) dbgcHlpVarGetRange(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t cbElement, uint64_t cbDefault,
913 uint64_t *pcbRange)
914{
915/** @todo implement this properly, strings/symbols are not resolved now. */
916 switch (pVar->enmRangeType)
917 {
918 default:
919 case DBGCVAR_RANGE_NONE:
920 *pcbRange = cbDefault;
921 break;
922 case DBGCVAR_RANGE_BYTES:
923 *pcbRange = pVar->u64Range;
924 break;
925 case DBGCVAR_RANGE_ELEMENTS:
926 *pcbRange = pVar->u64Range * cbElement;
927 break;
928 }
929 return VINF_SUCCESS;
930}
931
932
933/**
934 * @interface_method_impl{DBGCCMDHLP,pfnVarConvert}
935 */
936static DECLCALLBACK(int) dbgcHlpVarConvert(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pInVar, DBGCVARTYPE enmToType, bool fConvSyms,
937 PDBGCVAR pResult)
938{
939 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
940 DBGCVAR const InVar = *pInVar; /* if pInVar == pResult */
941 PCDBGCVAR pArg = &InVar; /* lazy bird, clean up later */
942 DBGFADDRESS Address;
943 int rc;
944
945 Assert(pDbgc->pUVM);
946
947 *pResult = InVar;
948 switch (InVar.enmType)
949 {
950 case DBGCVAR_TYPE_GC_FLAT:
951 switch (enmToType)
952 {
953 case DBGCVAR_TYPE_GC_FLAT:
954 return VINF_SUCCESS;
955
956 case DBGCVAR_TYPE_GC_FAR:
957 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
958
959 case DBGCVAR_TYPE_GC_PHYS:
960 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
961 rc = DBGFR3AddrToPhys(pDbgc->pUVM, pDbgc->idCpu,
962 DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat),
963 &pResult->u.GCPhys);
964 if (RT_SUCCESS(rc))
965 return VINF_SUCCESS;
966 return VERR_DBGC_PARSE_CONVERSION_FAILED;
967
968 case DBGCVAR_TYPE_HC_FLAT:
969 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
970 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu,
971 DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat),
972 false /*fReadOnly */,
973 &pResult->u.pvHCFlat);
974 if (RT_SUCCESS(rc))
975 return VINF_SUCCESS;
976 return VERR_DBGC_PARSE_CONVERSION_FAILED;
977
978 case DBGCVAR_TYPE_HC_PHYS:
979 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
980 rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu,
981 DBGFR3AddrFromFlat(pDbgc->pUVM, &Address, pArg->u.GCFlat),
982 &pResult->u.GCPhys);
983 if (RT_SUCCESS(rc))
984 return VINF_SUCCESS;
985 return VERR_DBGC_PARSE_CONVERSION_FAILED;
986
987 case DBGCVAR_TYPE_NUMBER:
988 pResult->enmType = enmToType;
989 pResult->u.u64Number = InVar.u.GCFlat;
990 return VINF_SUCCESS;
991
992 case DBGCVAR_TYPE_STRING:
993 case DBGCVAR_TYPE_SYMBOL:
994 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
995
996 case DBGCVAR_TYPE_UNKNOWN:
997 case DBGCVAR_TYPE_ANY:
998 break;
999 }
1000 break;
1001
1002 case DBGCVAR_TYPE_GC_FAR:
1003 switch (enmToType)
1004 {
1005 case DBGCVAR_TYPE_GC_FLAT:
1006 rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
1007 if (RT_SUCCESS(rc))
1008 {
1009 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
1010 pResult->u.GCFlat = Address.FlatPtr;
1011 return VINF_SUCCESS;
1012 }
1013 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1014
1015 case DBGCVAR_TYPE_GC_FAR:
1016 return VINF_SUCCESS;
1017
1018 case DBGCVAR_TYPE_GC_PHYS:
1019 rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
1020 if (RT_SUCCESS(rc))
1021 {
1022 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1023 rc = DBGFR3AddrToPhys(pDbgc->pUVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
1024 if (RT_SUCCESS(rc))
1025 return VINF_SUCCESS;
1026 }
1027 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1028
1029 case DBGCVAR_TYPE_HC_FLAT:
1030 rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
1031 if (RT_SUCCESS(rc))
1032 {
1033 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
1034 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu, &Address,
1035 false /*fReadOnly*/, &pResult->u.pvHCFlat);
1036 if (RT_SUCCESS(rc))
1037 return VINF_SUCCESS;
1038 }
1039 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1040
1041 case DBGCVAR_TYPE_HC_PHYS:
1042 rc = DBGFR3AddrFromSelOff(pDbgc->pUVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
1043 if (RT_SUCCESS(rc))
1044 {
1045 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1046 rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
1047 if (RT_SUCCESS(rc))
1048 return VINF_SUCCESS;
1049 }
1050 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1051
1052 case DBGCVAR_TYPE_NUMBER:
1053 pResult->enmType = enmToType;
1054 pResult->u.u64Number = InVar.u.GCFar.off;
1055 return VINF_SUCCESS;
1056
1057 case DBGCVAR_TYPE_STRING:
1058 case DBGCVAR_TYPE_SYMBOL:
1059 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1060
1061 case DBGCVAR_TYPE_UNKNOWN:
1062 case DBGCVAR_TYPE_ANY:
1063 break;
1064 }
1065 break;
1066
1067 case DBGCVAR_TYPE_GC_PHYS:
1068 switch (enmToType)
1069 {
1070 case DBGCVAR_TYPE_GC_FLAT:
1071 //rc = MMR3PhysGCPhys2GCVirtEx(pDbgc->pVM, pResult->u.GCPhys, ..., &pResult->u.GCFlat); - yea, sure.
1072 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1073
1074 case DBGCVAR_TYPE_GC_FAR:
1075 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1076
1077 case DBGCVAR_TYPE_GC_PHYS:
1078 return VINF_SUCCESS;
1079
1080 case DBGCVAR_TYPE_HC_FLAT:
1081 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
1082 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pUVM, pDbgc->idCpu,
1083 DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, pArg->u.GCPhys),
1084 false /*fReadOnly */,
1085 &pResult->u.pvHCFlat);
1086 if (RT_SUCCESS(rc))
1087 return VINF_SUCCESS;
1088 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1089
1090 case DBGCVAR_TYPE_HC_PHYS:
1091 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1092 rc = DBGFR3AddrToHostPhys(pDbgc->pUVM, pDbgc->idCpu,
1093 DBGFR3AddrFromPhys(pDbgc->pUVM, &Address, pArg->u.GCPhys),
1094 &pResult->u.HCPhys);
1095 if (RT_SUCCESS(rc))
1096 return VINF_SUCCESS;
1097 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1098
1099 case DBGCVAR_TYPE_NUMBER:
1100 pResult->enmType = enmToType;
1101 pResult->u.u64Number = InVar.u.GCPhys;
1102 return VINF_SUCCESS;
1103
1104 case DBGCVAR_TYPE_STRING:
1105 case DBGCVAR_TYPE_SYMBOL:
1106 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1107
1108 case DBGCVAR_TYPE_UNKNOWN:
1109 case DBGCVAR_TYPE_ANY:
1110 break;
1111 }
1112 break;
1113
1114 case DBGCVAR_TYPE_HC_FLAT:
1115 switch (enmToType)
1116 {
1117 case DBGCVAR_TYPE_GC_FLAT:
1118 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1119
1120 case DBGCVAR_TYPE_GC_FAR:
1121 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1122
1123 case DBGCVAR_TYPE_GC_PHYS:
1124 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1125 rc = PGMR3DbgR3Ptr2GCPhys(pDbgc->pUVM, pArg->u.pvHCFlat, &pResult->u.GCPhys);
1126 if (RT_SUCCESS(rc))
1127 return VINF_SUCCESS;
1128 /** @todo more memory types! */
1129 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1130
1131 case DBGCVAR_TYPE_HC_FLAT:
1132 return VINF_SUCCESS;
1133
1134 case DBGCVAR_TYPE_HC_PHYS:
1135 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1136 rc = PGMR3DbgR3Ptr2HCPhys(pDbgc->pUVM, pArg->u.pvHCFlat, &pResult->u.HCPhys);
1137 if (RT_SUCCESS(rc))
1138 return VINF_SUCCESS;
1139 /** @todo more memory types! */
1140 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1141
1142 case DBGCVAR_TYPE_NUMBER:
1143 pResult->enmType = enmToType;
1144 pResult->u.u64Number = (uintptr_t)InVar.u.pvHCFlat;
1145 return VINF_SUCCESS;
1146
1147 case DBGCVAR_TYPE_STRING:
1148 case DBGCVAR_TYPE_SYMBOL:
1149 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1150
1151 case DBGCVAR_TYPE_UNKNOWN:
1152 case DBGCVAR_TYPE_ANY:
1153 break;
1154 }
1155 break;
1156
1157 case DBGCVAR_TYPE_HC_PHYS:
1158 switch (enmToType)
1159 {
1160 case DBGCVAR_TYPE_GC_FLAT:
1161 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1162
1163 case DBGCVAR_TYPE_GC_FAR:
1164 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1165
1166 case DBGCVAR_TYPE_GC_PHYS:
1167 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1168 rc = PGMR3DbgHCPhys2GCPhys(pDbgc->pUVM, pArg->u.HCPhys, &pResult->u.GCPhys);
1169 if (RT_SUCCESS(rc))
1170 return VINF_SUCCESS;
1171 return VERR_DBGC_PARSE_CONVERSION_FAILED;
1172
1173 case DBGCVAR_TYPE_HC_FLAT:
1174 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1175
1176 case DBGCVAR_TYPE_HC_PHYS:
1177 return VINF_SUCCESS;
1178
1179 case DBGCVAR_TYPE_NUMBER:
1180 pResult->enmType = enmToType;
1181 pResult->u.u64Number = InVar.u.HCPhys;
1182 return VINF_SUCCESS;
1183
1184 case DBGCVAR_TYPE_STRING:
1185 case DBGCVAR_TYPE_SYMBOL:
1186 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1187
1188 case DBGCVAR_TYPE_UNKNOWN:
1189 case DBGCVAR_TYPE_ANY:
1190 break;
1191 }
1192 break;
1193
1194 case DBGCVAR_TYPE_NUMBER:
1195 switch (enmToType)
1196 {
1197 case DBGCVAR_TYPE_GC_FLAT:
1198 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
1199 pResult->u.GCFlat = (RTGCPTR)InVar.u.u64Number;
1200 return VINF_SUCCESS;
1201
1202 case DBGCVAR_TYPE_GC_FAR:
1203 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1204
1205 case DBGCVAR_TYPE_GC_PHYS:
1206 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1207 pResult->u.GCPhys = (RTGCPHYS)InVar.u.u64Number;
1208 return VINF_SUCCESS;
1209
1210 case DBGCVAR_TYPE_HC_FLAT:
1211 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
1212 pResult->u.pvHCFlat = (void *)(uintptr_t)InVar.u.u64Number;
1213 return VINF_SUCCESS;
1214
1215 case DBGCVAR_TYPE_HC_PHYS:
1216 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1217 pResult->u.HCPhys = (RTHCPHYS)InVar.u.u64Number;
1218 return VINF_SUCCESS;
1219
1220 case DBGCVAR_TYPE_NUMBER:
1221 return VINF_SUCCESS;
1222
1223 case DBGCVAR_TYPE_STRING:
1224 case DBGCVAR_TYPE_SYMBOL:
1225 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1226
1227 case DBGCVAR_TYPE_UNKNOWN:
1228 case DBGCVAR_TYPE_ANY:
1229 break;
1230 }
1231 break;
1232
1233 case DBGCVAR_TYPE_SYMBOL:
1234 case DBGCVAR_TYPE_STRING:
1235 switch (enmToType)
1236 {
1237 case DBGCVAR_TYPE_GC_FLAT:
1238 case DBGCVAR_TYPE_GC_FAR:
1239 case DBGCVAR_TYPE_GC_PHYS:
1240 case DBGCVAR_TYPE_HC_FLAT:
1241 case DBGCVAR_TYPE_HC_PHYS:
1242 case DBGCVAR_TYPE_NUMBER:
1243 if (fConvSyms)
1244 {
1245 rc = dbgcSymbolGet(pDbgc, InVar.u.pszString, enmToType, pResult);
1246 if (RT_SUCCESS(rc))
1247 return VINF_SUCCESS;
1248 }
1249 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
1250
1251 case DBGCVAR_TYPE_STRING:
1252 case DBGCVAR_TYPE_SYMBOL:
1253 pResult->enmType = enmToType;
1254 return VINF_SUCCESS;
1255
1256 case DBGCVAR_TYPE_UNKNOWN:
1257 case DBGCVAR_TYPE_ANY:
1258 break;
1259 }
1260 break;
1261
1262 case DBGCVAR_TYPE_UNKNOWN:
1263 case DBGCVAR_TYPE_ANY:
1264 break;
1265 }
1266
1267 AssertMsgFailed(("f=%d t=%d\n", InVar.enmType, enmToType));
1268 return VERR_INVALID_PARAMETER;
1269}
1270
1271
1272/**
1273 * @interface_method_impl{DBGFINFOHLP,pfnPrintf}
1274 */
1275static DECLCALLBACK(void) dbgcHlpGetDbgfOutputHlp_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
1276{
1277 PDBGC pDbgc = RT_FROM_MEMBER(pHlp, DBGC, DbgfOutputHlp);
1278 va_list va;
1279 va_start(va, pszFormat);
1280 pDbgc->CmdHlp.pfnPrintfV(&pDbgc->CmdHlp, NULL, pszFormat, va);
1281 va_end(va);
1282}
1283
1284
1285/**
1286 * @interface_method_impl{DBGFINFOHLP,pfnPrintfV}
1287 */
1288static DECLCALLBACK(void) dbgcHlpGetDbgfOutputHlp_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
1289{
1290 PDBGC pDbgc = RT_FROM_MEMBER(pHlp, DBGC, DbgfOutputHlp);
1291 pDbgc->CmdHlp.pfnPrintfV(&pDbgc->CmdHlp, NULL, pszFormat, args);
1292}
1293
1294
1295/**
1296 * @interface_method_impl{DBGCCMDHLP,pfnGetDbgfOutputHlp}
1297 */
1298static DECLCALLBACK(PCDBGFINFOHLP) dbgcHlpGetDbgfOutputHlp(PDBGCCMDHLP pCmdHlp)
1299{
1300 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
1301
1302 /* Lazy init */
1303 if (!pDbgc->DbgfOutputHlp.pfnPrintf)
1304 {
1305 pDbgc->DbgfOutputHlp.pfnPrintf = dbgcHlpGetDbgfOutputHlp_Printf;
1306 pDbgc->DbgfOutputHlp.pfnPrintfV = dbgcHlpGetDbgfOutputHlp_PrintfV;
1307 }
1308
1309 return &pDbgc->DbgfOutputHlp;
1310}
1311
1312
1313/**
1314 * @interface_method_impl{DBGCCMDHLP,pfnGetCurrentCpu}
1315 */
1316static DECLCALLBACK(VMCPUID) dbgcHlpGetCurrentCpu(PDBGCCMDHLP pCmdHlp)
1317{
1318 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
1319 return pDbgc->idCpu;
1320}
1321
1322
1323/**
1324 * @interface_method_impl{DBGCCMDHLP,pfnGetCpuMode}
1325 */
1326static DECLCALLBACK(CPUMMODE) dbgcHlpGetCpuMode(PDBGCCMDHLP pCmdHlp)
1327{
1328 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
1329 CPUMMODE enmMode = CPUMMODE_INVALID;
1330 if (pDbgc->fRegCtxGuest)
1331 {
1332 if (pDbgc->pUVM)
1333 enmMode = DBGFR3CpuGetMode(pDbgc->pUVM, DBGCCmdHlpGetCurrentCpu(pCmdHlp));
1334 if (enmMode == CPUMMODE_INVALID)
1335#if HC_ARCH_BITS == 64
1336 enmMode = CPUMMODE_LONG;
1337#else
1338 enmMode = CPUMMODE_PROTECTED;
1339#endif
1340 }
1341 else
1342 enmMode = CPUMMODE_PROTECTED;
1343 return enmMode;
1344}
1345
1346
1347/**
1348 * Initializes the Command Helpers for a DBGC instance.
1349 *
1350 * @param pDbgc Pointer to the DBGC instance.
1351 */
1352void dbgcInitCmdHlp(PDBGC pDbgc)
1353{
1354 pDbgc->CmdHlp.u32Magic = DBGCCMDHLP_MAGIC;
1355 pDbgc->CmdHlp.pfnPrintfV = dbgcHlpPrintfV;
1356 pDbgc->CmdHlp.pfnPrintf = dbgcHlpPrintf;
1357 pDbgc->CmdHlp.pfnStrPrintf = dbgcHlpStrPrintf;
1358 pDbgc->CmdHlp.pfnStrPrintfV = dbgcHlpStrPrintfV;
1359 pDbgc->CmdHlp.pfnVBoxErrorV = dbgcHlpVBoxErrorV;
1360 pDbgc->CmdHlp.pfnVBoxError = dbgcHlpVBoxError;
1361 pDbgc->CmdHlp.pfnMemRead = dbgcHlpMemRead;
1362 pDbgc->CmdHlp.pfnMemWrite = dbgcHlpMemWrite;
1363 pDbgc->CmdHlp.pfnEvalV = dbgcHlpEvalV;
1364 pDbgc->CmdHlp.pfnExec = dbgcHlpExec;
1365 pDbgc->CmdHlp.pfnFailV = dbgcHlpFailV;
1366 pDbgc->CmdHlp.pfnFailRcV = dbgcHlpFailRcV;
1367 pDbgc->CmdHlp.pfnParserError = dbgcHlpParserError;
1368 pDbgc->CmdHlp.pfnVarToDbgfAddr = dbgcHlpVarToDbgfAddr;
1369 pDbgc->CmdHlp.pfnVarFromDbgfAddr = dbgcHlpVarFromDbgfAddr;
1370 pDbgc->CmdHlp.pfnVarToNumber = dbgcHlpVarToNumber;
1371 pDbgc->CmdHlp.pfnVarToBool = dbgcHlpVarToBool;
1372 pDbgc->CmdHlp.pfnVarGetRange = dbgcHlpVarGetRange;
1373 pDbgc->CmdHlp.pfnVarConvert = dbgcHlpVarConvert;
1374 pDbgc->CmdHlp.pfnGetDbgfOutputHlp = dbgcHlpGetDbgfOutputHlp;
1375 pDbgc->CmdHlp.pfnGetCurrentCpu = dbgcHlpGetCurrentCpu;
1376 pDbgc->CmdHlp.pfnGetCpuMode = dbgcHlpGetCpuMode;
1377 pDbgc->CmdHlp.u32EndMarker = DBGCCMDHLP_MAGIC;
1378}
1379
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