VirtualBox

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

Last change on this file since 45786 was 44528, checked in by vboxsync, 12 years ago

header (C) fixes

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