VirtualBox

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

Last change on this file since 64226 was 62838, checked in by vboxsync, 8 years ago

Debugger: warnings

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