VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use