VirtualBox

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

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

DBGC: Fix copy'n'paste

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