VirtualBox

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

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

Got the DBGC parser testcase framework going. enough fun for now.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.1 KB
Line 
1/** $Id: DBGCCmdHlp.cpp 5686 2007-11-11 12:22:14Z 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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * 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 (VBOX_SUCCESS(rc) && pszFormat)
273 rc = pCmdHlp->pfnPrintfV(pCmdHlp, NULL, pszFormat, args);
274 break;
275 }
276 return rc;
277}
278
279
280/**
281 * Reports an error from a DBGF call.
282 *
283 * @returns VBox status code appropriate to return from a command.
284 * @param pCmdHlp Pointer to command helpers.
285 * @param rc The VBox status code returned by a DBGF call.
286 * @param pszFormat Format string for additional messages. Can be NULL.
287 * @param ... Format arguments, optional.
288 */
289static DECLCALLBACK(int) dbgcHlpVBoxError(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, ...)
290{
291 va_list args;
292 va_start(args, pszFormat);
293 int rcRet = pCmdHlp->pfnVBoxErrorV(pCmdHlp, rc, pszFormat, args);
294 va_end(args);
295 return rcRet;
296}
297
298
299/**
300 * Command helper for reading memory specified by a DBGC variable.
301 *
302 * @returns VBox status code appropriate to return from a command.
303 * @param pCmdHlp Pointer to the command callback structure.
304 * @param pVM VM handle if GC or physical HC address.
305 * @param pvBuffer Where to store the read data.
306 * @param cbRead Number of bytes to read.
307 * @param pVarPointer DBGC variable specifying where to start reading.
308 * @param pcbRead Where to store the number of bytes actually read.
309 * This optional, but it's useful when read GC virtual memory where a
310 * page in the requested range might not be present.
311 * If not specified not-present failure or end of a HC physical page
312 * will cause failure.
313 */
314static DECLCALLBACK(int) dbgcHlpMemRead(PDBGCCMDHLP pCmdHlp, PVM pVM, void *pvBuffer, size_t cbRead, PCDBGCVAR pVarPointer, size_t *pcbRead)
315{
316 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
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 {
337 /* Use DBGFR3AddrFromSelOff for the conversion. */
338 Assert(pDbgc->pVM);
339 DBGFADDRESS Address;
340 int rc = DBGFR3AddrFromSelOff(pDbgc->pVM, &Address, Var.u.GCFar.sel, Var.u.GCFar.off);
341 if (VBOX_FAILURE(rc))
342 return rc;
343
344 /* don't bother with flat selectors (for now). */
345 if (!DBGFADDRESS_IS_FLAT(&Address))
346 {
347 SELMSELINFO SelInfo;
348 rc = SELMR3GetSelectorInfo(pDbgc->pVM, Address.Sel, &SelInfo);
349 if (VBOX_SUCCESS(rc))
350 {
351 RTGCUINTPTR cb; /* -1 byte */
352 if (SELMSelInfoIsExpandDown(&SelInfo))
353 {
354 if ( !SelInfo.Raw.Gen.u1Granularity
355 && Address.off > UINT16_C(0xffff))
356 return VERR_OUT_OF_SELECTOR_BOUNDS;
357 if (Address.off <= SelInfo.cbLimit)
358 return VERR_OUT_OF_SELECTOR_BOUNDS;
359 cb = (SelInfo.Raw.Gen.u1Granularity ? UINT32_C(0xffffffff) : UINT32_C(0xffff)) - Address.off;
360 }
361 else
362 {
363 if (Address.off > SelInfo.cbLimit)
364 return VERR_OUT_OF_SELECTOR_BOUNDS;
365 cb = SelInfo.cbLimit - Address.off;
366 }
367 if (cbRead - 1 > cb)
368 {
369 if (!pcbRead)
370 return VERR_OUT_OF_SELECTOR_BOUNDS;
371 cbRead = cb + 1;
372 }
373 }
374
375 Var.enmType = DBGCVAR_TYPE_GC_FLAT;
376 Var.u.GCFlat = Address.FlatPtr;
377 }
378 break;
379 }
380
381 case DBGCVAR_TYPE_GC_FLAT:
382 case DBGCVAR_TYPE_GC_PHYS:
383 case DBGCVAR_TYPE_HC_FLAT:
384 case DBGCVAR_TYPE_HC_PHYS:
385 break;
386
387 case DBGCVAR_TYPE_HC_FAR: /* not supported yet! */
388 default:
389 return VERR_NOT_IMPLEMENTED;
390 }
391
392
393
394 /*
395 * Copy page by page.
396 */
397 size_t cbLeft = cbRead;
398 for (;;)
399 {
400 /*
401 * Calc read size.
402 */
403 size_t cb = RT_MIN(PAGE_SIZE, cbLeft);
404 switch (pVarPointer->enmType)
405 {
406 case DBGCVAR_TYPE_GC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCFlat & PAGE_OFFSET_MASK)); break;
407 case DBGCVAR_TYPE_GC_PHYS: cb = RT_MIN(cb, PAGE_SIZE - (Var.u.GCPhys & PAGE_OFFSET_MASK)); break;
408 case DBGCVAR_TYPE_HC_FLAT: cb = RT_MIN(cb, PAGE_SIZE - ((uintptr_t)Var.u.pvHCFlat & PAGE_OFFSET_MASK)); break;
409 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! */
410 default: break;
411 }
412
413 /*
414 * Perform read.
415 */
416 int rc;
417 switch (Var.enmType)
418 {
419 case DBGCVAR_TYPE_GC_FLAT:
420 rc = MMR3ReadGCVirt(pVM, pvBuffer, Var.u.GCFlat, cb);
421 break;
422 case DBGCVAR_TYPE_GC_PHYS:
423 rc = PGMPhysReadGCPhys(pVM, pvBuffer, Var.u.GCPhys, cb);
424 break;
425
426 case DBGCVAR_TYPE_HC_PHYS:
427 case DBGCVAR_TYPE_HC_FLAT:
428 case DBGCVAR_TYPE_HC_FAR:
429 {
430 DBGCVAR Var2;
431 rc = dbgcOpAddrFlat(pDbgc, &Var, &Var2);
432 if (VBOX_SUCCESS(rc))
433 {
434 /** @todo protect this!!! */
435 memcpy(pvBuffer, Var2.u.pvHCFlat, cb);
436 rc = 0;
437 }
438 else
439 rc = VERR_INVALID_POINTER;
440 break;
441 }
442
443 default:
444 rc = VERR_PARSE_INCORRECT_ARG_TYPE;
445 }
446
447 /*
448 * Check for failure.
449 */
450 if (VBOX_FAILURE(rc))
451 {
452 if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0)
453 return VINF_SUCCESS;
454 return rc;
455 }
456
457 /*
458 * Next.
459 */
460 cbLeft -= cb;
461 if (!cbLeft)
462 break;
463 pvBuffer = (char *)pvBuffer + cb;
464 rc = pCmdHlp->pfnEval(pCmdHlp, &Var, "%DV + %d", &Var, cb);
465 if (VBOX_FAILURE(rc))
466 {
467 if (pcbRead && (*pcbRead = cbRead - cbLeft) > 0)
468 return VINF_SUCCESS;
469 return rc;
470 }
471 }
472
473 /*
474 * Done
475 */
476 if (pcbRead)
477 *pcbRead = cbRead;
478 return 0;
479}
480
481/**
482 * Command helper for writing memory specified by a DBGC variable.
483 *
484 * @returns VBox status code appropriate to return from a command.
485 * @param pCmdHlp Pointer to the command callback structure.
486 * @param pVM VM handle if GC or physical HC address.
487 * @param pvBuffer What to write.
488 * @param cbWrite Number of bytes to write.
489 * @param pVarPointer DBGC variable specifying where to start reading.
490 * @param pcbWritten Where to store the number of bytes written.
491 * This is optional. If NULL be aware that some of the buffer
492 * might have been written to the specified address.
493 */
494static DECLCALLBACK(int) dbgcHlpMemWrite(PDBGCCMDHLP pCmdHlp, PVM pVM, const void *pvBuffer, size_t cbWrite, PCDBGCVAR pVarPointer, size_t *pcbWritten)
495{
496 NOREF(pCmdHlp); NOREF(pVM); NOREF(pvBuffer); NOREF(cbWrite); NOREF(pVarPointer); NOREF(pcbWritten);
497 return VERR_NOT_IMPLEMENTED;
498}
499
500
501/**
502 * Evaluates an expression.
503 * (Hopefully the parser and functions are fully reentrant.)
504 *
505 * @returns VBox status code appropriate to return from a command.
506 * @param pCmdHlp Pointer to the command callback structure.
507 * @param pResult Where to store the result.
508 * @param pszExpr The expression. Format string with the format DBGC extensions.
509 * @param ... Format arguments.
510 */
511static DECLCALLBACK(int) dbgcHlpEval(PDBGCCMDHLP pCmdHlp, PDBGCVAR pResult, const char *pszExpr, ...)
512{
513 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
514
515 /*
516 * Format the expression.
517 */
518 char szExprFormatted[2048];
519 va_list args;
520 va_start(args, pszExpr);
521 size_t cb = RTStrPrintfExV(dbgcStringFormatter, pDbgc, szExprFormatted, sizeof(szExprFormatted), pszExpr, args);
522 va_end(args);
523 /* ignore overflows. */
524
525 return dbgcEvalSub(pDbgc, &szExprFormatted[0], cb, pResult);
526}
527
528
529/**
530 * Executes one command expression.
531 * (Hopefully the parser and functions are fully reentrant.)
532 *
533 * @returns VBox status code appropriate to return from a command.
534 * @param pCmdHlp Pointer to the command callback structure.
535 * @param pszExpr The expression. Format string with the format DBGC extensions.
536 * @param ... Format arguments.
537 */
538static DECLCALLBACK(int) dbgcHlpExec(PDBGCCMDHLP pCmdHlp, const char *pszExpr, ...)
539{
540 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
541 /* Save the scratch state. */
542 char *pszScratch = pDbgc->pszScratch;
543 unsigned iArg = pDbgc->iArg;
544
545 /*
546 * Format the expression.
547 */
548 va_list args;
549 va_start(args, pszExpr);
550 size_t cbScratch = sizeof(pDbgc->achScratch) - (pDbgc->pszScratch - &pDbgc->achScratch[0]);
551 size_t cb = RTStrPrintfExV(dbgcStringFormatter, pDbgc, pDbgc->pszScratch, cbScratch, pszExpr, args);
552 va_end(args);
553 if (cb >= cbScratch)
554 return VERR_BUFFER_OVERFLOW;
555
556 /*
557 * Execute the command.
558 * We save and restore the arg index and scratch buffer pointer.
559 */
560 pDbgc->pszScratch = pDbgc->pszScratch + cb + 1;
561 int rc = dbgcProcessCommand(pDbgc, pszScratch, cb, false /* fNoExecute */);
562
563 /* Restore the scratch state. */
564 pDbgc->iArg = iArg;
565 pDbgc->pszScratch = pszScratch;
566
567 return rc;
568}
569
570
571/**
572 * Converts a DBGC variable to a DBGF address structure.
573 *
574 * @returns VBox status code.
575 * @param pCmdHlp Pointer to the command callback structure.
576 * @param pVar The variable to convert.
577 * @param pAddress The target address.
578 */
579static DECLCALLBACK(int) dbgcHlpVarToDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PDBGFADDRESS pAddress)
580{
581 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
582 return dbgcVarToDbgfAddr(pDbgc, pVar, pAddress);
583}
584
585
586/**
587 * Converts a DBGC variable to a boolean.
588 *
589 * @returns VBox status code.
590 * @param pCmdHlp Pointer to the command callback structure.
591 * @param pVar The variable to convert.
592 * @param pf Where to store the boolean.
593 */
594static DECLCALLBACK(int) dbgcHlpVarToBool(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, bool *pf)
595{
596 PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
597 NOREF(pDbgc);
598
599 switch (pVar->enmType)
600 {
601 case DBGCVAR_TYPE_STRING:
602 /** @todo add strcasecmp / stricmp wrappers to iprt/string.h. */
603 if ( !strcmp(pVar->u.pszString, "true")
604 || !strcmp(pVar->u.pszString, "True")
605 || !strcmp(pVar->u.pszString, "TRUE")
606 || !strcmp(pVar->u.pszString, "on")
607 || !strcmp(pVar->u.pszString, "On")
608 || !strcmp(pVar->u.pszString, "oN")
609 || !strcmp(pVar->u.pszString, "ON")
610 || !strcmp(pVar->u.pszString, "enabled")
611 || !strcmp(pVar->u.pszString, "Enabled")
612 || !strcmp(pVar->u.pszString, "DISABLED"))
613 {
614 *pf = true;
615 return VINF_SUCCESS;
616 }
617 if ( !strcmp(pVar->u.pszString, "false")
618 || !strcmp(pVar->u.pszString, "False")
619 || !strcmp(pVar->u.pszString, "FALSE")
620 || !strcmp(pVar->u.pszString, "off")
621 || !strcmp(pVar->u.pszString, "Off")
622 || !strcmp(pVar->u.pszString, "OFF")
623 || !strcmp(pVar->u.pszString, "disabled")
624 || !strcmp(pVar->u.pszString, "Disabled")
625 || !strcmp(pVar->u.pszString, "DISABLED"))
626 {
627 *pf = false;
628 return VINF_SUCCESS;
629 }
630 return VERR_PARSE_INCORRECT_ARG_TYPE; /** @todo better error code! */
631
632 case DBGCVAR_TYPE_GC_FLAT:
633 case DBGCVAR_TYPE_GC_PHYS:
634 case DBGCVAR_TYPE_HC_FLAT:
635 case DBGCVAR_TYPE_HC_PHYS:
636 case DBGCVAR_TYPE_NUMBER:
637 *pf = pVar->u.u64Number != 0;
638 return VINF_SUCCESS;
639
640 case DBGCVAR_TYPE_HC_FAR:
641 case DBGCVAR_TYPE_GC_FAR:
642 case DBGCVAR_TYPE_SYMBOL:
643 default:
644 return VERR_PARSE_INCORRECT_ARG_TYPE;
645 }
646}
647
648
649/**
650 * Initializes the Command Helpers for a DBGC instance.
651 *
652 * @param pDbgc Pointer to the DBGC instance.
653 */
654void dbgcInitCmdHlp(PDBGC pDbgc)
655{
656 pDbgc->CmdHlp.pfnWrite = dbgcHlpWrite;
657 pDbgc->CmdHlp.pfnPrintfV = dbgcHlpPrintfV;
658 pDbgc->CmdHlp.pfnPrintf = dbgcHlpPrintf;
659 pDbgc->CmdHlp.pfnVBoxErrorV = dbgcHlpVBoxErrorV;
660 pDbgc->CmdHlp.pfnVBoxError = dbgcHlpVBoxError;
661 pDbgc->CmdHlp.pfnMemRead = dbgcHlpMemRead;
662 pDbgc->CmdHlp.pfnMemWrite = dbgcHlpMemWrite;
663 pDbgc->CmdHlp.pfnEval = dbgcHlpEval;
664 pDbgc->CmdHlp.pfnExec = dbgcHlpExec;
665 pDbgc->CmdHlp.pfnVarToDbgfAddr = dbgcHlpVarToDbgfAddr;
666 pDbgc->CmdHlp.pfnVarToBool = dbgcHlpVarToBool;
667}
668
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