VirtualBox

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

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

Debugger Console: Clean up, split the command evaluation code out of DBGConsole.cpp and into DBGCEval.cpp.

  • 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 35628 2011-01-19 14:58:26Z 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.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/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, 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
697 /** @todo DBGC: Implement failure / success on command level. */
698 return VINF_SUCCESS;
699}
700
701
702/**
703 * Converts a DBGC variable to a DBGF address structure.
704 *
705 * @returns VBox status code.
706 * @param pCmdHlp Pointer to the command callback structure.
707 * @param pVar The variable to convert.
708 * @param pAddress The target address.
709 */
710static DECLCALLBACK(int) dbgcHlpVarToDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PDBGFADDRESS pAddress)
711{
712 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
713 return dbgcVarToDbgfAddr(pDbgc, pVar, pAddress);
714}
715
716
717/**
718 * Converts a DBGC variable to a number.
719 *
720 * @returns VBox status code.
721 * @param pCmdHlp Pointer to the command callback structure.
722 * @param pVar The variable to convert.
723 * @param pu64Number Where to store the number value.
724 */
725static DECLCALLBACK(int) dbgcHlpVarToNumber(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t *pu64Number)
726{
727 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
728 NOREF(pDbgc);
729
730 uint64_t u64Number;
731 switch (pVar->enmType)
732 {
733 case DBGCVAR_TYPE_GC_FLAT:
734 u64Number = pVar->u.GCFlat;
735 break;
736 case DBGCVAR_TYPE_GC_PHYS:
737 u64Number = pVar->u.GCPhys;
738 break;
739 case DBGCVAR_TYPE_HC_FLAT:
740 u64Number = (uintptr_t)pVar->u.pvHCFlat;
741 break;
742 case DBGCVAR_TYPE_HC_PHYS:
743 u64Number = (uintptr_t)pVar->u.HCPhys;
744 break;
745 case DBGCVAR_TYPE_NUMBER:
746 u64Number = (uintptr_t)pVar->u.u64Number;
747 return VINF_SUCCESS;
748 case DBGCVAR_TYPE_GC_FAR:
749 u64Number = (uintptr_t)pVar->u.GCFar.off;
750 break;
751 case DBGCVAR_TYPE_SYMBOL:
752 case DBGCVAR_TYPE_STRING:
753 return VERR_PARSE_INCORRECT_ARG_TYPE; /** @todo better error code! */
754 default:
755 return VERR_PARSE_INCORRECT_ARG_TYPE;
756 }
757 *pu64Number = u64Number;
758 return VINF_SUCCESS;
759}
760
761
762/**
763 * Converts a DBGC variable to a boolean.
764 *
765 * @returns VBox status code.
766 * @param pCmdHlp Pointer to the command callback structure.
767 * @param pVar The variable to convert.
768 * @param pf Where to store the boolean.
769 */
770static DECLCALLBACK(int) dbgcHlpVarToBool(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, bool *pf)
771{
772 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
773 NOREF(pDbgc);
774
775 switch (pVar->enmType)
776 {
777 case DBGCVAR_TYPE_STRING:
778 /** @todo add strcasecmp / stricmp wrappers to iprt/string.h. */
779 if ( !strcmp(pVar->u.pszString, "true")
780 || !strcmp(pVar->u.pszString, "True")
781 || !strcmp(pVar->u.pszString, "TRUE")
782 || !strcmp(pVar->u.pszString, "on")
783 || !strcmp(pVar->u.pszString, "On")
784 || !strcmp(pVar->u.pszString, "oN")
785 || !strcmp(pVar->u.pszString, "ON")
786 || !strcmp(pVar->u.pszString, "enabled")
787 || !strcmp(pVar->u.pszString, "Enabled")
788 || !strcmp(pVar->u.pszString, "DISABLED"))
789 {
790 *pf = true;
791 return VINF_SUCCESS;
792 }
793 if ( !strcmp(pVar->u.pszString, "false")
794 || !strcmp(pVar->u.pszString, "False")
795 || !strcmp(pVar->u.pszString, "FALSE")
796 || !strcmp(pVar->u.pszString, "off")
797 || !strcmp(pVar->u.pszString, "Off")
798 || !strcmp(pVar->u.pszString, "OFF")
799 || !strcmp(pVar->u.pszString, "disabled")
800 || !strcmp(pVar->u.pszString, "Disabled")
801 || !strcmp(pVar->u.pszString, "DISABLED"))
802 {
803 *pf = false;
804 return VINF_SUCCESS;
805 }
806 return VERR_PARSE_INCORRECT_ARG_TYPE; /** @todo better error code! */
807
808 case DBGCVAR_TYPE_GC_FLAT:
809 case DBGCVAR_TYPE_GC_PHYS:
810 case DBGCVAR_TYPE_HC_FLAT:
811 case DBGCVAR_TYPE_HC_PHYS:
812 case DBGCVAR_TYPE_NUMBER:
813 *pf = pVar->u.u64Number != 0;
814 return VINF_SUCCESS;
815
816 case DBGCVAR_TYPE_GC_FAR:
817 case DBGCVAR_TYPE_SYMBOL:
818 default:
819 return VERR_PARSE_INCORRECT_ARG_TYPE;
820 }
821}
822
823
824/**
825 * @interface_method_impl{DBGCCMDHLP,pfnVarGetRange}
826 */
827static DECLCALLBACK(int) dbgcHlpVarGetRange(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t cbElement, uint64_t cbDefault,
828 uint64_t *pcbRange)
829{
830/** @todo implement this properly, strings/symbols are not resolved now. */
831 switch (pVar->enmRangeType)
832 {
833 default:
834 case DBGCVAR_RANGE_NONE:
835 *pcbRange = cbDefault;
836 break;
837 case DBGCVAR_RANGE_BYTES:
838 *pcbRange = pVar->u64Range;
839 break;
840 case DBGCVAR_RANGE_ELEMENTS:
841 *pcbRange = pVar->u64Range * cbElement;
842 break;
843 }
844 return VINF_SUCCESS;
845}
846
847
848/**
849 * @interface_method_impl{DBGCCMDHLP,pfnVarConvert}
850 */
851static DECLCALLBACK(int) dbgcHlpVarConvert(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pInVar, DBGCVARTYPE enmToType, bool fConvSyms,
852 PDBGCVAR pResult)
853{
854 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
855 DBGCVAR const InVar = *pInVar; /* if pInVar == pResult */
856 PCDBGCVAR pArg = &InVar; /* lazy bird, clean up later */
857 DBGFADDRESS Address;
858 int rc;
859
860 Assert(pDbgc->pVM);
861
862 *pResult = InVar;
863 switch (InVar.enmType)
864 {
865 case DBGCVAR_TYPE_GC_FLAT:
866 switch (enmToType)
867 {
868 case DBGCVAR_TYPE_GC_FLAT:
869 return VINF_SUCCESS;
870
871 case DBGCVAR_TYPE_GC_FAR:
872 return VERR_PARSE_INCORRECT_ARG_TYPE;
873
874 case DBGCVAR_TYPE_GC_PHYS:
875 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
876 rc = DBGFR3AddrToPhys(pDbgc->pVM, pDbgc->idCpu,
877 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
878 &pResult->u.GCPhys);
879 if (RT_SUCCESS(rc))
880 return VINF_SUCCESS;
881 return VERR_PARSE_CONVERSION_FAILED;
882
883 case DBGCVAR_TYPE_HC_FLAT:
884 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
885 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu,
886 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
887 false /*fReadOnly */,
888 &pResult->u.pvHCFlat);
889 if (RT_SUCCESS(rc))
890 return VINF_SUCCESS;
891 return VERR_PARSE_CONVERSION_FAILED;
892
893 case DBGCVAR_TYPE_HC_PHYS:
894 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
895 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu,
896 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
897 &pResult->u.GCPhys);
898 if (RT_SUCCESS(rc))
899 return VINF_SUCCESS;
900 return VERR_PARSE_CONVERSION_FAILED;
901
902 case DBGCVAR_TYPE_NUMBER:
903 pResult->enmType = enmToType;
904 pResult->u.u64Number = InVar.u.GCFlat;
905 return VINF_SUCCESS;
906
907 case DBGCVAR_TYPE_STRING:
908 case DBGCVAR_TYPE_SYMBOL:
909 return VERR_PARSE_INCORRECT_ARG_TYPE;
910
911 case DBGCVAR_TYPE_UNKNOWN:
912 case DBGCVAR_TYPE_ANY:
913 break;
914 }
915 break;
916
917 case DBGCVAR_TYPE_GC_FAR:
918 switch (enmToType)
919 {
920 case DBGCVAR_TYPE_GC_FLAT:
921 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
922 if (RT_SUCCESS(rc))
923 {
924 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
925 pResult->u.GCFlat = Address.FlatPtr;
926 return VINF_SUCCESS;
927 }
928 return VERR_PARSE_CONVERSION_FAILED;
929
930 case DBGCVAR_TYPE_GC_FAR:
931 return VINF_SUCCESS;
932
933 case DBGCVAR_TYPE_GC_PHYS:
934 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
935 if (RT_SUCCESS(rc))
936 {
937 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
938 rc = DBGFR3AddrToPhys(pDbgc->pVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
939 if (RT_SUCCESS(rc))
940 return VINF_SUCCESS;
941 }
942 return VERR_PARSE_CONVERSION_FAILED;
943
944 case DBGCVAR_TYPE_HC_FLAT:
945 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
946 if (RT_SUCCESS(rc))
947 {
948 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
949 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu, &Address,
950 false /*fReadOnly*/, &pResult->u.pvHCFlat);
951 if (RT_SUCCESS(rc))
952 return VINF_SUCCESS;
953 }
954 return VERR_PARSE_CONVERSION_FAILED;
955
956 case DBGCVAR_TYPE_HC_PHYS:
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_PHYS;
961 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
962 if (RT_SUCCESS(rc))
963 return VINF_SUCCESS;
964 }
965 return VERR_PARSE_CONVERSION_FAILED;
966
967 case DBGCVAR_TYPE_NUMBER:
968 pResult->enmType = enmToType;
969 pResult->u.u64Number = InVar.u.GCFar.off;
970 return VINF_SUCCESS;
971
972 case DBGCVAR_TYPE_STRING:
973 case DBGCVAR_TYPE_SYMBOL:
974 return VERR_PARSE_INCORRECT_ARG_TYPE;
975
976 case DBGCVAR_TYPE_UNKNOWN:
977 case DBGCVAR_TYPE_ANY:
978 break;
979 }
980 break;
981
982 case DBGCVAR_TYPE_GC_PHYS:
983 switch (enmToType)
984 {
985 case DBGCVAR_TYPE_GC_FLAT:
986 //rc = MMR3PhysGCPhys2GCVirtEx(pDbgc->pVM, pResult->u.GCPhys, ..., &pResult->u.GCFlat); - yea, sure.
987 return VERR_PARSE_INCORRECT_ARG_TYPE;
988
989 case DBGCVAR_TYPE_GC_FAR:
990 return VERR_PARSE_INCORRECT_ARG_TYPE;
991
992 case DBGCVAR_TYPE_GC_PHYS:
993 return VINF_SUCCESS;
994
995 case DBGCVAR_TYPE_HC_FLAT:
996 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
997 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu,
998 DBGFR3AddrFromPhys(pDbgc->pVM, &Address, pArg->u.GCPhys),
999 false /*fReadOnly */,
1000 &pResult->u.pvHCFlat);
1001 if (RT_SUCCESS(rc))
1002 return VINF_SUCCESS;
1003 return VERR_PARSE_CONVERSION_FAILED;
1004
1005 case DBGCVAR_TYPE_HC_PHYS:
1006 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1007 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu,
1008 DBGFR3AddrFromPhys(pDbgc->pVM, &Address, pArg->u.GCPhys),
1009 &pResult->u.HCPhys);
1010 if (RT_SUCCESS(rc))
1011 return VINF_SUCCESS;
1012 return VERR_PARSE_CONVERSION_FAILED;
1013
1014 case DBGCVAR_TYPE_NUMBER:
1015 pResult->enmType = enmToType;
1016 pResult->u.u64Number = InVar.u.GCPhys;
1017 return VINF_SUCCESS;
1018
1019 case DBGCVAR_TYPE_STRING:
1020 case DBGCVAR_TYPE_SYMBOL:
1021 return VERR_PARSE_INCORRECT_ARG_TYPE;
1022
1023 case DBGCVAR_TYPE_UNKNOWN:
1024 case DBGCVAR_TYPE_ANY:
1025 break;
1026 }
1027 break;
1028
1029 case DBGCVAR_TYPE_HC_FLAT:
1030 switch (enmToType)
1031 {
1032 case DBGCVAR_TYPE_GC_FLAT:
1033 return VERR_PARSE_INCORRECT_ARG_TYPE;
1034
1035 case DBGCVAR_TYPE_GC_FAR:
1036 return VERR_PARSE_INCORRECT_ARG_TYPE;
1037
1038 case DBGCVAR_TYPE_GC_PHYS:
1039 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1040 rc = PGMR3DbgR3Ptr2GCPhys(pDbgc->pVM, pArg->u.pvHCFlat, &pResult->u.GCPhys);
1041 if (RT_SUCCESS(rc))
1042 return VINF_SUCCESS;
1043 /** @todo more memory types! */
1044 return VERR_PARSE_CONVERSION_FAILED;
1045
1046 case DBGCVAR_TYPE_HC_FLAT:
1047 return VINF_SUCCESS;
1048
1049 case DBGCVAR_TYPE_HC_PHYS:
1050 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1051 rc = PGMR3DbgR3Ptr2HCPhys(pDbgc->pVM, pArg->u.pvHCFlat, &pResult->u.HCPhys);
1052 if (RT_SUCCESS(rc))
1053 return VINF_SUCCESS;
1054 /** @todo more memory types! */
1055 return VERR_PARSE_CONVERSION_FAILED;
1056
1057 case DBGCVAR_TYPE_NUMBER:
1058 pResult->enmType = enmToType;
1059 pResult->u.u64Number = (uintptr_t)InVar.u.pvHCFlat;
1060 return VINF_SUCCESS;
1061
1062 case DBGCVAR_TYPE_STRING:
1063 case DBGCVAR_TYPE_SYMBOL:
1064 return VERR_PARSE_INCORRECT_ARG_TYPE;
1065
1066 case DBGCVAR_TYPE_UNKNOWN:
1067 case DBGCVAR_TYPE_ANY:
1068 break;
1069 }
1070 break;
1071
1072 case DBGCVAR_TYPE_HC_PHYS:
1073 switch (enmToType)
1074 {
1075 case DBGCVAR_TYPE_GC_FLAT:
1076 return VERR_PARSE_INCORRECT_ARG_TYPE;
1077
1078 case DBGCVAR_TYPE_GC_FAR:
1079 return VERR_PARSE_INCORRECT_ARG_TYPE;
1080
1081 case DBGCVAR_TYPE_GC_PHYS:
1082 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1083 rc = PGMR3DbgHCPhys2GCPhys(pDbgc->pVM, pArg->u.HCPhys, &pResult->u.GCPhys);
1084 if (RT_SUCCESS(rc))
1085 return VINF_SUCCESS;
1086 return VERR_PARSE_CONVERSION_FAILED;
1087
1088 case DBGCVAR_TYPE_HC_FLAT:
1089 return VERR_PARSE_INCORRECT_ARG_TYPE;
1090
1091 case DBGCVAR_TYPE_HC_PHYS:
1092 return VINF_SUCCESS;
1093
1094 case DBGCVAR_TYPE_NUMBER:
1095 pResult->enmType = enmToType;
1096 pResult->u.u64Number = InVar.u.HCPhys;
1097 return VINF_SUCCESS;
1098
1099 case DBGCVAR_TYPE_STRING:
1100 case DBGCVAR_TYPE_SYMBOL:
1101 return VERR_PARSE_INCORRECT_ARG_TYPE;
1102
1103 case DBGCVAR_TYPE_UNKNOWN:
1104 case DBGCVAR_TYPE_ANY:
1105 break;
1106 }
1107 break;
1108
1109 case DBGCVAR_TYPE_NUMBER:
1110 switch (enmToType)
1111 {
1112 case DBGCVAR_TYPE_GC_FLAT:
1113 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
1114 pResult->u.GCFlat = (RTGCPTR)InVar.u.u64Number;
1115 return VERR_PARSE_INCORRECT_ARG_TYPE;
1116
1117 case DBGCVAR_TYPE_GC_FAR:
1118 return VERR_PARSE_INCORRECT_ARG_TYPE;
1119
1120 case DBGCVAR_TYPE_GC_PHYS:
1121 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
1122 pResult->u.GCPhys = (RTGCPHYS)InVar.u.u64Number;
1123 return VERR_PARSE_INCORRECT_ARG_TYPE;
1124
1125 case DBGCVAR_TYPE_HC_FLAT:
1126 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
1127 pResult->u.pvHCFlat = (void *)(uintptr_t)InVar.u.u64Number;
1128 return VERR_PARSE_INCORRECT_ARG_TYPE;
1129
1130 case DBGCVAR_TYPE_HC_PHYS:
1131 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
1132 pResult->u.HCPhys = (RTHCPHYS)InVar.u.u64Number;
1133 return VINF_SUCCESS;
1134
1135 case DBGCVAR_TYPE_NUMBER:
1136 return VINF_SUCCESS;
1137
1138 case DBGCVAR_TYPE_STRING:
1139 case DBGCVAR_TYPE_SYMBOL:
1140 return VERR_PARSE_INCORRECT_ARG_TYPE;
1141
1142 case DBGCVAR_TYPE_UNKNOWN:
1143 case DBGCVAR_TYPE_ANY:
1144 break;
1145 }
1146 break;
1147
1148 case DBGCVAR_TYPE_SYMBOL:
1149 case DBGCVAR_TYPE_STRING:
1150 switch (enmToType)
1151 {
1152 case DBGCVAR_TYPE_GC_FLAT:
1153 case DBGCVAR_TYPE_GC_FAR:
1154 case DBGCVAR_TYPE_GC_PHYS:
1155 case DBGCVAR_TYPE_HC_FLAT:
1156 case DBGCVAR_TYPE_HC_PHYS:
1157 case DBGCVAR_TYPE_NUMBER:
1158 if (fConvSyms)
1159 {
1160 rc = dbgcSymbolGet(pDbgc, InVar.u.pszString, enmToType, pResult);
1161 if (RT_SUCCESS(rc))
1162 {
1163 if (InVar.enmRangeType != DBGCVAR_RANGE_NONE)
1164 {
1165 pResult->enmRangeType = InVar.enmRangeType;
1166 pResult->u64Range = InVar.u64Range;
1167 }
1168 return VINF_SUCCESS;
1169 }
1170 }
1171 return VERR_PARSE_INCORRECT_ARG_TYPE;
1172
1173 case DBGCVAR_TYPE_STRING:
1174 case DBGCVAR_TYPE_SYMBOL:
1175 pResult->enmType = enmToType;
1176 return VINF_SUCCESS;
1177
1178 case DBGCVAR_TYPE_UNKNOWN:
1179 case DBGCVAR_TYPE_ANY:
1180 break;
1181 }
1182 break;
1183
1184 case DBGCVAR_TYPE_UNKNOWN:
1185 case DBGCVAR_TYPE_ANY:
1186 break;
1187 }
1188
1189 AssertMsgFailed(("f=%d t=%d\n", InVar.enmType, enmToType));
1190 return VERR_INVALID_PARAMETER;
1191}
1192
1193
1194/**
1195 * Info helper callback wrapper - print formatted string.
1196 *
1197 * @param pHlp Pointer to this structure.
1198 * @param pszFormat The format string.
1199 * @param ... Arguments.
1200 */
1201static DECLCALLBACK(void) dbgcHlpGetDbgfOutputHlp_Printf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
1202{
1203 PDBGC pDbgc = RT_FROM_MEMBER(pHlp, DBGC, DbgfOutputHlp);
1204 va_list va;
1205 va_start(va, pszFormat);
1206 pDbgc->CmdHlp.pfnPrintfV(&pDbgc->CmdHlp, NULL, pszFormat, va);
1207 va_end(va);
1208}
1209
1210
1211/**
1212 * Info helper callback wrapper - print formatted string.
1213 *
1214 * @param pHlp Pointer to this structure.
1215 * @param pszFormat The format string.
1216 * @param args Argument list.
1217 */
1218static DECLCALLBACK(void) dbgcHlpGetDbgfOutputHlp_PrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
1219{
1220 PDBGC pDbgc = RT_FROM_MEMBER(pHlp, DBGC, DbgfOutputHlp);
1221 pDbgc->CmdHlp.pfnPrintfV(&pDbgc->CmdHlp, NULL, pszFormat, args);
1222}
1223
1224
1225/**
1226 * @interface_method_impl{DBGCCMDHLP,pfnGetDbgfOutputHlp}
1227 */
1228static DECLCALLBACK(PCDBGFINFOHLP) dbgcHlpGetDbgfOutputHlp(PDBGCCMDHLP pCmdHlp)
1229{
1230 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
1231
1232 /* Lazy init */
1233 if (!pDbgc->DbgfOutputHlp.pfnPrintf)
1234 {
1235 pDbgc->DbgfOutputHlp.pfnPrintf = dbgcHlpGetDbgfOutputHlp_Printf;
1236 pDbgc->DbgfOutputHlp.pfnPrintfV = dbgcHlpGetDbgfOutputHlp_PrintfV;
1237 }
1238
1239 return &pDbgc->DbgfOutputHlp;
1240}
1241
1242
1243/**
1244 * Initializes the Command Helpers for a DBGC instance.
1245 *
1246 * @param pDbgc Pointer to the DBGC instance.
1247 */
1248void dbgcInitCmdHlp(PDBGC pDbgc)
1249{
1250 pDbgc->CmdHlp.pfnWrite = dbgcHlpWrite;
1251 pDbgc->CmdHlp.pfnPrintfV = dbgcHlpPrintfV;
1252 pDbgc->CmdHlp.pfnPrintf = dbgcHlpPrintf;
1253 pDbgc->CmdHlp.pfnVBoxErrorV = dbgcHlpVBoxErrorV;
1254 pDbgc->CmdHlp.pfnVBoxError = dbgcHlpVBoxError;
1255 pDbgc->CmdHlp.pfnMemRead = dbgcHlpMemRead;
1256 pDbgc->CmdHlp.pfnMemWrite = dbgcHlpMemWrite;
1257 pDbgc->CmdHlp.pfnEvalV = dbgcHlpEvalV;
1258 pDbgc->CmdHlp.pfnExec = dbgcHlpExec;
1259 pDbgc->CmdHlp.pfnFailV = dbgcHlpFailV;
1260 pDbgc->CmdHlp.pfnVarToDbgfAddr = dbgcHlpVarToDbgfAddr;
1261 pDbgc->CmdHlp.pfnVarToNumber = dbgcHlpVarToNumber;
1262 pDbgc->CmdHlp.pfnVarToBool = dbgcHlpVarToBool;
1263 pDbgc->CmdHlp.pfnVarGetRange = dbgcHlpVarGetRange;
1264 pDbgc->CmdHlp.pfnVarConvert = dbgcHlpVarConvert;
1265 pDbgc->CmdHlp.pfnGetDbgfOutputHlp = dbgcHlpGetDbgfOutputHlp;
1266}
1267
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