3 * Copyright (C) 2005 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/dbg/kdb_expr.c
22 * PURPOSE: Kernel debugger expression evaluation
23 * PROGRAMMER: Gregor Anich (blight@blight.eu.org)
30 * The given expression is parsed and stored in reverse polish notation,
31 * then it is evaluated and the result is returned.
34 /* INCLUDES ******************************************************************/
40 /* TYPES *********************************************************************/
41 typedef enum _RPN_OP_TYPE
51 typedef ULONGLONG (*RPN_BINARY_OPERATOR
)(ULONGLONG a
, ULONGLONG b
);
53 typedef struct _RPN_OP
56 ULONG CharacterOffset
;
59 /* RpnOpBinaryOperator */
60 RPN_BINARY_OPERATOR BinaryOperator
;
65 /* RpnOpDereference */
66 UCHAR DerefMemorySize
;
72 typedef struct _RPN_STACK
74 ULONG Size
; /* Number of RPN_OPs on Ops */
75 ULONG Sp
; /* Stack pointer */
76 RPN_OP Ops
[1]; /* Array of RPN_OPs */
78 RPN_STACK
, *PRPN_STACK
;
80 /* DEFINES *******************************************************************/
81 #define stricmp _stricmp
83 #ifndef RTL_FIELD_SIZE
84 # define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
87 #define CONST_STRCPY(dst, src) \
88 do { if ((dst)) { memcpy(dst, src, sizeof(src)); } } while (0);
90 #define RPN_OP_STACK_SIZE 256
91 #define RPN_VALUE_STACK_SIZE 256
93 /* GLOBALS *******************************************************************/
98 RPN_OP Ops
[RPN_OP_STACK_SIZE
];
112 RegisterToTrapFrame
[] =
114 {"eip", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Eip
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Eip
)},
115 {"eflags", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.EFlags
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.EFlags
)},
116 {"eax", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Eax
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Eax
)},
117 {"ebx", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Ebx
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Ebx
)},
118 {"ecx", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Ecx
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Ecx
)},
119 {"edx", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Edx
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Edx
)},
120 {"esi", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Esi
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Esi
)},
121 {"edi", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Edi
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Edi
)},
122 {"esp", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.HardwareEsp
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.HardwareEsp
)},
123 {"ebp", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Ebp
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Ebp
)},
124 {"cs", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.SegCs
), 2 }, /* Use only the lower 2 bytes */
125 {"ds", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.SegDs
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.SegDs
)},
126 {"es", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.SegEs
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.SegEs
)},
127 {"fs", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.SegFs
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.SegFs
)},
128 {"gs", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.SegGs
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.SegGs
)},
129 {"ss", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.HardwareSegSs
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.HardwareSegSs
)},
130 {"dr0", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Dr0
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Dr0
)},
131 {"dr1", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Dr1
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Dr1
)},
132 {"dr2", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Dr2
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Dr2
)},
133 {"dr3", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Dr3
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Dr3
)},
134 {"dr6", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Dr6
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Dr6
)},
135 {"dr7", FIELD_OFFSET(KDB_KTRAP_FRAME
, Tf
.Dr7
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Tf
.Dr7
)},
136 {"cr0", FIELD_OFFSET(KDB_KTRAP_FRAME
, Cr0
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Cr0
)},
137 {"cr2", FIELD_OFFSET(KDB_KTRAP_FRAME
, Cr2
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Cr2
)},
138 {"cr3", FIELD_OFFSET(KDB_KTRAP_FRAME
, Cr3
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Cr3
)},
139 {"cr4", FIELD_OFFSET(KDB_KTRAP_FRAME
, Cr4
), RTL_FIELD_SIZE(KDB_KTRAP_FRAME
, Cr4
)}
141 static const INT RegisterToTrapFrameCount
= sizeof (RegisterToTrapFrame
) / sizeof (RegisterToTrapFrame
[0]);
143 /* FUNCTIONS *****************************************************************/
146 RpnBinaryOperatorAdd(
154 RpnBinaryOperatorSub(
162 RpnBinaryOperatorMul(
170 RpnBinaryOperatorDiv(
178 RpnBinaryOperatorMod(
186 RpnBinaryOperatorEquals(
194 RpnBinaryOperatorNotEquals(
202 RpnBinaryOperatorLessThan(
210 RpnBinaryOperatorLessThanOrEquals(
218 RpnBinaryOperatorGreaterThan(
226 RpnBinaryOperatorGreaterThanOrEquals(
233 /*!\brief Dumps the given RPN stack content
235 * \param Stack Pointer to a RPN_STACK structure.
244 DbgPrint("\nStack size: %ld\n", Stack
->Sp
);
246 for (ul
= 0; ul
< Stack
->Sp
; ul
++)
248 PRPN_OP Op
= Stack
->Ops
+ ul
;
256 DbgPrint("0x%I64x,", Op
->Data
.Immediate
);
259 case RpnOpBinaryOperator
:
260 if (Op
->Data
.BinaryOperator
== RpnBinaryOperatorAdd
)
262 else if (Op
->Data
.BinaryOperator
== RpnBinaryOperatorSub
)
264 else if (Op
->Data
.BinaryOperator
== RpnBinaryOperatorMul
)
266 else if (Op
->Data
.BinaryOperator
== RpnBinaryOperatorDiv
)
268 else if (Op
->Data
.BinaryOperator
== RpnBinaryOperatorMod
)
270 else if (Op
->Data
.BinaryOperator
== RpnBinaryOperatorEquals
)
272 else if (Op
->Data
.BinaryOperator
== RpnBinaryOperatorNotEquals
)
274 else if (Op
->Data
.BinaryOperator
== RpnBinaryOperatorLessThan
)
276 else if (Op
->Data
.BinaryOperator
== RpnBinaryOperatorLessThanOrEquals
)
278 else if (Op
->Data
.BinaryOperator
== RpnBinaryOperatorGreaterThan
)
280 else if (Op
->Data
.BinaryOperator
== RpnBinaryOperatorGreaterThanOrEquals
)
283 DbgPrint("UNKNOWN OP,");
288 DbgPrint("%s,", RegisterToTrapFrame
[Op
->Data
.Register
].Name
);
291 case RpnOpDereference
:
293 (Op
->Data
.DerefMemorySize
== 1) ? ("byte") :
294 ((Op
->Data
.DerefMemorySize
== 2) ? ("word") :
295 ((Op
->Data
.DerefMemorySize
== 4) ? ("dword") : ("qword"))));
299 DbgPrint("\nUnsupported Type: %d\n", Op
->Type
);
308 /*!\brief Clears the given RPN stack.
310 * \param Stack Pointer to a RPN_STACK structure.
314 OUT PRPN_STACK Stack
)
320 /*!\brief Pushes an RPN_OP onto the stack.
322 * \param Stack Pointer to a RPN_STACK structure.
323 * \param Op RPN_OP to be copied onto the stack.
327 IN OUT PRPN_STACK Stack
,
333 if (Stack
->Sp
>= Stack
->Size
)
336 memcpy(Stack
->Ops
+ Stack
->Sp
, Op
, sizeof (RPN_OP
));
342 /*!\brief Pops the top op from the stack.
344 * \param Stack Pointer to a RPN_STACK structure.
345 * \param Op Pointer to an RPN_OP to store the popped op into (can be NULL).
347 * \retval TRUE Success.
348 * \retval FALSE Failure (stack empty)
352 IN OUT PRPN_STACK Stack
,
353 OUT PRPN_OP Op OPTIONAL
)
362 memcpy(Op
, Stack
->Ops
+ Stack
->Sp
, sizeof (RPN_OP
));
367 /*!\brief Gets the top op from the stack (not popping it)
369 * \param Stack Pointer to a RPN_STACK structure.
370 * \param Op Pointer to an RPN_OP to copy the top op into.
372 * \retval TRUE Success.
373 * \retval FALSE Failure (stack empty)
386 memcpy(Op
, Stack
->Ops
+ Stack
->Sp
- 1, sizeof (RPN_OP
));
391 /*!\brief Parses an expression.
393 * This functions parses the given expression until the end of string or a closing
394 * brace is found. As the function parses the string it pushes RPN_OPs onto the
397 * Examples: 1+2*3 ; eax+10 ; (eax+16) * (ebx+4) ; dword[eax]
399 * \param Stack Pointer to a RPN_STACK structure.
400 * \param Expression String to parse.
401 * \param CharacterOffset Character offset of the subexpression from the beginning of the expression.
402 * \param End On success End is set to the character at which parsing stopped.
403 * \param ErrOffset On failure this is set to the character offset at which the error occoured.
404 * \param ErrMsg On failure a message describing the problem is copied into this buffer (128 bytes)
406 * \retval TRUE Success.
407 * \retval FALSE Failure.
413 OUT PCHAR
*End OPTIONAL
,
414 IN ULONG CharacterOffset
,
415 OUT PLONG ErrOffset OPTIONAL
,
416 OUT PCHAR ErrMsg OPTIONAL
)
418 PCHAR p
= Expression
;
420 PCHAR Operator
= NULL
;
421 LONG OperatorOffset
= -1;
423 RPN_OP PoppedOperator
;
424 BOOLEAN HavePoppedOperator
= FALSE
;
425 RPN_OP ComparativeOp
;
426 BOOLEAN ComparativeOpFilled
= FALSE
;
427 BOOLEAN IsComparativeOp
;
440 /* Skip whitespace */
447 /* Check for end of expression */
448 if (p
[0] == '\0' || p
[0] == ')' || p
[0] == ']')
453 /* Remember operator */
455 OperatorOffset
= CharacterOffset
++;
457 /* Pop operator (to get the right operator precedence) */
458 HavePoppedOperator
= FALSE
;
459 if (*Operator
== '*' || *Operator
== '/' || *Operator
== '%')
461 if (RpnpTopStack(Stack
, &PoppedOperator
) &&
462 PoppedOperator
.Type
== RpnOpBinaryOperator
&&
463 (PoppedOperator
.Data
.BinaryOperator
== RpnBinaryOperatorAdd
||
464 PoppedOperator
.Data
.BinaryOperator
== RpnBinaryOperatorSub
))
466 RpnpPopStack(Stack
, NULL
);
467 HavePoppedOperator
= TRUE
;
469 else if (PoppedOperator
.Type
== RpnOpNop
)
471 RpnpPopStack(Stack
, NULL
);
472 /* Discard the NOP - it was only pushed to indicate there was a
473 * closing brace, so the previous operator shouldn't be popped.
477 else if ((Operator
[0] == '=' && Operator
[1] == '=') ||
478 (Operator
[0] == '!' && Operator
[1] == '=') ||
479 Operator
[0] == '<' || Operator
[0] == '>')
481 if (Operator
[0] == '=' || Operator
[0] == '!' ||
482 (Operator
[0] == '<' && Operator
[1] == '=') ||
483 (Operator
[0] == '>' && Operator
[1] == '='))
489 /* Parse rest of expression */
490 if (!RpnpParseExpression(Stack
, p
+ 1, &pend
, CharacterOffset
+ 1,
495 else if (pend
== p
+ 1)
497 CONST_STRCPY(ErrMsg
, "Expression expected");
500 *ErrOffset
= CharacterOffset
+ 1;
505 goto end_of_expression
; /* return */
508 else if (Operator
[0] != '+' && Operator
[0] != '-')
510 CONST_STRCPY(ErrMsg
, "Operator expected");
513 *ErrOffset
= OperatorOffset
;
518 /* Skip whitespace */
527 MemorySize
= sizeof(ULONG_PTR
); /* default to pointer size */
530 i
= strcspn(p
, "+-*/%()[]<>!=");
535 /* Copy register name/memory size */
536 while (isspace(p
[--i2
]));
538 i2
= min(i2
+ 1, (INT
)sizeof (Buffer
) - 1);
539 strncpy(Buffer
, p
, i2
);
542 /* Memory size prefix */
545 if (stricmp(Buffer
, "byte") == 0)
547 else if (stricmp(Buffer
, "word") == 0)
549 else if (stricmp(Buffer
, "dword") == 0)
551 else if (stricmp(Buffer
, "qword") == 0)
555 CONST_STRCPY(ErrMsg
, "Invalid memory size prefix");
558 *ErrOffset
= CharacterOffset
;
564 CharacterOffset
+= i
;
568 /* Try to find register */
569 for (i
= 0; i
< RegisterToTrapFrameCount
; i
++)
571 if (stricmp(RegisterToTrapFrame
[i
].Name
, Buffer
) == 0)
575 if (i
< RegisterToTrapFrameCount
)
577 RpnOp
.Type
= RpnOpRegister
;
578 RpnOp
.CharacterOffset
= CharacterOffset
;
579 RpnOp
.Data
.Register
= i
;
580 i
= strlen(RegisterToTrapFrame
[i
].Name
);
581 CharacterOffset
+= i
;
586 /* Immediate value */
587 /* FIXME: Need string to ULONGLONG function */
588 ul
= strtoul(p
, &pend
, 0);
591 RpnOp
.Type
= RpnOpImmediate
;
592 RpnOp
.CharacterOffset
= CharacterOffset
;
593 RpnOp
.Data
.Immediate
= (ULONGLONG
)ul
;
594 CharacterOffset
+= pend
- p
;
599 CONST_STRCPY(ErrMsg
, "Operand expected");
602 *ErrOffset
= CharacterOffset
;
609 if (!RpnpPushStack(Stack
, &RpnOp
))
611 CONST_STRCPY(ErrMsg
, "RPN op stack overflow");
621 if (p
[0] == '(' || p
[0] == '[') /* subexpression */
623 if (!RpnpParseExpression(Stack
, p
+ 1, &pend
, CharacterOffset
+ 1,
628 else if (pend
== p
+ 1)
630 CONST_STRCPY(ErrMsg
, "Expression expected");
633 *ErrOffset
= CharacterOffset
+ 1;
638 if (p
[0] == '[') /* dereference */
640 ASSERT(MemorySize
== 1 || MemorySize
== 2 ||
641 MemorySize
== 4 || MemorySize
== 8);
645 CONST_STRCPY(ErrMsg
, "']' expected");
648 *ErrOffset
= CharacterOffset
+ (pend
- p
);
653 RpnOp
.Type
= RpnOpDereference
;
654 RpnOp
.CharacterOffset
= CharacterOffset
;
655 RpnOp
.Data
.DerefMemorySize
= MemorySize
;
657 if (!RpnpPushStack(Stack
, &RpnOp
))
659 CONST_STRCPY(ErrMsg
, "RPN op stack overflow");
667 else /* p[0] == '(' */
671 CONST_STRCPY(ErrMsg
, "')' expected");
674 *ErrOffset
= CharacterOffset
+ (pend
- p
);
680 /* Push a "nop" to prevent popping of the + operator (which would
681 * result in (10+10)/2 beeing evaluated as 15)
683 RpnOp
.Type
= RpnOpNop
;
684 if (!RpnpPushStack(Stack
, &RpnOp
))
686 CONST_STRCPY(ErrMsg
, "RPN op stack overflow");
694 /* Skip closing brace/bracket */
697 CharacterOffset
+= pend
- p
;
700 else if (First
&& p
[0] == '-') /* Allow expressions like "- eax" */
702 RpnOp
.Type
= RpnOpImmediate
;
703 RpnOp
.CharacterOffset
= CharacterOffset
;
704 RpnOp
.Data
.Immediate
= 0;
706 if (!RpnpPushStack(Stack
, &RpnOp
))
708 CONST_STRCPY(ErrMsg
, "RPN op stack overflow");
718 CONST_STRCPY(ErrMsg
, "Operand expected");
721 *ErrOffset
= CharacterOffset
;
728 CONST_STRCPY(ErrMsg
, "strcspn() failed");
739 RpnOp
.CharacterOffset
= OperatorOffset
;
740 RpnOp
.Type
= RpnOpBinaryOperator
;
741 IsComparativeOp
= FALSE
;
746 RpnOp
.Data
.BinaryOperator
= RpnBinaryOperatorAdd
;
750 RpnOp
.Data
.BinaryOperator
= RpnBinaryOperatorSub
;
754 RpnOp
.Data
.BinaryOperator
= RpnBinaryOperatorMul
;
758 RpnOp
.Data
.BinaryOperator
= RpnBinaryOperatorDiv
;
762 RpnOp
.Data
.BinaryOperator
= RpnBinaryOperatorMod
;
766 ASSERT(Operator
[1] == '=');
767 IsComparativeOp
= TRUE
;
768 RpnOp
.Data
.BinaryOperator
= RpnBinaryOperatorEquals
;
772 ASSERT(Operator
[1] == '=');
773 IsComparativeOp
= TRUE
;
774 RpnOp
.Data
.BinaryOperator
= RpnBinaryOperatorNotEquals
;
778 IsComparativeOp
= TRUE
;
780 if (Operator
[1] == '=')
781 RpnOp
.Data
.BinaryOperator
= RpnBinaryOperatorLessThanOrEquals
;
783 RpnOp
.Data
.BinaryOperator
= RpnBinaryOperatorLessThan
;
788 IsComparativeOp
= TRUE
;
790 if (Operator
[1] == '=')
791 RpnOp
.Data
.BinaryOperator
= RpnBinaryOperatorGreaterThanOrEquals
;
793 RpnOp
.Data
.BinaryOperator
= RpnBinaryOperatorGreaterThan
;
804 if (ComparativeOpFilled
&& !RpnpPushStack(Stack
, &ComparativeOp
))
806 CONST_STRCPY(ErrMsg
, "RPN op stack overflow");
814 memcpy(&ComparativeOp
, &RpnOp
, sizeof(RPN_OP
));
815 ComparativeOpFilled
= TRUE
;
817 else if (!RpnpPushStack(Stack
, &RpnOp
))
819 CONST_STRCPY(ErrMsg
, "RPN op stack overflow");
827 /* Push popped operator */
828 if (HavePoppedOperator
)
830 if (!RpnpPushStack(Stack
, &PoppedOperator
))
832 CONST_STRCPY(ErrMsg
, "RPN op stack overflow");
847 if (ComparativeOpFilled
&& !RpnpPushStack(Stack
, &ComparativeOp
))
849 CONST_STRCPY(ErrMsg
, "RPN op stack overflow");
857 /* Skip whitespace */
870 /*!\brief Evaluates the RPN op stack and returns the result.
872 * \param Stack Pointer to a RPN_STACK structure.
873 * \param TrapFrame Register values.
874 * \param Result Pointer to an ULONG to store the result into.
875 * \param ErrOffset On failure this is set to the character offset at which the error occoured.
876 * \param ErrMsg Buffer which receives an error message on failure (128 bytes)
878 * \retval TRUE Success.
879 * \retval FALSE Failure.
884 IN PKDB_KTRAP_FRAME TrapFrame
,
885 OUT PULONGLONG Result
,
886 OUT PLONG ErrOffset OPTIONAL
,
887 OUT PCHAR ErrMsg OPTIONAL
)
889 ULONGLONG ValueStack
[RPN_VALUE_STACK_SIZE
];
890 ULONG ValueStackPointer
= 0;
899 ULONG ValueStackPointerMax
= 0;
906 for (index
= 0; index
< Stack
->Sp
; index
++)
908 PRPN_OP Op
= Stack
->Ops
+ index
;
911 ValueStackPointerMax
= max(ValueStackPointerMax
, ValueStackPointer
);
921 if (ValueStackPointer
== RPN_VALUE_STACK_SIZE
)
923 CONST_STRCPY(ErrMsg
, "Value stack overflow");
931 ValueStack
[ValueStackPointer
++] = Op
->Data
.Immediate
;
935 if (ValueStackPointer
== RPN_VALUE_STACK_SIZE
)
937 CONST_STRCPY(ErrMsg
, "Value stack overflow");
945 ul
= Op
->Data
.Register
;
946 p
= (PVOID
)((ULONG_PTR
)TrapFrame
+ RegisterToTrapFrame
[ul
].Offset
);
948 switch (RegisterToTrapFrame
[ul
].Size
)
950 case 1: ull
= (ULONGLONG
)(*(PUCHAR
)p
); break;
951 case 2: ull
= (ULONGLONG
)(*(PUSHORT
)p
); break;
952 case 4: ull
= (ULONGLONG
)(*(PULONG
)p
); break;
953 case 8: ull
= (ULONGLONG
)(*(PULONGLONG
)p
); break;
954 default: ASSERT(0); return FALSE
; break;
957 ValueStack
[ValueStackPointer
++] = ull
;
960 case RpnOpDereference
:
961 if (ValueStackPointer
< 1)
963 CONST_STRCPY(ErrMsg
, "Value stack underflow");
971 /* FIXME: Print a warning when address is out of range */
972 p
= (PVOID
)(ULONG_PTR
)ValueStack
[ValueStackPointer
- 1];
975 switch (Op
->Data
.DerefMemorySize
)
978 if (NT_SUCCESS(KdbpSafeReadMemory(&uc
, p
, sizeof (uc
))))
986 if (NT_SUCCESS(KdbpSafeReadMemory(&us
, p
, sizeof (us
))))
994 if (NT_SUCCESS(KdbpSafeReadMemory(&ul
, p
, sizeof (ul
))))
1002 if (NT_SUCCESS(KdbpSafeReadMemory(&ull
, p
, sizeof (ull
))))
1016 _snprintf(ErrMsg
, 128, "Couldn't access memory at 0x%lx", (ULONG
)p
);
1019 *ErrOffset
= Op
->CharacterOffset
;
1024 ValueStack
[ValueStackPointer
- 1] = ull
;
1027 case RpnOpBinaryOperator
:
1028 if (ValueStackPointer
< 2)
1030 CONST_STRCPY(ErrMsg
, "Value stack underflow");
1038 ValueStackPointer
--;
1039 ull
= ValueStack
[ValueStackPointer
];
1041 if (ull
== 0 && Op
->Data
.BinaryOperator
== RpnBinaryOperatorDiv
)
1043 CONST_STRCPY(ErrMsg
, "Division by zero");
1046 *ErrOffset
= Op
->CharacterOffset
;
1051 ull
= Op
->Data
.BinaryOperator(ValueStack
[ValueStackPointer
- 1], ull
);
1052 ValueStack
[ValueStackPointer
- 1] = ull
;
1062 DPRINT1("Max value stack pointer: %d\n", ValueStackPointerMax
);
1065 if (ValueStackPointer
!= 1)
1067 CONST_STRCPY(ErrMsg
, "Stack not empty after evaluation");
1075 *Result
= ValueStack
[0];
1079 /*!\brief Evaluates the given expression
1081 * \param Expression Expression to evaluate.
1082 * \param TrapFrame Register values.
1083 * \param Result Variable which receives the result on success.
1084 * \param ErrOffset Variable which receives character offset on parse error (-1 on other errors)
1085 * \param ErrMsg Buffer which receives an error message on failure (128 bytes)
1087 * \retval TRUE Success.
1088 * \retval FALSE Failure.
1091 KdbpRpnEvaluateExpression(
1092 IN PCHAR Expression
,
1093 IN PKDB_KTRAP_FRAME TrapFrame
,
1094 OUT PULONGLONG Result
,
1095 OUT PLONG ErrOffset OPTIONAL
,
1096 OUT PCHAR ErrMsg OPTIONAL
)
1098 PRPN_STACK Stack
= (PRPN_STACK
)&RpnStack
;
1104 /* Clear the stack and parse the expression */
1105 RpnpClearStack(Stack
);
1106 if (!RpnpParseExpression(Stack
, Expression
, NULL
, 0, ErrOffset
, ErrMsg
))
1110 RpnpDumpStack(Stack
);
1113 /* Evaluate the stack */
1114 if (!RpnpEvaluateStack(Stack
, TrapFrame
, Result
, ErrOffset
, ErrMsg
))
1120 /*!\brief Parses the given expression and returns a "handle" to it.
1122 * \param Expression Expression to evaluate.
1123 * \param ErrOffset Variable which receives character offset on parse error (-1 on other errors)
1124 * \param ErrMsg Buffer which receives an error message on failure (128 bytes)
1126 * \returns "Handle" for the expression, NULL on failure.
1128 * \sa KdbpRpnEvaluateExpression
1131 KdbpRpnParseExpression(
1132 IN PCHAR Expression
,
1133 OUT PLONG ErrOffset OPTIONAL
,
1134 OUT PCHAR ErrMsg OPTIONAL
)
1137 PRPN_STACK Stack
= (PRPN_STACK
)&RpnStack
;
1138 PRPN_STACK NewStack
;
1142 /* Clear the stack and parse the expression */
1143 RpnpClearStack(Stack
);
1144 if (!RpnpParseExpression(Stack
, Expression
, NULL
, 0, ErrOffset
, ErrMsg
))
1148 RpnpDumpStack(Stack
);
1151 /* Duplicate the stack and return a pointer/handle to it */
1152 ASSERT(Stack
->Sp
>= 1);
1153 Size
= sizeof (RPN_STACK
) + (RTL_FIELD_SIZE(RPN_STACK
, Ops
[0]) * (Stack
->Sp
- 1));
1154 NewStack
= ExAllocatePoolWithTag(NonPagedPool
, Size
, TAG_KDBG
);
1158 CONST_STRCPY(ErrMsg
, "Out of memory");
1166 memcpy(NewStack
, Stack
, Size
);
1167 NewStack
->Size
= NewStack
->Sp
;
1172 /*!\brief Evaluates the given expression and returns the result.
1174 * \param Expression Expression "handle" returned by KdbpRpnParseExpression.
1175 * \param TrapFrame Register values.
1176 * \param Result Variable which receives the result on success.
1177 * \param ErrOffset Variable which receives character offset on parse error (-1 on other errors)
1178 * \param ErrMsg Buffer which receives an error message on failure (128 bytes)
1180 * \returns "Handle" for the expression, NULL on failure.
1182 * \sa KdbpRpnParseExpression
1185 KdbpRpnEvaluateParsedExpression(
1186 IN PVOID Expression
,
1187 IN PKDB_KTRAP_FRAME TrapFrame
,
1188 OUT PULONGLONG Result
,
1189 OUT PLONG ErrOffset OPTIONAL
,
1190 OUT PCHAR ErrMsg OPTIONAL
)
1192 PRPN_STACK Stack
= (PRPN_STACK
)Expression
;
1198 /* Evaluate the stack */
1199 return RpnpEvaluateStack(Stack
, TrapFrame
, Result
, ErrOffset
, ErrMsg
);