VirtualBox

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

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

Debugger console: Made the evaluator a bit smarter wrt to the register and variable operators (e.g. don't confuse @ah with a hexadecimal number).

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