VirtualBox

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

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

The debugger is back in the OSE.

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