VirtualBox

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

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

The Big Sun Rebranding Header Change

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