VirtualBox

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

Last change on this file since 45733 was 44528, checked in by vboxsync, 12 years ago

header (C) fixes

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