VirtualBox

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

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

Debugger Console: cleaning up...

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette