VirtualBox

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

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

Debugger Console: Drop the HC_FAR type.

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