VirtualBox

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

Last change on this file since 56296 was 56296, checked in by vboxsync, 9 years ago

Debugger: Updated (C) year.

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