VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGCOps.cpp@ 31530

Last change on this file since 31530 was 31530, checked in by vboxsync, 14 years ago

Debugger: Updated the file headers.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 54.3 KB
Line 
1/* $Id: DBGCOps.cpp 31530 2010-08-10 12:24:45Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Operators.
4 */
5
6/*
7 * Copyright (C) 2006-2010 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/dbgf.h>
25#include <VBox/vm.h>
26#include <VBox/vmm.h>
27#include <VBox/mm.h>
28#include <VBox/pgm.h>
29#include <VBox/selm.h>
30#include <VBox/dis.h>
31#include <VBox/param.h>
32#include <VBox/err.h>
33#include <VBox/log.h>
34
35#include <iprt/alloc.h>
36#include <iprt/alloca.h>
37#include <iprt/string.h>
38#include <iprt/assert.h>
39#include <iprt/ctype.h>
40
41#include <stdlib.h>
42#include <stdio.h>
43
44#include "DBGCInternal.h"
45
46
47/*******************************************************************************
48* Internal Functions *
49*******************************************************************************/
50static DECLCALLBACK(int) dbgcOpMinus(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
51static DECLCALLBACK(int) dbgcOpPluss(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
52static DECLCALLBACK(int) dbgcOpBooleanNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
53static DECLCALLBACK(int) dbgcOpBitwiseNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
54static DECLCALLBACK(int) dbgcOpVar(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
55
56static DECLCALLBACK(int) dbgcOpAddrFar(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
57static DECLCALLBACK(int) dbgcOpMult(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
58static DECLCALLBACK(int) dbgcOpDiv(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
59static DECLCALLBACK(int) dbgcOpMod(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
60static DECLCALLBACK(int) dbgcOpAdd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
61static DECLCALLBACK(int) dbgcOpSub(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
62static DECLCALLBACK(int) dbgcOpBitwiseShiftLeft(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
63static DECLCALLBACK(int) dbgcOpBitwiseShiftRight(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
64static DECLCALLBACK(int) dbgcOpBitwiseAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
65static DECLCALLBACK(int) dbgcOpBitwiseXor(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
66static DECLCALLBACK(int) dbgcOpBitwiseOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
67static DECLCALLBACK(int) dbgcOpBooleanAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
68static DECLCALLBACK(int) dbgcOpBooleanOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
69static DECLCALLBACK(int) dbgcOpRangeLength(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
70static DECLCALLBACK(int) dbgcOpRangeLengthBytes(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
71static DECLCALLBACK(int) dbgcOpRangeTo(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
72
73
74/*******************************************************************************
75* Global Variables *
76*******************************************************************************/
77/** Operators. */
78const DBGCOP g_aOps[] =
79{
80 /* szName is initialized as a 4 char array because of M$C elsewise optimizing it away in /Ox mode (the 'const char' vs 'char' problem). */
81 /* szName, cchName, fBinary, iPrecedence, pfnHandlerUnary, pfnHandlerBitwise */
82 { {'-'}, 1, false, 1, dbgcOpMinus, NULL, "Unary minus." },
83 { {'+'}, 1, false, 1, dbgcOpPluss, NULL, "Unary plus." },
84 { {'!'}, 1, false, 1, dbgcOpBooleanNot, NULL, "Boolean not." },
85 { {'~'}, 1, false, 1, dbgcOpBitwiseNot, NULL, "Bitwise complement." },
86 { {':'}, 1, true, 2, NULL, dbgcOpAddrFar, "Far pointer." },
87 { {'%'}, 1, false, 3, dbgcOpAddrFlat, NULL, "Flat address." },
88 { {'%','%'}, 2, false, 3, dbgcOpAddrPhys, NULL, "Physical address." },
89 { {'#'}, 1, false, 3, dbgcOpAddrHost, NULL, "Flat host address." },
90 { {'#','%','%'}, 3, false, 3, dbgcOpAddrHostPhys, NULL, "Physical host address." },
91 { {'$'}, 1, false, 3, dbgcOpVar, NULL, "Reference a variable." },
92 { {'*'}, 1, true, 10, NULL, dbgcOpMult, "Multiplication." },
93 { {'/'}, 1, true, 11, NULL, dbgcOpDiv, "Division." },
94 { {'%'}, 1, true, 12, NULL, dbgcOpMod, "Modulus." },
95 { {'+'}, 1, true, 13, NULL, dbgcOpAdd, "Addition." },
96 { {'-'}, 1, true, 14, NULL, dbgcOpSub, "Subtraction." },
97 { {'<','<'}, 2, true, 15, NULL, dbgcOpBitwiseShiftLeft, "Bitwise left shift." },
98 { {'>','>'}, 2, true, 16, NULL, dbgcOpBitwiseShiftRight, "Bitwise right shift." },
99 { {'&'}, 1, true, 17, NULL, dbgcOpBitwiseAnd, "Bitwise and." },
100 { {'^'}, 1, true, 18, NULL, dbgcOpBitwiseXor, "Bitwise exclusiv or." },
101 { {'|'}, 1, true, 19, NULL, dbgcOpBitwiseOr, "Bitwise inclusive or." },
102 { {'&','&'}, 2, true, 20, NULL, dbgcOpBooleanAnd, "Boolean and." },
103 { {'|','|'}, 2, true, 21, NULL, dbgcOpBooleanOr, "Boolean or." },
104 { {'L'}, 1, true, 22, NULL, dbgcOpRangeLength, "Range elements." },
105 { {'L','B'}, 2, true, 23, NULL, dbgcOpRangeLengthBytes, "Range bytes." },
106 { {'T'}, 1, true, 24, NULL, dbgcOpRangeTo, "Range to." }
107};
108
109/** Number of operators in the operator array. */
110const unsigned g_cOps = RT_ELEMENTS(g_aOps);
111
112
113/**
114 * Minus (unary).
115 *
116 * @returns 0 on success.
117 * @returns VBox evaluation / parsing error code on failure.
118 * The caller does the bitching.
119 * @param pDbgc Debugger console instance data.
120 * @param pArg The argument.
121 * @param pResult Where to store the result.
122 */
123static DECLCALLBACK(int) dbgcOpMinus(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
124{
125// LogFlow(("dbgcOpMinus\n"));
126 *pResult = *pArg;
127 switch (pArg->enmType)
128 {
129 case DBGCVAR_TYPE_GC_FLAT:
130 pResult->u.GCFlat = -(RTGCINTPTR)pResult->u.GCFlat;
131 break;
132 case DBGCVAR_TYPE_GC_FAR:
133 pResult->u.GCFar.off = -(int32_t)pResult->u.GCFar.off;
134 break;
135 case DBGCVAR_TYPE_GC_PHYS:
136 pResult->u.GCPhys = (RTGCPHYS) -(int64_t)pResult->u.GCPhys;
137 break;
138 case DBGCVAR_TYPE_HC_FLAT:
139 pResult->u.pvHCFlat = (void *) -(intptr_t)pResult->u.pvHCFlat;
140 break;
141 case DBGCVAR_TYPE_HC_FAR:
142 pResult->u.HCFar.off = -(int32_t)pResult->u.HCFar.off;
143 break;
144 case DBGCVAR_TYPE_HC_PHYS:
145 pResult->u.HCPhys = (RTHCPHYS) -(int64_t)pResult->u.HCPhys;
146 break;
147 case DBGCVAR_TYPE_NUMBER:
148 pResult->u.u64Number = -(int64_t)pResult->u.u64Number;
149 break;
150
151 case DBGCVAR_TYPE_UNKNOWN:
152 case DBGCVAR_TYPE_STRING:
153 default:
154 return VERR_PARSE_INCORRECT_ARG_TYPE;
155 }
156 NOREF(pDbgc);
157 return 0;
158}
159
160
161/**
162 * Pluss (unary).
163 *
164 * @returns 0 on success.
165 * @returns VBox evaluation / parsing error code on failure.
166 * The caller does the bitching.
167 * @param pDbgc Debugger console instance data.
168 * @param pArg The argument.
169 * @param pResult Where to store the result.
170 */
171static DECLCALLBACK(int) dbgcOpPluss(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
172{
173// LogFlow(("dbgcOpPluss\n"));
174 *pResult = *pArg;
175 switch (pArg->enmType)
176 {
177 case DBGCVAR_TYPE_GC_FLAT:
178 case DBGCVAR_TYPE_GC_FAR:
179 case DBGCVAR_TYPE_GC_PHYS:
180 case DBGCVAR_TYPE_HC_FLAT:
181 case DBGCVAR_TYPE_HC_FAR:
182 case DBGCVAR_TYPE_HC_PHYS:
183 case DBGCVAR_TYPE_NUMBER:
184 break;
185
186 case DBGCVAR_TYPE_UNKNOWN:
187 case DBGCVAR_TYPE_STRING:
188 default:
189 return VERR_PARSE_INCORRECT_ARG_TYPE;
190 }
191 NOREF(pDbgc);
192 return 0;
193}
194
195
196/**
197 * Boolean not (unary).
198 *
199 * @returns 0 on success.
200 * @returns VBox evaluation / parsing error code on failure.
201 * The caller does the bitching.
202 * @param pDbgc Debugger console instance data.
203 * @param pArg The argument.
204 * @param pResult Where to store the result.
205 */
206static DECLCALLBACK(int) dbgcOpBooleanNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
207{
208// LogFlow(("dbgcOpBooleanNot\n"));
209 *pResult = *pArg;
210 switch (pArg->enmType)
211 {
212 case DBGCVAR_TYPE_GC_FLAT:
213 pResult->u.u64Number = !pResult->u.GCFlat;
214 break;
215 case DBGCVAR_TYPE_GC_FAR:
216 pResult->u.u64Number = !pResult->u.GCFar.off && pResult->u.GCFar.sel <= 3;
217 break;
218 case DBGCVAR_TYPE_GC_PHYS:
219 pResult->u.u64Number = !pResult->u.GCPhys;
220 break;
221 case DBGCVAR_TYPE_HC_FLAT:
222 pResult->u.u64Number = !pResult->u.pvHCFlat;
223 break;
224 case DBGCVAR_TYPE_HC_FAR:
225 pResult->u.u64Number = !pResult->u.HCFar.off && pResult->u.HCFar.sel <= 3;
226 break;
227 case DBGCVAR_TYPE_HC_PHYS:
228 pResult->u.u64Number = !pResult->u.HCPhys;
229 break;
230 case DBGCVAR_TYPE_NUMBER:
231 pResult->u.u64Number = !pResult->u.u64Number;
232 break;
233 case DBGCVAR_TYPE_STRING:
234 pResult->u.u64Number = !pResult->u64Range;
235 break;
236
237 case DBGCVAR_TYPE_UNKNOWN:
238 default:
239 return VERR_PARSE_INCORRECT_ARG_TYPE;
240 }
241 pResult->enmType = DBGCVAR_TYPE_NUMBER;
242 NOREF(pDbgc);
243 return 0;
244}
245
246
247/**
248 * Bitwise not (unary).
249 *
250 * @returns 0 on success.
251 * @returns VBox evaluation / parsing error code on failure.
252 * The caller does the bitching.
253 * @param pDbgc Debugger console instance data.
254 * @param pArg The argument.
255 * @param pResult Where to store the result.
256 */
257static DECLCALLBACK(int) dbgcOpBitwiseNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
258{
259// LogFlow(("dbgcOpBitwiseNot\n"));
260 *pResult = *pArg;
261 switch (pArg->enmType)
262 {
263 case DBGCVAR_TYPE_GC_FLAT:
264 pResult->u.GCFlat = ~pResult->u.GCFlat;
265 break;
266 case DBGCVAR_TYPE_GC_FAR:
267 pResult->u.GCFar.off = ~pResult->u.GCFar.off;
268 break;
269 case DBGCVAR_TYPE_GC_PHYS:
270 pResult->u.GCPhys = ~pResult->u.GCPhys;
271 break;
272 case DBGCVAR_TYPE_HC_FLAT:
273 pResult->u.pvHCFlat = (void *)~(uintptr_t)pResult->u.pvHCFlat;
274 break;
275 case DBGCVAR_TYPE_HC_FAR:
276 pResult->u.HCFar.off= ~pResult->u.HCFar.off;
277 break;
278 case DBGCVAR_TYPE_HC_PHYS:
279 pResult->u.HCPhys = ~pResult->u.HCPhys;
280 break;
281 case DBGCVAR_TYPE_NUMBER:
282 pResult->u.u64Number = ~pResult->u.u64Number;
283 break;
284
285 case DBGCVAR_TYPE_UNKNOWN:
286 case DBGCVAR_TYPE_STRING:
287 default:
288 return VERR_PARSE_INCORRECT_ARG_TYPE;
289 }
290 NOREF(pDbgc);
291 return 0;
292}
293
294
295/**
296 * Reference variable (unary).
297 *
298 * @returns 0 on success.
299 * @returns VBox evaluation / parsing error code on failure.
300 * The caller does the bitching.
301 * @param pDbgc Debugger console instance data.
302 * @param pArg The argument.
303 * @param pResult Where to store the result.
304 */
305static DECLCALLBACK(int) dbgcOpVar(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
306{
307// LogFlow(("dbgcOpVar: %s\n", pArg->u.pszString));
308 /*
309 * Parse sanity.
310 */
311 if (pArg->enmType != DBGCVAR_TYPE_STRING)
312 return VERR_PARSE_INCORRECT_ARG_TYPE;
313
314 /*
315 * Lookup the variable.
316 */
317 const char *pszVar = pArg->u.pszString;
318 for (unsigned iVar = 0; iVar < pDbgc->cVars; iVar++)
319 {
320 if (!strcmp(pszVar, pDbgc->papVars[iVar]->szName))
321 {
322 *pResult = pDbgc->papVars[iVar]->Var;
323 return 0;
324 }
325 }
326
327 return VERR_PARSE_VARIABLE_NOT_FOUND;
328}
329
330
331/**
332 * Flat address (unary).
333 *
334 * @returns VINF_SUCCESS on success.
335 * @returns VBox evaluation / parsing error code on failure.
336 * The caller does the bitching.
337 * @param pDbgc Debugger console instance data.
338 * @param pArg The argument.
339 * @param pResult Where to store the result.
340 */
341DECLCALLBACK(int) dbgcOpAddrFlat(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
342{
343// LogFlow(("dbgcOpAddrFlat\n"));
344 int rc;
345 *pResult = *pArg;
346
347 switch (pArg->enmType)
348 {
349 case DBGCVAR_TYPE_GC_FLAT:
350 return VINF_SUCCESS;
351
352 case DBGCVAR_TYPE_GC_FAR:
353 {
354 Assert(pDbgc->pVM);
355 DBGFADDRESS Address;
356 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
357 if (RT_SUCCESS(rc))
358 {
359 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
360 pResult->u.GCFlat = Address.FlatPtr;
361 return VINF_SUCCESS;
362 }
363 return VERR_PARSE_CONVERSION_FAILED;
364 }
365
366 case DBGCVAR_TYPE_GC_PHYS:
367 //rc = MMR3PhysGCPhys2GCVirtEx(pDbgc->pVM, pResult->u.GCPhys, ..., &pResult->u.GCFlat); - yea, sure.
368 return VERR_PARSE_INCORRECT_ARG_TYPE;
369
370 case DBGCVAR_TYPE_HC_FLAT:
371 return VINF_SUCCESS;
372
373 case DBGCVAR_TYPE_HC_FAR:
374 return VERR_PARSE_INCORRECT_ARG_TYPE;
375
376 case DBGCVAR_TYPE_HC_PHYS:
377 Assert(pDbgc->pVM);
378 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
379 rc = MMR3HCPhys2HCVirt(pDbgc->pVM, pResult->u.HCPhys, &pResult->u.pvHCFlat);
380 if (RT_SUCCESS(rc))
381 return VINF_SUCCESS;
382 return VERR_PARSE_CONVERSION_FAILED;
383
384 case DBGCVAR_TYPE_NUMBER:
385 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
386 pResult->u.GCFlat = (RTGCPTR)pResult->u.u64Number;
387 return VINF_SUCCESS;
388
389 case DBGCVAR_TYPE_STRING:
390 return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_GC_FLAT, pResult);
391
392 case DBGCVAR_TYPE_UNKNOWN:
393 default:
394 return VERR_PARSE_INCORRECT_ARG_TYPE;
395 }
396}
397
398
399/**
400 * Physical address (unary).
401 *
402 * @returns 0 on success.
403 * @returns VBox evaluation / parsing error code on failure.
404 * The caller does the bitching.
405 * @param pDbgc Debugger console instance data.
406 * @param pArg The argument.
407 * @param pResult Where to store the result.
408 */
409DECLCALLBACK(int) dbgcOpAddrPhys(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
410{
411// LogFlow(("dbgcOpAddrPhys\n"));
412 int rc;
413 DBGFADDRESS Address;
414
415 *pResult = *pArg;
416 switch (pArg->enmType)
417 {
418 case DBGCVAR_TYPE_GC_FLAT:
419 Assert(pDbgc->pVM);
420 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
421 rc = DBGFR3AddrToPhys(pDbgc->pVM, pDbgc->idCpu,
422 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
423 &pResult->u.GCPhys);
424 if (RT_SUCCESS(rc))
425 return 0;
426 return VERR_PARSE_CONVERSION_FAILED;
427
428 case DBGCVAR_TYPE_GC_FAR:
429 Assert(pDbgc->pVM);
430 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
431 if (RT_SUCCESS(rc))
432 {
433 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
434 rc = DBGFR3AddrToPhys(pDbgc->pVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
435 if (RT_SUCCESS(rc))
436 return 0;
437 }
438 return VERR_PARSE_CONVERSION_FAILED;
439
440 case DBGCVAR_TYPE_GC_PHYS:
441 return 0;
442
443 case DBGCVAR_TYPE_HC_FLAT:
444 Assert(pDbgc->pVM);
445 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
446 rc = PGMR3DbgR3Ptr2GCPhys(pDbgc->pVM, pArg->u.pvHCFlat, &pResult->u.GCPhys);
447 if (RT_SUCCESS(rc))
448 return 0;
449 /** @todo more memory types! */
450 return VERR_PARSE_CONVERSION_FAILED;
451
452 case DBGCVAR_TYPE_HC_FAR:
453 return VERR_PARSE_INCORRECT_ARG_TYPE;
454
455 case DBGCVAR_TYPE_HC_PHYS:
456 return 0;
457
458 case DBGCVAR_TYPE_NUMBER:
459 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
460 pResult->u.GCPhys = (RTGCPHYS)pResult->u.u64Number;
461 return 0;
462
463 case DBGCVAR_TYPE_STRING:
464 return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_GC_PHYS, pResult);
465
466 case DBGCVAR_TYPE_UNKNOWN:
467 default:
468 return VERR_PARSE_INCORRECT_ARG_TYPE;
469 }
470 return 0;
471}
472
473
474/**
475 * Physical host address (unary).
476 *
477 * @returns 0 on success.
478 * @returns VBox evaluation / parsing error code on failure.
479 * The caller does the bitching.
480 * @param pDbgc Debugger console instance data.
481 * @param pArg The argument.
482 * @param pResult Where to store the result.
483 */
484DECLCALLBACK(int) dbgcOpAddrHostPhys(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
485{
486// LogFlow(("dbgcOpAddrPhys\n"));
487 DBGFADDRESS Address;
488 int rc;
489
490 *pResult = *pArg;
491 switch (pArg->enmType)
492 {
493 case DBGCVAR_TYPE_GC_FLAT:
494 Assert(pDbgc->pVM);
495 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
496 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu,
497 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
498 &pResult->u.GCPhys);
499 if (RT_SUCCESS(rc))
500 return 0;
501 return VERR_PARSE_CONVERSION_FAILED;
502
503 case DBGCVAR_TYPE_GC_FAR:
504 {
505 Assert(pDbgc->pVM);
506 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
507 if (RT_SUCCESS(rc))
508 {
509 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
510 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
511 if (RT_SUCCESS(rc))
512 return 0;
513 }
514 return VERR_PARSE_CONVERSION_FAILED;
515 }
516
517 case DBGCVAR_TYPE_GC_PHYS:
518 Assert(pDbgc->pVM);
519 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
520 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu,
521 DBGFR3AddrFromPhys(pDbgc->pVM, &Address, pArg->u.GCPhys),
522 &pResult->u.GCPhys);
523 if (RT_SUCCESS(rc))
524 return 0;
525 return VERR_PARSE_CONVERSION_FAILED;
526
527 case DBGCVAR_TYPE_HC_FLAT:
528 Assert(pDbgc->pVM);
529 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
530 rc = PGMR3DbgR3Ptr2HCPhys(pDbgc->pVM, pArg->u.pvHCFlat, &pResult->u.HCPhys);
531 if (RT_SUCCESS(rc))
532 return 0;
533 /** @todo more memory types! */
534 return VERR_PARSE_CONVERSION_FAILED;
535
536 case DBGCVAR_TYPE_HC_FAR:
537 return VERR_PARSE_INCORRECT_ARG_TYPE;
538
539 case DBGCVAR_TYPE_HC_PHYS:
540 return 0;
541
542 case DBGCVAR_TYPE_NUMBER:
543 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
544 pResult->u.HCPhys = (RTGCPHYS)pResult->u.u64Number;
545 return 0;
546
547 case DBGCVAR_TYPE_STRING:
548 return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_HC_PHYS, pResult);
549
550 case DBGCVAR_TYPE_UNKNOWN:
551 default:
552 return VERR_PARSE_INCORRECT_ARG_TYPE;
553 }
554 return 0;
555}
556
557
558/**
559 * Host address (unary).
560 *
561 * @returns 0 on success.
562 * @returns VBox evaluation / parsing error code on failure.
563 * The caller does the bitching.
564 * @param pDbgc Debugger console instance data.
565 * @param pArg The argument.
566 * @param pResult Where to store the result.
567 */
568DECLCALLBACK(int) dbgcOpAddrHost(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
569{
570 Log6(("dbgcOpAddrHost\n"));
571 int rc;
572 DBGFADDRESS Address;
573
574 *pResult = *pArg;
575 switch (pArg->enmType)
576 {
577 case DBGCVAR_TYPE_GC_FLAT:
578 Assert(pDbgc->pVM);
579 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
580 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu,
581 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
582 false /*fReadOnly */,
583 &pResult->u.pvHCFlat);
584 if (RT_SUCCESS(rc))
585 return 0;
586 return VERR_PARSE_CONVERSION_FAILED;
587
588 case DBGCVAR_TYPE_GC_FAR:
589 Assert(pDbgc->pVM);
590 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
591 if (RT_SUCCESS(rc))
592 {
593 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
594 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu, &Address,
595 false /*fReadOnly*/, &pResult->u.pvHCFlat);
596 if (RT_SUCCESS(rc))
597 return 0;
598 }
599 return VERR_PARSE_CONVERSION_FAILED;
600
601 case DBGCVAR_TYPE_GC_PHYS:
602 Assert(pDbgc->pVM);
603 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
604 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu,
605 DBGFR3AddrFromPhys(pDbgc->pVM, &Address, pArg->u.GCPhys),
606 false /*fReadOnly */,
607 &pResult->u.pvHCFlat);
608 if (RT_SUCCESS(rc))
609 return 0;
610 return VERR_PARSE_CONVERSION_FAILED;
611
612 case DBGCVAR_TYPE_HC_FLAT:
613 return 0;
614
615 case DBGCVAR_TYPE_HC_FAR:
616 case DBGCVAR_TYPE_HC_PHYS:
617 /** @todo !*/
618 return VERR_PARSE_CONVERSION_FAILED;
619
620 case DBGCVAR_TYPE_NUMBER:
621 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
622 pResult->u.pvHCFlat = (void *)(uintptr_t)pResult->u.u64Number;
623 return 0;
624
625 case DBGCVAR_TYPE_STRING:
626 return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_HC_FLAT, pResult);
627
628 case DBGCVAR_TYPE_UNKNOWN:
629 default:
630 return VERR_PARSE_INCORRECT_ARG_TYPE;
631 }
632}
633
634
635/**
636 * Bitwise not (unary).
637 *
638 * @returns 0 on success.
639 * @returns VBox evaluation / parsing error code on failure.
640 * The caller does the bitching.
641 * @param pDbgc Debugger console instance data.
642 * @param pArg The argument.
643 * @param pResult Where to store the result.
644 */
645static DECLCALLBACK(int) dbgcOpAddrFar(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
646{
647// LogFlow(("dbgcOpAddrFar\n"));
648 int rc;
649
650 switch (pArg1->enmType)
651 {
652 case DBGCVAR_TYPE_STRING:
653 rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_NUMBER, pResult);
654 if (RT_FAILURE(rc))
655 return rc;
656 break;
657 case DBGCVAR_TYPE_NUMBER:
658 *pResult = *pArg1;
659 break;
660
661 case DBGCVAR_TYPE_GC_FLAT:
662 case DBGCVAR_TYPE_GC_FAR:
663 case DBGCVAR_TYPE_GC_PHYS:
664 case DBGCVAR_TYPE_HC_FLAT:
665 case DBGCVAR_TYPE_HC_FAR:
666 case DBGCVAR_TYPE_HC_PHYS:
667 case DBGCVAR_TYPE_UNKNOWN:
668 default:
669 return VERR_PARSE_INCORRECT_ARG_TYPE;
670 }
671 pResult->u.GCFar.sel = (RTSEL)pResult->u.u64Number;
672
673 /* common code for the two types we support. */
674 switch (pArg2->enmType)
675 {
676 case DBGCVAR_TYPE_GC_FLAT:
677 pResult->u.GCFar.off = pArg2->u.GCFlat;
678 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
679 break;
680
681 case DBGCVAR_TYPE_HC_FLAT:
682 pResult->u.HCFar.off = pArg2->u.GCFlat;
683 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
684 break;
685
686 case DBGCVAR_TYPE_NUMBER:
687 pResult->u.GCFar.off = (RTGCPTR)pArg2->u.u64Number;
688 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
689 break;
690
691 case DBGCVAR_TYPE_STRING:
692 {
693 DBGCVAR Var;
694 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
695 if (RT_FAILURE(rc))
696 return rc;
697 pResult->u.GCFar.off = (RTGCPTR)Var.u.u64Number;
698 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
699 break;
700 }
701
702 case DBGCVAR_TYPE_GC_FAR:
703 case DBGCVAR_TYPE_GC_PHYS:
704 case DBGCVAR_TYPE_HC_FAR:
705 case DBGCVAR_TYPE_HC_PHYS:
706 case DBGCVAR_TYPE_UNKNOWN:
707 default:
708 return VERR_PARSE_INCORRECT_ARG_TYPE;
709 }
710 return 0;
711
712}
713
714
715/**
716 * Multiplication operator (binary).
717 *
718 * @returns 0 on success.
719 * @returns VBox evaluation / parsing error code on failure.
720 * The caller does the bitching.
721 * @param pDbgc Debugger console instance data.
722 * @param pArg1 The first argument.
723 * @param pArg2 The 2nd argument.
724 * @param pResult Where to store the result.
725 */
726static DECLCALLBACK(int) dbgcOpMult(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
727{
728// LogFlow(("dbgcOpMult\n"));
729 int rc;
730
731 /*
732 * Switch the factors so we preserve pointers, far pointers are considered more
733 * important that physical and flat pointers.
734 */
735 if ( DBGCVAR_ISPOINTER(pArg2->enmType)
736 && ( !DBGCVAR_ISPOINTER(pArg1->enmType)
737 || ( DBGCVAR_IS_FAR_PTR(pArg2->enmType)
738 && !DBGCVAR_IS_FAR_PTR(pArg1->enmType))))
739 {
740 PCDBGCVAR pTmp = pArg1;
741 pArg2 = pArg1;
742 pArg1 = pTmp;
743 }
744
745 /*
746 * Convert the 2nd number into a number we use multiply the first with.
747 */
748 DBGCVAR Factor2 = *pArg2;
749 if ( Factor2.enmType == DBGCVAR_TYPE_STRING
750 || Factor2.enmType == DBGCVAR_TYPE_SYMBOL)
751 {
752 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Factor2);
753 if (RT_FAILURE(rc))
754 return rc;
755 }
756 uint64_t u64Factor;
757 switch (Factor2.enmType)
758 {
759 case DBGCVAR_TYPE_GC_FLAT: u64Factor = Factor2.u.GCFlat; break;
760 case DBGCVAR_TYPE_GC_FAR: u64Factor = Factor2.u.GCFar.off; break;
761 case DBGCVAR_TYPE_GC_PHYS: u64Factor = Factor2.u.GCPhys; break;
762 case DBGCVAR_TYPE_HC_FLAT: u64Factor = (uintptr_t)Factor2.u.pvHCFlat; break;
763 case DBGCVAR_TYPE_HC_FAR: u64Factor = Factor2.u.HCFar.off; break;
764 case DBGCVAR_TYPE_HC_PHYS: u64Factor = Factor2.u.HCPhys; break;
765 case DBGCVAR_TYPE_NUMBER: u64Factor = Factor2.u.u64Number; break;
766 default:
767 return VERR_PARSE_INCORRECT_ARG_TYPE;
768 }
769
770 /*
771 * Fix symbols in the 1st factor.
772 */
773 *pResult = *pArg1;
774 if ( pResult->enmType == DBGCVAR_TYPE_STRING
775 || pResult->enmType == DBGCVAR_TYPE_SYMBOL)
776 {
777 rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, pResult);
778 if (RT_FAILURE(rc))
779 return rc;
780 }
781
782 /*
783 * Do the multiplication.
784 */
785 switch (pArg1->enmType)
786 {
787 case DBGCVAR_TYPE_GC_FLAT: pResult->u.GCFlat *= u64Factor; break;
788 case DBGCVAR_TYPE_GC_FAR: pResult->u.GCFar.off *= u64Factor; break;
789 case DBGCVAR_TYPE_GC_PHYS: pResult->u.GCPhys *= u64Factor; break;
790 case DBGCVAR_TYPE_HC_FLAT:
791 pResult->u.pvHCFlat = (void *)(uintptr_t)((uintptr_t)pResult->u.pvHCFlat * u64Factor);
792 break;
793 case DBGCVAR_TYPE_HC_FAR: pResult->u.HCFar.off *= u64Factor; break;
794 case DBGCVAR_TYPE_HC_PHYS: pResult->u.HCPhys *= u64Factor; break;
795 case DBGCVAR_TYPE_NUMBER: pResult->u.u64Number *= u64Factor; break;
796 default:
797 return VERR_PARSE_INCORRECT_ARG_TYPE;
798 }
799 return 0;
800}
801
802
803/**
804 * Division operator (binary).
805 *
806 * @returns 0 on success.
807 * @returns VBox evaluation / parsing error code on failure.
808 * The caller does the bitching.
809 * @param pDbgc Debugger console instance data.
810 * @param pArg1 The first argument.
811 * @param pArg2 The 2nd argument.
812 * @param pResult Where to store the result.
813 */
814static DECLCALLBACK(int) dbgcOpDiv(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
815{
816 LogFlow(("dbgcOpDiv\n"));
817 NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
818 return -1;
819}
820
821
822/**
823 * Modulus operator (binary).
824 *
825 * @returns 0 on success.
826 * @returns VBox evaluation / parsing error code on failure.
827 * The caller does the bitching.
828 * @param pDbgc Debugger console instance data.
829 * @param pArg1 The first argument.
830 * @param pArg2 The 2nd argument.
831 * @param pResult Where to store the result.
832 */
833static DECLCALLBACK(int) dbgcOpMod(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
834{
835 LogFlow(("dbgcOpMod\n"));
836 NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
837 return -1;
838}
839
840
841/**
842 * Addition operator (binary).
843 *
844 * @returns 0 on success.
845 * @returns VBox evaluation / parsing error code on failure.
846 * The caller does the bitching.
847 * @param pDbgc Debugger console instance data.
848 * @param pArg1 The first argument.
849 * @param pArg2 The 2nd argument.
850 * @param pResult Where to store the result.
851 */
852static DECLCALLBACK(int) dbgcOpAdd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
853{
854// LogFlow(("dbgcOpAdd\n"));
855
856 /*
857 * An addition operation will return (when possible) the left side type in the
858 * expression. We make an omission for numbers, where we'll take the right side
859 * type instead. An expression where only the left hand side is a string we'll
860 * use the right hand type assuming that the string is a symbol.
861 */
862 if ( (pArg1->enmType == DBGCVAR_TYPE_NUMBER && pArg2->enmType != DBGCVAR_TYPE_STRING)
863 || (pArg1->enmType == DBGCVAR_TYPE_STRING && pArg2->enmType != DBGCVAR_TYPE_STRING))
864 {
865 PCDBGCVAR pTmp = pArg2;
866 pArg2 = pArg1;
867 pArg1 = pTmp;
868 }
869 DBGCVAR Sym1, Sym2;
870 if (pArg1->enmType == DBGCVAR_TYPE_STRING)
871 {
872 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, &Sym1);
873 if (RT_FAILURE(rc))
874 return rc;
875 pArg1 = &Sym1;
876
877 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2);
878 if (RT_FAILURE(rc))
879 return rc;
880 pArg2 = &Sym2;
881 }
882
883 int rc;
884 DBGCVAR Var;
885 DBGCVAR Var2;
886 switch (pArg1->enmType)
887 {
888 /*
889 * GC Flat
890 */
891 case DBGCVAR_TYPE_GC_FLAT:
892 switch (pArg2->enmType)
893 {
894 case DBGCVAR_TYPE_HC_FLAT:
895 case DBGCVAR_TYPE_HC_FAR:
896 case DBGCVAR_TYPE_HC_PHYS:
897 return VERR_PARSE_INVALID_OPERATION;
898 default:
899 *pResult = *pArg1;
900 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
901 if (RT_FAILURE(rc))
902 return rc;
903 pResult->u.GCFlat += pArg2->u.GCFlat;
904 break;
905 }
906 break;
907
908 /*
909 * GC Far
910 */
911 case DBGCVAR_TYPE_GC_FAR:
912 switch (pArg2->enmType)
913 {
914 case DBGCVAR_TYPE_HC_FLAT:
915 case DBGCVAR_TYPE_HC_FAR:
916 case DBGCVAR_TYPE_HC_PHYS:
917 return VERR_PARSE_INVALID_OPERATION;
918 case DBGCVAR_TYPE_NUMBER:
919 *pResult = *pArg1;
920 pResult->u.GCFar.off += (RTGCPTR)pArg2->u.u64Number;
921 break;
922 default:
923 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
924 if (RT_FAILURE(rc))
925 return rc;
926 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
927 if (RT_FAILURE(rc))
928 return rc;
929 pResult->u.GCFlat += pArg2->u.GCFlat;
930 break;
931 }
932 break;
933
934 /*
935 * GC Phys
936 */
937 case DBGCVAR_TYPE_GC_PHYS:
938 switch (pArg2->enmType)
939 {
940 case DBGCVAR_TYPE_HC_FLAT:
941 case DBGCVAR_TYPE_HC_FAR:
942 case DBGCVAR_TYPE_HC_PHYS:
943 return VERR_PARSE_INVALID_OPERATION;
944 default:
945 *pResult = *pArg1;
946 rc = dbgcOpAddrPhys(pDbgc, pArg2, &Var);
947 if (RT_FAILURE(rc))
948 return rc;
949 if (Var.enmType != DBGCVAR_TYPE_GC_PHYS)
950 return VERR_PARSE_INVALID_OPERATION;
951 pResult->u.GCPhys += Var.u.GCPhys;
952 break;
953 }
954 break;
955
956 /*
957 * HC Flat
958 */
959 case DBGCVAR_TYPE_HC_FLAT:
960 *pResult = *pArg1;
961 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
962 if (RT_FAILURE(rc))
963 return rc;
964 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
965 if (RT_FAILURE(rc))
966 return rc;
967 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat + (uintptr_t)Var.u.pvHCFlat;
968 break;
969
970 /*
971 * HC Far
972 */
973 case DBGCVAR_TYPE_HC_FAR:
974 switch (pArg2->enmType)
975 {
976 case DBGCVAR_TYPE_NUMBER:
977 *pResult = *pArg1;
978 pResult->u.HCFar.off += (uintptr_t)pArg2->u.u64Number;
979 break;
980
981 default:
982 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
983 if (RT_FAILURE(rc))
984 return rc;
985 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
986 if (RT_FAILURE(rc))
987 return rc;
988 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
989 if (RT_FAILURE(rc))
990 return rc;
991 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat + (uintptr_t)Var.u.pvHCFlat;
992 break;
993 }
994 break;
995
996 /*
997 * HC Phys
998 */
999 case DBGCVAR_TYPE_HC_PHYS:
1000 *pResult = *pArg1;
1001 rc = dbgcOpAddrHostPhys(pDbgc, pArg2, &Var);
1002 if (RT_FAILURE(rc))
1003 return rc;
1004 pResult->u.HCPhys += Var.u.HCPhys;
1005 break;
1006
1007 /*
1008 * Numbers (see start of function)
1009 */
1010 case DBGCVAR_TYPE_NUMBER:
1011 *pResult = *pArg1;
1012 switch (pArg2->enmType)
1013 {
1014 case DBGCVAR_TYPE_SYMBOL:
1015 case DBGCVAR_TYPE_STRING:
1016 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
1017 if (RT_FAILURE(rc))
1018 return rc;
1019 case DBGCVAR_TYPE_NUMBER:
1020 pResult->u.u64Number += pArg2->u.u64Number;
1021 break;
1022 default:
1023 return VERR_PARSE_INVALID_OPERATION;
1024 }
1025 break;
1026
1027 default:
1028 return VERR_PARSE_INVALID_OPERATION;
1029
1030 }
1031 return 0;
1032}
1033
1034
1035/**
1036 * Subtration operator (binary).
1037 *
1038 * @returns 0 on success.
1039 * @returns VBox evaluation / parsing error code on failure.
1040 * The caller does the bitching.
1041 * @param pDbgc Debugger console instance data.
1042 * @param pArg1 The first argument.
1043 * @param pArg2 The 2nd argument.
1044 * @param pResult Where to store the result.
1045 */
1046static DECLCALLBACK(int) dbgcOpSub(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1047{
1048// LogFlow(("dbgcOpSub\n"));
1049
1050 /*
1051 * An subtraction operation will return the left side type in the expression.
1052 * However, if the left hand side is a number and the right hand a pointer of
1053 * some kind we'll convert the left hand side to the same type as the right hand.
1054 * Any strings will be attempted resolved as symbols.
1055 */
1056 DBGCVAR Sym1, Sym2;
1057 if ( pArg2->enmType == DBGCVAR_TYPE_STRING
1058 && ( pArg1->enmType == DBGCVAR_TYPE_NUMBER
1059 || pArg1->enmType == DBGCVAR_TYPE_STRING))
1060 {
1061 int rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2);
1062 if (RT_FAILURE(rc))
1063 return rc;
1064 pArg2 = &Sym2;
1065 }
1066
1067 if (pArg1->enmType == DBGCVAR_TYPE_STRING)
1068 {
1069 DBGCVARTYPE enmType;
1070 switch (pArg2->enmType)
1071 {
1072 case DBGCVAR_TYPE_NUMBER:
1073 enmType = DBGCVAR_TYPE_ANY;
1074 break;
1075 case DBGCVAR_TYPE_GC_FLAT:
1076 case DBGCVAR_TYPE_GC_PHYS:
1077 case DBGCVAR_TYPE_HC_FLAT:
1078 case DBGCVAR_TYPE_HC_PHYS:
1079 enmType = pArg2->enmType;
1080 break;
1081 case DBGCVAR_TYPE_GC_FAR:
1082 enmType = DBGCVAR_TYPE_GC_FLAT;
1083 break;
1084 case DBGCVAR_TYPE_HC_FAR:
1085 enmType = DBGCVAR_TYPE_HC_FLAT;
1086 break;
1087
1088 default:
1089 case DBGCVAR_TYPE_STRING:
1090 AssertMsgFailed(("Can't happen\n"));
1091 enmType = DBGCVAR_TYPE_STRING;
1092 break;
1093 }
1094 if (enmType != DBGCVAR_TYPE_STRING)
1095 {
1096 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, &Sym1);
1097 if (RT_FAILURE(rc))
1098 return rc;
1099 pArg1 = &Sym1;
1100 }
1101 }
1102 else if (pArg1->enmType == DBGCVAR_TYPE_NUMBER)
1103 {
1104 PFNDBGCOPUNARY pOp = NULL;
1105 switch (pArg2->enmType)
1106 {
1107 case DBGCVAR_TYPE_GC_FAR:
1108 case DBGCVAR_TYPE_GC_FLAT:
1109 pOp = dbgcOpAddrFlat;
1110 break;
1111 case DBGCVAR_TYPE_GC_PHYS:
1112 pOp = dbgcOpAddrPhys;
1113 break;
1114 case DBGCVAR_TYPE_HC_FAR:
1115 case DBGCVAR_TYPE_HC_FLAT:
1116 pOp = dbgcOpAddrHost;
1117 break;
1118 case DBGCVAR_TYPE_HC_PHYS:
1119 pOp = dbgcOpAddrHostPhys;
1120 break;
1121 case DBGCVAR_TYPE_NUMBER:
1122 break;
1123 default:
1124 case DBGCVAR_TYPE_STRING:
1125 AssertMsgFailed(("Can't happen\n"));
1126 break;
1127 }
1128 if (pOp)
1129 {
1130 int rc = pOp(pDbgc, pArg1, &Sym1);
1131 if (RT_FAILURE(rc))
1132 return rc;
1133 pArg1 = &Sym1;
1134 }
1135 }
1136
1137
1138 /*
1139 * Normal processing.
1140 */
1141 int rc;
1142 DBGCVAR Var;
1143 DBGCVAR Var2;
1144 switch (pArg1->enmType)
1145 {
1146 /*
1147 * GC Flat
1148 */
1149 case DBGCVAR_TYPE_GC_FLAT:
1150 switch (pArg2->enmType)
1151 {
1152 case DBGCVAR_TYPE_HC_FLAT:
1153 case DBGCVAR_TYPE_HC_FAR:
1154 case DBGCVAR_TYPE_HC_PHYS:
1155 return VERR_PARSE_INVALID_OPERATION;
1156 default:
1157 *pResult = *pArg1;
1158 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
1159 if (RT_FAILURE(rc))
1160 return rc;
1161 pResult->u.GCFlat -= pArg2->u.GCFlat;
1162 break;
1163 }
1164 break;
1165
1166 /*
1167 * GC Far
1168 */
1169 case DBGCVAR_TYPE_GC_FAR:
1170 switch (pArg2->enmType)
1171 {
1172 case DBGCVAR_TYPE_HC_FLAT:
1173 case DBGCVAR_TYPE_HC_FAR:
1174 case DBGCVAR_TYPE_HC_PHYS:
1175 return VERR_PARSE_INVALID_OPERATION;
1176 case DBGCVAR_TYPE_NUMBER:
1177 *pResult = *pArg1;
1178 pResult->u.GCFar.off -= (RTGCPTR)pArg2->u.u64Number;
1179 break;
1180 default:
1181 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
1182 if (RT_FAILURE(rc))
1183 return rc;
1184 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
1185 if (RT_FAILURE(rc))
1186 return rc;
1187 pResult->u.GCFlat -= pArg2->u.GCFlat;
1188 break;
1189 }
1190 break;
1191
1192 /*
1193 * GC Phys
1194 */
1195 case DBGCVAR_TYPE_GC_PHYS:
1196 switch (pArg2->enmType)
1197 {
1198 case DBGCVAR_TYPE_HC_FLAT:
1199 case DBGCVAR_TYPE_HC_FAR:
1200 case DBGCVAR_TYPE_HC_PHYS:
1201 return VERR_PARSE_INVALID_OPERATION;
1202 default:
1203 *pResult = *pArg1;
1204 rc = dbgcOpAddrPhys(pDbgc, pArg2, &Var);
1205 if (RT_FAILURE(rc))
1206 return rc;
1207 if (Var.enmType != DBGCVAR_TYPE_GC_PHYS)
1208 return VERR_PARSE_INVALID_OPERATION;
1209 pResult->u.GCPhys -= Var.u.GCPhys;
1210 break;
1211 }
1212 break;
1213
1214 /*
1215 * HC Flat
1216 */
1217 case DBGCVAR_TYPE_HC_FLAT:
1218 *pResult = *pArg1;
1219 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
1220 if (RT_FAILURE(rc))
1221 return rc;
1222 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
1223 if (RT_FAILURE(rc))
1224 return rc;
1225 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat - (uintptr_t)Var.u.pvHCFlat;
1226 break;
1227
1228 /*
1229 * HC Far
1230 */
1231 case DBGCVAR_TYPE_HC_FAR:
1232 switch (pArg2->enmType)
1233 {
1234 case DBGCVAR_TYPE_NUMBER:
1235 *pResult = *pArg1;
1236 pResult->u.HCFar.off -= (uintptr_t)pArg2->u.u64Number;
1237 break;
1238
1239 default:
1240 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
1241 if (RT_FAILURE(rc))
1242 return rc;
1243 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
1244 if (RT_FAILURE(rc))
1245 return rc;
1246 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
1247 if (RT_FAILURE(rc))
1248 return rc;
1249 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat - (uintptr_t)Var.u.pvHCFlat;
1250 break;
1251 }
1252 break;
1253
1254 /*
1255 * HC Phys
1256 */
1257 case DBGCVAR_TYPE_HC_PHYS:
1258 *pResult = *pArg1;
1259 rc = dbgcOpAddrHostPhys(pDbgc, pArg2, &Var);
1260 if (RT_FAILURE(rc))
1261 return rc;
1262 pResult->u.HCPhys -= Var.u.HCPhys;
1263 break;
1264
1265 /*
1266 * Numbers (see start of function)
1267 */
1268 case DBGCVAR_TYPE_NUMBER:
1269 *pResult = *pArg1;
1270 switch (pArg2->enmType)
1271 {
1272 case DBGCVAR_TYPE_SYMBOL:
1273 case DBGCVAR_TYPE_STRING:
1274 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
1275 if (RT_FAILURE(rc))
1276 return rc;
1277 case DBGCVAR_TYPE_NUMBER:
1278 pResult->u.u64Number -= pArg2->u.u64Number;
1279 break;
1280 default:
1281 return VERR_PARSE_INVALID_OPERATION;
1282 }
1283 break;
1284
1285 default:
1286 return VERR_PARSE_INVALID_OPERATION;
1287
1288 }
1289 return 0;
1290}
1291
1292
1293/**
1294 * Bitwise shift left operator (binary).
1295 *
1296 * @returns 0 on success.
1297 * @returns VBox evaluation / parsing error code on failure.
1298 * The caller does the bitching.
1299 * @param pDbgc Debugger console instance data.
1300 * @param pArg1 The first argument.
1301 * @param pArg2 The 2nd argument.
1302 * @param pResult Where to store the result.
1303 */
1304static DECLCALLBACK(int) dbgcOpBitwiseShiftLeft(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1305{
1306 LogFlow(("dbgcOpBitwiseShiftLeft\n"));
1307 NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
1308 return -1;
1309}
1310
1311
1312/**
1313 * Bitwise shift right operator (binary).
1314 *
1315 * @returns 0 on success.
1316 * @returns VBox evaluation / parsing error code on failure.
1317 * The caller does the bitching.
1318 * @param pDbgc Debugger console instance data.
1319 * @param pArg1 The first argument.
1320 * @param pArg2 The 2nd argument.
1321 * @param pResult Where to store the result.
1322 */
1323static DECLCALLBACK(int) dbgcOpBitwiseShiftRight(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1324{
1325 LogFlow(("dbgcOpBitwiseShiftRight\n"));
1326 NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
1327 return -1;
1328}
1329
1330
1331/**
1332 * Bitwise and operator (binary).
1333 *
1334 * @returns 0 on success.
1335 * @returns VBox evaluation / parsing error code on failure.
1336 * The caller does the bitching.
1337 * @param pDbgc Debugger console instance data.
1338 * @param pArg1 The first argument.
1339 * @param pArg2 The 2nd argument.
1340 * @param pResult Where to store the result.
1341 */
1342static DECLCALLBACK(int) dbgcOpBitwiseAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1343{
1344 LogFlow(("dbgcOpBitwiseAnd\n"));
1345 NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
1346 return -1;
1347}
1348
1349
1350/**
1351 * Bitwise exclusive or operator (binary).
1352 *
1353 * @returns 0 on success.
1354 * @returns VBox evaluation / parsing error code on failure.
1355 * The caller does the bitching.
1356 * @param pDbgc Debugger console instance data.
1357 * @param pArg1 The first argument.
1358 * @param pArg2 The 2nd argument.
1359 * @param pResult Where to store the result.
1360 */
1361static DECLCALLBACK(int) dbgcOpBitwiseXor(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1362{
1363 LogFlow(("dbgcOpBitwiseXor\n"));
1364 NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
1365 return -1;
1366}
1367
1368
1369/**
1370 * Bitwise inclusive or operator (binary).
1371 *
1372 * @returns 0 on success.
1373 * @returns VBox evaluation / parsing error code on failure.
1374 * The caller does the bitching.
1375 * @param pDbgc Debugger console instance data.
1376 * @param pArg1 The first argument.
1377 * @param pArg2 The 2nd argument.
1378 * @param pResult Where to store the result.
1379 */
1380static DECLCALLBACK(int) dbgcOpBitwiseOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1381{
1382 LogFlow(("dbgcOpBitwiseOr\n"));
1383 NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
1384 return -1;
1385}
1386
1387
1388/**
1389 * Boolean and operator (binary).
1390 *
1391 * @returns 0 on success.
1392 * @returns VBox evaluation / parsing error code on failure.
1393 * The caller does the bitching.
1394 * @param pDbgc Debugger console instance data.
1395 * @param pArg1 The first argument.
1396 * @param pArg2 The 2nd argument.
1397 * @param pResult Where to store the result.
1398 */
1399static DECLCALLBACK(int) dbgcOpBooleanAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1400{
1401 LogFlow(("dbgcOpBooleanAnd\n"));
1402 NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
1403 return -1;
1404}
1405
1406
1407/**
1408 * Boolean or operator (binary).
1409 *
1410 * @returns 0 on success.
1411 * @returns VBox evaluation / parsing error code on failure.
1412 * The caller does the bitching.
1413 * @param pDbgc Debugger console instance data.
1414 * @param pArg1 The first argument.
1415 * @param pArg2 The 2nd argument.
1416 * @param pResult Where to store the result.
1417 */
1418static DECLCALLBACK(int) dbgcOpBooleanOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1419{
1420 LogFlow(("dbgcOpBooleanOr\n"));
1421 NOREF(pDbgc); NOREF(pArg1); NOREF(pArg2); NOREF(pResult);
1422 return -1;
1423}
1424
1425
1426/**
1427 * Range to operator (binary).
1428 *
1429 * @returns 0 on success.
1430 * @returns VBox evaluation / parsing error code on failure.
1431 * The caller does the bitching.
1432 * @param pDbgc Debugger console instance data.
1433 * @param pArg1 The first argument.
1434 * @param pArg2 The 2nd argument.
1435 * @param pResult Where to store the result.
1436 */
1437static DECLCALLBACK(int) dbgcOpRangeLength(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1438{
1439// LogFlow(("dbgcOpRangeLength\n"));
1440 /*
1441 * Make result. Strings needs to be resolved into symbols.
1442 */
1443 if (pArg1->enmType == DBGCVAR_TYPE_STRING)
1444 {
1445 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, pResult);
1446 if (RT_FAILURE(rc))
1447 return rc;
1448 }
1449 else
1450 *pResult = *pArg1;
1451
1452 /*
1453 * Convert 2nd argument to element count.
1454 */
1455 pResult->enmRangeType = DBGCVAR_RANGE_ELEMENTS;
1456 switch (pArg2->enmType)
1457 {
1458 case DBGCVAR_TYPE_NUMBER:
1459 pResult->u64Range = pArg2->u.u64Number;
1460 break;
1461
1462 case DBGCVAR_TYPE_STRING:
1463 {
1464 int rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, pResult);
1465 if (RT_FAILURE(rc))
1466 return rc;
1467 pResult->u64Range = pArg2->u.u64Number;
1468 break;
1469 }
1470
1471 default:
1472 return VERR_PARSE_INVALID_OPERATION;
1473 }
1474
1475 return VINF_SUCCESS;
1476}
1477
1478
1479/**
1480 * Range to operator (binary).
1481 *
1482 * @returns 0 on success.
1483 * @returns VBox evaluation / parsing error code on failure.
1484 * The caller does the bitching.
1485 * @param pDbgc Debugger console instance data.
1486 * @param pArg1 The first argument.
1487 * @param pArg2 The 2nd argument.
1488 * @param pResult Where to store the result.
1489 */
1490static DECLCALLBACK(int) dbgcOpRangeLengthBytes(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1491{
1492// LogFlow(("dbgcOpRangeLengthBytes\n"));
1493 int rc = dbgcOpRangeLength(pDbgc, pArg1, pArg2, pResult);
1494 if (RT_SUCCESS(rc))
1495 pResult->enmRangeType = DBGCVAR_RANGE_BYTES;
1496 return rc;
1497}
1498
1499
1500/**
1501 * Range to operator (binary).
1502 *
1503 * @returns 0 on success.
1504 * @returns VBox evaluation / parsing error code on failure.
1505 * The caller does the bitching.
1506 * @param pDbgc Debugger console instance data.
1507 * @param pArg1 The first argument.
1508 * @param pArg2 The 2nd argument.
1509 * @param pResult Where to store the result.
1510 */
1511static DECLCALLBACK(int) dbgcOpRangeTo(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1512{
1513// LogFlow(("dbgcOpRangeTo\n"));
1514 /*
1515 * Calc number of bytes between the two args.
1516 */
1517 DBGCVAR Diff;
1518 int rc = dbgcOpSub(pDbgc, pArg2, pArg1, &Diff);
1519 if (RT_FAILURE(rc))
1520 return rc;
1521
1522 /*
1523 * Use the diff as the range of Arg1.
1524 */
1525 *pResult = *pArg1;
1526 pResult->enmRangeType = DBGCVAR_RANGE_BYTES;
1527 switch (Diff.enmType)
1528 {
1529 case DBGCVAR_TYPE_GC_FLAT:
1530 pResult->u64Range = (RTGCUINTPTR)Diff.u.GCFlat;
1531 break;
1532 case DBGCVAR_TYPE_GC_PHYS:
1533 pResult->u64Range = Diff.u.GCPhys;
1534 break;
1535 case DBGCVAR_TYPE_HC_FLAT:
1536 pResult->u64Range = (uintptr_t)Diff.u.pvHCFlat;
1537 break;
1538 case DBGCVAR_TYPE_HC_PHYS:
1539 pResult->u64Range = Diff.u.HCPhys;
1540 break;
1541 case DBGCVAR_TYPE_NUMBER:
1542 pResult->u64Range = Diff.u.u64Number;
1543 break;
1544
1545 case DBGCVAR_TYPE_GC_FAR:
1546 case DBGCVAR_TYPE_STRING:
1547 case DBGCVAR_TYPE_HC_FAR:
1548 default:
1549 AssertMsgFailed(("Impossible!\n"));
1550 return VERR_PARSE_INVALID_OPERATION;
1551 }
1552
1553 return 0;
1554}
1555
1556
1557/**
1558 * Searches for an operator descriptor which matches the start of
1559 * the expression given us.
1560 *
1561 * @returns Pointer to the operator on success.
1562 * @param pDbgc The debug console instance.
1563 * @param pszExpr Pointer to the expression string which might start with an operator.
1564 * @param fPreferBinary Whether to favour binary or unary operators.
1565 * Caller must assert that it's the disired type! Both types will still
1566 * be returned, this is only for resolving duplicates.
1567 * @param chPrev The previous char. Some operators requires a blank in front of it.
1568 */
1569PCDBGCOP dbgcOperatorLookup(PDBGC pDbgc, const char *pszExpr, bool fPreferBinary, char chPrev)
1570{
1571 PCDBGCOP pOp = NULL;
1572 for (unsigned iOp = 0; iOp < RT_ELEMENTS(g_aOps); iOp++)
1573 {
1574 if ( g_aOps[iOp].szName[0] == pszExpr[0]
1575 && (!g_aOps[iOp].szName[1] || g_aOps[iOp].szName[1] == pszExpr[1])
1576 && (!g_aOps[iOp].szName[2] || g_aOps[iOp].szName[2] == pszExpr[2]))
1577 {
1578 /*
1579 * Check that we don't mistake it for some other operator which have more chars.
1580 */
1581 unsigned j;
1582 for (j = iOp + 1; j < RT_ELEMENTS(g_aOps); j++)
1583 if ( g_aOps[j].cchName > g_aOps[iOp].cchName
1584 && g_aOps[j].szName[0] == pszExpr[0]
1585 && (!g_aOps[j].szName[1] || g_aOps[j].szName[1] == pszExpr[1])
1586 && (!g_aOps[j].szName[2] || g_aOps[j].szName[2] == pszExpr[2]) )
1587 break;
1588 if (j < RT_ELEMENTS(g_aOps))
1589 continue; /* we'll catch it later. (for theoretical +,++,+++ cases.) */
1590 pOp = &g_aOps[iOp];
1591
1592 /*
1593 * Prefered type?
1594 */
1595 if (g_aOps[iOp].fBinary == fPreferBinary)
1596 break;
1597 }
1598 }
1599
1600 if (pOp)
1601 Log2(("dbgcOperatorLookup: pOp=%p %s\n", pOp, pOp->szName));
1602 NOREF(pDbgc); NOREF(chPrev);
1603 return pOp;
1604}
1605
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