VirtualBox

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

Last change on this file since 33000 was 31928, checked in by vboxsync, 14 years ago

DBGC: some adjustments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 57.7 KB
Line 
1/* $Id: DBGCOps.cpp 31928 2010-08-24 14:12:14Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Operators.
4 */
5
6/*
7 * Copyright (C) 2006-2010 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/dbgf.h>
25#include <VBox/vm.h>
26#include <VBox/vmm.h>
27#include <VBox/mm.h>
28#include <VBox/pgm.h>
29#include <VBox/selm.h>
30#include <VBox/dis.h>
31#include <VBox/param.h>
32#include <VBox/err.h>
33#include <VBox/log.h>
34
35#include <iprt/alloc.h>
36#include <iprt/alloca.h>
37#include <iprt/string.h>
38#include <iprt/assert.h>
39#include <iprt/ctype.h>
40
41#include <stdlib.h>
42#include <stdio.h>
43
44#include "DBGCInternal.h"
45
46
47/*******************************************************************************
48* Internal Functions *
49*******************************************************************************/
50static DECLCALLBACK(int) dbgcOpMinus(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
51static DECLCALLBACK(int) dbgcOpPluss(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
52static DECLCALLBACK(int) dbgcOpBooleanNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
53static DECLCALLBACK(int) dbgcOpBitwiseNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
54static DECLCALLBACK(int) dbgcOpVar(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult);
55
56static DECLCALLBACK(int) dbgcOpAddrFar(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
57static DECLCALLBACK(int) dbgcOpMult(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
58static DECLCALLBACK(int) dbgcOpDiv(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
59static DECLCALLBACK(int) dbgcOpMod(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
60static DECLCALLBACK(int) dbgcOpAdd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
61static DECLCALLBACK(int) dbgcOpSub(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
62static DECLCALLBACK(int) dbgcOpBitwiseShiftLeft(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
63static DECLCALLBACK(int) dbgcOpBitwiseShiftRight(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
64static DECLCALLBACK(int) dbgcOpBitwiseAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
65static DECLCALLBACK(int) dbgcOpBitwiseXor(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
66static DECLCALLBACK(int) dbgcOpBitwiseOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
67static DECLCALLBACK(int) dbgcOpBooleanAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
68static DECLCALLBACK(int) dbgcOpBooleanOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
69static DECLCALLBACK(int) dbgcOpRangeLength(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
70static DECLCALLBACK(int) dbgcOpRangeLengthBytes(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
71static DECLCALLBACK(int) dbgcOpRangeTo(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult);
72
73
74/*******************************************************************************
75* Defined Constants And Macros *
76*******************************************************************************/
77/**
78 * Generic implementation of a binary operator.
79 *
80 * @returns VINF_SUCCESS on success.
81 * @returns VBox evaluation / parsing error code on failure.
82 * The caller does the bitching.
83 * @param pDbgc Debugger console instance data.
84 * @param pArg1 The first argument.
85 * @param pArg2 The 2nd argument.
86 * @param pResult Where to store the result.
87 * @param Operator The C operator.
88 * @param fIsDiv Set if it's division and we need to check for zero on the
89 * right hand side.
90 */
91#define DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, Operator, fIsDiv) \
92 do \
93 { \
94 /* Get the 64-bit right side value. */ \
95 uint64_t u64Right; \
96 int rc = dbgcOpHelperGetNumber((pDbgc), (pArg2), &u64Right); \
97 if ((fIsDiv) && RT_SUCCESS(rc) && !u64Right) /* div/0 kludge */ \
98 DBGCVAR_INIT_NUMBER((pResult), UINT64_MAX); \
99 else if (RT_SUCCESS(rc)) \
100 { \
101 /* Apply it to the left hand side. */ \
102 if ( (pArg1)->enmType == DBGCVAR_TYPE_SYMBOL \
103 || (pArg1)->enmType == DBGCVAR_TYPE_STRING) \
104 { \
105 rc = dbgcSymbolGet((pDbgc), (pArg1)->u.pszString, DBGCVAR_TYPE_ANY, (pResult)); \
106 if (RT_FAILURE(rc)) \
107 return rc; \
108 } \
109 else \
110 *(pResult) = *(pArg1); \
111 switch ((pResult)->enmType) \
112 { \
113 case DBGCVAR_TYPE_GC_FLAT: \
114 (pResult)->u.GCFlat = (pResult)->u.GCFlat Operator u64Right; \
115 break; \
116 case DBGCVAR_TYPE_GC_FAR: \
117 (pResult)->u.GCFar.off = (pResult)->u.GCFar.off Operator u64Right; \
118 break; \
119 case DBGCVAR_TYPE_GC_PHYS: \
120 (pResult)->u.GCPhys = (pResult)->u.GCPhys Operator u64Right; \
121 break; \
122 case DBGCVAR_TYPE_HC_FLAT: \
123 (pResult)->u.pvHCFlat = (void *)((uintptr_t)(pResult)->u.pvHCFlat Operator u64Right); \
124 break; \
125 case DBGCVAR_TYPE_HC_FAR: \
126 (pResult)->u.HCFar.off = (pResult)->u.HCFar.off Operator u64Right; \
127 break; \
128 case DBGCVAR_TYPE_HC_PHYS: \
129 (pResult)->u.HCPhys = (pResult)->u.HCPhys Operator u64Right; \
130 break; \
131 case DBGCVAR_TYPE_NUMBER: \
132 (pResult)->u.u64Number = (pResult)->u.u64Number Operator u64Right; \
133 break; \
134 default: \
135 return VERR_PARSE_INCORRECT_ARG_TYPE; \
136 } \
137 } \
138 return rc; \
139 } while (0)
140
141
142/**
143 * Switch the factors/whatver so we preserve pointers.
144 * Far pointers are considered more important that physical and flat pointers.
145 *
146 * @param pArg1 The left side argument. Input & output.
147 * @param pArg2 The right side argument. Input & output.
148 */
149#define DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2) \
150 do \
151 { \
152 if ( DBGCVAR_ISPOINTER((pArg2)->enmType) \
153 && ( !DBGCVAR_ISPOINTER((pArg1)->enmType) \
154 || ( DBGCVAR_IS_FAR_PTR((pArg2)->enmType) \
155 && !DBGCVAR_IS_FAR_PTR((pArg1)->enmType)))) \
156 { \
157 PCDBGCVAR pTmp = (pArg1); \
158 (pArg2) = (pArg1); \
159 (pArg1) = pTmp; \
160 } \
161 } while (0)
162
163
164/*******************************************************************************
165* Global Variables *
166*******************************************************************************/
167/** Operators. */
168const DBGCOP g_aOps[] =
169{
170 /* 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). */
171 /* szName, cchName, fBinary, iPrecedence, pfnHandlerUnary, pfnHandlerBitwise */
172 { {'-'}, 1, false, 1, dbgcOpMinus, NULL, "Unary minus." },
173 { {'+'}, 1, false, 1, dbgcOpPluss, NULL, "Unary plus." },
174 { {'!'}, 1, false, 1, dbgcOpBooleanNot, NULL, "Boolean not." },
175 { {'~'}, 1, false, 1, dbgcOpBitwiseNot, NULL, "Bitwise complement." },
176 { {':'}, 1, true, 2, NULL, dbgcOpAddrFar, "Far pointer." },
177 { {'%'}, 1, false, 3, dbgcOpAddrFlat, NULL, "Flat address." },
178 { {'%','%'}, 2, false, 3, dbgcOpAddrPhys, NULL, "Physical address." },
179 { {'#'}, 1, false, 3, dbgcOpAddrHost, NULL, "Flat host address." },
180 { {'#','%','%'}, 3, false, 3, dbgcOpAddrHostPhys, NULL, "Physical host address." },
181 { {'$'}, 1, false, 3, dbgcOpVar, NULL, "Reference a variable." },
182 { {'*'}, 1, true, 10, NULL, dbgcOpMult, "Multiplication." },
183 { {'/'}, 1, true, 11, NULL, dbgcOpDiv, "Division." },
184 { {'%'}, 1, true, 12, NULL, dbgcOpMod, "Modulus." },
185 { {'+'}, 1, true, 13, NULL, dbgcOpAdd, "Addition." },
186 { {'-'}, 1, true, 14, NULL, dbgcOpSub, "Subtraction." },
187 { {'<','<'}, 2, true, 15, NULL, dbgcOpBitwiseShiftLeft, "Bitwise left shift." },
188 { {'>','>'}, 2, true, 16, NULL, dbgcOpBitwiseShiftRight, "Bitwise right shift." },
189 { {'&'}, 1, true, 17, NULL, dbgcOpBitwiseAnd, "Bitwise and." },
190 { {'^'}, 1, true, 18, NULL, dbgcOpBitwiseXor, "Bitwise exclusiv or." },
191 { {'|'}, 1, true, 19, NULL, dbgcOpBitwiseOr, "Bitwise inclusive or." },
192 { {'&','&'}, 2, true, 20, NULL, dbgcOpBooleanAnd, "Boolean and." },
193 { {'|','|'}, 2, true, 21, NULL, dbgcOpBooleanOr, "Boolean or." },
194 { {'L'}, 1, true, 22, NULL, dbgcOpRangeLength, "Range elements." },
195 { {'L','B'}, 2, true, 23, NULL, dbgcOpRangeLengthBytes, "Range bytes." },
196 { {'T'}, 1, true, 24, NULL, dbgcOpRangeTo, "Range to." }
197};
198
199/** Number of operators in the operator array. */
200const unsigned g_cOps = RT_ELEMENTS(g_aOps);
201
202
203/**
204 * Convers an argument to a number value.
205 *
206 * @returns VBox status code.
207 * @param pDbgc The DBGC instance.
208 * @param pArg The argument to convert.
209 * @param pu64Ret Where to return the value.
210 */
211static int dbgcOpHelperGetNumber(PDBGC pDbgc, PCDBGCVAR pArg, uint64_t *pu64Ret)
212{
213 DBGCVAR Var = *pArg;
214 switch (Var.enmType)
215 {
216 case DBGCVAR_TYPE_GC_FLAT:
217 *pu64Ret = Var.u.GCFlat;
218 break;
219 case DBGCVAR_TYPE_GC_FAR:
220 *pu64Ret = Var.u.GCFar.off;
221 break;
222 case DBGCVAR_TYPE_GC_PHYS:
223 *pu64Ret = Var.u.GCPhys;
224 break;
225 case DBGCVAR_TYPE_HC_FLAT:
226 *pu64Ret = (uintptr_t)Var.u.pvHCFlat;
227 break;
228 case DBGCVAR_TYPE_HC_FAR:
229 *pu64Ret = Var.u.HCFar.off;
230 break;
231 case DBGCVAR_TYPE_HC_PHYS:
232 *pu64Ret = Var.u.HCPhys;
233 break;
234 case DBGCVAR_TYPE_STRING:
235 case DBGCVAR_TYPE_SYMBOL:
236 {
237 int rc = dbgcSymbolGet(pDbgc, Var.u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
238 if (RT_FAILURE(rc))
239 return rc;
240 /* fall thru */
241 }
242 case DBGCVAR_TYPE_NUMBER:
243 *pu64Ret = Var.u.u64Number;
244 break;
245 default:
246 return VERR_PARSE_INCORRECT_ARG_TYPE;
247 }
248 return VINF_SUCCESS;
249}
250
251
252/**
253 * Minus (unary).
254 *
255 * @returns VINF_SUCCESS on success.
256 * @returns VBox evaluation / parsing error code on failure.
257 * The caller does the bitching.
258 * @param pDbgc Debugger console instance data.
259 * @param pArg The argument.
260 * @param pResult Where to store the result.
261 */
262static DECLCALLBACK(int) dbgcOpMinus(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
263{
264 LogFlow(("dbgcOpMinus\n"));
265 *pResult = *pArg;
266 switch (pArg->enmType)
267 {
268 case DBGCVAR_TYPE_GC_FLAT:
269 pResult->u.GCFlat = -(RTGCINTPTR)pResult->u.GCFlat;
270 break;
271 case DBGCVAR_TYPE_GC_FAR:
272 pResult->u.GCFar.off = -(int32_t)pResult->u.GCFar.off;
273 break;
274 case DBGCVAR_TYPE_GC_PHYS:
275 pResult->u.GCPhys = (RTGCPHYS) -(int64_t)pResult->u.GCPhys;
276 break;
277 case DBGCVAR_TYPE_HC_FLAT:
278 pResult->u.pvHCFlat = (void *) -(intptr_t)pResult->u.pvHCFlat;
279 break;
280 case DBGCVAR_TYPE_HC_FAR:
281 pResult->u.HCFar.off = -(int32_t)pResult->u.HCFar.off;
282 break;
283 case DBGCVAR_TYPE_HC_PHYS:
284 pResult->u.HCPhys = (RTHCPHYS) -(int64_t)pResult->u.HCPhys;
285 break;
286 case DBGCVAR_TYPE_NUMBER:
287 pResult->u.u64Number = -(int64_t)pResult->u.u64Number;
288 break;
289
290 case DBGCVAR_TYPE_UNKNOWN:
291 case DBGCVAR_TYPE_STRING:
292 default:
293 return VERR_PARSE_INCORRECT_ARG_TYPE;
294 }
295 NOREF(pDbgc);
296 return VINF_SUCCESS;
297}
298
299
300/**
301 * Pluss (unary).
302 *
303 * @returns VINF_SUCCESS on success.
304 * @returns VBox evaluation / parsing error code on failure.
305 * The caller does the bitching.
306 * @param pDbgc Debugger console instance data.
307 * @param pArg The argument.
308 * @param pResult Where to store the result.
309 */
310static DECLCALLBACK(int) dbgcOpPluss(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
311{
312 LogFlow(("dbgcOpPluss\n"));
313 *pResult = *pArg;
314 switch (pArg->enmType)
315 {
316 case DBGCVAR_TYPE_GC_FLAT:
317 case DBGCVAR_TYPE_GC_FAR:
318 case DBGCVAR_TYPE_GC_PHYS:
319 case DBGCVAR_TYPE_HC_FLAT:
320 case DBGCVAR_TYPE_HC_FAR:
321 case DBGCVAR_TYPE_HC_PHYS:
322 case DBGCVAR_TYPE_NUMBER:
323 break;
324
325 case DBGCVAR_TYPE_UNKNOWN:
326 case DBGCVAR_TYPE_STRING:
327 default:
328 return VERR_PARSE_INCORRECT_ARG_TYPE;
329 }
330 NOREF(pDbgc);
331 return VINF_SUCCESS;
332}
333
334
335/**
336 * Boolean not (unary).
337 *
338 * @returns VINF_SUCCESS on success.
339 * @returns VBox evaluation / parsing error code on failure.
340 * The caller does the bitching.
341 * @param pDbgc Debugger console instance data.
342 * @param pArg The argument.
343 * @param pResult Where to store the result.
344 */
345static DECLCALLBACK(int) dbgcOpBooleanNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
346{
347 LogFlow(("dbgcOpBooleanNot\n"));
348 *pResult = *pArg;
349 switch (pArg->enmType)
350 {
351 case DBGCVAR_TYPE_GC_FLAT:
352 pResult->u.u64Number = !pResult->u.GCFlat;
353 break;
354 case DBGCVAR_TYPE_GC_FAR:
355 pResult->u.u64Number = !pResult->u.GCFar.off && pResult->u.GCFar.sel <= 3;
356 break;
357 case DBGCVAR_TYPE_GC_PHYS:
358 pResult->u.u64Number = !pResult->u.GCPhys;
359 break;
360 case DBGCVAR_TYPE_HC_FLAT:
361 pResult->u.u64Number = !pResult->u.pvHCFlat;
362 break;
363 case DBGCVAR_TYPE_HC_FAR:
364 pResult->u.u64Number = !pResult->u.HCFar.off && pResult->u.HCFar.sel <= 3;
365 break;
366 case DBGCVAR_TYPE_HC_PHYS:
367 pResult->u.u64Number = !pResult->u.HCPhys;
368 break;
369 case DBGCVAR_TYPE_NUMBER:
370 pResult->u.u64Number = !pResult->u.u64Number;
371 break;
372 case DBGCVAR_TYPE_STRING:
373 pResult->u.u64Number = !pResult->u64Range;
374 break;
375
376 case DBGCVAR_TYPE_UNKNOWN:
377 default:
378 return VERR_PARSE_INCORRECT_ARG_TYPE;
379 }
380 pResult->enmType = DBGCVAR_TYPE_NUMBER;
381 NOREF(pDbgc);
382 return VINF_SUCCESS;
383}
384
385
386/**
387 * Bitwise not (unary).
388 *
389 * @returns VINF_SUCCESS on success.
390 * @returns VBox evaluation / parsing error code on failure.
391 * The caller does the bitching.
392 * @param pDbgc Debugger console instance data.
393 * @param pArg The argument.
394 * @param pResult Where to store the result.
395 */
396static DECLCALLBACK(int) dbgcOpBitwiseNot(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
397{
398 LogFlow(("dbgcOpBitwiseNot\n"));
399 *pResult = *pArg;
400 switch (pArg->enmType)
401 {
402 case DBGCVAR_TYPE_GC_FLAT:
403 pResult->u.GCFlat = ~pResult->u.GCFlat;
404 break;
405 case DBGCVAR_TYPE_GC_FAR:
406 pResult->u.GCFar.off = ~pResult->u.GCFar.off;
407 break;
408 case DBGCVAR_TYPE_GC_PHYS:
409 pResult->u.GCPhys = ~pResult->u.GCPhys;
410 break;
411 case DBGCVAR_TYPE_HC_FLAT:
412 pResult->u.pvHCFlat = (void *)~(uintptr_t)pResult->u.pvHCFlat;
413 break;
414 case DBGCVAR_TYPE_HC_FAR:
415 pResult->u.HCFar.off= ~pResult->u.HCFar.off;
416 break;
417 case DBGCVAR_TYPE_HC_PHYS:
418 pResult->u.HCPhys = ~pResult->u.HCPhys;
419 break;
420 case DBGCVAR_TYPE_NUMBER:
421 pResult->u.u64Number = ~pResult->u.u64Number;
422 break;
423
424 case DBGCVAR_TYPE_UNKNOWN:
425 case DBGCVAR_TYPE_STRING:
426 default:
427 return VERR_PARSE_INCORRECT_ARG_TYPE;
428 }
429 NOREF(pDbgc);
430 return VINF_SUCCESS;
431}
432
433
434/**
435 * Reference variable (unary).
436 *
437 * @returns VINF_SUCCESS on success.
438 * @returns VBox evaluation / parsing error code on failure.
439 * The caller does the bitching.
440 * @param pDbgc Debugger console instance data.
441 * @param pArg The argument.
442 * @param pResult Where to store the result.
443 */
444static DECLCALLBACK(int) dbgcOpVar(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
445{
446 LogFlow(("dbgcOpVar: %s\n", pArg->u.pszString));
447
448 /*
449 * Parse sanity.
450 */
451 if (pArg->enmType != DBGCVAR_TYPE_STRING)
452 return VERR_PARSE_INCORRECT_ARG_TYPE;
453
454 /*
455 * Lookup the variable.
456 */
457 const char *pszVar = pArg->u.pszString;
458 for (unsigned iVar = 0; iVar < pDbgc->cVars; iVar++)
459 {
460 if (!strcmp(pszVar, pDbgc->papVars[iVar]->szName))
461 {
462 *pResult = pDbgc->papVars[iVar]->Var;
463 return VINF_SUCCESS;
464 }
465 }
466
467 return VERR_PARSE_VARIABLE_NOT_FOUND;
468}
469
470
471/**
472 * Flat address (unary).
473 *
474 * @returns VINF_SUCCESS on success.
475 * @returns VBox evaluation / parsing error code on failure.
476 * The caller does the bitching.
477 * @param pDbgc Debugger console instance data.
478 * @param pArg The argument.
479 * @param pResult Where to store the result.
480 */
481DECLCALLBACK(int) dbgcOpAddrFlat(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
482{
483 LogFlow(("dbgcOpAddrFlat\n"));
484 int rc;
485 *pResult = *pArg;
486
487 switch (pArg->enmType)
488 {
489 case DBGCVAR_TYPE_GC_FLAT:
490 return VINF_SUCCESS;
491
492 case DBGCVAR_TYPE_GC_FAR:
493 {
494 Assert(pDbgc->pVM);
495 DBGFADDRESS Address;
496 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
497 if (RT_SUCCESS(rc))
498 {
499 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
500 pResult->u.GCFlat = Address.FlatPtr;
501 return VINF_SUCCESS;
502 }
503 return VERR_PARSE_CONVERSION_FAILED;
504 }
505
506 case DBGCVAR_TYPE_GC_PHYS:
507 //rc = MMR3PhysGCPhys2GCVirtEx(pDbgc->pVM, pResult->u.GCPhys, ..., &pResult->u.GCFlat); - yea, sure.
508 return VERR_PARSE_INCORRECT_ARG_TYPE;
509
510 case DBGCVAR_TYPE_HC_FLAT:
511 return VINF_SUCCESS;
512
513 case DBGCVAR_TYPE_HC_FAR:
514 return VERR_PARSE_INCORRECT_ARG_TYPE;
515
516 case DBGCVAR_TYPE_HC_PHYS:
517 Assert(pDbgc->pVM);
518 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
519 rc = MMR3HCPhys2HCVirt(pDbgc->pVM, pResult->u.HCPhys, &pResult->u.pvHCFlat);
520 if (RT_SUCCESS(rc))
521 return VINF_SUCCESS;
522 return VERR_PARSE_CONVERSION_FAILED;
523
524 case DBGCVAR_TYPE_NUMBER:
525 pResult->enmType = DBGCVAR_TYPE_GC_FLAT;
526 pResult->u.GCFlat = (RTGCPTR)pResult->u.u64Number;
527 return VINF_SUCCESS;
528
529 case DBGCVAR_TYPE_STRING:
530 return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_GC_FLAT, pResult);
531
532 case DBGCVAR_TYPE_UNKNOWN:
533 default:
534 return VERR_PARSE_INCORRECT_ARG_TYPE;
535 }
536}
537
538
539/**
540 * Physical address (unary).
541 *
542 * @returns VINF_SUCCESS on success.
543 * @returns VBox evaluation / parsing error code on failure.
544 * The caller does the bitching.
545 * @param pDbgc Debugger console instance data.
546 * @param pArg The argument.
547 * @param pResult Where to store the result.
548 */
549DECLCALLBACK(int) dbgcOpAddrPhys(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
550{
551 LogFlow(("dbgcOpAddrPhys\n"));
552 int rc;
553 DBGFADDRESS Address;
554
555 *pResult = *pArg;
556 switch (pArg->enmType)
557 {
558 case DBGCVAR_TYPE_GC_FLAT:
559 Assert(pDbgc->pVM);
560 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
561 rc = DBGFR3AddrToPhys(pDbgc->pVM, pDbgc->idCpu,
562 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
563 &pResult->u.GCPhys);
564 if (RT_SUCCESS(rc))
565 return VINF_SUCCESS;
566 return VERR_PARSE_CONVERSION_FAILED;
567
568 case DBGCVAR_TYPE_GC_FAR:
569 Assert(pDbgc->pVM);
570 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
571 if (RT_SUCCESS(rc))
572 {
573 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
574 rc = DBGFR3AddrToPhys(pDbgc->pVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
575 if (RT_SUCCESS(rc))
576 return VINF_SUCCESS;
577 }
578 return VERR_PARSE_CONVERSION_FAILED;
579
580 case DBGCVAR_TYPE_GC_PHYS:
581 return VINF_SUCCESS;
582
583 case DBGCVAR_TYPE_HC_FLAT:
584 Assert(pDbgc->pVM);
585 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
586 rc = PGMR3DbgR3Ptr2GCPhys(pDbgc->pVM, pArg->u.pvHCFlat, &pResult->u.GCPhys);
587 if (RT_SUCCESS(rc))
588 return VINF_SUCCESS;
589 /** @todo more memory types! */
590 return VERR_PARSE_CONVERSION_FAILED;
591
592 case DBGCVAR_TYPE_HC_FAR:
593 return VERR_PARSE_INCORRECT_ARG_TYPE;
594
595 case DBGCVAR_TYPE_HC_PHYS:
596 return VINF_SUCCESS;
597
598 case DBGCVAR_TYPE_NUMBER:
599 pResult->enmType = DBGCVAR_TYPE_GC_PHYS;
600 pResult->u.GCPhys = (RTGCPHYS)pResult->u.u64Number;
601 return VINF_SUCCESS;
602
603 case DBGCVAR_TYPE_STRING:
604 return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_GC_PHYS, pResult);
605
606 case DBGCVAR_TYPE_UNKNOWN:
607 default:
608 return VERR_PARSE_INCORRECT_ARG_TYPE;
609 }
610 return VINF_SUCCESS;
611}
612
613
614/**
615 * Physical host address (unary).
616 *
617 * @returns VINF_SUCCESS on success.
618 * @returns VBox evaluation / parsing error code on failure.
619 * The caller does the bitching.
620 * @param pDbgc Debugger console instance data.
621 * @param pArg The argument.
622 * @param pResult Where to store the result.
623 */
624DECLCALLBACK(int) dbgcOpAddrHostPhys(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
625{
626 LogFlow(("dbgcOpAddrPhys\n"));
627 DBGFADDRESS Address;
628 int rc;
629
630 *pResult = *pArg;
631 switch (pArg->enmType)
632 {
633 case DBGCVAR_TYPE_GC_FLAT:
634 Assert(pDbgc->pVM);
635 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
636 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu,
637 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
638 &pResult->u.GCPhys);
639 if (RT_SUCCESS(rc))
640 return VINF_SUCCESS;
641 return VERR_PARSE_CONVERSION_FAILED;
642
643 case DBGCVAR_TYPE_GC_FAR:
644 {
645 Assert(pDbgc->pVM);
646 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
647 if (RT_SUCCESS(rc))
648 {
649 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
650 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu, &Address, &pResult->u.GCPhys);
651 if (RT_SUCCESS(rc))
652 return VINF_SUCCESS;
653 }
654 return VERR_PARSE_CONVERSION_FAILED;
655 }
656
657 case DBGCVAR_TYPE_GC_PHYS:
658 Assert(pDbgc->pVM);
659 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
660 rc = DBGFR3AddrToHostPhys(pDbgc->pVM, pDbgc->idCpu,
661 DBGFR3AddrFromPhys(pDbgc->pVM, &Address, pArg->u.GCPhys),
662 &pResult->u.GCPhys);
663 if (RT_SUCCESS(rc))
664 return VINF_SUCCESS;
665 return VERR_PARSE_CONVERSION_FAILED;
666
667 case DBGCVAR_TYPE_HC_FLAT:
668 Assert(pDbgc->pVM);
669 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
670 rc = PGMR3DbgR3Ptr2HCPhys(pDbgc->pVM, pArg->u.pvHCFlat, &pResult->u.HCPhys);
671 if (RT_SUCCESS(rc))
672 return VINF_SUCCESS;
673 /** @todo more memory types! */
674 return VERR_PARSE_CONVERSION_FAILED;
675
676 case DBGCVAR_TYPE_HC_FAR:
677 return VERR_PARSE_INCORRECT_ARG_TYPE;
678
679 case DBGCVAR_TYPE_HC_PHYS:
680 return VINF_SUCCESS;
681
682 case DBGCVAR_TYPE_NUMBER:
683 pResult->enmType = DBGCVAR_TYPE_HC_PHYS;
684 pResult->u.HCPhys = (RTGCPHYS)pResult->u.u64Number;
685 return VINF_SUCCESS;
686
687 case DBGCVAR_TYPE_STRING:
688 return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_HC_PHYS, pResult);
689
690 case DBGCVAR_TYPE_UNKNOWN:
691 default:
692 return VERR_PARSE_INCORRECT_ARG_TYPE;
693 }
694 return VINF_SUCCESS;
695}
696
697
698/**
699 * Host address (unary).
700 *
701 * @returns VINF_SUCCESS on success.
702 * @returns VBox evaluation / parsing error code on failure.
703 * The caller does the bitching.
704 * @param pDbgc Debugger console instance data.
705 * @param pArg The argument.
706 * @param pResult Where to store the result.
707 */
708DECLCALLBACK(int) dbgcOpAddrHost(PDBGC pDbgc, PCDBGCVAR pArg, PDBGCVAR pResult)
709{
710 LogFlow(("dbgcOpAddrHost\n"));
711 int rc;
712 DBGFADDRESS Address;
713
714 *pResult = *pArg;
715 switch (pArg->enmType)
716 {
717 case DBGCVAR_TYPE_GC_FLAT:
718 Assert(pDbgc->pVM);
719 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
720 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu,
721 DBGFR3AddrFromFlat(pDbgc->pVM, &Address, pArg->u.GCFlat),
722 false /*fReadOnly */,
723 &pResult->u.pvHCFlat);
724 if (RT_SUCCESS(rc))
725 return VINF_SUCCESS;
726 return VERR_PARSE_CONVERSION_FAILED;
727
728 case DBGCVAR_TYPE_GC_FAR:
729 Assert(pDbgc->pVM);
730 rc = DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, &Address, pArg->u.GCFar.sel, pArg->u.GCFar.off);
731 if (RT_SUCCESS(rc))
732 {
733 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
734 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu, &Address,
735 false /*fReadOnly*/, &pResult->u.pvHCFlat);
736 if (RT_SUCCESS(rc))
737 return VINF_SUCCESS;
738 }
739 return VERR_PARSE_CONVERSION_FAILED;
740
741 case DBGCVAR_TYPE_GC_PHYS:
742 Assert(pDbgc->pVM);
743 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
744 rc = DBGFR3AddrToVolatileR3Ptr(pDbgc->pVM, pDbgc->idCpu,
745 DBGFR3AddrFromPhys(pDbgc->pVM, &Address, pArg->u.GCPhys),
746 false /*fReadOnly */,
747 &pResult->u.pvHCFlat);
748 if (RT_SUCCESS(rc))
749 return VINF_SUCCESS;
750 return VERR_PARSE_CONVERSION_FAILED;
751
752 case DBGCVAR_TYPE_HC_FLAT:
753 return VINF_SUCCESS;
754
755 case DBGCVAR_TYPE_HC_FAR:
756 case DBGCVAR_TYPE_HC_PHYS:
757 /** @todo !*/
758 return VERR_PARSE_CONVERSION_FAILED;
759
760 case DBGCVAR_TYPE_NUMBER:
761 pResult->enmType = DBGCVAR_TYPE_HC_FLAT;
762 pResult->u.pvHCFlat = (void *)(uintptr_t)pResult->u.u64Number;
763 return VINF_SUCCESS;
764
765 case DBGCVAR_TYPE_STRING:
766 return dbgcSymbolGet(pDbgc, pArg->u.pszString, DBGCVAR_TYPE_HC_FLAT, pResult);
767
768 case DBGCVAR_TYPE_UNKNOWN:
769 default:
770 return VERR_PARSE_INCORRECT_ARG_TYPE;
771 }
772}
773
774
775/**
776 * Bitwise not (unary).
777 *
778 * @returns VINF_SUCCESS on success.
779 * @returns VBox evaluation / parsing error code on failure.
780 * The caller does the bitching.
781 * @param pDbgc Debugger console instance data.
782 * @param pArg The argument.
783 * @param pResult Where to store the result.
784 */
785static DECLCALLBACK(int) dbgcOpAddrFar(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
786{
787 LogFlow(("dbgcOpAddrFar\n"));
788 int rc;
789
790 switch (pArg1->enmType)
791 {
792 case DBGCVAR_TYPE_STRING:
793 rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_NUMBER, pResult);
794 if (RT_FAILURE(rc))
795 return rc;
796 break;
797 case DBGCVAR_TYPE_NUMBER:
798 *pResult = *pArg1;
799 break;
800
801 case DBGCVAR_TYPE_GC_FLAT:
802 case DBGCVAR_TYPE_GC_FAR:
803 case DBGCVAR_TYPE_GC_PHYS:
804 case DBGCVAR_TYPE_HC_FLAT:
805 case DBGCVAR_TYPE_HC_FAR:
806 case DBGCVAR_TYPE_HC_PHYS:
807 case DBGCVAR_TYPE_UNKNOWN:
808 default:
809 return VERR_PARSE_INCORRECT_ARG_TYPE;
810 }
811 pResult->u.GCFar.sel = (RTSEL)pResult->u.u64Number;
812
813 /* common code for the two types we support. */
814 switch (pArg2->enmType)
815 {
816 case DBGCVAR_TYPE_GC_FLAT:
817 pResult->u.GCFar.off = pArg2->u.GCFlat;
818 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
819 break;
820
821 case DBGCVAR_TYPE_HC_FLAT:
822 pResult->u.HCFar.off = pArg2->u.GCFlat;
823 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
824 break;
825
826 case DBGCVAR_TYPE_NUMBER:
827 pResult->u.GCFar.off = (RTGCPTR)pArg2->u.u64Number;
828 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
829 break;
830
831 case DBGCVAR_TYPE_STRING:
832 {
833 DBGCVAR Var;
834 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
835 if (RT_FAILURE(rc))
836 return rc;
837 pResult->u.GCFar.off = (RTGCPTR)Var.u.u64Number;
838 pResult->enmType = DBGCVAR_TYPE_GC_FAR;
839 break;
840 }
841
842 case DBGCVAR_TYPE_GC_FAR:
843 case DBGCVAR_TYPE_GC_PHYS:
844 case DBGCVAR_TYPE_HC_FAR:
845 case DBGCVAR_TYPE_HC_PHYS:
846 case DBGCVAR_TYPE_UNKNOWN:
847 default:
848 return VERR_PARSE_INCORRECT_ARG_TYPE;
849 }
850 return VINF_SUCCESS;
851
852}
853
854
855/**
856 * Multiplication operator (binary).
857 *
858 * @returns VINF_SUCCESS on success.
859 * @returns VBox evaluation / parsing error code on failure.
860 * The caller does the bitching.
861 * @param pDbgc Debugger console instance data.
862 * @param pArg1 The first argument.
863 * @param pArg2 The 2nd argument.
864 * @param pResult Where to store the result.
865 */
866static DECLCALLBACK(int) dbgcOpMult(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
867{
868 LogFlow(("dbgcOpMult\n"));
869 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
870 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, *, false);
871}
872
873
874/**
875 * Division operator (binary).
876 *
877 * @returns VINF_SUCCESS on success.
878 * @returns VBox evaluation / parsing error code on failure.
879 * The caller does the bitching.
880 * @param pDbgc Debugger console instance data.
881 * @param pArg1 The first argument.
882 * @param pArg2 The 2nd argument.
883 * @param pResult Where to store the result.
884 */
885static DECLCALLBACK(int) dbgcOpDiv(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
886{
887 LogFlow(("dbgcOpDiv\n"));
888 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, /, true);
889}
890
891
892/**
893 * Modulus operator (binary).
894 *
895 * @returns VINF_SUCCESS on success.
896 * @returns VBox evaluation / parsing error code on failure.
897 * The caller does the bitching.
898 * @param pDbgc Debugger console instance data.
899 * @param pArg1 The first argument.
900 * @param pArg2 The 2nd argument.
901 * @param pResult Where to store the result.
902 */
903static DECLCALLBACK(int) dbgcOpMod(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
904{
905 LogFlow(("dbgcOpMod\n"));
906 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, %, false);
907}
908
909
910/**
911 * Addition operator (binary).
912 *
913 * @returns VINF_SUCCESS on success.
914 * @returns VBox evaluation / parsing error code on failure.
915 * The caller does the bitching.
916 * @param pDbgc Debugger console instance data.
917 * @param pArg1 The first argument.
918 * @param pArg2 The 2nd argument.
919 * @param pResult Where to store the result.
920 */
921static DECLCALLBACK(int) dbgcOpAdd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
922{
923 LogFlow(("dbgcOpAdd\n"));
924
925 /*
926 * An addition operation will return (when possible) the left side type in the
927 * expression. We make an omission for numbers, where we'll take the right side
928 * type instead. An expression where only the left hand side is a string we'll
929 * use the right hand type assuming that the string is a symbol.
930 */
931 if ( (pArg1->enmType == DBGCVAR_TYPE_NUMBER && pArg2->enmType != DBGCVAR_TYPE_STRING)
932 || (pArg1->enmType == DBGCVAR_TYPE_STRING && pArg2->enmType != DBGCVAR_TYPE_STRING))
933 {
934 PCDBGCVAR pTmp = pArg2;
935 pArg2 = pArg1;
936 pArg1 = pTmp;
937 }
938 DBGCVAR Sym1, Sym2;
939 if (pArg1->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 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2);
947 if (RT_FAILURE(rc))
948 return rc;
949 pArg2 = &Sym2;
950 }
951
952 int rc;
953 DBGCVAR Var;
954 DBGCVAR Var2;
955 switch (pArg1->enmType)
956 {
957 /*
958 * GC Flat
959 */
960 case DBGCVAR_TYPE_GC_FLAT:
961 switch (pArg2->enmType)
962 {
963 case DBGCVAR_TYPE_HC_FLAT:
964 case DBGCVAR_TYPE_HC_FAR:
965 case DBGCVAR_TYPE_HC_PHYS:
966 return VERR_PARSE_INVALID_OPERATION;
967 default:
968 *pResult = *pArg1;
969 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
970 if (RT_FAILURE(rc))
971 return rc;
972 pResult->u.GCFlat += pArg2->u.GCFlat;
973 break;
974 }
975 break;
976
977 /*
978 * GC Far
979 */
980 case DBGCVAR_TYPE_GC_FAR:
981 switch (pArg2->enmType)
982 {
983 case DBGCVAR_TYPE_HC_FLAT:
984 case DBGCVAR_TYPE_HC_FAR:
985 case DBGCVAR_TYPE_HC_PHYS:
986 return VERR_PARSE_INVALID_OPERATION;
987 case DBGCVAR_TYPE_NUMBER:
988 *pResult = *pArg1;
989 pResult->u.GCFar.off += (RTGCPTR)pArg2->u.u64Number;
990 break;
991 default:
992 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
993 if (RT_FAILURE(rc))
994 return rc;
995 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
996 if (RT_FAILURE(rc))
997 return rc;
998 pResult->u.GCFlat += pArg2->u.GCFlat;
999 break;
1000 }
1001 break;
1002
1003 /*
1004 * GC Phys
1005 */
1006 case DBGCVAR_TYPE_GC_PHYS:
1007 switch (pArg2->enmType)
1008 {
1009 case DBGCVAR_TYPE_HC_FLAT:
1010 case DBGCVAR_TYPE_HC_FAR:
1011 case DBGCVAR_TYPE_HC_PHYS:
1012 return VERR_PARSE_INVALID_OPERATION;
1013 default:
1014 *pResult = *pArg1;
1015 rc = dbgcOpAddrPhys(pDbgc, pArg2, &Var);
1016 if (RT_FAILURE(rc))
1017 return rc;
1018 if (Var.enmType != DBGCVAR_TYPE_GC_PHYS)
1019 return VERR_PARSE_INVALID_OPERATION;
1020 pResult->u.GCPhys += Var.u.GCPhys;
1021 break;
1022 }
1023 break;
1024
1025 /*
1026 * HC Flat
1027 */
1028 case DBGCVAR_TYPE_HC_FLAT:
1029 *pResult = *pArg1;
1030 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
1031 if (RT_FAILURE(rc))
1032 return rc;
1033 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
1034 if (RT_FAILURE(rc))
1035 return rc;
1036 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat + (uintptr_t)Var.u.pvHCFlat;
1037 break;
1038
1039 /*
1040 * HC Far
1041 */
1042 case DBGCVAR_TYPE_HC_FAR:
1043 switch (pArg2->enmType)
1044 {
1045 case DBGCVAR_TYPE_NUMBER:
1046 *pResult = *pArg1;
1047 pResult->u.HCFar.off += (uintptr_t)pArg2->u.u64Number;
1048 break;
1049
1050 default:
1051 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
1052 if (RT_FAILURE(rc))
1053 return rc;
1054 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
1055 if (RT_FAILURE(rc))
1056 return rc;
1057 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
1058 if (RT_FAILURE(rc))
1059 return rc;
1060 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat + (uintptr_t)Var.u.pvHCFlat;
1061 break;
1062 }
1063 break;
1064
1065 /*
1066 * HC Phys
1067 */
1068 case DBGCVAR_TYPE_HC_PHYS:
1069 *pResult = *pArg1;
1070 rc = dbgcOpAddrHostPhys(pDbgc, pArg2, &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 case DBGCVAR_TYPE_STRING:
1085 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
1086 if (RT_FAILURE(rc))
1087 return rc;
1088 case DBGCVAR_TYPE_NUMBER:
1089 pResult->u.u64Number += pArg2->u.u64Number;
1090 break;
1091 default:
1092 return VERR_PARSE_INVALID_OPERATION;
1093 }
1094 break;
1095
1096 default:
1097 return VERR_PARSE_INVALID_OPERATION;
1098
1099 }
1100 return VINF_SUCCESS;
1101}
1102
1103
1104/**
1105 * Subtration operator (binary).
1106 *
1107 * @returns VINF_SUCCESS on success.
1108 * @returns VBox evaluation / parsing error code on failure.
1109 * The caller does the bitching.
1110 * @param pDbgc Debugger console instance data.
1111 * @param pArg1 The first argument.
1112 * @param pArg2 The 2nd argument.
1113 * @param pResult Where to store the result.
1114 */
1115static DECLCALLBACK(int) dbgcOpSub(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1116{
1117 LogFlow(("dbgcOpSub\n"));
1118
1119 /*
1120 * An subtraction operation will return the left side type in the expression.
1121 * However, if the left hand side is a number and the right hand a pointer of
1122 * some kind we'll convert the left hand side to the same type as the right hand.
1123 * Any strings will be attempted resolved as symbols.
1124 */
1125 DBGCVAR Sym1, Sym2;
1126 if ( pArg2->enmType == DBGCVAR_TYPE_STRING
1127 && ( pArg1->enmType == DBGCVAR_TYPE_NUMBER
1128 || pArg1->enmType == DBGCVAR_TYPE_STRING))
1129 {
1130 int rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_ANY, &Sym2);
1131 if (RT_FAILURE(rc))
1132 return rc;
1133 pArg2 = &Sym2;
1134 }
1135
1136 if (pArg1->enmType == DBGCVAR_TYPE_STRING)
1137 {
1138 DBGCVARTYPE enmType;
1139 switch (pArg2->enmType)
1140 {
1141 case DBGCVAR_TYPE_NUMBER:
1142 enmType = DBGCVAR_TYPE_ANY;
1143 break;
1144 case DBGCVAR_TYPE_GC_FLAT:
1145 case DBGCVAR_TYPE_GC_PHYS:
1146 case DBGCVAR_TYPE_HC_FLAT:
1147 case DBGCVAR_TYPE_HC_PHYS:
1148 enmType = pArg2->enmType;
1149 break;
1150 case DBGCVAR_TYPE_GC_FAR:
1151 enmType = DBGCVAR_TYPE_GC_FLAT;
1152 break;
1153 case DBGCVAR_TYPE_HC_FAR:
1154 enmType = DBGCVAR_TYPE_HC_FLAT;
1155 break;
1156
1157 default:
1158 case DBGCVAR_TYPE_STRING:
1159 AssertMsgFailed(("Can't happen\n"));
1160 enmType = DBGCVAR_TYPE_STRING;
1161 break;
1162 }
1163 if (enmType != DBGCVAR_TYPE_STRING)
1164 {
1165 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, &Sym1);
1166 if (RT_FAILURE(rc))
1167 return rc;
1168 pArg1 = &Sym1;
1169 }
1170 }
1171 else if (pArg1->enmType == DBGCVAR_TYPE_NUMBER)
1172 {
1173 PFNDBGCOPUNARY pOp = NULL;
1174 switch (pArg2->enmType)
1175 {
1176 case DBGCVAR_TYPE_GC_FAR:
1177 case DBGCVAR_TYPE_GC_FLAT:
1178 pOp = dbgcOpAddrFlat;
1179 break;
1180 case DBGCVAR_TYPE_GC_PHYS:
1181 pOp = dbgcOpAddrPhys;
1182 break;
1183 case DBGCVAR_TYPE_HC_FAR:
1184 case DBGCVAR_TYPE_HC_FLAT:
1185 pOp = dbgcOpAddrHost;
1186 break;
1187 case DBGCVAR_TYPE_HC_PHYS:
1188 pOp = dbgcOpAddrHostPhys;
1189 break;
1190 case DBGCVAR_TYPE_NUMBER:
1191 break;
1192 default:
1193 case DBGCVAR_TYPE_STRING:
1194 AssertMsgFailed(("Can't happen\n"));
1195 break;
1196 }
1197 if (pOp)
1198 {
1199 int rc = pOp(pDbgc, pArg1, &Sym1);
1200 if (RT_FAILURE(rc))
1201 return rc;
1202 pArg1 = &Sym1;
1203 }
1204 }
1205
1206
1207 /*
1208 * Normal processing.
1209 */
1210 int rc;
1211 DBGCVAR Var;
1212 DBGCVAR Var2;
1213 switch (pArg1->enmType)
1214 {
1215 /*
1216 * GC Flat
1217 */
1218 case DBGCVAR_TYPE_GC_FLAT:
1219 switch (pArg2->enmType)
1220 {
1221 case DBGCVAR_TYPE_HC_FLAT:
1222 case DBGCVAR_TYPE_HC_FAR:
1223 case DBGCVAR_TYPE_HC_PHYS:
1224 return VERR_PARSE_INVALID_OPERATION;
1225 default:
1226 *pResult = *pArg1;
1227 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
1228 if (RT_FAILURE(rc))
1229 return rc;
1230 pResult->u.GCFlat -= pArg2->u.GCFlat;
1231 break;
1232 }
1233 break;
1234
1235 /*
1236 * GC Far
1237 */
1238 case DBGCVAR_TYPE_GC_FAR:
1239 switch (pArg2->enmType)
1240 {
1241 case DBGCVAR_TYPE_HC_FLAT:
1242 case DBGCVAR_TYPE_HC_FAR:
1243 case DBGCVAR_TYPE_HC_PHYS:
1244 return VERR_PARSE_INVALID_OPERATION;
1245 case DBGCVAR_TYPE_NUMBER:
1246 *pResult = *pArg1;
1247 pResult->u.GCFar.off -= (RTGCPTR)pArg2->u.u64Number;
1248 break;
1249 default:
1250 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
1251 if (RT_FAILURE(rc))
1252 return rc;
1253 rc = dbgcOpAddrFlat(pDbgc, pArg2, &Var);
1254 if (RT_FAILURE(rc))
1255 return rc;
1256 pResult->u.GCFlat -= pArg2->u.GCFlat;
1257 break;
1258 }
1259 break;
1260
1261 /*
1262 * GC Phys
1263 */
1264 case DBGCVAR_TYPE_GC_PHYS:
1265 switch (pArg2->enmType)
1266 {
1267 case DBGCVAR_TYPE_HC_FLAT:
1268 case DBGCVAR_TYPE_HC_FAR:
1269 case DBGCVAR_TYPE_HC_PHYS:
1270 return VERR_PARSE_INVALID_OPERATION;
1271 default:
1272 *pResult = *pArg1;
1273 rc = dbgcOpAddrPhys(pDbgc, pArg2, &Var);
1274 if (RT_FAILURE(rc))
1275 return rc;
1276 if (Var.enmType != DBGCVAR_TYPE_GC_PHYS)
1277 return VERR_PARSE_INVALID_OPERATION;
1278 pResult->u.GCPhys -= Var.u.GCPhys;
1279 break;
1280 }
1281 break;
1282
1283 /*
1284 * HC Flat
1285 */
1286 case DBGCVAR_TYPE_HC_FLAT:
1287 *pResult = *pArg1;
1288 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
1289 if (RT_FAILURE(rc))
1290 return rc;
1291 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
1292 if (RT_FAILURE(rc))
1293 return rc;
1294 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat - (uintptr_t)Var.u.pvHCFlat;
1295 break;
1296
1297 /*
1298 * HC Far
1299 */
1300 case DBGCVAR_TYPE_HC_FAR:
1301 switch (pArg2->enmType)
1302 {
1303 case DBGCVAR_TYPE_NUMBER:
1304 *pResult = *pArg1;
1305 pResult->u.HCFar.off -= (uintptr_t)pArg2->u.u64Number;
1306 break;
1307
1308 default:
1309 rc = dbgcOpAddrFlat(pDbgc, pArg1, pResult);
1310 if (RT_FAILURE(rc))
1311 return rc;
1312 rc = dbgcOpAddrHost(pDbgc, pArg2, &Var2);
1313 if (RT_FAILURE(rc))
1314 return rc;
1315 rc = dbgcOpAddrFlat(pDbgc, &Var2, &Var);
1316 if (RT_FAILURE(rc))
1317 return rc;
1318 pResult->u.pvHCFlat = (char *)pResult->u.pvHCFlat - (uintptr_t)Var.u.pvHCFlat;
1319 break;
1320 }
1321 break;
1322
1323 /*
1324 * HC Phys
1325 */
1326 case DBGCVAR_TYPE_HC_PHYS:
1327 *pResult = *pArg1;
1328 rc = dbgcOpAddrHostPhys(pDbgc, pArg2, &Var);
1329 if (RT_FAILURE(rc))
1330 return rc;
1331 pResult->u.HCPhys -= Var.u.HCPhys;
1332 break;
1333
1334 /*
1335 * Numbers (see start of function)
1336 */
1337 case DBGCVAR_TYPE_NUMBER:
1338 *pResult = *pArg1;
1339 switch (pArg2->enmType)
1340 {
1341 case DBGCVAR_TYPE_SYMBOL:
1342 case DBGCVAR_TYPE_STRING:
1343 rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, &Var);
1344 if (RT_FAILURE(rc))
1345 return rc;
1346 case DBGCVAR_TYPE_NUMBER:
1347 pResult->u.u64Number -= pArg2->u.u64Number;
1348 break;
1349 default:
1350 return VERR_PARSE_INVALID_OPERATION;
1351 }
1352 break;
1353
1354 default:
1355 return VERR_PARSE_INVALID_OPERATION;
1356
1357 }
1358 return VINF_SUCCESS;
1359}
1360
1361
1362/**
1363 * Bitwise shift left operator (binary).
1364 *
1365 * @returns VINF_SUCCESS on success.
1366 * @returns VBox evaluation / parsing error code on failure.
1367 * The caller does the bitching.
1368 * @param pDbgc Debugger console instance data.
1369 * @param pArg1 The first argument.
1370 * @param pArg2 The 2nd argument.
1371 * @param pResult Where to store the result.
1372 */
1373static DECLCALLBACK(int) dbgcOpBitwiseShiftLeft(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1374{
1375 LogFlow(("dbgcOpBitwiseShiftLeft\n"));
1376 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, <<, false);
1377}
1378
1379
1380/**
1381 * Bitwise shift right operator (binary).
1382 *
1383 * @returns VINF_SUCCESS on success.
1384 * @returns VBox evaluation / parsing error code on failure.
1385 * The caller does the bitching.
1386 * @param pDbgc Debugger console instance data.
1387 * @param pArg1 The first argument.
1388 * @param pArg2 The 2nd argument.
1389 * @param pResult Where to store the result.
1390 */
1391static DECLCALLBACK(int) dbgcOpBitwiseShiftRight(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1392{
1393 LogFlow(("dbgcOpBitwiseShiftRight\n"));
1394 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, >>, false);
1395}
1396
1397
1398/**
1399 * Bitwise and operator (binary).
1400 *
1401 * @returns VINF_SUCCESS on success.
1402 * @returns VBox evaluation / parsing error code on failure.
1403 * The caller does the bitching.
1404 * @param pDbgc Debugger console instance data.
1405 * @param pArg1 The first argument.
1406 * @param pArg2 The 2nd argument.
1407 * @param pResult Where to store the result.
1408 */
1409static DECLCALLBACK(int) dbgcOpBitwiseAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1410{
1411 LogFlow(("dbgcOpBitwiseAnd\n"));
1412 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
1413 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, &, false);
1414}
1415
1416
1417/**
1418 * Bitwise exclusive or operator (binary).
1419 *
1420 * @returns VINF_SUCCESS on success.
1421 * @returns VBox evaluation / parsing error code on failure.
1422 * The caller does the bitching.
1423 * @param pDbgc Debugger console instance data.
1424 * @param pArg1 The first argument.
1425 * @param pArg2 The 2nd argument.
1426 * @param pResult Where to store the result.
1427 */
1428static DECLCALLBACK(int) dbgcOpBitwiseXor(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1429{
1430 LogFlow(("dbgcOpBitwiseXor\n"));
1431 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
1432 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, ^, false);
1433}
1434
1435
1436/**
1437 * Bitwise inclusive or operator (binary).
1438 *
1439 * @returns VINF_SUCCESS on success.
1440 * @returns VBox evaluation / parsing error code on failure.
1441 * The caller does the bitching.
1442 * @param pDbgc Debugger console instance data.
1443 * @param pArg1 The first argument.
1444 * @param pArg2 The 2nd argument.
1445 * @param pResult Where to store the result.
1446 */
1447static DECLCALLBACK(int) dbgcOpBitwiseOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1448{
1449 LogFlow(("dbgcOpBitwiseOr\n"));
1450 DBGC_GEN_ARIT_POINTER_TO_THE_LEFT(pArg1, pArg2);
1451 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, |, false);
1452}
1453
1454
1455/**
1456 * Boolean and operator (binary).
1457 *
1458 * @returns VINF_SUCCESS on success.
1459 * @returns VBox evaluation / parsing error code on failure.
1460 * The caller does the bitching.
1461 * @param pDbgc Debugger console instance data.
1462 * @param pArg1 The first argument.
1463 * @param pArg2 The 2nd argument.
1464 * @param pResult Where to store the result.
1465 */
1466static DECLCALLBACK(int) dbgcOpBooleanAnd(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1467{
1468 LogFlow(("dbgcOpBooleanAnd\n"));
1469 /** @todo force numeric return value? */
1470 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, &&, false);
1471}
1472
1473
1474/**
1475 * Boolean or operator (binary).
1476 *
1477 * @returns VINF_SUCCESS on success.
1478 * @returns VBox evaluation / parsing error code on failure.
1479 * The caller does the bitching.
1480 * @param pDbgc Debugger console instance data.
1481 * @param pArg1 The first argument.
1482 * @param pArg2 The 2nd argument.
1483 * @param pResult Where to store the result.
1484 */
1485static DECLCALLBACK(int) dbgcOpBooleanOr(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1486{
1487 LogFlow(("dbgcOpBooleanOr\n"));
1488 /** @todo force numeric return value? */
1489 DBGC_GEN_ARIT_BINARY_OP(pDbgc, pArg1, pArg2, pResult, ||, false);
1490}
1491
1492
1493/**
1494 * Range to operator (binary).
1495 *
1496 * @returns VINF_SUCCESS on success.
1497 * @returns VBox evaluation / parsing error code on failure.
1498 * The caller does the bitching.
1499 * @param pDbgc Debugger console instance data.
1500 * @param pArg1 The first argument.
1501 * @param pArg2 The 2nd argument.
1502 * @param pResult Where to store the result.
1503 */
1504static DECLCALLBACK(int) dbgcOpRangeLength(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1505{
1506 LogFlow(("dbgcOpRangeLength\n"));
1507
1508 /*
1509 * Make result. Strings needs to be resolved into symbols.
1510 */
1511 if (pArg1->enmType == DBGCVAR_TYPE_STRING)
1512 {
1513 int rc = dbgcSymbolGet(pDbgc, pArg1->u.pszString, DBGCVAR_TYPE_ANY, pResult);
1514 if (RT_FAILURE(rc))
1515 return rc;
1516 }
1517 else
1518 *pResult = *pArg1;
1519
1520 /*
1521 * Convert 2nd argument to element count.
1522 */
1523 pResult->enmRangeType = DBGCVAR_RANGE_ELEMENTS;
1524 switch (pArg2->enmType)
1525 {
1526 case DBGCVAR_TYPE_NUMBER:
1527 pResult->u64Range = pArg2->u.u64Number;
1528 break;
1529
1530 case DBGCVAR_TYPE_STRING:
1531 {
1532 int rc = dbgcSymbolGet(pDbgc, pArg2->u.pszString, DBGCVAR_TYPE_NUMBER, pResult);
1533 if (RT_FAILURE(rc))
1534 return rc;
1535 pResult->u64Range = pArg2->u.u64Number;
1536 break;
1537 }
1538
1539 default:
1540 return VERR_PARSE_INVALID_OPERATION;
1541 }
1542
1543 return VINF_SUCCESS;
1544}
1545
1546
1547/**
1548 * Range to operator (binary).
1549 *
1550 * @returns VINF_SUCCESS on success.
1551 * @returns VBox evaluation / parsing error code on failure.
1552 * The caller does the bitching.
1553 * @param pDbgc Debugger console instance data.
1554 * @param pArg1 The first argument.
1555 * @param pArg2 The 2nd argument.
1556 * @param pResult Where to store the result.
1557 */
1558static DECLCALLBACK(int) dbgcOpRangeLengthBytes(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1559{
1560 LogFlow(("dbgcOpRangeLengthBytes\n"));
1561 int rc = dbgcOpRangeLength(pDbgc, pArg1, pArg2, pResult);
1562 if (RT_SUCCESS(rc))
1563 pResult->enmRangeType = DBGCVAR_RANGE_BYTES;
1564 return rc;
1565}
1566
1567
1568/**
1569 * Range to operator (binary).
1570 *
1571 * @returns VINF_SUCCESS on success.
1572 * @returns VBox evaluation / parsing error code on failure.
1573 * The caller does the bitching.
1574 * @param pDbgc Debugger console instance data.
1575 * @param pArg1 The first argument.
1576 * @param pArg2 The 2nd argument.
1577 * @param pResult Where to store the result.
1578 */
1579static DECLCALLBACK(int) dbgcOpRangeTo(PDBGC pDbgc, PCDBGCVAR pArg1, PCDBGCVAR pArg2, PDBGCVAR pResult)
1580{
1581 LogFlow(("dbgcOpRangeTo\n"));
1582
1583 /*
1584 * Calc number of bytes between the two args.
1585 */
1586 DBGCVAR Diff;
1587 int rc = dbgcOpSub(pDbgc, pArg2, pArg1, &Diff);
1588 if (RT_FAILURE(rc))
1589 return rc;
1590
1591 /*
1592 * Use the diff as the range of Arg1.
1593 */
1594 *pResult = *pArg1;
1595 pResult->enmRangeType = DBGCVAR_RANGE_BYTES;
1596 switch (Diff.enmType)
1597 {
1598 case DBGCVAR_TYPE_GC_FLAT:
1599 pResult->u64Range = (RTGCUINTPTR)Diff.u.GCFlat;
1600 break;
1601 case DBGCVAR_TYPE_GC_PHYS:
1602 pResult->u64Range = Diff.u.GCPhys;
1603 break;
1604 case DBGCVAR_TYPE_HC_FLAT:
1605 pResult->u64Range = (uintptr_t)Diff.u.pvHCFlat;
1606 break;
1607 case DBGCVAR_TYPE_HC_PHYS:
1608 pResult->u64Range = Diff.u.HCPhys;
1609 break;
1610 case DBGCVAR_TYPE_NUMBER:
1611 pResult->u64Range = Diff.u.u64Number;
1612 break;
1613
1614 case DBGCVAR_TYPE_GC_FAR:
1615 case DBGCVAR_TYPE_STRING:
1616 case DBGCVAR_TYPE_HC_FAR:
1617 default:
1618 AssertMsgFailed(("Impossible!\n"));
1619 return VERR_PARSE_INVALID_OPERATION;
1620 }
1621
1622 return VINF_SUCCESS;
1623}
1624
1625
1626/**
1627 * Searches for an operator descriptor which matches the start of
1628 * the expression given us.
1629 *
1630 * @returns Pointer to the operator on success.
1631 * @param pDbgc The debug console instance.
1632 * @param pszExpr Pointer to the expression string which might start with an operator.
1633 * @param fPreferBinary Whether to favour binary or unary operators.
1634 * Caller must assert that it's the disired type! Both types will still
1635 * be returned, this is only for resolving duplicates.
1636 * @param chPrev The previous char. Some operators requires a blank in front of it.
1637 */
1638PCDBGCOP dbgcOperatorLookup(PDBGC pDbgc, const char *pszExpr, bool fPreferBinary, char chPrev)
1639{
1640 PCDBGCOP pOp = NULL;
1641 for (unsigned iOp = 0; iOp < RT_ELEMENTS(g_aOps); iOp++)
1642 {
1643 if ( g_aOps[iOp].szName[0] == pszExpr[0]
1644 && (!g_aOps[iOp].szName[1] || g_aOps[iOp].szName[1] == pszExpr[1])
1645 && (!g_aOps[iOp].szName[2] || g_aOps[iOp].szName[2] == pszExpr[2]))
1646 {
1647 /*
1648 * Check that we don't mistake it for some other operator which have more chars.
1649 */
1650 unsigned j;
1651 for (j = iOp + 1; j < RT_ELEMENTS(g_aOps); j++)
1652 if ( g_aOps[j].cchName > g_aOps[iOp].cchName
1653 && g_aOps[j].szName[0] == pszExpr[0]
1654 && (!g_aOps[j].szName[1] || g_aOps[j].szName[1] == pszExpr[1])
1655 && (!g_aOps[j].szName[2] || g_aOps[j].szName[2] == pszExpr[2]) )
1656 break;
1657 if (j < RT_ELEMENTS(g_aOps))
1658 continue; /* we'll catch it later. (for theoretical +,++,+++ cases.) */
1659 pOp = &g_aOps[iOp];
1660
1661 /*
1662 * Prefered type?
1663 */
1664 if (g_aOps[iOp].fBinary == fPreferBinary)
1665 break;
1666 }
1667 }
1668
1669 if (pOp)
1670 Log2(("dbgcOperatorLookup: pOp=%p %s\n", pOp, pOp->szName));
1671 NOREF(pDbgc); NOREF(chPrev);
1672 return pOp;
1673}
1674
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use