VirtualBox

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

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

Debugger Console: cleaning up...

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 49.1 KB
Line 
1/* $Id: DBGCOps.cpp 35627 2011-01-19 13:22:02Z 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 && pArg->enmType != DBGCVAR_TYPE_SYMBOL)
475 return VERR_PARSE_INCORRECT_ARG_TYPE;
476
477 /*
478 * Get the register.
479 */
480 DBGFREGVALTYPE enmType;
481 DBGFREGVAL Value;
482 int rc = DBGFR3RegNmQuery(pDbgc->pVM, pDbgc->idCpu, pArg->u.pszString, &Value, &enmType);
483 if (RT_SUCCESS(rc))
484 {
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 rc = VERR_INTERNAL_ERROR_5;
525 }
526 return rc;
527}
528
529
530/**
531 * Flat address (unary).
532 *
533 * @returns VINF_SUCCESS on success.
534 * @returns VBox evaluation / parsing error code on failure.
535 * The caller does the bitching.
536 * @param pDbgc Debugger console instance data.
537 * @param pArg The argument.
538 * @param pResult Where to store the result.
539 */
540DECLCALLBACK(int) dbgcOpAddrFlat(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
541{
542 LogFlow(("dbgcOpAddrFlat\n"));
543 DBGCVARTYPE enmType = DBGCVAR_ISHCPOINTER(pArg->enmType) ? DBGCVAR_TYPE_HC_FLAT : DBGCVAR_TYPE_GC_FLAT;
544 return DBGCCmdHlpConvert(&pDbgc->CmdHlp, pArg, enmType, true /*fConvSyms*/, pResult);
545}
546
547
548/**
549 * Physical address (unary).
550 *
551 * @returns VINF_SUCCESS on success.
552 * @returns VBox evaluation / parsing error code on failure.
553 * The caller does the bitching.
554 * @param pDbgc Debugger console instance data.
555 * @param pArg The argument.
556 * @param pResult Where to store the result.
557 */
558DECLCALLBACK(int) dbgcOpAddrPhys(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
559{
560 LogFlow(("dbgcOpAddrPhys\n"));
561 DBGCVARTYPE enmType = DBGCVAR_ISHCPOINTER(pArg->enmType) ? DBGCVAR_TYPE_HC_PHYS : DBGCVAR_TYPE_GC_PHYS;
562 return DBGCCmdHlpConvert(&pDbgc->CmdHlp, pArg, enmType, true /*fConvSyms*/, pResult);
563}
564
565
566/**
567 * Physical host address (unary).
568 *
569 * @returns VINF_SUCCESS on success.
570 * @returns VBox evaluation / parsing error code on failure.
571 * The caller does the bitching.
572 * @param pDbgc Debugger console instance data.
573 * @param pArg The argument.
574 * @param pResult Where to store the result.
575 */
576DECLCALLBACK(int) dbgcOpAddrHostPhys(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
577{
578 LogFlow(("dbgcOpAddrPhys\n"));
579 return DBGCCmdHlpConvert(&pDbgc->CmdHlp, pArg, DBGCVAR_TYPE_HC_PHYS, true /*fConvSyms*/, pResult);
580}
581
582
583/**
584 * Host address (unary).
585 *
586 * @returns VINF_SUCCESS on success.
587 * @returns VBox evaluation / parsing error code on failure.
588 * The caller does the bitching.
589 * @param pDbgc Debugger console instance data.
590 * @param pArg The argument.
591 * @param pResult Where to store the result.
592 */
593DECLCALLBACK(int) dbgcOpAddrHost(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
594{
595 LogFlow(("dbgcOpAddrHost\n"));
596 return DBGCCmdHlpConvert(&pDbgc->CmdHlp, pArg, DBGCVAR_TYPE_HC_FLAT, true /*fConvSyms*/, pResult);
597}
598
599
600/**
601 * Bitwise not (unary).
602 *
603 * @returns VINF_SUCCESS on success.
604 * @returns VBox evaluation / parsing error code on failure.
605 * The caller does the bitching.
606 * @param pDbgc Debugger console instance data.
607 * @param pArg The argument.
608 * @param pResult Where to store the result.
609 */
610static DECLCALLBACK(int) dbgcOpAddrFar(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
611{
612 LogFlow(("dbgcOpAddrFar\n"));
613 int rc;
614
615 switch (pArg1->enmType)
616 {
617 case DBGCVAR_TYPE_STRING:
618 rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_NUMBER, pResult);
619 if (RT_FAILURE(rc))
620 return rc;
621 break;
622 case DBGCVAR_TYPE_NUMBER:
623 *pResult = *pArg1;
624 break;
625
626 case DBGCVAR_TYPE_GC_FLAT:
627 case DBGCVAR_TYPE_GC_FAR:
628 case DBGCVAR_TYPE_GC_PHYS:
629 case DBGCVAR_TYPE_HC_FLAT:
630 case DBGCVAR_TYPE_HC_PHYS:
631 case DBGCVAR_TYPE_UNKNOWN:
632 default:
633 return VERR_PARSE_INCORRECT_ARG_TYPE;
634 }
635 pResult->u.GCFar.sel = (RTSEL)pResult->u.u64Number;
636
637 /* common code for the two types we support. */
638 switch (pArg2->enmType)
639 {
640 case DBGCVAR_TYPE_GC_FLAT:
641 pResult->u.GCFar.off = pArg2->u.GCFlat;
642 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
643 break;
644
645 case DBGCVAR_TYPE_HC_FLAT:
646 pResult->u.pvHCFlat = (void *)(uintptr_t)pArg2->u.GCFlat;
647 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
648 break;
649
650 case DBGCVAR_TYPE_NUMBER:
651 pResult->u.GCFar.off = (RTGCPTR)pArg2->u.u64Number;
652 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
653 break;
654
655 case DBGCVAR_TYPE_STRING:
656 {
657 DBGCVAR Var;
658 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
659 if (RT_FAILURE(rc))
660 return rc;
661 pResult->u.GCFar.off = (RTGCPTR)Var.u.u64Number;
662 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
663 break;
664 }
665
666 case DBGCVAR_TYPE_GC_FAR:
667 case DBGCVAR_TYPE_GC_PHYS:
668 case DBGCVAR_TYPE_HC_PHYS:
669 case DBGCVAR_TYPE_UNKNOWN:
670 default:
671 return VERR_PARSE_INCORRECT_ARG_TYPE;
672 }
673 return VINF_SUCCESS;
674
675}
676
677
678/**
679 * Multiplication operator (binary).
680 *
681 * @returns VINF_SUCCESS on success.
682 * @returns VBox evaluation / parsing error code on failure.
683 * The caller does the bitching.
684 * @param pDbgc Debugger console instance data.
685 * @param pArg1 The first argument.
686 * @param pArg2 The 2nd argument.
687 * @param pResult Where to store the result.
688 */
689static DECLCALLBACK(int) dbgcOpMult(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
690{
691 LogFlow(("dbgcOpMult\n"));
692 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
693 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, *, false);
694}
695
696
697/**
698 * Division operator (binary).
699 *
700 * @returns VINF_SUCCESS on success.
701 * @returns VBox evaluation / parsing error code on failure.
702 * The caller does the bitching.
703 * @param pDbgc Debugger console instance data.
704 * @param pArg1 The first argument.
705 * @param pArg2 The 2nd argument.
706 * @param pResult Where to store the result.
707 */
708static DECLCALLBACK(int) dbgcOpDiv(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
709{
710 LogFlow(("dbgcOpDiv\n"));
711 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, /, true);
712}
713
714
715/**
716 * Modulus operator (binary).
717 *
718 * @returns VINF_SUCCESS on success.
719 * @returns VBox evaluation / parsing error code on failure.
720 * The caller does the bitching.
721 * @param pDbgc Debugger console instance data.
722 * @param pArg1 The first argument.
723 * @param pArg2 The 2nd argument.
724 * @param pResult Where to store the result.
725 */
726static DECLCALLBACK(int) dbgcOpMod(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
727{
728 LogFlow(("dbgcOpMod\n"));
729 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, %, false);
730}
731
732
733/**
734 * Addition operator (binary).
735 *
736 * @returns VINF_SUCCESS on success.
737 * @returns VBox evaluation / parsing error code on failure.
738 * The caller does the bitching.
739 * @param pDbgc Debugger console instance data.
740 * @param pArg1 The first argument.
741 * @param pArg2 The 2nd argument.
742 * @param pResult Where to store the result.
743 */
744static DECLCALLBACK(int) dbgcOpAdd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
745{
746 LogFlow(("dbgcOpAdd\n"));
747
748 /*
749 * An addition operation will return (when possible) the left side type in the
750 * expression. We make an omission for numbers, where we'll take the right side
751 * type instead. An expression where only the left hand side is a string we'll
752 * use the right hand type assuming that the string is a symbol.
753 */
754 if ( (pArg1->enmType == DBGCVAR_TYPE_NUMBER && pArg2->enmType != DBGCVAR_TYPE_STRING)
755 || (pArg1->enmType == DBGCVAR_TYPE_STRING && pArg2->enmType != DBGCVAR_TYPE_STRING))
756 {
757 PCDBGCVAR pTmp = pArg2;
758 pArg2 = pArg1;
759 pArg1 = pTmp;
760 }
761 DBGCVAR Sym1, Sym2;
762 if (pArg1->enmType == DBGCVAR_TYPE_STRING)
763 {
764 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, &Sym1);
765 if (RT_FAILURE(rc))
766 return rc;
767 pArg1 = &Sym1;
768
769 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2);
770 if (RT_FAILURE(rc))
771 return rc;
772 pArg2 = &Sym2;
773 }
774
775 int rc;
776 DBGCVAR Var;
777 DBGCVAR Var2;
778 switch (pArg1->enmType)
779 {
780 /*
781 * GC Flat
782 */
783 case DBGCVAR_TYPE_GC_FLAT:
784 switch (pArg2->enmType)
785 {
786 case DBGCVAR_TYPE_HC_FLAT:
787 case DBGCVAR_TYPE_HC_PHYS:
788 return VERR_PARSE_INVALID_OPERATION;
789 default:
790 *pResult = *pArg1;
791 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
792 if (RT_FAILURE(rc))
793 return rc;
794 pResult->u.GCFlat += pArg2->u.GCFlat;
795 break;
796 }
797 break;
798
799 /*
800 * GC Far
801 */
802 case DBGCVAR_TYPE_GC_FAR:
803 switch (pArg2->enmType)
804 {
805 case DBGCVAR_TYPE_HC_FLAT:
806 case DBGCVAR_TYPE_HC_PHYS:
807 return VERR_PARSE_INVALID_OPERATION;
808 case DBGCVAR_TYPE_NUMBER:
809 *pResult = *pArg1;
810 pResult->u.GCFar.off += (RTGCPTR)pArg2->u.u64Number;
811 break;
812 default:
813 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
814 if (RT_FAILURE(rc))
815 return rc;
816 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
817 if (RT_FAILURE(rc))
818 return rc;
819 pResult->u.GCFlat += pArg2->u.GCFlat;
820 break;
821 }
822 break;
823
824 /*
825 * GC Phys
826 */
827 case DBGCVAR_TYPE_GC_PHYS:
828 switch (pArg2->enmType)
829 {
830 case DBGCVAR_TYPE_HC_FLAT:
831 case DBGCVAR_TYPE_HC_PHYS:
832 return VERR_PARSE_INVALID_OPERATION;
833 default:
834 *pResult = *pArg1;
835 rc = dbgcOpAddrPhys(pDbgc, pArg2, &Var);
836 if (RT_FAILURE(rc))
837 return rc;
838 if (Var.enmType != DBGCVAR_TYPE_GC_PHYS)
839 return VERR_PARSE_INVALID_OPERATION;
840 pResult->u.GCPhys += Var.u.GCPhys;
841 break;
842 }
843 break;
844
845 /*
846 * HC Flat
847 */
848 case DBGCVAR_TYPE_HC_FLAT:
849 *pResult = *pArg1;
850 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
851 if (RT_FAILURE(rc))
852 return rc;
853 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
854 if (RT_FAILURE(rc))
855 return rc;
856 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat + (uintptr_t)Var.u.pvHCFlat;
857 break;
858
859 /*
860 * HC Phys
861 */
862 case DBGCVAR_TYPE_HC_PHYS:
863 *pResult = *pArg1;
864 rc = dbgcOpAddrHostPhys(pDbgc, pArg2, &Var);
865 if (RT_FAILURE(rc))
866 return rc;
867 pResult->u.HCPhys += Var.u.HCPhys;
868 break;
869
870 /*
871 * Numbers (see start of function)
872 */
873 case DBGCVAR_TYPE_NUMBER:
874 *pResult = *pArg1;
875 switch (pArg2->enmType)
876 {
877 case DBGCVAR_TYPE_SYMBOL:
878 case DBGCVAR_TYPE_STRING:
879 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
880 if (RT_FAILURE(rc))
881 return rc;
882 case DBGCVAR_TYPE_NUMBER:
883 pResult->u.u64Number += pArg2->u.u64Number;
884 break;
885 default:
886 return VERR_PARSE_INVALID_OPERATION;
887 }
888 break;
889
890 default:
891 return VERR_PARSE_INVALID_OPERATION;
892
893 }
894 return VINF_SUCCESS;
895}
896
897
898/**
899 * Subtraction operator (binary).
900 *
901 * @returns VINF_SUCCESS on success.
902 * @returns VBox evaluation / parsing error code on failure.
903 * The caller does the bitching.
904 * @param pDbgc Debugger console instance data.
905 * @param pArg1 The first argument.
906 * @param pArg2 The 2nd argument.
907 * @param pResult Where to store the result.
908 */
909static DECLCALLBACK(int) dbgcOpSub(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
910{
911 LogFlow(("dbgcOpSub\n"));
912
913 /*
914 * An subtraction operation will return the left side type in the expression.
915 * However, if the left hand side is a number and the right hand a pointer of
916 * some kind we'll convert the left hand side to the same type as the right hand.
917 * Any strings will be attempted resolved as symbols.
918 */
919 DBGCVAR Sym1, Sym2;
920 if ( pArg2->enmType == DBGCVAR_TYPE_STRING
921 && ( pArg1->enmType == DBGCVAR_TYPE_NUMBER
922 || pArg1->enmType == DBGCVAR_TYPE_STRING))
923 {
924 int rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2);
925 if (RT_FAILURE(rc))
926 return rc;
927 pArg2 = &Sym2;
928 }
929
930 if (pArg1->enmType == DBGCVAR_TYPE_STRING)
931 {
932 DBGCVARTYPE enmType;
933 switch (pArg2->enmType)
934 {
935 case DBGCVAR_TYPE_NUMBER:
936 enmType = DBGCVAR_TYPE_ANY;
937 break;
938 case DBGCVAR_TYPE_GC_FLAT:
939 case DBGCVAR_TYPE_GC_PHYS:
940 case DBGCVAR_TYPE_HC_FLAT:
941 case DBGCVAR_TYPE_HC_PHYS:
942 enmType = pArg2->enmType;
943 break;
944 case DBGCVAR_TYPE_GC_FAR:
945 enmType = DBGCVAR_TYPE_GC_FLAT;
946 break;
947
948 default:
949 case DBGCVAR_TYPE_STRING:
950 AssertMsgFailed(("Can't happen\n"));
951 enmType = DBGCVAR_TYPE_STRING;
952 break;
953 }
954 if (enmType != DBGCVAR_TYPE_STRING)
955 {
956 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, &Sym1);
957 if (RT_FAILURE(rc))
958 return rc;
959 pArg1 = &Sym1;
960 }
961 }
962 else if (pArg1->enmType == DBGCVAR_TYPE_NUMBER)
963 {
964 PFNDBGCOPUNARY pOp = NULL;
965 switch (pArg2->enmType)
966 {
967 case DBGCVAR_TYPE_GC_FAR:
968 case DBGCVAR_TYPE_GC_FLAT:
969 pOp = dbgcOpAddrFlat;
970 break;
971 case DBGCVAR_TYPE_GC_PHYS:
972 pOp = dbgcOpAddrPhys;
973 break;
974 case DBGCVAR_TYPE_HC_FLAT:
975 pOp = dbgcOpAddrHost;
976 break;
977 case DBGCVAR_TYPE_HC_PHYS:
978 pOp = dbgcOpAddrHostPhys;
979 break;
980 case DBGCVAR_TYPE_NUMBER:
981 break;
982 default:
983 case DBGCVAR_TYPE_STRING:
984 AssertMsgFailed(("Can't happen\n"));
985 break;
986 }
987 if (pOp)
988 {
989 int rc = pOp(pDbgc, pArg1, &Sym1);
990 if (RT_FAILURE(rc))
991 return rc;
992 pArg1 = &Sym1;
993 }
994 }
995
996
997 /*
998 * Normal processing.
999 */
1000 int rc;
1001 DBGCVAR Var;
1002 DBGCVAR Var2;
1003 switch (pArg1->enmType)
1004 {
1005 /*
1006 * GC Flat
1007 */
1008 case DBGCVAR_TYPE_GC_FLAT:
1009 switch (pArg2->enmType)
1010 {
1011 case DBGCVAR_TYPE_HC_FLAT:
1012 case DBGCVAR_TYPE_HC_PHYS:
1013 return VERR_PARSE_INVALID_OPERATION;
1014 default:
1015 *pResult = *pArg1;
1016 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
1017 if (RT_FAILURE(rc))
1018 return rc;
1019 pResult->u.GCFlat -= pArg2->u.GCFlat;
1020 break;
1021 }
1022 break;
1023
1024 /*
1025 * GC Far
1026 */
1027 case DBGCVAR_TYPE_GC_FAR:
1028 switch (pArg2->enmType)
1029 {
1030 case DBGCVAR_TYPE_HC_FLAT:
1031 case DBGCVAR_TYPE_HC_PHYS:
1032 return VERR_PARSE_INVALID_OPERATION;
1033 case DBGCVAR_TYPE_NUMBER:
1034 *pResult = *pArg1;
1035 pResult->u.GCFar.off -= (RTGCPTR)pArg2->u.u64Number;
1036 break;
1037 default:
1038 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
1039 if (RT_FAILURE(rc))
1040 return rc;
1041 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
1042 if (RT_FAILURE(rc))
1043 return rc;
1044 pResult->u.GCFlat -= pArg2->u.GCFlat;
1045 break;
1046 }
1047 break;
1048
1049 /*
1050 * GC Phys
1051 */
1052 case DBGCVAR_TYPE_GC_PHYS:
1053 switch (pArg2->enmType)
1054 {
1055 case DBGCVAR_TYPE_HC_FLAT:
1056 case DBGCVAR_TYPE_HC_PHYS:
1057 return VERR_PARSE_INVALID_OPERATION;
1058 default:
1059 *pResult = *pArg1;
1060 rc = dbgcOpAddrPhys(pDbgc, pArg2, &Var);
1061 if (RT_FAILURE(rc))
1062 return rc;
1063 if (Var.enmType != DBGCVAR_TYPE_GC_PHYS)
1064 return VERR_PARSE_INVALID_OPERATION;
1065 pResult->u.GCPhys -= Var.u.GCPhys;
1066 break;
1067 }
1068 break;
1069
1070 /*
1071 * HC Flat
1072 */
1073 case DBGCVAR_TYPE_HC_FLAT:
1074 *pResult = *pArg1;
1075 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
1076 if (RT_FAILURE(rc))
1077 return rc;
1078 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
1079 if (RT_FAILURE(rc))
1080 return rc;
1081 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat - (uintptr_t)Var.u.pvHCFlat;
1082 break;
1083
1084 /*
1085 * HC Phys
1086 */
1087 case DBGCVAR_TYPE_HC_PHYS:
1088 *pResult = *pArg1;
1089 rc = dbgcOpAddrHostPhys(pDbgc, pArg2, &Var);
1090 if (RT_FAILURE(rc))
1091 return rc;
1092 pResult->u.HCPhys -= Var.u.HCPhys;
1093 break;
1094
1095 /*
1096 * Numbers (see start of function)
1097 */
1098 case DBGCVAR_TYPE_NUMBER:
1099 *pResult = *pArg1;
1100 switch (pArg2->enmType)
1101 {
1102 case DBGCVAR_TYPE_SYMBOL:
1103 case DBGCVAR_TYPE_STRING:
1104 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
1105 if (RT_FAILURE(rc))
1106 return rc;
1107 case DBGCVAR_TYPE_NUMBER:
1108 pResult->u.u64Number -= pArg2->u.u64Number;
1109 break;
1110 default:
1111 return VERR_PARSE_INVALID_OPERATION;
1112 }
1113 break;
1114
1115 default:
1116 return VERR_PARSE_INVALID_OPERATION;
1117
1118 }
1119 return VINF_SUCCESS;
1120}
1121
1122
1123/**
1124 * Bitwise shift left operator (binary).
1125 *
1126 * @returns VINF_SUCCESS on success.
1127 * @returns VBox evaluation / parsing error code on failure.
1128 * The caller does the bitching.
1129 * @param pDbgc Debugger console instance data.
1130 * @param pArg1 The first argument.
1131 * @param pArg2 The 2nd argument.
1132 * @param pResult Where to store the result.
1133 */
1134static DECLCALLBACK(int) dbgcOpBitwiseShiftLeft(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1135{
1136 LogFlow(("dbgcOpBitwiseShiftLeft\n"));
1137 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, <<, false);
1138}
1139
1140
1141/**
1142 * Bitwise shift right operator (binary).
1143 *
1144 * @returns VINF_SUCCESS on success.
1145 * @returns VBox evaluation / parsing error code on failure.
1146 * The caller does the bitching.
1147 * @param pDbgc Debugger console instance data.
1148 * @param pArg1 The first argument.
1149 * @param pArg2 The 2nd argument.
1150 * @param pResult Where to store the result.
1151 */
1152static DECLCALLBACK(int) dbgcOpBitwiseShiftRight(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1153{
1154 LogFlow(("dbgcOpBitwiseShiftRight\n"));
1155 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, >>, false);
1156}
1157
1158
1159/**
1160 * Bitwise and operator (binary).
1161 *
1162 * @returns VINF_SUCCESS on success.
1163 * @returns VBox evaluation / parsing error code on failure.
1164 * The caller does the bitching.
1165 * @param pDbgc Debugger console instance data.
1166 * @param pArg1 The first argument.
1167 * @param pArg2 The 2nd argument.
1168 * @param pResult Where to store the result.
1169 */
1170static DECLCALLBACK(int) dbgcOpBitwiseAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1171{
1172 LogFlow(("dbgcOpBitwiseAnd\n"));
1173 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
1174 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, &, false);
1175}
1176
1177
1178/**
1179 * Bitwise exclusive or operator (binary).
1180 *
1181 * @returns VINF_SUCCESS on success.
1182 * @returns VBox evaluation / parsing error code on failure.
1183 * The caller does the bitching.
1184 * @param pDbgc Debugger console instance data.
1185 * @param pArg1 The first argument.
1186 * @param pArg2 The 2nd argument.
1187 * @param pResult Where to store the result.
1188 */
1189static DECLCALLBACK(int) dbgcOpBitwiseXor(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1190{
1191 LogFlow(("dbgcOpBitwiseXor\n"));
1192 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
1193 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, ^, false);
1194}
1195
1196
1197/**
1198 * Bitwise inclusive or operator (binary).
1199 *
1200 * @returns VINF_SUCCESS on success.
1201 * @returns VBox evaluation / parsing error code on failure.
1202 * The caller does the bitching.
1203 * @param pDbgc Debugger console instance data.
1204 * @param pArg1 The first argument.
1205 * @param pArg2 The 2nd argument.
1206 * @param pResult Where to store the result.
1207 */
1208static DECLCALLBACK(int) dbgcOpBitwiseOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1209{
1210 LogFlow(("dbgcOpBitwiseOr\n"));
1211 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
1212 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, |, false);
1213}
1214
1215
1216/**
1217 * Boolean and operator (binary).
1218 *
1219 * @returns VINF_SUCCESS on success.
1220 * @returns VBox evaluation / parsing error code on failure.
1221 * The caller does the bitching.
1222 * @param pDbgc Debugger console instance data.
1223 * @param pArg1 The first argument.
1224 * @param pArg2 The 2nd argument.
1225 * @param pResult Where to store the result.
1226 */
1227static DECLCALLBACK(int) dbgcOpBooleanAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1228{
1229 LogFlow(("dbgcOpBooleanAnd\n"));
1230 /** @todo force numeric return value? */
1231 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, &&, false);
1232}
1233
1234
1235/**
1236 * Boolean or operator (binary).
1237 *
1238 * @returns VINF_SUCCESS on success.
1239 * @returns VBox evaluation / parsing error code on failure.
1240 * The caller does the bitching.
1241 * @param pDbgc Debugger console instance data.
1242 * @param pArg1 The first argument.
1243 * @param pArg2 The 2nd argument.
1244 * @param pResult Where to store the result.
1245 */
1246static DECLCALLBACK(int) dbgcOpBooleanOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1247{
1248 LogFlow(("dbgcOpBooleanOr\n"));
1249 /** @todo force numeric return value? */
1250 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, ||, false);
1251}
1252
1253
1254/**
1255 * Range to operator (binary).
1256 *
1257 * @returns VINF_SUCCESS on success.
1258 * @returns VBox evaluation / parsing error code on failure.
1259 * The caller does the bitching.
1260 * @param pDbgc Debugger console instance data.
1261 * @param pArg1 The first argument.
1262 * @param pArg2 The 2nd argument.
1263 * @param pResult Where to store the result.
1264 */
1265static DECLCALLBACK(int) dbgcOpRangeLength(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1266{
1267 LogFlow(("dbgcOpRangeLength\n"));
1268
1269 /*
1270 * Make result. Strings needs to be resolved into symbols.
1271 */
1272 if (pArg1->enmType == DBGCVAR_TYPE_STRING)
1273 {
1274 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, pResult);
1275 if (RT_FAILURE(rc))
1276 return rc;
1277 }
1278 else
1279 *pResult = *pArg1;
1280
1281 /*
1282 * Convert 2nd argument to element count.
1283 */
1284 pResult->enmRangeType = DBGCVAR_RANGE_ELEMENTS;
1285 switch (pArg2->enmType)
1286 {
1287 case DBGCVAR_TYPE_NUMBER:
1288 pResult->u64Range = pArg2->u.u64Number;
1289 break;
1290
1291 case DBGCVAR_TYPE_STRING:
1292 {
1293 int rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, pResult);
1294 if (RT_FAILURE(rc))
1295 return rc;
1296 pResult->u64Range = pArg2->u.u64Number;
1297 break;
1298 }
1299
1300 default:
1301 return VERR_PARSE_INVALID_OPERATION;
1302 }
1303
1304 return VINF_SUCCESS;
1305}
1306
1307
1308/**
1309 * Range to operator (binary).
1310 *
1311 * @returns VINF_SUCCESS on success.
1312 * @returns VBox evaluation / parsing error code on failure.
1313 * The caller does the bitching.
1314 * @param pDbgc Debugger console instance data.
1315 * @param pArg1 The first argument.
1316 * @param pArg2 The 2nd argument.
1317 * @param pResult Where to store the result.
1318 */
1319static DECLCALLBACK(int) dbgcOpRangeLengthBytes(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1320{
1321 LogFlow(("dbgcOpRangeLengthBytes\n"));
1322 int rc = dbgcOpRangeLength(pDbgc, pArg1, pArg2, pResult);
1323 if (RT_SUCCESS(rc))
1324 pResult->enmRangeType = DBGCVAR_RANGE_BYTES;
1325 return rc;
1326}
1327
1328
1329/**
1330 * Range to operator (binary).
1331 *
1332 * @returns VINF_SUCCESS on success.
1333 * @returns VBox evaluation / parsing error code on failure.
1334 * The caller does the bitching.
1335 * @param pDbgc Debugger console instance data.
1336 * @param pArg1 The first argument.
1337 * @param pArg2 The 2nd argument.
1338 * @param pResult Where to store the result.
1339 */
1340static DECLCALLBACK(int) dbgcOpRangeTo(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1341{
1342 LogFlow(("dbgcOpRangeTo\n"));
1343
1344 /*
1345 * Calc number of bytes between the two args.
1346 */
1347 DBGCVAR Diff;
1348 int rc = dbgcOpSub(pDbgc, pArg2, pArg1, &Diff);
1349 if (RT_FAILURE(rc))
1350 return rc;
1351
1352 /*
1353 * Use the diff as the range of Arg1.
1354 */
1355 *pResult = *pArg1;
1356 pResult->enmRangeType = DBGCVAR_RANGE_BYTES;
1357 switch (Diff.enmType)
1358 {
1359 case DBGCVAR_TYPE_GC_FLAT:
1360 pResult->u64Range = (RTGCUINTPTR)Diff.u.GCFlat;
1361 break;
1362 case DBGCVAR_TYPE_GC_PHYS:
1363 pResult->u64Range = Diff.u.GCPhys;
1364 break;
1365 case DBGCVAR_TYPE_HC_FLAT:
1366 pResult->u64Range = (uintptr_t)Diff.u.pvHCFlat;
1367 break;
1368 case DBGCVAR_TYPE_HC_PHYS:
1369 pResult->u64Range = Diff.u.HCPhys;
1370 break;
1371 case DBGCVAR_TYPE_NUMBER:
1372 pResult->u64Range = Diff.u.u64Number;
1373 break;
1374
1375 case DBGCVAR_TYPE_GC_FAR:
1376 case DBGCVAR_TYPE_STRING:
1377 default:
1378 AssertMsgFailed(("Impossible!\n"));
1379 return VERR_PARSE_INVALID_OPERATION;
1380 }
1381
1382 return VINF_SUCCESS;
1383}
1384
1385
1386/**
1387 * Searches for an operator descriptor which matches the start of
1388 * the expression given us.
1389 *
1390 * @returns Pointer to the operator on success.
1391 * @param pDbgc The debug console instance.
1392 * @param pszExpr Pointer to the expression string which might start with an operator.
1393 * @param fPreferBinary Whether to favour binary or unary operators.
1394 * Caller must assert that it's the desired type! Both types will still
1395 * be returned, this is only for resolving duplicates.
1396 * @param chPrev The previous char. Some operators requires a blank in front of it.
1397 */
1398PCDBGCOP dbgcOperatorLookup(PDBGC pDbgc, const char *pszExpr, bool fPreferBinary, char chPrev)
1399{
1400 PCDBGCOP pOp = NULL;
1401 for (unsigned iOp = 0; iOp < RT_ELEMENTS(g_aOps); iOp++)
1402 {
1403 if ( g_aOps[iOp].szName[0] == pszExpr[0]
1404 && (!g_aOps[iOp].szName[1] || g_aOps[iOp].szName[1] == pszExpr[1])
1405 && (!g_aOps[iOp].szName[2] || g_aOps[iOp].szName[2] == pszExpr[2]))
1406 {
1407 /*
1408 * Check that we don't mistake it for some other operator which have more chars.
1409 */
1410 unsigned j;
1411 for (j = iOp + 1; j < RT_ELEMENTS(g_aOps); j++)
1412 if ( g_aOps[j].cchName > g_aOps[iOp].cchName
1413 && g_aOps[j].szName[0] == pszExpr[0]
1414 && (!g_aOps[j].szName[1] || g_aOps[j].szName[1] == pszExpr[1])
1415 && (!g_aOps[j].szName[2] || g_aOps[j].szName[2] == pszExpr[2]) )
1416 break;
1417 if (j < RT_ELEMENTS(g_aOps))
1418 continue; /* we'll catch it later. (for theoretical +,++,+++ cases.) */
1419 pOp = &g_aOps[iOp];
1420
1421 /*
1422 * Preferred type?
1423 */
1424 if (g_aOps[iOp].fBinary == fPreferBinary)
1425 break;
1426 }
1427 }
1428
1429 if (pOp)
1430 Log2(("dbgcOperatorLookup: pOp=%p %s\n", pOp, pOp->szName));
1431 NOREF(pDbgc); NOREF(chPrev);
1432 return pOp;
1433}
1434
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