VirtualBox

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

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

gcc 7: Debugger: fall thru

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 49.0 KB
Line 
1/* $Id: DBGCOps.cpp 65645 2017-02-07 11:32:14Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Operators.
4 */
5
6/*
7 * Copyright (C) 2006-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DBGC
23#include <VBox/dbg.h>
24#include <VBox/vmm/dbgf.h>
25#include <VBox/param.h>
26#include <VBox/err.h>
27#include <VBox/log.h>
28
29#include <iprt/assert.h>
30#include <iprt/mem.h>
31#include <iprt/string.h>
32
33#include "DBGCInternal.h"
34
35
36/*********************************************************************************************************************************
37* Internal Functions *
38*********************************************************************************************************************************/
39static DECLCALLBACK(int) dbgcOpMinus(PDBGC pDbgc, PCDBGCVAR pArg, DBGCVARCAT enmCat, PDBGCVAR pResult);
40static DECLCALLBACK(int) dbgcOpPluss(PDBGC pDbgc, PCDBGCVAR pArg, DBGCVARCAT enmCat, PDBGCVAR pResult);
41static DECLCALLBACK(int) dbgcOpBooleanNot(PDBGC pDbgc, PCDBGCVAR pArg, DBGCVARCAT enmCat, PDBGCVAR pResult);
42static DECLCALLBACK(int) dbgcOpBitwiseNot(PDBGC pDbgc, PCDBGCVAR pArg, DBGCVARCAT enmCat, PDBGCVAR pResult);
43static DECLCALLBACK(int) dbgcOpVar(PDBGC pDbgc, PCDBGCVAR pArg, DBGCVARCAT enmCat, PDBGCVAR pResult);
44
45static DECLCALLBACK(int) dbgcOpAddrFar(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
46static DECLCALLBACK(int) dbgcOpMult(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
47static DECLCALLBACK(int) dbgcOpDiv(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
48static DECLCALLBACK(int) dbgcOpMod(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
49static DECLCALLBACK(int) dbgcOpAdd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
50static DECLCALLBACK(int) dbgcOpSub(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
51static DECLCALLBACK(int) dbgcOpBitwiseShiftLeft(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
52static DECLCALLBACK(int) dbgcOpBitwiseShiftRight(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
53static DECLCALLBACK(int) dbgcOpBitwiseAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
54static DECLCALLBACK(int) dbgcOpBitwiseXor(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
55static DECLCALLBACK(int) dbgcOpBitwiseOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
56static DECLCALLBACK(int) dbgcOpBooleanAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
57static DECLCALLBACK(int) dbgcOpBooleanOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
58static DECLCALLBACK(int) dbgcOpRangeLength(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
59static DECLCALLBACK(int) dbgcOpRangeLengthBytes(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
60static DECLCALLBACK(int) dbgcOpRangeTo(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
61
62
63/*********************************************************************************************************************************
64* Defined Constants And Macros *
65*********************************************************************************************************************************/
66/**
67 * Generic implementation of a binary operator.
68 *
69 * @returns VINF_SUCCESS on success.
70 * @returns VBox evaluation / parsing error code on failure.
71 * The caller does the bitching.
72 * @param pDbgc Debugger console instance data.
73 * @param pArg1 The first argument.
74 * @param pArg2 The 2nd argument.
75 * @param pResult Where to store the result.
76 * @param Operator The C operator.
77 * @param fIsDiv Set if it's division and we need to check for zero on the
78 * right hand side.
79 */
80#define DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, Operator, fIsDiv) \
81 do \
82 { \
83 if ((pArg1)->enmType == DBGCVAR_TYPE_STRING) \
84 return VERR_DBGC_PARSE_INVALID_OPERATION; \
85 \
86 /* Get the 64-bit right side value. */ \
87 uint64_t u64Right; \
88 int rc = dbgcOpHelperGetNumber((pDbgc), (pArg2), &u64Right); \
89 if ((fIsDiv) && RT_SUCCESS(rc) && !u64Right) /* div/0 kludge */ \
90 DBGCVAR_INIT_NUMBER((pResult), UINT64_MAX); \
91 else if (RT_SUCCESS(rc)) \
92 { \
93 /* Apply it to the left hand side. */ \
94 if ((pArg1)->enmType == DBGCVAR_TYPE_SYMBOL) \
95 { \
96 rc = dbgcSymbolGet((pDbgc), (pArg1)->u.pszString, DBGCVAR_TYPE_ANY, (pResult)); \
97 if (RT_FAILURE(rc)) \
98 return rc; \
99 } \
100 else \
101 *(pResult) = *(pArg1); \
102 switch ((pResult)->enmType) \
103 { \
104 case DBGCVAR_TYPE_GC_FLAT: \
105 (pResult)->u.GCFlat = (pResult)->u.GCFlat Operator u64Right; \
106 break; \
107 case DBGCVAR_TYPE_GC_FAR: \
108 (pResult)->u.GCFar.off = (pResult)->u.GCFar.off Operator u64Right; \
109 break; \
110 case DBGCVAR_TYPE_GC_PHYS: \
111 (pResult)->u.GCPhys = (pResult)->u.GCPhys Operator u64Right; \
112 break; \
113 case DBGCVAR_TYPE_HC_FLAT: \
114 (pResult)->u.pvHCFlat = (void *)((uintptr_t)(pResult)->u.pvHCFlat Operator u64Right); \
115 break; \
116 case DBGCVAR_TYPE_HC_PHYS: \
117 (pResult)->u.HCPhys = (pResult)->u.HCPhys Operator u64Right; \
118 break; \
119 case DBGCVAR_TYPE_NUMBER: \
120 (pResult)->u.u64Number = (pResult)->u.u64Number Operator u64Right; \
121 break; \
122 default: \
123 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE; \
124 } \
125 } \
126 return rc; \
127 } while (0)
128
129
130/**
131 * Switch the factors/whatever so we preserve pointers.
132 * Far pointers are considered more important that physical and flat pointers.
133 *
134 * @param pArg1 The left side argument. Input & output.
135 * @param pArg2 The right side argument. Input & output.
136 */
137#define DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2) \
138 do \
139 { \
140 if ( DBGCVAR_ISPOINTER((pArg2)->enmType) \
141 && ( !DBGCVAR_ISPOINTER((pArg1)->enmType) \
142 || ( DBGCVAR_IS_FAR_PTR((pArg2)->enmType) \
143 && !DBGCVAR_IS_FAR_PTR((pArg1)->enmType)))) \
144 { \
145 PCDBGCVAR pTmp = (pArg1); \
146 (pArg2) = (pArg1); \
147 (pArg1) = pTmp; \
148 } \
149 } while (0)
150
151
152/*********************************************************************************************************************************
153* Global Variables *
154*********************************************************************************************************************************/
155/** Operators. */
156const DBGCOP g_aDbgcOps[] =
157{
158 /* szName is initialized as a 4 char array because of M$C elsewise optimizing it away in /Ox mode (the 'const char' vs 'char' problem). */
159 /* szName, cchName, fBinary, iPrecedence, pfnHandlerUnary, pfnHandlerBitwise */
160 { {'-'}, 1, false, 1, dbgcOpMinus, NULL, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Unary minus." },
161 { {'+'}, 1, false, 1, dbgcOpPluss, NULL, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Unary plus." },
162 { {'!'}, 1, false, 1, dbgcOpBooleanNot, NULL, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Boolean not." },
163 { {'~'}, 1, false, 1, dbgcOpBitwiseNot, NULL, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Bitwise complement." },
164 { {':'}, 1, true, 2, NULL, dbgcOpAddrFar, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Far pointer." },
165 { {'%'}, 1, false, 3, dbgcOpAddrFlat, NULL, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Flat address." },
166 { {'%','%'}, 2, false, 3, dbgcOpAddrPhys, NULL, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Physical address." },
167 { {'#'}, 1, false, 3, dbgcOpAddrHost, NULL, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Flat host address." },
168 { {'#','%','%'}, 3, false, 3, dbgcOpAddrHostPhys, NULL, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Physical host address." },
169 { {'$'}, 1, false, 3, dbgcOpVar, NULL, DBGCVAR_CAT_SYMBOL, DBGCVAR_CAT_ANY, "Reference a variable." },
170 { {'@'}, 1, false, 3, dbgcOpRegister, NULL, DBGCVAR_CAT_SYMBOL, DBGCVAR_CAT_ANY, "Reference a register." },
171 { {'*'}, 1, true, 10, NULL, dbgcOpMult, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Multiplication." },
172 { {'/'}, 1, true, 11, NULL, dbgcOpDiv, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Division." },
173 { {'m','o','d'}, 3, true, 12, NULL, dbgcOpMod, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Modulus." },
174 { {'+'}, 1, true, 13, NULL, dbgcOpAdd, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Addition." },
175 { {'-'}, 1, true, 14, NULL, dbgcOpSub, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Subtraction." },
176 { {'<','<'}, 2, true, 15, NULL, dbgcOpBitwiseShiftLeft, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Bitwise left shift." },
177 { {'>','>'}, 2, true, 16, NULL, dbgcOpBitwiseShiftRight, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Bitwise right shift." },
178 { {'&'}, 1, true, 17, NULL, dbgcOpBitwiseAnd, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Bitwise and." },
179 { {'^'}, 1, true, 18, NULL, dbgcOpBitwiseXor, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Bitwise exclusiv or." },
180 { {'|'}, 1, true, 19, NULL, dbgcOpBitwiseOr, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Bitwise inclusive or." },
181 { {'&','&'}, 2, true, 20, NULL, dbgcOpBooleanAnd, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Boolean and." },
182 { {'|','|'}, 2, true, 21, NULL, dbgcOpBooleanOr, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Boolean or." },
183 { {'L'}, 1, true, 22, NULL, dbgcOpRangeLength, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Range elements." },
184 { {'L','B'}, 2, true, 23, NULL, dbgcOpRangeLengthBytes, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Range bytes." },
185 { {'T'}, 1, true, 24, NULL, dbgcOpRangeTo, DBGCVAR_CAT_ANY, DBGCVAR_CAT_ANY, "Range to." }
186};
187
188/** Number of operators in the operator array. */
189const uint32_t g_cDbgcOps = RT_ELEMENTS(g_aDbgcOps);
190
191
192/**
193 * Converts an argument to a number value.
194 *
195 * @returns VBox status code.
196 * @param pDbgc The DBGC instance.
197 * @param pArg The argument to convert.
198 * @param pu64Ret Where to return the value.
199 */
200static int dbgcOpHelperGetNumber(PDBGC pDbgc, PCDBGCVAR pArg, uint64_t *pu64Ret)
201{
202 DBGCVAR Var = *pArg;
203 switch (Var.enmType)
204 {
205 case DBGCVAR_TYPE_GC_FLAT:
206 *pu64Ret = Var.u.GCFlat;
207 break;
208 case DBGCVAR_TYPE_GC_FAR:
209 *pu64Ret = Var.u.GCFar.off;
210 break;
211 case DBGCVAR_TYPE_GC_PHYS:
212 *pu64Ret = Var.u.GCPhys;
213 break;
214 case DBGCVAR_TYPE_HC_FLAT:
215 *pu64Ret = (uintptr_t)Var.u.pvHCFlat;
216 break;
217 case DBGCVAR_TYPE_HC_PHYS:
218 *pu64Ret = Var.u.HCPhys;
219 break;
220 case DBGCVAR_TYPE_NUMBER:
221 *pu64Ret = Var.u.u64Number;
222 break;
223 case DBGCVAR_TYPE_SYMBOL:
224 {
225 int rc = dbgcSymbolGet(pDbgc, Var.u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
226 if (RT_FAILURE(rc))
227 return rc;
228 }
229 /* 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_R80:
473#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
474 DBGCVAR_INIT_NUMBER(pResult, (uint64_t)Value.r80Ex.lrd);
475#else
476 DBGCVAR_INIT_NUMBER(pResult, (uint64_t)Value.r80Ex.sj64.u63Fraction);
477#endif
478 return VINF_SUCCESS;
479
480 case DBGFREGVALTYPE_DTR:
481 DBGCVAR_INIT_NUMBER(pResult, Value.dtr.u64Base);
482 return VINF_SUCCESS;
483
484 case DBGFREGVALTYPE_INVALID:
485 case DBGFREGVALTYPE_END:
486 case DBGFREGVALTYPE_32BIT_HACK:
487 break;
488 }
489 rc = VERR_INTERNAL_ERROR_5;
490 }
491 return rc;
492}
493
494
495/**
496 * @callback_method_impl{FNDBGCOPUNARY, Flat address (unary).}
497 */
498DECLCALLBACK(int) dbgcOpAddrFlat(PDBGC pDbgc, PCDBGCVAR pArg, DBGCVARCAT enmCat, PDBGCVAR pResult)
499{
500 RT_NOREF1(enmCat);
501 LogFlow(("dbgcOpAddrFlat\n"));
502 DBGCVARTYPE enmType = DBGCVAR_ISHCPOINTER(pArg->enmType) ? DBGCVAR_TYPE_HC_FLAT : DBGCVAR_TYPE_GC_FLAT;
503 return DBGCCmdHlpConvert(&pDbgc->CmdHlp, pArg, enmType, true /*fConvSyms*/, pResult);
504}
505
506
507/**
508 * @callback_method_impl{FNDBGCOPUNARY, Physical address (unary).}
509 */
510DECLCALLBACK(int) dbgcOpAddrPhys(PDBGC pDbgc, PCDBGCVAR pArg, DBGCVARCAT enmCat, PDBGCVAR pResult)
511{
512 RT_NOREF1(enmCat);
513 LogFlow(("dbgcOpAddrPhys\n"));
514 DBGCVARTYPE enmType = DBGCVAR_ISHCPOINTER(pArg->enmType) ? DBGCVAR_TYPE_HC_PHYS : DBGCVAR_TYPE_GC_PHYS;
515 return DBGCCmdHlpConvert(&pDbgc->CmdHlp, pArg, enmType, true /*fConvSyms*/, pResult);
516}
517
518
519/**
520 * @callback_method_impl{FNDBGCOPUNARY, Physical host address (unary).}
521 */
522DECLCALLBACK(int) dbgcOpAddrHostPhys(PDBGC pDbgc, PCDBGCVAR pArg, DBGCVARCAT enmCat, PDBGCVAR pResult)
523{
524 RT_NOREF1(enmCat);
525 LogFlow(("dbgcOpAddrPhys\n"));
526 return DBGCCmdHlpConvert(&pDbgc->CmdHlp, pArg, DBGCVAR_TYPE_HC_PHYS, true /*fConvSyms*/, pResult);
527}
528
529
530/**
531 * @callback_method_impl{FNDBGCOPUNARY, Host address (unary).}
532 */
533DECLCALLBACK(int) dbgcOpAddrHost(PDBGC pDbgc, PCDBGCVAR pArg, DBGCVARCAT enmCat, PDBGCVAR pResult)
534{
535 RT_NOREF1(enmCat);
536 LogFlow(("dbgcOpAddrHost\n"));
537 return DBGCCmdHlpConvert(&pDbgc->CmdHlp, pArg, DBGCVAR_TYPE_HC_FLAT, true /*fConvSyms*/, pResult);
538}
539
540
541/**
542 * @callback_method_impl{FNDBGCOPUNARY, Far address (unary).}
543 */
544static DECLCALLBACK(int) dbgcOpAddrFar(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
545{
546 LogFlow(("dbgcOpAddrFar\n"));
547 int rc;
548
549 switch (pArg1->enmType)
550 {
551 case DBGCVAR_TYPE_SYMBOL:
552 rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_NUMBER, pResult);
553 if (RT_FAILURE(rc))
554 return rc;
555 break;
556 case DBGCVAR_TYPE_NUMBER:
557 *pResult = *pArg1;
558 break;
559 default:
560 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
561 }
562 pResult->u.GCFar.sel = (RTSEL)pResult->u.u64Number;
563
564 /* common code for the two types we support. */
565 switch (pArg2->enmType)
566 {
567 case DBGCVAR_TYPE_GC_FLAT:
568 pResult->u.GCFar.off = pArg2->u.GCFlat;
569 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
570 break;
571
572 case DBGCVAR_TYPE_HC_FLAT:
573 pResult->u.pvHCFlat = (void *)(uintptr_t)pArg2->u.GCFlat;
574 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
575 break;
576
577 case DBGCVAR_TYPE_NUMBER:
578 pResult->u.GCFar.off = (RTGCPTR)pArg2->u.u64Number;
579 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
580 break;
581
582 case DBGCVAR_TYPE_SYMBOL:
583 {
584 DBGCVAR Var;
585 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
586 if (RT_FAILURE(rc))
587 return rc;
588 pResult->u.GCFar.off = (RTGCPTR)Var.u.u64Number;
589 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
590 break;
591 }
592
593 default:
594 return VERR_DBGC_PARSE_INCORRECT_ARG_TYPE;
595 }
596 return VINF_SUCCESS;
597
598}
599
600
601/**
602 * Multiplication operator (binary).
603 *
604 * @returns VINF_SUCCESS on success.
605 * @returns VBox evaluation / parsing error code on failure.
606 * The caller does the bitching.
607 * @param pDbgc Debugger console instance data.
608 * @param pArg1 The first argument.
609 * @param pArg2 The 2nd argument.
610 * @param pResult Where to store the result.
611 */
612static DECLCALLBACK(int) dbgcOpMult(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
613{
614 LogFlow(("dbgcOpMult\n"));
615 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
616 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, *, false);
617}
618
619
620/**
621 * Division operator (binary).
622 *
623 * @returns VINF_SUCCESS on success.
624 * @returns VBox evaluation / parsing error code on failure.
625 * The caller does the bitching.
626 * @param pDbgc Debugger console instance data.
627 * @param pArg1 The first argument.
628 * @param pArg2 The 2nd argument.
629 * @param pResult Where to store the result.
630 */
631static DECLCALLBACK(int) dbgcOpDiv(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
632{
633 LogFlow(("dbgcOpDiv\n"));
634 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, /, true);
635}
636
637
638/**
639 * Modulus operator (binary).
640 *
641 * @returns VINF_SUCCESS on success.
642 * @returns VBox evaluation / parsing error code on failure.
643 * The caller does the bitching.
644 * @param pDbgc Debugger console instance data.
645 * @param pArg1 The first argument.
646 * @param pArg2 The 2nd argument.
647 * @param pResult Where to store the result.
648 */
649static DECLCALLBACK(int) dbgcOpMod(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
650{
651 LogFlow(("dbgcOpMod\n"));
652 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, %, false);
653}
654
655
656/**
657 * Addition operator (binary).
658 *
659 * @returns VINF_SUCCESS on success.
660 * @returns VBox evaluation / parsing error code on failure.
661 * The caller does the bitching.
662 * @param pDbgc Debugger console instance data.
663 * @param pArg1 The first argument.
664 * @param pArg2 The 2nd argument.
665 * @param pResult Where to store the result.
666 */
667static DECLCALLBACK(int) dbgcOpAdd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
668{
669 LogFlow(("dbgcOpAdd\n"));
670
671 /*
672 * An addition operation will return (when possible) the left side type in the
673 * expression. We make an omission for numbers, where we'll take the right side
674 * type instead. An expression where only the left hand side is a symbol we'll
675 * use the right hand type to try resolve it.
676 */
677 if ( pArg1->enmType == DBGCVAR_TYPE_STRING
678 || pArg2->enmType == DBGCVAR_TYPE_STRING)
679 return VERR_DBGC_PARSE_INVALID_OPERATION; /** @todo string contactenation later. */
680
681 if ( (pArg1->enmType == DBGCVAR_TYPE_NUMBER && pArg2->enmType != DBGCVAR_TYPE_SYMBOL)
682 || (pArg1->enmType == DBGCVAR_TYPE_SYMBOL && pArg2->enmType != DBGCVAR_TYPE_SYMBOL))
683 {
684 PCDBGCVAR pTmp = pArg2;
685 pArg2 = pArg1;
686 pArg1 = pTmp;
687 }
688
689 DBGCVAR Sym1, Sym2;
690 if (pArg1->enmType == DBGCVAR_TYPE_SYMBOL)
691 {
692 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, &Sym1);
693 if (RT_FAILURE(rc))
694 return rc;
695 pArg1 = &Sym1;
696
697 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2);
698 if (RT_FAILURE(rc))
699 return rc;
700 pArg2 = &Sym2;
701 }
702
703 int rc;
704 DBGCVAR Var;
705 DBGCVAR Var2;
706 switch (pArg1->enmType)
707 {
708 /*
709 * GC Flat
710 */
711 case DBGCVAR_TYPE_GC_FLAT:
712 switch (pArg2->enmType)
713 {
714 case DBGCVAR_TYPE_HC_FLAT:
715 case DBGCVAR_TYPE_HC_PHYS:
716 return VERR_DBGC_PARSE_INVALID_OPERATION;
717 default:
718 *pResult = *pArg1;
719 rc = dbgcOpAddrFlat(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var);
720 if (RT_FAILURE(rc))
721 return rc;
722 pResult->u.GCFlat += pArg2->u.GCFlat;
723 break;
724 }
725 break;
726
727 /*
728 * GC Far
729 */
730 case DBGCVAR_TYPE_GC_FAR:
731 switch (pArg2->enmType)
732 {
733 case DBGCVAR_TYPE_HC_FLAT:
734 case DBGCVAR_TYPE_HC_PHYS:
735 return VERR_DBGC_PARSE_INVALID_OPERATION;
736 case DBGCVAR_TYPE_NUMBER:
737 *pResult = *pArg1;
738 pResult->u.GCFar.off += (RTGCPTR)pArg2->u.u64Number;
739 break;
740 default:
741 rc = dbgcOpAddrFlat(pDbgc, pArg1, DBGCVAR_CAT_ANY, pResult);
742 if (RT_FAILURE(rc))
743 return rc;
744 rc = dbgcOpAddrFlat(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var);
745 if (RT_FAILURE(rc))
746 return rc;
747 pResult->u.GCFlat += pArg2->u.GCFlat;
748 break;
749 }
750 break;
751
752 /*
753 * GC Phys
754 */
755 case DBGCVAR_TYPE_GC_PHYS:
756 switch (pArg2->enmType)
757 {
758 case DBGCVAR_TYPE_HC_FLAT:
759 case DBGCVAR_TYPE_HC_PHYS:
760 return VERR_DBGC_PARSE_INVALID_OPERATION;
761 default:
762 *pResult = *pArg1;
763 rc = dbgcOpAddrPhys(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var);
764 if (RT_FAILURE(rc))
765 return rc;
766 if (Var.enmType != DBGCVAR_TYPE_GC_PHYS)
767 return VERR_DBGC_PARSE_INVALID_OPERATION;
768 pResult->u.GCPhys += Var.u.GCPhys;
769 break;
770 }
771 break;
772
773 /*
774 * HC Flat
775 */
776 case DBGCVAR_TYPE_HC_FLAT:
777 *pResult = *pArg1;
778 rc = dbgcOpAddrHost(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var2);
779 if (RT_FAILURE(rc))
780 return rc;
781 rc = dbgcOpAddrFlat(pDbgc, &Var2, DBGCVAR_CAT_ANY, &Var);
782 if (RT_FAILURE(rc))
783 return rc;
784 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat + (uintptr_t)Var.u.pvHCFlat;
785 break;
786
787 /*
788 * HC Phys
789 */
790 case DBGCVAR_TYPE_HC_PHYS:
791 *pResult = *pArg1;
792 rc = dbgcOpAddrHostPhys(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var);
793 if (RT_FAILURE(rc))
794 return rc;
795 pResult->u.HCPhys += Var.u.HCPhys;
796 break;
797
798 /*
799 * Numbers (see start of function)
800 */
801 case DBGCVAR_TYPE_NUMBER:
802 *pResult = *pArg1;
803 switch (pArg2->enmType)
804 {
805 case DBGCVAR_TYPE_SYMBOL:
806 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
807 if (RT_FAILURE(rc))
808 return rc;
809 /* fall thru */
810 case DBGCVAR_TYPE_NUMBER:
811 pResult->u.u64Number += pArg2->u.u64Number;
812 break;
813 default:
814 return VERR_DBGC_PARSE_INVALID_OPERATION;
815 }
816 break;
817
818 default:
819 return VERR_DBGC_PARSE_INVALID_OPERATION;
820
821 }
822 return VINF_SUCCESS;
823}
824
825
826/**
827 * Subtraction operator (binary).
828 *
829 * @returns VINF_SUCCESS on success.
830 * @returns VBox evaluation / parsing error code on failure.
831 * The caller does the bitching.
832 * @param pDbgc Debugger console instance data.
833 * @param pArg1 The first argument.
834 * @param pArg2 The 2nd argument.
835 * @param pResult Where to store the result.
836 */
837static DECLCALLBACK(int) dbgcOpSub(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
838{
839 LogFlow(("dbgcOpSub\n"));
840
841 /*
842 * An subtraction operation will return the left side type in the expression.
843 * However, if the left hand side is a number and the right hand a pointer of
844 * some kind we'll convert the left hand side to the same type as the right hand.
845 * Any symbols will be resolved, strings will be rejected.
846 */
847 DBGCVAR Sym1, Sym2;
848 if ( pArg2->enmType == DBGCVAR_TYPE_SYMBOL
849 && ( pArg1->enmType == DBGCVAR_TYPE_NUMBER
850 || pArg1->enmType == DBGCVAR_TYPE_SYMBOL))
851 {
852 int rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2);
853 if (RT_FAILURE(rc))
854 return rc;
855 pArg2 = &Sym2;
856 }
857
858 if ( pArg1->enmType == DBGCVAR_TYPE_STRING
859 || pArg2->enmType == DBGCVAR_TYPE_STRING)
860 return VERR_DBGC_PARSE_INVALID_OPERATION;
861
862 if (pArg1->enmType == DBGCVAR_TYPE_SYMBOL)
863 {
864 DBGCVARTYPE enmType;
865 switch (pArg2->enmType)
866 {
867 case DBGCVAR_TYPE_NUMBER:
868 enmType = DBGCVAR_TYPE_ANY;
869 break;
870 case DBGCVAR_TYPE_GC_FLAT:
871 case DBGCVAR_TYPE_GC_PHYS:
872 case DBGCVAR_TYPE_HC_FLAT:
873 case DBGCVAR_TYPE_HC_PHYS:
874 enmType = pArg2->enmType;
875 break;
876 case DBGCVAR_TYPE_GC_FAR:
877 enmType = DBGCVAR_TYPE_GC_FLAT;
878 break;
879 default: AssertFailedReturn(VERR_DBGC_IPE);
880 }
881 if (enmType != DBGCVAR_TYPE_STRING)
882 {
883 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, &Sym1);
884 if (RT_FAILURE(rc))
885 return rc;
886 pArg1 = &Sym1;
887 }
888 }
889 else if (pArg1->enmType == DBGCVAR_TYPE_NUMBER)
890 {
891 PFNDBGCOPUNARY pOp = NULL;
892 switch (pArg2->enmType)
893 {
894 case DBGCVAR_TYPE_GC_FAR:
895 case DBGCVAR_TYPE_GC_FLAT:
896 pOp = dbgcOpAddrFlat;
897 break;
898 case DBGCVAR_TYPE_GC_PHYS:
899 pOp = dbgcOpAddrPhys;
900 break;
901 case DBGCVAR_TYPE_HC_FLAT:
902 pOp = dbgcOpAddrHost;
903 break;
904 case DBGCVAR_TYPE_HC_PHYS:
905 pOp = dbgcOpAddrHostPhys;
906 break;
907 case DBGCVAR_TYPE_NUMBER:
908 break;
909 default: AssertFailedReturn(VERR_DBGC_IPE);
910 }
911 if (pOp)
912 {
913 int rc = pOp(pDbgc, pArg1, DBGCVAR_CAT_ANY, &Sym1);
914 if (RT_FAILURE(rc))
915 return rc;
916 pArg1 = &Sym1;
917 }
918 }
919
920 /*
921 * Normal processing.
922 */
923 int rc;
924 DBGCVAR Var;
925 DBGCVAR Var2;
926 switch (pArg1->enmType)
927 {
928 /*
929 * GC Flat
930 */
931 case DBGCVAR_TYPE_GC_FLAT:
932 switch (pArg2->enmType)
933 {
934 case DBGCVAR_TYPE_HC_FLAT:
935 case DBGCVAR_TYPE_HC_PHYS:
936 return VERR_DBGC_PARSE_INVALID_OPERATION;
937 default:
938 *pResult = *pArg1;
939 rc = dbgcOpAddrFlat(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var);
940 if (RT_FAILURE(rc))
941 return rc;
942 pResult->u.GCFlat -= pArg2->u.GCFlat;
943 break;
944 }
945 break;
946
947 /*
948 * GC Far
949 */
950 case DBGCVAR_TYPE_GC_FAR:
951 switch (pArg2->enmType)
952 {
953 case DBGCVAR_TYPE_HC_FLAT:
954 case DBGCVAR_TYPE_HC_PHYS:
955 return VERR_DBGC_PARSE_INVALID_OPERATION;
956 case DBGCVAR_TYPE_NUMBER:
957 *pResult = *pArg1;
958 pResult->u.GCFar.off -= (RTGCPTR)pArg2->u.u64Number;
959 break;
960 default:
961 rc = dbgcOpAddrFlat(pDbgc, pArg1, DBGCVAR_CAT_ANY, pResult);
962 if (RT_FAILURE(rc))
963 return rc;
964 rc = dbgcOpAddrFlat(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var);
965 if (RT_FAILURE(rc))
966 return rc;
967 pResult->u.GCFlat -= pArg2->u.GCFlat;
968 break;
969 }
970 break;
971
972 /*
973 * GC Phys
974 */
975 case DBGCVAR_TYPE_GC_PHYS:
976 switch (pArg2->enmType)
977 {
978 case DBGCVAR_TYPE_HC_FLAT:
979 case DBGCVAR_TYPE_HC_PHYS:
980 return VERR_DBGC_PARSE_INVALID_OPERATION;
981 default:
982 *pResult = *pArg1;
983 rc = dbgcOpAddrPhys(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var);
984 if (RT_FAILURE(rc))
985 return rc;
986 if (Var.enmType != DBGCVAR_TYPE_GC_PHYS)
987 return VERR_DBGC_PARSE_INVALID_OPERATION;
988 pResult->u.GCPhys -= Var.u.GCPhys;
989 break;
990 }
991 break;
992
993 /*
994 * HC Flat
995 */
996 case DBGCVAR_TYPE_HC_FLAT:
997 *pResult = *pArg1;
998 rc = dbgcOpAddrHost(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var2);
999 if (RT_FAILURE(rc))
1000 return rc;
1001 rc = dbgcOpAddrFlat(pDbgc, &Var2, DBGCVAR_CAT_ANY, &Var);
1002 if (RT_FAILURE(rc))
1003 return rc;
1004 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat - (uintptr_t)Var.u.pvHCFlat;
1005 break;
1006
1007 /*
1008 * HC Phys
1009 */
1010 case DBGCVAR_TYPE_HC_PHYS:
1011 *pResult = *pArg1;
1012 rc = dbgcOpAddrHostPhys(pDbgc, pArg2, DBGCVAR_CAT_ANY, &Var);
1013 if (RT_FAILURE(rc))
1014 return rc;
1015 pResult->u.HCPhys -= Var.u.HCPhys;
1016 break;
1017
1018 /*
1019 * Numbers (see start of function)
1020 */
1021 case DBGCVAR_TYPE_NUMBER:
1022 *pResult = *pArg1;
1023 switch (pArg2->enmType)
1024 {
1025 case DBGCVAR_TYPE_SYMBOL:
1026 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
1027 if (RT_FAILURE(rc))
1028 return rc;
1029 /* fall thru */
1030 case DBGCVAR_TYPE_NUMBER:
1031 pResult->u.u64Number -= pArg2->u.u64Number;
1032 break;
1033 default:
1034 return VERR_DBGC_PARSE_INVALID_OPERATION;
1035 }
1036 break;
1037
1038 default:
1039 return VERR_DBGC_PARSE_INVALID_OPERATION;
1040
1041 }
1042 return VINF_SUCCESS;
1043}
1044
1045
1046/**
1047 * Bitwise shift left operator (binary).
1048 *
1049 * @returns VINF_SUCCESS on success.
1050 * @returns VBox evaluation / parsing error code on failure.
1051 * The caller does the bitching.
1052 * @param pDbgc Debugger console instance data.
1053 * @param pArg1 The first argument.
1054 * @param pArg2 The 2nd argument.
1055 * @param pResult Where to store the result.
1056 */
1057static DECLCALLBACK(int) dbgcOpBitwiseShiftLeft(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1058{
1059 LogFlow(("dbgcOpBitwiseShiftLeft\n"));
1060 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, <<, false);
1061}
1062
1063
1064/**
1065 * Bitwise shift right 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) dbgcOpBitwiseShiftRight(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1076{
1077 LogFlow(("dbgcOpBitwiseShiftRight\n"));
1078 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, >>, false);
1079}
1080
1081
1082/**
1083 * Bitwise and 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) dbgcOpBitwiseAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1094{
1095 LogFlow(("dbgcOpBitwiseAnd\n"));
1096 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
1097 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, &, false);
1098}
1099
1100
1101/**
1102 * Bitwise exclusive or operator (binary).
1103 *
1104 * @returns VINF_SUCCESS on success.
1105 * @returns VBox evaluation / parsing error code on failure.
1106 * The caller does the bitching.
1107 * @param pDbgc Debugger console instance data.
1108 * @param pArg1 The first argument.
1109 * @param pArg2 The 2nd argument.
1110 * @param pResult Where to store the result.
1111 */
1112static DECLCALLBACK(int) dbgcOpBitwiseXor(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1113{
1114 LogFlow(("dbgcOpBitwiseXor\n"));
1115 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
1116 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, ^, false);
1117}
1118
1119
1120/**
1121 * Bitwise inclusive or operator (binary).
1122 *
1123 * @returns VINF_SUCCESS on success.
1124 * @returns VBox evaluation / parsing error code on failure.
1125 * The caller does the bitching.
1126 * @param pDbgc Debugger console instance data.
1127 * @param pArg1 The first argument.
1128 * @param pArg2 The 2nd argument.
1129 * @param pResult Where to store the result.
1130 */
1131static DECLCALLBACK(int) dbgcOpBitwiseOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1132{
1133 LogFlow(("dbgcOpBitwiseOr\n"));
1134 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
1135 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, |, false);
1136}
1137
1138
1139/**
1140 * Boolean and operator (binary).
1141 *
1142 * @returns VINF_SUCCESS on success.
1143 * @returns VBox evaluation / parsing error code on failure.
1144 * The caller does the bitching.
1145 * @param pDbgc Debugger console instance data.
1146 * @param pArg1 The first argument.
1147 * @param pArg2 The 2nd argument.
1148 * @param pResult Where to store the result.
1149 */
1150static DECLCALLBACK(int) dbgcOpBooleanAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1151{
1152 LogFlow(("dbgcOpBooleanAnd\n"));
1153 /** @todo force numeric return value? */
1154 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, &&, false);
1155}
1156
1157
1158/**
1159 * Boolean or operator (binary).
1160 *
1161 * @returns VINF_SUCCESS on success.
1162 * @returns VBox evaluation / parsing error code on failure.
1163 * The caller does the bitching.
1164 * @param pDbgc Debugger console instance data.
1165 * @param pArg1 The first argument.
1166 * @param pArg2 The 2nd argument.
1167 * @param pResult Where to store the result.
1168 */
1169static DECLCALLBACK(int) dbgcOpBooleanOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1170{
1171 LogFlow(("dbgcOpBooleanOr\n"));
1172 /** @todo force numeric return value? */
1173 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, ||, false);
1174}
1175
1176
1177/**
1178 * Range to operator (binary).
1179 *
1180 * @returns VINF_SUCCESS on success.
1181 * @returns VBox evaluation / parsing error code on failure.
1182 * The caller does the bitching.
1183 * @param pDbgc Debugger console instance data.
1184 * @param pArg1 The first argument.
1185 * @param pArg2 The 2nd argument.
1186 * @param pResult Where to store the result.
1187 */
1188static DECLCALLBACK(int) dbgcOpRangeLength(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1189{
1190 LogFlow(("dbgcOpRangeLength\n"));
1191
1192 if (pArg1->enmType == DBGCVAR_TYPE_STRING)
1193 return VERR_DBGC_PARSE_INVALID_OPERATION;
1194
1195 /*
1196 * Make result. Symbols needs to be resolved.
1197 */
1198 if (pArg1->enmType == DBGCVAR_TYPE_SYMBOL)
1199 {
1200 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, pResult);
1201 if (RT_FAILURE(rc))
1202 return rc;
1203 }
1204 else
1205 *pResult = *pArg1;
1206
1207 /*
1208 * Convert 2nd argument to element count.
1209 */
1210 pResult->enmRangeType = DBGCVAR_RANGE_ELEMENTS;
1211 switch (pArg2->enmType)
1212 {
1213 case DBGCVAR_TYPE_NUMBER:
1214 pResult->u64Range = pArg2->u.u64Number;
1215 break;
1216
1217 case DBGCVAR_TYPE_SYMBOL:
1218 {
1219 int rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, pResult);
1220 if (RT_FAILURE(rc))
1221 return rc;
1222 pResult->u64Range = pArg2->u.u64Number;
1223 break;
1224 }
1225
1226 case DBGCVAR_TYPE_STRING:
1227 default:
1228 return VERR_DBGC_PARSE_INVALID_OPERATION;
1229 }
1230
1231 return VINF_SUCCESS;
1232}
1233
1234
1235/**
1236 * Range to operator (binary).
1237 *
1238 * @returns VINF_SUCCESS on success.
1239 * @returns VBox evaluation / parsing error code on failure.
1240 * The caller does the bitching.
1241 * @param pDbgc Debugger console instance data.
1242 * @param pArg1 The first argument.
1243 * @param pArg2 The 2nd argument.
1244 * @param pResult Where to store the result.
1245 */
1246static DECLCALLBACK(int) dbgcOpRangeLengthBytes(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1247{
1248 LogFlow(("dbgcOpRangeLengthBytes\n"));
1249 int rc = dbgcOpRangeLength(pDbgc, pArg1, pArg2, pResult);
1250 if (RT_SUCCESS(rc))
1251 pResult->enmRangeType = DBGCVAR_RANGE_BYTES;
1252 return rc;
1253}
1254
1255
1256/**
1257 * Range to operator (binary).
1258 *
1259 * @returns VINF_SUCCESS on success.
1260 * @returns VBox evaluation / parsing error code on failure.
1261 * The caller does the bitching.
1262 * @param pDbgc Debugger console instance data.
1263 * @param pArg1 The first argument.
1264 * @param pArg2 The 2nd argument.
1265 * @param pResult Where to store the result.
1266 */
1267static DECLCALLBACK(int) dbgcOpRangeTo(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1268{
1269 LogFlow(("dbgcOpRangeTo\n"));
1270
1271 /*
1272 * Calc number of bytes between the two args.
1273 */
1274 DBGCVAR Diff;
1275 int rc = dbgcOpSub(pDbgc, pArg2, pArg1, &Diff);
1276 if (RT_FAILURE(rc))
1277 return rc;
1278
1279 /*
1280 * Use the diff as the range of Arg1.
1281 */
1282 *pResult = *pArg1;
1283 pResult->enmRangeType = DBGCVAR_RANGE_BYTES;
1284 switch (Diff.enmType)
1285 {
1286 case DBGCVAR_TYPE_GC_FLAT:
1287 pResult->u64Range = (RTGCUINTPTR)Diff.u.GCFlat;
1288 break;
1289 case DBGCVAR_TYPE_GC_PHYS:
1290 pResult->u64Range = Diff.u.GCPhys;
1291 break;
1292 case DBGCVAR_TYPE_HC_FLAT:
1293 pResult->u64Range = (uintptr_t)Diff.u.pvHCFlat;
1294 break;
1295 case DBGCVAR_TYPE_HC_PHYS:
1296 pResult->u64Range = Diff.u.HCPhys;
1297 break;
1298 case DBGCVAR_TYPE_NUMBER:
1299 pResult->u64Range = Diff.u.u64Number;
1300 break;
1301
1302 case DBGCVAR_TYPE_GC_FAR:
1303 case DBGCVAR_TYPE_STRING:
1304 case DBGCVAR_TYPE_SYMBOL:
1305 default:
1306 AssertMsgFailed(("Impossible!\n"));
1307 return VERR_DBGC_PARSE_INVALID_OPERATION;
1308 }
1309
1310 return VINF_SUCCESS;
1311}
1312
1313
1314/**
1315 * Searches for an operator descriptor which matches the start of
1316 * the expression given us.
1317 *
1318 * @returns Pointer to the operator on success.
1319 * @param pDbgc The debug console instance.
1320 * @param pszExpr Pointer to the expression string which might start with an operator.
1321 * @param fPreferBinary Whether to favour binary or unary operators.
1322 * Caller must assert that it's the desired type! Both types will still
1323 * be returned, this is only for resolving duplicates.
1324 * @param chPrev The previous char. Some operators requires a blank in front of it.
1325 */
1326PCDBGCOP dbgcOperatorLookup(PDBGC pDbgc, const char *pszExpr, bool fPreferBinary, char chPrev)
1327{
1328 PCDBGCOP pOp = NULL;
1329 for (unsigned iOp = 0; iOp < RT_ELEMENTS(g_aDbgcOps); iOp++)
1330 {
1331 if ( g_aDbgcOps[iOp].szName[0] == pszExpr[0]
1332 && (!g_aDbgcOps[iOp].szName[1] || g_aDbgcOps[iOp].szName[1] == pszExpr[1])
1333 && (!g_aDbgcOps[iOp].szName[2] || g_aDbgcOps[iOp].szName[2] == pszExpr[2]))
1334 {
1335 /*
1336 * Check that we don't mistake it for some other operator which have more chars.
1337 */
1338 unsigned j;
1339 for (j = iOp + 1; j < RT_ELEMENTS(g_aDbgcOps); j++)
1340 if ( g_aDbgcOps[j].cchName > g_aDbgcOps[iOp].cchName
1341 && g_aDbgcOps[j].szName[0] == pszExpr[0]
1342 && (!g_aDbgcOps[j].szName[1] || g_aDbgcOps[j].szName[1] == pszExpr[1])
1343 && (!g_aDbgcOps[j].szName[2] || g_aDbgcOps[j].szName[2] == pszExpr[2]) )
1344 break;
1345 if (j < RT_ELEMENTS(g_aDbgcOps))
1346 continue; /* we'll catch it later. (for theoretical +,++,+++ cases.) */
1347 pOp = &g_aDbgcOps[iOp];
1348
1349 /*
1350 * Preferred type?
1351 */
1352 if (g_aDbgcOps[iOp].fBinary == fPreferBinary)
1353 break;
1354 }
1355 }
1356
1357 if (pOp)
1358 Log2(("dbgcOperatorLookup: pOp=%p %s\n", pOp, pOp->szName));
1359 NOREF(pDbgc); NOREF(chPrev);
1360 return pOp;
1361}
1362
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