VirtualBox

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

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

DBGC: Implemented the missing operators.

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