VirtualBox

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

Last change on this file since 93217 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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