VirtualBox

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

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