VirtualBox

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

Last change on this file since 41561 was 41561, checked in by vboxsync, 13 years ago

DBGC: Made the parse cope with functions.

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