VirtualBox

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

Last change on this file since 6941 was 6000, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change, fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.2 KB
Line 
1/** $Id: DBGCCmdHlp.cpp 6000 2007-12-07 15:12:49Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Command Helpers.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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/dbgf.h>
24#include <VBox/vm.h>
25#include <VBox/vmm.h>
26#include <VBox/mm.h>
27#include <VBox/pgm.h>
28#include <VBox/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, "%%%VGv", 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, "%%%%%VGp", pVar->u.GCPhys);
129 case DBGCVAR_TYPE_HC_FLAT:
130 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%#%VHv", (uintptr_t)pVar->u.pvHCFlat);
131 case DBGCVAR_TYPE_HC_FAR:
132 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "#%04x:%08x", pVar->u.HCFar.sel, pVar->u.HCFar.off);
133 case DBGCVAR_TYPE_HC_PHYS:
134 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "#%%%%%VHp", pVar->u.HCPhys);
135 case DBGCVAR_TYPE_STRING:
136 return pfnOutput(pvArgOutput, pVar->u.pszString, (size_t)pVar->u64Range);
137 case DBGCVAR_TYPE_NUMBER:
138 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%llx", pVar->u.u64Number);
139
140 case DBGCVAR_TYPE_UNKNOWN:
141 default:
142 return pfnOutput(pvArgOutput, "??", 2);
143 }
144 }
145
146 /*
147 * Print variable with range.
148 * The argument is a const pointer to the variable.
149 */
150 case 'v':
151 {
152 (*ppszFormat)++;
153 PCDBGCVAR pVar = va_arg(*pArgs, PCDBGCVAR);
154
155 char szRange[32];
156 switch (pVar->enmRangeType)
157 {
158 case DBGCVAR_RANGE_NONE:
159 szRange[0] = '\0';
160 break;
161 case DBGCVAR_RANGE_ELEMENTS:
162 RTStrPrintf(szRange, sizeof(szRange), " L %llx", pVar->u64Range);
163 break;
164 case DBGCVAR_RANGE_BYTES:
165 RTStrPrintf(szRange, sizeof(szRange), " LB %llx", pVar->u64Range);
166 break;
167 }
168
169 switch (pVar->enmType)
170 {
171 case DBGCVAR_TYPE_GC_FLAT:
172 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%VGv%s", pVar->u.GCFlat, szRange);
173 case DBGCVAR_TYPE_GC_FAR:
174 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%04x:%08x%s", pVar->u.GCFar.sel, pVar->u.GCFar.off, szRange);
175 case DBGCVAR_TYPE_GC_PHYS:
176 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%%%%VGp%s", pVar->u.GCPhys, szRange);
177 case DBGCVAR_TYPE_HC_FLAT:
178 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%%#%VHv%s", (uintptr_t)pVar->u.pvHCFlat, szRange);
179 case DBGCVAR_TYPE_HC_FAR:
180 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "#%04x:%08x%s", pVar->u.HCFar.sel, pVar->u.HCFar.off, szRange);
181 case DBGCVAR_TYPE_HC_PHYS:
182 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "#%%%%%VHp%s", pVar->u.HCPhys, szRange);
183 case DBGCVAR_TYPE_STRING:
184 return pfnOutput(pvArgOutput, pVar->u.pszString, (size_t)pVar->u64Range);
185 case DBGCVAR_TYPE_NUMBER:
186 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%llx%s", pVar->u.u64Number, szRange);
187
188 case DBGCVAR_TYPE_UNKNOWN:
189 default:
190 return pfnOutput(pvArgOutput, "??", 2);
191 }
192 }
193
194 default:
195 AssertMsgFailed(("Invalid format type '%s'!\n", **ppszFormat));
196 return 0;
197 }
198}
199
200
201/**
202 * Output callback.
203 *
204 * @returns number of bytes written.
205 * @param pvArg User argument.
206 * @param pachChars Pointer to an array of utf-8 characters.
207 * @param cbChars Number of bytes in the character array pointed to by pachChars.
208 */
209static DECLCALLBACK(size_t) dbgcFormatOutput(void *pvArg, const char *pachChars, size_t cbChars)
210{
211 PDBGC pDbgc = (PDBGC)pvArg;
212 if (cbChars)
213 {
214 int rc = pDbgc->pBack->pfnWrite(pDbgc->pBack, pachChars, cbChars, NULL);
215 if (VBOX_FAILURE(rc))
216 {
217 pDbgc->rcOutput = rc;
218 cbChars = 0;
219 }
220 }
221
222 return cbChars;
223}
224
225
226
227/**
228 * Command helper for writing formatted text to the debug console.
229 *
230 * @returns VBox status.
231 * @param pCmdHlp Pointer to the command callback structure.
232 * @param pcb Where to store the number of bytes written.
233 * @param pszFormat The format string.
234 * This is using the log formatter, so it's format extensions can be used.
235 * @param args Arguments specified in the format string.
236 */
237static DECLCALLBACK(int) dbgcHlpPrintfV(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten, const char *pszFormat, va_list args)
238{
239 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
240
241 /*
242 * Do the formatting and output.
243 */
244 pDbgc->rcOutput = 0;
245 size_t cb = RTStrFormatV(dbgcFormatOutput, pDbgc, dbgcStringFormatter, pDbgc, pszFormat, args);
246
247 if (pcbWritten)
248 *pcbWritten = cb;
249
250 return pDbgc->rcOutput;
251}
252
253
254/**
255 * Reports an error from a DBGF call.
256 *
257 * @returns VBox status code appropriate to return from a command.
258 * @param pCmdHlp Pointer to command helpers.
259 * @param rc The VBox status code returned by a DBGF call.
260 * @param pszFormat Format string for additional messages. Can be NULL.
261 * @param ... Format arguments, optional.
262 */
263static DECLCALLBACK(int) dbgcHlpVBoxErrorV(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, va_list args)
264{
265 switch (rc)
266 {
267 case VINF_SUCCESS:
268 break;
269
270 default:
271 rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: %Vrc: %s", rc, pszFormat ? " " : "\n");
272 if (RT_SUCCESS(rc) && pszFormat)
273 rc = pCmdHlp->pfnPrintfV(pCmdHlp, NULL, pszFormat, args);
274 if (RT_SUCCESS(rc))
275 rc = VERR_DBGC_COMMAND_FAILED;
276 break;
277 }
278 return rc;
279}
280
281
282/**
283 * Reports an error from a DBGF call.
284 *
285 * @returns VBox status code appropriate to return from a command.
286 * @param pCmdHlp Pointer to command helpers.
287 * @param rc The VBox status code returned by a DBGF call.
288 * @param pszFormat Format string for additional messages. Can be NULL.
289 * @param ... Format arguments, optional.
290 */
291static DECLCALLBACK(int) dbgcHlpVBoxError(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, ...)
292{
293 va_list args;
294 va_start(args, pszFormat);
295 int rcRet = pCmdHlp->pfnVBoxErrorV(pCmdHlp, rc, pszFormat, args);
296 va_end(args);
297 return rcRet;
298}
299
300
301/**
302 * Command helper for reading memory specified by a DBGC variable.
303 *
304 * @returns VBox status code appropriate to return from a command.
305 * @param pCmdHlp Pointer to the command callback structure.
306 * @param pVM VM handle if GC or physical HC address.
307 * @param pvBuffer Where to store the read data.
308 * @param cbRead Number of bytes to read.
309 * @param pVarPointer DBGC variable specifying where to start reading.
310 * @param pcbRead Where to store the number of bytes actually read.
311 * This optional, but it's useful when read GC virtual memory where a
312 * page in the requested range might not be present.
313 * If not specified not-present failure or end of a HC physical page
314 * will cause failure.
315 */
316static DECLCALLBACK(int) dbgcHlpMemRead(PDBGCCMDHLP pCmdHlp, PVM pVM, void *pvBuffer, size_t cbRead, PCDBGCVAR pVarPointer, size_t *pcbRead)
317{
318 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
319
320 /*
321 * Dummy check.
322 */
323 if (cbRead == 0)
324 {
325 if (*pcbRead)
326 *pcbRead = 0;
327 return VINF_SUCCESS;
328 }
329
330 /*
331 * Convert Far addresses getting size and the correct base address.
332 * Getting and checking the size is what makes this messy and slow.
333 */
334 DBGCVAR Var = *pVarPointer;
335 switch (pVarPointer->enmType)
336 {
337 case DBGCVAR_TYPE_GC_FAR:
338 {
339 /* Use DBGFR3AddrFromSelOff for the conversion. */
340 Assert(pDbgc->pVM);
341 DBGFADDRESS Address;
342 int rc = DBGFR3AddrFromSelOff(pDbgc->pVM, &Address, Var.u.GCFar.sel, Var.u.GCFar.off);
343 if (VBOX_FAILURE(rc))
344 return rc;
345
346 /* don't bother with flat selectors (for now). */
347 if (!DBGFADDRESS_IS_FLAT(&Address))
348 {
349 SELMSELINFO SelInfo;
350 rc = SELMR3GetSelectorInfo(pDbgc->pVM, Address.Sel, &SelInfo);
351 if (VBOX_SUCCESS(rc))
352 {
353 RTGCUINTPTR cb; /* -1 byte */
354 if (SELMSelInfoIsExpandDown(&SelInfo))
355 {
356 if ( !SelInfo.Raw.Gen.u1Granularity
357 && Address.off > UINT16_C(0xffff))
358 return VERR_OUT_OF_SELECTOR_BOUNDS;
359 if (Address.off <= SelInfo.cbLimit)
360 return VERR_OUT_OF_SELECTOR_BOUNDS;
361 cb = (SelInfo.Raw.Gen.u1Granularity ? UINT32_C(0xffffffff) : UINT32_C(0xffff)) - Address.off;
362 }
363 else
364 {
365 if (Address.off > SelInfo.cbLimit)
366 return VERR_OUT_OF_SELECTOR_BOUNDS;
367 cb = SelInfo.cbLimit - Address.off;
368 }
369 if (cbRead - 1 > cb)
370 {
371 if (!pcbRead)
372 return VERR_OUT_OF_SELECTOR_BOUNDS;
373 cbRead = cb + 1;
374 }
375 }
376
377 Var.enmType = DBGCVAR_TYPE_GC_FLAT;
378 Var.u.GCFlat = Address.FlatPtr;
379 }
380 break;
381 }
382
383 case DBGCVAR_TYPE_GC_FLAT:
384 case DBGCVAR_TYPE_GC_PHYS:
385 case DBGCVAR_TYPE_HC_FLAT:
386 case DBGCVAR_TYPE_HC_PHYS:
387 break;
388
389 case DBGCVAR_TYPE_HC_FAR: /* not supported yet! */
390 default:
391 return VERR_NOT_IMPLEMENTED;
392 }
393
394
395
396 /*
397 * Copy page by page.
398 */
399 size_t cbLeft = cbRead;
400 for (;;)
401 {
402 /*
403 * Calc read size.
404 */
405 size_t cb = RT_MIN(PAGE_SIZE, cbLeft);
406 switch (pVarPointer->enmType)
407 {
408 case DBGCVAR_TYPE_GC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCFlat & PAGE_OFFSET_MASK)); break;
409 case DBGCVAR_TYPE_GC_PHYS: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCPhys & PAGE_OFFSET_MASK)); break;
410 case DBGCVAR_TYPE_HC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - ((uintptr_t)Var.u.pvHCFlat & PAGE_OFFSET_MASK)); break;
411 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! */
412 default: break;
413 }
414
415 /*
416 * Perform read.
417 */
418 int rc;
419 switch (Var.enmType)
420 {
421 case DBGCVAR_TYPE_GC_FLAT:
422 rc = MMR3ReadGCVirt(pVM, pvBuffer, Var.u.GCFlat, cb);
423 break;
424 case DBGCVAR_TYPE_GC_PHYS:
425 rc = PGMPhysReadGCPhys(pVM, pvBuffer, Var.u.GCPhys, cb);
426 break;
427
428 case DBGCVAR_TYPE_HC_PHYS:
429 case DBGCVAR_TYPE_HC_FLAT:
430 case DBGCVAR_TYPE_HC_FAR:
431 {
432 DBGCVAR Var2;
433 rc = dbgcOpAddrFlat(pDbgc, &Var, &Var2);
434 if (VBOX_SUCCESS(rc))
435 {
436 /** @todo protect this!!! */
437 memcpy(pvBuffer, Var2.u.pvHCFlat, cb);
438 rc = 0;
439 }
440 else
441 rc = VERR_INVALID_POINTER;
442 break;
443 }
444
445 default:
446 rc = VERR_PARSE_INCORRECT_ARG_TYPE;
447 }
448
449 /*
450 * Check for failure.
451 */
452 if (VBOX_FAILURE(rc))
453 {
454 if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0)
455 return VINF_SUCCESS;
456 return rc;
457 }
458
459 /*
460 * Next.
461 */
462 cbLeft -= cb;
463 if (!cbLeft)
464 break;
465 pvBuffer = (char *)pvBuffer + cb;
466 rc = pCmdHlp->pfnEval(pCmdHlp, &Var, "%DV + %d", &Var, cb);
467 if (VBOX_FAILURE(rc))
468 {
469 if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0)
470 return VINF_SUCCESS;
471 return rc;
472 }
473 }
474
475 /*
476 * Done
477 */
478 if (pcbRead)
479 *pcbRead = cbRead;
480 return 0;
481}
482
483/**
484 * Command helper for writing memory specified by a DBGC variable.
485 *
486 * @returns VBox status code appropriate to return from a command.
487 * @param pCmdHlp Pointer to the command callback structure.
488 * @param pVM VM handle if GC or physical HC address.
489 * @param pvBuffer What to write.
490 * @param cbWrite Number of bytes to write.
491 * @param pVarPointer DBGC variable specifying where to start reading.
492 * @param pcbWritten Where to store the number of bytes written.
493 * This is optional. If NULL be aware that some of the buffer
494 * might have been written to the specified address.
495 */
496static DECLCALLBACK(int) dbgcHlpMemWrite(PDBGCCMDHLP pCmdHlp, PVM pVM, const void *pvBuffer, size_t cbWrite, PCDBGCVAR pVarPointer, size_t *pcbWritten)
497{
498 NOREF(pCmdHlp); NOREF(pVM); NOREF(pvBuffer); NOREF(cbWrite); NOREF(pVarPointer); NOREF(pcbWritten);
499 return VERR_NOT_IMPLEMENTED;
500}
501
502
503/**
504 * Evaluates an expression.
505 * (Hopefully the parser and functions are fully reentrant.)
506 *
507 * @returns VBox status code appropriate to return from a command.
508 * @param pCmdHlp Pointer to the command callback structure.
509 * @param pResult Where to store the result.
510 * @param pszExpr The expression. Format string with the format DBGC extensions.
511 * @param ... Format arguments.
512 */
513static DECLCALLBACK(int) dbgcHlpEval(PDBGCCMDHLP pCmdHlp, PDBGCVAR pResult, const char *pszExpr, ...)
514{
515 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
516
517 /*
518 * Format the expression.
519 */
520 char szExprFormatted[2048];
521 va_list args;
522 va_start(args, pszExpr);
523 size_t cb = RTStrPrintfExV(dbgcStringFormatter, pDbgc, szExprFormatted, sizeof(szExprFormatted), pszExpr, args);
524 va_end(args);
525 /* ignore overflows. */
526
527 return dbgcEvalSub(pDbgc, &szExprFormatted[0], cb, pResult);
528}
529
530
531/**
532 * Executes one command expression.
533 * (Hopefully the parser and functions are fully reentrant.)
534 *
535 * @returns VBox status code appropriate to return from a command.
536 * @param pCmdHlp Pointer to the command callback structure.
537 * @param pszExpr The expression. Format string with the format DBGC extensions.
538 * @param ... Format arguments.
539 */
540static DECLCALLBACK(int) dbgcHlpExec(PDBGCCMDHLP pCmdHlp, const char *pszExpr, ...)
541{
542 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
543 /* Save the scratch state. */
544 char *pszScratch = pDbgc->pszScratch;
545 unsigned iArg = pDbgc->iArg;
546
547 /*
548 * Format the expression.
549 */
550 va_list args;
551 va_start(args, pszExpr);
552 size_t cbScratch = sizeof(pDbgc->achScratch) - (pDbgc->pszScratch - &pDbgc->achScratch[0]);
553 size_t cb = RTStrPrintfExV(dbgcStringFormatter, pDbgc, pDbgc->pszScratch, cbScratch, pszExpr, args);
554 va_end(args);
555 if (cb >= cbScratch)
556 return VERR_BUFFER_OVERFLOW;
557
558 /*
559 * Execute the command.
560 * We save and restore the arg index and scratch buffer pointer.
561 */
562 pDbgc->pszScratch = pDbgc->pszScratch + cb + 1;
563 int rc = dbgcProcessCommand(pDbgc, pszScratch, cb, false /* fNoExecute */);
564
565 /* Restore the scratch state. */
566 pDbgc->iArg = iArg;
567 pDbgc->pszScratch = pszScratch;
568
569 return rc;
570}
571
572
573/**
574 * Converts a DBGC variable to a DBGF address structure.
575 *
576 * @returns VBox status code.
577 * @param pCmdHlp Pointer to the command callback structure.
578 * @param pVar The variable to convert.
579 * @param pAddress The target address.
580 */
581static DECLCALLBACK(int) dbgcHlpVarToDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PDBGFADDRESS pAddress)
582{
583 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
584 return dbgcVarToDbgfAddr(pDbgc, pVar, pAddress);
585}
586
587
588/**
589 * Converts a DBGC variable to a boolean.
590 *
591 * @returns VBox status code.
592 * @param pCmdHlp Pointer to the command callback structure.
593 * @param pVar The variable to convert.
594 * @param pf Where to store the boolean.
595 */
596static DECLCALLBACK(int) dbgcHlpVarToBool(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, bool *pf)
597{
598 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
599 NOREF(pDbgc);
600
601 switch (pVar->enmType)
602 {
603 case DBGCVAR_TYPE_STRING:
604 /** @todo add strcasecmp / stricmp wrappers to iprt/string.h. */
605 if ( !strcmp(pVar->u.pszString, "true")
606 || !strcmp(pVar->u.pszString, "True")
607 || !strcmp(pVar->u.pszString, "TRUE")
608 || !strcmp(pVar->u.pszString, "on")
609 || !strcmp(pVar->u.pszString, "On")
610 || !strcmp(pVar->u.pszString, "oN")
611 || !strcmp(pVar->u.pszString, "ON")
612 || !strcmp(pVar->u.pszString, "enabled")
613 || !strcmp(pVar->u.pszString, "Enabled")
614 || !strcmp(pVar->u.pszString, "DISABLED"))
615 {
616 *pf = true;
617 return VINF_SUCCESS;
618 }
619 if ( !strcmp(pVar->u.pszString, "false")
620 || !strcmp(pVar->u.pszString, "False")
621 || !strcmp(pVar->u.pszString, "FALSE")
622 || !strcmp(pVar->u.pszString, "off")
623 || !strcmp(pVar->u.pszString, "Off")
624 || !strcmp(pVar->u.pszString, "OFF")
625 || !strcmp(pVar->u.pszString, "disabled")
626 || !strcmp(pVar->u.pszString, "Disabled")
627 || !strcmp(pVar->u.pszString, "DISABLED"))
628 {
629 *pf = false;
630 return VINF_SUCCESS;
631 }
632 return VERR_PARSE_INCORRECT_ARG_TYPE; /** @todo better error code! */
633
634 case DBGCVAR_TYPE_GC_FLAT:
635 case DBGCVAR_TYPE_GC_PHYS:
636 case DBGCVAR_TYPE_HC_FLAT:
637 case DBGCVAR_TYPE_HC_PHYS:
638 case DBGCVAR_TYPE_NUMBER:
639 *pf = pVar->u.u64Number != 0;
640 return VINF_SUCCESS;
641
642 case DBGCVAR_TYPE_HC_FAR:
643 case DBGCVAR_TYPE_GC_FAR:
644 case DBGCVAR_TYPE_SYMBOL:
645 default:
646 return VERR_PARSE_INCORRECT_ARG_TYPE;
647 }
648}
649
650
651/**
652 * Initializes the Command Helpers for a DBGC instance.
653 *
654 * @param pDbgc Pointer to the DBGC instance.
655 */
656void dbgcInitCmdHlp(PDBGC pDbgc)
657{
658 pDbgc->CmdHlp.pfnWrite = dbgcHlpWrite;
659 pDbgc->CmdHlp.pfnPrintfV = dbgcHlpPrintfV;
660 pDbgc->CmdHlp.pfnPrintf = dbgcHlpPrintf;
661 pDbgc->CmdHlp.pfnVBoxErrorV = dbgcHlpVBoxErrorV;
662 pDbgc->CmdHlp.pfnVBoxError = dbgcHlpVBoxError;
663 pDbgc->CmdHlp.pfnMemRead = dbgcHlpMemRead;
664 pDbgc->CmdHlp.pfnMemWrite = dbgcHlpMemWrite;
665 pDbgc->CmdHlp.pfnEval = dbgcHlpEval;
666 pDbgc->CmdHlp.pfnExec = dbgcHlpExec;
667 pDbgc->CmdHlp.pfnVarToDbgfAddr = dbgcHlpVarToDbgfAddr;
668 pDbgc->CmdHlp.pfnVarToBool = dbgcHlpVarToBool;
669}
670
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