VirtualBox

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

Last change on this file since 41565 was 41565, checked in by vboxsync, 13 years ago

DBGC: Implemented the functions by(addr), dwo(addr), not(value/addr), poi(addr), qwo(addr), and wo(addr). (untested)

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