VirtualBox

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

Last change on this file since 60404 was 58132, checked in by vboxsync, 9 years ago

*: Doxygen fixes.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use