VirtualBox

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

Last change on this file since 50653 was 46156, checked in by vboxsync, 11 years ago

List near, unassemble, hyper register and more tiny debugger fixes.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use