VirtualBox

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

Last change on this file since 35650 was 35637, checked in by vboxsync, 14 years ago

Debugger console: Made the evaluator a bit smarter wrt to the register and variable operators (e.g. don't confuse @ah with a hexadecimal number).

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