ReactOS  0.4.15-dev-2979-gfd8baca
kdb_expr.c
Go to the documentation of this file.
1 /*
2  * ReactOS kernel
3  * Copyright (C) 2005 ReactOS Team
4  *
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.
9  *
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.
14  *
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.
18  */
19 /*
20  * PROJECT: ReactOS kernel
21  * FILE: ntoskrnl/kdbg/kdb_expr.c
22  * PURPOSE: Kernel debugger expression evaluation
23  * PROGRAMMER: Gregor Anich (blight@blight.eu.org)
24  * UPDATE HISTORY:
25  * Created 15/01/2005
26  */
27 
28 /* Note:
29  *
30  * The given expression is parsed and stored in reverse polish notation,
31  * then it is evaluated and the result is returned.
32  */
33 
34 /* INCLUDES ******************************************************************/
35 
36 #include <ntoskrnl.h>
37 #define NDEBUG
38 #include <debug.h>
39 
40 /* TYPES *********************************************************************/
41 typedef enum _RPN_OP_TYPE
42 {
49 } RPN_OP_TYPE;
50 
52 
53 typedef struct _RPN_OP
54 {
57  union
58  {
59  /* RpnOpBinaryOperator */
61  /* RpnOpImmediate */
63  /* RpnOpRegister */
65  /* RpnOpDereference */
67  }
68  Data;
69 }
70 RPN_OP, *PRPN_OP;
71 
72 typedef struct _RPN_STACK
73 {
74  ULONG Size; /* Number of RPN_OPs on Ops */
75  ULONG Sp; /* Stack pointer */
76  RPN_OP Ops[1]; /* Array of RPN_OPs */
77 }
79 
80 /* DEFINES *******************************************************************/
81 #define stricmp _stricmp
82 
83 #ifndef RTL_FIELD_SIZE
84 # define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
85 #endif
86 
87 #define CONST_STRCPY(dst, src) \
88  do { if ((dst)) { memcpy(dst, src, sizeof(src)); } } while (0);
89 
90 #define RPN_OP_STACK_SIZE 256
91 #define RPN_VALUE_STACK_SIZE 256
92 
93 /* GLOBALS *******************************************************************/
94 static struct
95 {
99 }
100 RpnStack =
101 {
103  0
104 };
105 
106 static const struct
107 {
110  UCHAR Size;
111 }
113 {
114  /* FIXME: X86 only */
115 #ifdef _M_IX86
117 #else
119 #endif
120  {"eflags", FIELD_OFFSET(KDB_KTRAP_FRAME, EFlags), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, EFlags)},
121 #ifdef _M_IX86
130 #else
139 #endif
140  {"cs", FIELD_OFFSET(KDB_KTRAP_FRAME, SegCs), 2 }, /* Use only the lower 2 bytes */
152 };
154 
155 /* FUNCTIONS *****************************************************************/
156 
157 ULONGLONG
159  ULONGLONG a,
160  ULONGLONG b)
161 {
162  return a + b;
163 }
164 
165 ULONGLONG
167  ULONGLONG a,
168  ULONGLONG b)
169 {
170  return a - b;
171 }
172 
173 ULONGLONG
175  ULONGLONG a,
176  ULONGLONG b)
177 {
178  return a * b;
179 }
180 
181 ULONGLONG
183  ULONGLONG a,
184  ULONGLONG b)
185 {
186  return a / b;
187 }
188 
189 ULONGLONG
191  ULONGLONG a,
192  ULONGLONG b)
193 {
194  return a % b;
195 }
196 
197 ULONGLONG
199  ULONGLONG a,
200  ULONGLONG b)
201 {
202  return (a == b);
203 }
204 
205 ULONGLONG
207  ULONGLONG a,
208  ULONGLONG b)
209 {
210  return (a != b);
211 }
212 
213 ULONGLONG
215  ULONGLONG a,
216  ULONGLONG b)
217 {
218  return (a < b);
219 }
220 
221 ULONGLONG
223  ULONGLONG a,
224  ULONGLONG b)
225 {
226  return (a <= b);
227 }
228 
229 ULONGLONG
231  ULONGLONG a,
232  ULONGLONG b)
233 {
234  return (a > b);
235 }
236 
237 ULONGLONG
239  ULONGLONG a,
240  ULONGLONG b)
241 {
242  return (a >= b);
243 }
244 
249 VOID
252 {
253  ULONG ul;
254 
255  ASSERT(Stack);
256  KdpDprintf("\nStack size: %ld\n", Stack->Sp);
257 
258  for (ul = 0; ul < Stack->Sp; ul++)
259  {
260  PRPN_OP Op = Stack->Ops + ul;
261  switch (Op->Type)
262  {
263  case RpnOpNop:
264  KdpDprintf("NOP,");
265  break;
266 
267  case RpnOpImmediate:
268  KdpDprintf("0x%I64x,", Op->Data.Immediate);
269  break;
270 
271  case RpnOpBinaryOperator:
273  KdpDprintf("+,");
274  else if (Op->Data.BinaryOperator == RpnBinaryOperatorSub)
275  KdpDprintf("-,");
276  else if (Op->Data.BinaryOperator == RpnBinaryOperatorMul)
277  KdpDprintf("*,");
278  else if (Op->Data.BinaryOperator == RpnBinaryOperatorDiv)
279  KdpDprintf("/,");
280  else if (Op->Data.BinaryOperator == RpnBinaryOperatorMod)
281  KdpDprintf("%%,");
283  KdpDprintf("==,");
285  KdpDprintf("!=,");
287  KdpDprintf("<,");
289  KdpDprintf("<=,");
291  KdpDprintf(">,");
293  KdpDprintf(">=,");
294  else
295  KdpDprintf("UNKNOWN OP,");
296 
297  break;
298 
299  case RpnOpRegister:
300  KdpDprintf("%s,", RegisterToTrapFrame[Op->Data.Register].Name);
301  break;
302 
303  case RpnOpDereference:
304  KdpDprintf("[%s],",
305  (Op->Data.DerefMemorySize == 1) ? ("byte") :
306  ((Op->Data.DerefMemorySize == 2) ? ("word") :
307  ((Op->Data.DerefMemorySize == 4) ? ("dword") : ("qword"))));
308  break;
309 
310  default:
311  KdpDprintf("\nUnsupported Type: %d\n", Op->Type);
312  ul = Stack->Sp;
313  break;
314  }
315  }
316 
317  KdpDprintf("\n");
318 }
319 
324 static VOID
327 {
328  ASSERT(Stack);
329  Stack->Sp = 0;
330 }
331 
337 static BOOLEAN
340  IN PRPN_OP Op)
341 {
342  ASSERT(Stack);
343  ASSERT(Op);
344 
345  if (Stack->Sp >= Stack->Size)
346  return FALSE;
347 
348  memcpy(Stack->Ops + Stack->Sp, Op, sizeof (RPN_OP));
349  Stack->Sp++;
350 
351  return TRUE;
352 }
353 
362 static BOOLEAN
365  OUT PRPN_OP Op OPTIONAL)
366 {
367  ASSERT(Stack);
368 
369  if (Stack->Sp == 0)
370  return FALSE;
371 
372  Stack->Sp--;
373  if (Op)
374  memcpy(Op, Stack->Ops + Stack->Sp, sizeof (RPN_OP));
375 
376  return TRUE;
377 }
378 
387 static BOOLEAN
390  OUT PRPN_OP Op)
391 {
392  ASSERT(Stack);
393  ASSERT(Op);
394 
395  if (Stack->Sp == 0)
396  return FALSE;
397 
398  memcpy(Op, Stack->Ops + Stack->Sp - 1, sizeof (RPN_OP));
399 
400  return TRUE;
401 }
402 
421 static BOOLEAN
425  OUT PCHAR *End OPTIONAL,
426  IN ULONG CharacterOffset,
427  OUT PLONG ErrOffset OPTIONAL,
428  OUT PCHAR ErrMsg OPTIONAL)
429 {
430  PCHAR p = Expression;
431  PCHAR pend;
432  PCHAR Operator = NULL;
433  LONG OperatorOffset = -1;
434  RPN_OP RpnOp;
435  RPN_OP PoppedOperator;
436  BOOLEAN HavePoppedOperator = FALSE;
437  RPN_OP ComparativeOp;
438  BOOLEAN ComparativeOpFilled = FALSE;
439  BOOLEAN IsComparativeOp;
440  INT i, i2;
441  ULONG ul;
443  CHAR Buffer[16];
444  BOOLEAN First;
445 
446  ASSERT(Stack);
448 
449  First = TRUE;
450  for (;;)
451  {
452  /* Skip whitespace */
453  while (isspace(*p))
454  {
455  p++;
456  CharacterOffset++;
457  }
458 
459  /* Check for end of expression */
460  if (p[0] == '\0' || p[0] == ')' || p[0] == ']')
461  break;
462 
463  if (!First)
464  {
465  /* Remember operator */
466  Operator = p++;
467  OperatorOffset = CharacterOffset++;
468 
469  /* Pop operator (to get the right operator precedence) */
470  HavePoppedOperator = FALSE;
471  if (*Operator == '*' || *Operator == '/' || *Operator == '%')
472  {
473  if (RpnpTopStack(Stack, &PoppedOperator) &&
474  PoppedOperator.Type == RpnOpBinaryOperator &&
475  (PoppedOperator.Data.BinaryOperator == RpnBinaryOperatorAdd ||
476  PoppedOperator.Data.BinaryOperator == RpnBinaryOperatorSub))
477  {
479  HavePoppedOperator = TRUE;
480  }
481  else if (PoppedOperator.Type == RpnOpNop)
482  {
484  /* Discard the NOP - it was only pushed to indicate there was a
485  * closing brace, so the previous operator shouldn't be popped.
486  */
487  }
488  }
489  else if ((Operator[0] == '=' && Operator[1] == '=') ||
490  (Operator[0] == '!' && Operator[1] == '=') ||
491  Operator[0] == '<' || Operator[0] == '>')
492  {
493  if (Operator[0] == '=' || Operator[0] == '!' ||
494  (Operator[0] == '<' && Operator[1] == '=') ||
495  (Operator[0] == '>' && Operator[1] == '='))
496  {
497  p++;
498  CharacterOffset++;
499  }
500 #if 0
501  /* Parse rest of expression */
502  if (!RpnpParseExpression(Stack, p + 1, &pend, CharacterOffset + 1,
503  ErrOffset, ErrMsg))
504  {
505  return FALSE;
506  }
507  else if (pend == p + 1)
508  {
509  CONST_STRCPY(ErrMsg, "Expression expected");
510 
511  if (ErrOffset)
512  *ErrOffset = CharacterOffset + 1;
513 
514  return FALSE;
515  }
516 
517  goto end_of_expression; /* return */
518 #endif
519  }
520  else if (Operator[0] != '+' && Operator[0] != '-')
521  {
522  CONST_STRCPY(ErrMsg, "Operator expected");
523 
524  if (ErrOffset)
525  *ErrOffset = OperatorOffset;
526 
527  return FALSE;
528  }
529 
530  /* Skip whitespace */
531  while (isspace(*p))
532  {
533  p++;
534  CharacterOffset++;
535  }
536  }
537 
538  /* Get operand */
539  MemorySize = sizeof(ULONG_PTR); /* default to pointer size */
540 
541 get_operand:
542  i = strcspn(p, "+-*/%()[]<>!=");
543  if (i > 0)
544  {
545  i2 = i;
546 
547  /* Copy register name/memory size */
548  while (isspace(p[--i2]));
549 
550  i2 = min(i2 + 1, (INT)sizeof (Buffer) - 1);
551  strncpy(Buffer, p, i2);
552  Buffer[i2] = '\0';
553 
554  /* Memory size prefix */
555  if (p[i] == '[')
556  {
557  if (stricmp(Buffer, "byte") == 0)
558  MemorySize = 1;
559  else if (stricmp(Buffer, "word") == 0)
560  MemorySize = 2;
561  else if (stricmp(Buffer, "dword") == 0)
562  MemorySize = 4;
563  else if (stricmp(Buffer, "qword") == 0)
564  MemorySize = 8;
565  else
566  {
567  CONST_STRCPY(ErrMsg, "Invalid memory size prefix");
568 
569  if (ErrOffset)
570  *ErrOffset = CharacterOffset;
571 
572  return FALSE;
573  }
574 
575  p += i;
576  CharacterOffset += i;
577  goto get_operand;
578  }
579 
580  /* Try to find register */
581  for (i = 0; i < RegisterToTrapFrameCount; i++)
582  {
584  break;
585  }
586 
588  {
589  RpnOp.Type = RpnOpRegister;
590  RpnOp.CharacterOffset = CharacterOffset;
591  RpnOp.Data.Register = i;
593  CharacterOffset += i;
594  p += i;
595  }
596  else
597  {
598  /* Immediate value */
599  /* FIXME: Need string to ULONGLONG function */
600  ul = strtoul(p, &pend, 0);
601  if (p != pend)
602  {
603  RpnOp.Type = RpnOpImmediate;
604  RpnOp.CharacterOffset = CharacterOffset;
605  RpnOp.Data.Immediate = (ULONGLONG)ul;
606  CharacterOffset += pend - p;
607  p = pend;
608  }
609  else
610  {
611  CONST_STRCPY(ErrMsg, "Operand expected");
612 
613  if (ErrOffset)
614  *ErrOffset = CharacterOffset;
615 
616  return FALSE;
617  }
618  }
619 
620  /* Push operand */
621  if (!RpnpPushStack(Stack, &RpnOp))
622  {
623  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
624 
625  if (ErrOffset)
626  *ErrOffset = -1;
627 
628  return FALSE;
629  }
630  }
631  else if (i == 0)
632  {
633  if (p[0] == '(' || p[0] == '[') /* subexpression */
634  {
635  if (!RpnpParseExpression(Stack, p + 1, &pend, CharacterOffset + 1,
636  ErrOffset, ErrMsg))
637  {
638  return FALSE;
639  }
640  else if (pend == p + 1)
641  {
642  CONST_STRCPY(ErrMsg, "Expression expected");
643 
644  if (ErrOffset)
645  *ErrOffset = CharacterOffset + 1;
646 
647  return FALSE;
648  }
649 
650  if (p[0] == '[') /* dereference */
651  {
652  ASSERT(MemorySize == 1 || MemorySize == 2 ||
653  MemorySize == 4 || MemorySize == 8);
654 
655  if (pend[0] != ']')
656  {
657  CONST_STRCPY(ErrMsg, "']' expected");
658 
659  if (ErrOffset)
660  *ErrOffset = CharacterOffset + (pend - p);
661 
662  return FALSE;
663  }
664 
665  RpnOp.Type = RpnOpDereference;
666  RpnOp.CharacterOffset = CharacterOffset;
668 
669  if (!RpnpPushStack(Stack, &RpnOp))
670  {
671  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
672 
673  if (ErrOffset)
674  *ErrOffset = -1;
675 
676  return FALSE;
677  }
678  }
679  else /* p[0] == '(' */
680  {
681  if (pend[0] != ')')
682  {
683  CONST_STRCPY(ErrMsg, "')' expected");
684 
685  if (ErrOffset)
686  *ErrOffset = CharacterOffset + (pend - p);
687 
688  return FALSE;
689  }
690  }
691 
692  /* Push a "nop" to prevent popping of the + operator (which would
693  * result in (10+10)/2 beeing evaluated as 15)
694  */
695  RpnOp.Type = RpnOpNop;
696  if (!RpnpPushStack(Stack, &RpnOp))
697  {
698  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
699 
700  if (ErrOffset)
701  *ErrOffset = -1;
702 
703  return FALSE;
704  }
705 
706  /* Skip closing brace/bracket */
707  pend++;
708 
709  CharacterOffset += pend - p;
710  p = pend;
711  }
712  else if (First && p[0] == '-') /* Allow expressions like "- eax" */
713  {
714  RpnOp.Type = RpnOpImmediate;
715  RpnOp.CharacterOffset = CharacterOffset;
716  RpnOp.Data.Immediate = 0;
717 
718  if (!RpnpPushStack(Stack, &RpnOp))
719  {
720  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
721 
722  if (ErrOffset)
723  *ErrOffset = -1;
724 
725  return FALSE;
726  }
727  }
728  else
729  {
730  CONST_STRCPY(ErrMsg, "Operand expected");
731 
732  if (ErrOffset)
733  *ErrOffset = CharacterOffset;
734 
735  return FALSE;
736  }
737  }
738  else
739  {
740  CONST_STRCPY(ErrMsg, "strcspn() failed");
741 
742  if (ErrOffset)
743  *ErrOffset = -1;
744 
745  return FALSE;
746  }
747 
748  if (!First)
749  {
750  /* Push operator */
751  RpnOp.CharacterOffset = OperatorOffset;
752  RpnOp.Type = RpnOpBinaryOperator;
753  IsComparativeOp = FALSE;
754 
755  switch (*Operator)
756  {
757  case '+':
759  break;
760 
761  case '-':
763  break;
764 
765  case '*':
767  break;
768 
769  case '/':
771  break;
772 
773  case '%':
775  break;
776 
777  case '=':
778  ASSERT(Operator[1] == '=');
779  IsComparativeOp = TRUE;
781  break;
782 
783  case '!':
784  ASSERT(Operator[1] == '=');
785  IsComparativeOp = TRUE;
787  break;
788 
789  case '<':
790  IsComparativeOp = TRUE;
791 
792  if (Operator[1] == '=')
794  else
796 
797  break;
798 
799  case '>':
800  IsComparativeOp = TRUE;
801 
802  if (Operator[1] == '=')
804  else
806 
807  break;
808 
809  default:
810  ASSERT(0);
811  break;
812  }
813 
814  if (IsComparativeOp)
815  {
816  if (ComparativeOpFilled && !RpnpPushStack(Stack, &ComparativeOp))
817  {
818  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
819 
820  if (ErrOffset)
821  *ErrOffset = -1;
822 
823  return FALSE;
824  }
825 
826  memcpy(&ComparativeOp, &RpnOp, sizeof(RPN_OP));
827  ComparativeOpFilled = TRUE;
828  }
829  else if (!RpnpPushStack(Stack, &RpnOp))
830  {
831  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
832 
833  if (ErrOffset)
834  *ErrOffset = -1;
835 
836  return FALSE;
837  }
838 
839  /* Push popped operator */
840  if (HavePoppedOperator)
841  {
842  if (!RpnpPushStack(Stack, &PoppedOperator))
843  {
844  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
845 
846  if (ErrOffset)
847  *ErrOffset = -1;
848 
849  return FALSE;
850  }
851  }
852  }
853 
854  First = FALSE;
855  }
856 
857 //end_of_expression:
858 
859  if (ComparativeOpFilled && !RpnpPushStack(Stack, &ComparativeOp))
860  {
861  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
862 
863  if (ErrOffset)
864  *ErrOffset = -1;
865 
866  return FALSE;
867  }
868 
869  /* Skip whitespace */
870  while (isspace(*p))
871  {
872  p++;
873  CharacterOffset++;
874  }
875 
876  if (End)
877  *End = p;
878 
879  return TRUE;
880 }
881 
893 static BOOLEAN
896  IN PKDB_KTRAP_FRAME TrapFrame,
898  OUT PLONG ErrOffset OPTIONAL,
899  OUT PCHAR ErrMsg OPTIONAL)
900 {
901  ULONGLONG ValueStack[RPN_VALUE_STACK_SIZE];
902  ULONG ValueStackPointer = 0;
903  ULONG index;
904  ULONGLONG ull;
905  ULONG ul;
906  USHORT us;
907  UCHAR uc;
908  PVOID p;
909  BOOLEAN Ok;
910 #ifdef DEBUG_RPN
911  ULONG ValueStackPointerMax = 0;
912 #endif
913 
914  ASSERT(Stack);
915  ASSERT(TrapFrame);
916  ASSERT(Result);
917 
918  for (index = 0; index < Stack->Sp; index++)
919  {
920  PRPN_OP Op = Stack->Ops + index;
921 
922 #ifdef DEBUG_RPN
923  ValueStackPointerMax = max(ValueStackPointerMax, ValueStackPointer);
924 #endif
925 
926  switch (Op->Type)
927  {
928  case RpnOpNop:
929  /* No operation */
930  break;
931 
932  case RpnOpImmediate:
933  if (ValueStackPointer == RPN_VALUE_STACK_SIZE)
934  {
935  CONST_STRCPY(ErrMsg, "Value stack overflow");
936 
937  if (ErrOffset)
938  *ErrOffset = -1;
939 
940  return FALSE;
941  }
942 
943  ValueStack[ValueStackPointer++] = Op->Data.Immediate;
944  break;
945 
946  case RpnOpRegister:
947  if (ValueStackPointer == RPN_VALUE_STACK_SIZE)
948  {
949  CONST_STRCPY(ErrMsg, "Value stack overflow");
950 
951  if (ErrOffset)
952  *ErrOffset = -1;
953 
954  return FALSE;
955  }
956 
957  ul = Op->Data.Register;
958  p = (PVOID)((ULONG_PTR)TrapFrame + RegisterToTrapFrame[ul].Offset);
959 
960  switch (RegisterToTrapFrame[ul].Size)
961  {
962  case 1: ull = (ULONGLONG)(*(PUCHAR)p); break;
963  case 2: ull = (ULONGLONG)(*(PUSHORT)p); break;
964  case 4: ull = (ULONGLONG)(*(PULONG)p); break;
965  case 8: ull = (ULONGLONG)(*(PULONGLONG)p); break;
966  default: ASSERT(0); return FALSE; break;
967  }
968 
969  ValueStack[ValueStackPointer++] = ull;
970  break;
971 
972  case RpnOpDereference:
973  if (ValueStackPointer < 1)
974  {
975  CONST_STRCPY(ErrMsg, "Value stack underflow");
976 
977  if (ErrOffset)
978  *ErrOffset = -1;
979 
980  return FALSE;
981  }
982 
983  /* FIXME: Print a warning when address is out of range */
984  p = (PVOID)(ULONG_PTR)ValueStack[ValueStackPointer - 1];
985  Ok = FALSE;
986 
987  switch (Op->Data.DerefMemorySize)
988  {
989  case 1:
990  if (NT_SUCCESS(KdbpSafeReadMemory(&uc, p, sizeof (uc))))
991  {
992  Ok = TRUE;
993  ull = (ULONGLONG)uc;
994  }
995  break;
996 
997  case 2:
998  if (NT_SUCCESS(KdbpSafeReadMemory(&us, p, sizeof (us))))
999  {
1000  Ok = TRUE;
1001  ull = (ULONGLONG)us;
1002  }
1003  break;
1004 
1005  case 4:
1006  if (NT_SUCCESS(KdbpSafeReadMemory(&ul, p, sizeof (ul))))
1007  {
1008  Ok = TRUE;
1009  ull = (ULONGLONG)ul;
1010  }
1011  break;
1012 
1013  case 8:
1014  if (NT_SUCCESS(KdbpSafeReadMemory(&ull, p, sizeof (ull))))
1015  {
1016  Ok = TRUE;
1017  }
1018  break;
1019 
1020  default:
1021  ASSERT(0);
1022  return FALSE;
1023  break;
1024  }
1025 
1026  if (!Ok)
1027  {
1028  _snprintf(ErrMsg, 128, "Couldn't access memory at 0x%p", p);
1029 
1030  if (ErrOffset)
1031  *ErrOffset = Op->CharacterOffset;
1032 
1033  return FALSE;
1034  }
1035 
1036  ValueStack[ValueStackPointer - 1] = ull;
1037  break;
1038 
1039  case RpnOpBinaryOperator:
1040  if (ValueStackPointer < 2)
1041  {
1042  CONST_STRCPY(ErrMsg, "Value stack underflow");
1043 
1044  if (ErrOffset)
1045  *ErrOffset = -1;
1046 
1047  return FALSE;
1048  }
1049 
1050  ValueStackPointer--;
1051  ull = ValueStack[ValueStackPointer];
1052 
1053  if (ull == 0 && Op->Data.BinaryOperator == RpnBinaryOperatorDiv)
1054  {
1055  CONST_STRCPY(ErrMsg, "Division by zero");
1056 
1057  if (ErrOffset)
1058  *ErrOffset = Op->CharacterOffset;
1059 
1060  return FALSE;
1061  }
1062 
1063  ull = Op->Data.BinaryOperator(ValueStack[ValueStackPointer - 1], ull);
1064  ValueStack[ValueStackPointer - 1] = ull;
1065  break;
1066 
1067  default:
1068  ASSERT(0);
1069  return FALSE;
1070  }
1071  }
1072 
1073 #ifdef DEBUG_RPN
1074  DPRINT1("Max value stack pointer: %d\n", ValueStackPointerMax);
1075 #endif
1076 
1077  if (ValueStackPointer != 1)
1078  {
1079  CONST_STRCPY(ErrMsg, "Stack not empty after evaluation");
1080 
1081  if (ErrOffset)
1082  *ErrOffset = -1;
1083 
1084  return FALSE;
1085  }
1086 
1087  *Result = ValueStack[0];
1088  return TRUE;
1089 }
1090 
1102 BOOLEAN
1105  IN PKDB_KTRAP_FRAME TrapFrame,
1107  OUT PLONG ErrOffset OPTIONAL,
1108  OUT PCHAR ErrMsg OPTIONAL)
1109 {
1111 
1112  ASSERT(Expression);
1113  ASSERT(TrapFrame);
1114  ASSERT(Result);
1115 
1116  /* Clear the stack and parse the expression */
1118  if (!RpnpParseExpression(Stack, Expression, NULL, 0, ErrOffset, ErrMsg))
1119  return FALSE;
1120 
1121 #ifdef DEBUG_RPN
1123 #endif
1124 
1125  /* Evaluate the stack */
1126  if (!RpnpEvaluateStack(Stack, TrapFrame, Result, ErrOffset, ErrMsg))
1127  return FALSE;
1128 
1129  return TRUE;
1130 }
1131 
1142 PVOID
1145  OUT PLONG ErrOffset OPTIONAL,
1146  OUT PCHAR ErrMsg OPTIONAL)
1147 {
1148  LONG Size;
1150  PRPN_STACK NewStack;
1151 
1152  ASSERT(Expression);
1153 
1154  /* Clear the stack and parse the expression */
1156  if (!RpnpParseExpression(Stack, Expression, NULL, 0, ErrOffset, ErrMsg))
1157  return FALSE;
1158 
1159 #ifdef DEBUG_RPN
1161 #endif
1162 
1163  /* Duplicate the stack and return a pointer/handle to it */
1164  ASSERT(Stack->Sp >= 1);
1165  Size = sizeof (RPN_STACK) + (RTL_FIELD_SIZE(RPN_STACK, Ops[0]) * (Stack->Sp - 1));
1167 
1168  if (!NewStack)
1169  {
1170  CONST_STRCPY(ErrMsg, "Out of memory");
1171 
1172  if (ErrOffset)
1173  *ErrOffset = -1;
1174 
1175  return NULL;
1176  }
1177 
1178  memcpy(NewStack, Stack, Size);
1179  NewStack->Size = NewStack->Sp;
1180 
1181  return NewStack;
1182 }
1183 
1196 BOOLEAN
1199  IN PKDB_KTRAP_FRAME TrapFrame,
1201  OUT PLONG ErrOffset OPTIONAL,
1202  OUT PCHAR ErrMsg OPTIONAL)
1203 {
1205 
1206  ASSERT(Expression);
1207  ASSERT(TrapFrame);
1208  ASSERT(Result);
1209 
1210  /* Evaluate the stack */
1211  return RpnpEvaluateStack(Stack, TrapFrame, Result, ErrOffset, ErrMsg);
1212 }
1213 
#define TAG_KDBG
Definition: kdb.h:8
signed char * PCHAR
Definition: retypes.h:7
struct _RPN_STACK * PRPN_STACK
RPN_OP_TYPE Type
Definition: kdb_expr.c:55
#define RTL_FIELD_SIZE(type, field)
Definition: kdb_expr.c:84
#define stricmp
Definition: kdb_expr.c:81
static BOOLEAN RpnpTopStack(IN PRPN_STACK Stack, OUT PRPN_OP Op)
Gets the top op from the stack (not popping it)
Definition: kdb_expr.c:388
#define IN
Definition: typedefs.h:39
ULONGLONG Immediate
Definition: kdb_expr.c:62
#define isspace(c)
Definition: acclib.h:69
PCWSTR Expression
#define max(a, b)
Definition: svc.c:63
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
static BOOLEAN RpnpParseExpression(IN PRPN_STACK Stack, IN PCHAR Expression, OUT PCHAR *End OPTIONAL, IN ULONG CharacterOffset, OUT PLONG ErrOffset OPTIONAL, OUT PCHAR ErrMsg OPTIONAL)
Parses an expression.
Definition: kdb_expr.c:422
static BOOLEAN RpnpPopStack(IN OUT PRPN_STACK Stack, OUT PRPN_OP Op OPTIONAL)
Pops the top op from the stack.
Definition: kdb_expr.c:363
RPN_OP Ops[RPN_OP_STACK_SIZE]
Definition: kdb_expr.c:98
struct _RPN_OP * PRPN_OP
UCHAR DerefMemorySize
Definition: kdb_expr.c:66
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
ULONGLONG RpnBinaryOperatorMod(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:190
static const struct @1798 RegisterToTrapFrame[]
RPN_OP Ops[1]
Definition: kdb_expr.c:76
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
VOID RpnpDumpStack(IN PRPN_STACK Stack)
Dumps the given RPN stack content.
Definition: kdb_expr.c:250
#define TRUE
Definition: types.h:120
static const BYTE us[]
Definition: encode.c:689
ULONG CharacterOffset
Definition: kdb_expr.c:56
_Check_return_ _CRTIMP size_t __cdecl strcspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
ULONGLONG(* RPN_BINARY_OPERATOR)(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:51
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
ULONGLONG RpnBinaryOperatorGreaterThanOrEquals(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:238
#define RPN_OP_STACK_SIZE
Definition: kdb_expr.c:90
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
WCHAR First[]
Definition: FormatMessage.c:11
static BOOLEAN RpnpPushStack(IN OUT PRPN_STACK Stack, IN PRPN_OP Op)
Pushes an RPN_OP onto the stack.
Definition: kdb_expr.c:338
#define _snprintf
Definition: xmlstorage.h:200
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
_RPN_OP_TYPE
Definition: kdb_expr.c:41
#define a
Definition: ke_i.h:78
UCHAR Offset
Definition: kdb_expr.c:109
unsigned char BOOLEAN
ULONG Size
Definition: kdb_expr.c:96
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
Definition: bufpool.h:45
GLuint index
Definition: glext.h:6031
void * PVOID
Definition: retypes.h:9
PCHAR Name
Definition: kdb_expr.c:108
struct _RPN_STACK RPN_STACK
#define b
Definition: ke_i.h:79
struct _RPN_OP RPN_OP
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t ULONGLONG
Definition: typedefs.h:67
ULONG Sp
Definition: kdb_expr.c:97
static struct @1797 RpnStack
ULONGLONG RpnBinaryOperatorNotEquals(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:206
ULONG Sp
Definition: kdb_expr.c:75
enum _RPN_OP_TYPE RPN_OP_TYPE
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned char UCHAR
Definition: xmlstorage.h:181
#define index(s, c)
Definition: various.h:29
ULONGLONG RpnBinaryOperatorLessThanOrEquals(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:222
static CONST DWORD MemorySize[]
Definition: svga.c:32
union _RPN_OP::@1799 Data
ULONGLONG RpnBinaryOperatorEquals(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:198
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
ULONGLONG RpnBinaryOperatorSub(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:166
ULONG Size
Definition: kdb_expr.c:74
static BOOLEAN RpnpEvaluateStack(IN PRPN_STACK Stack, IN PKDB_KTRAP_FRAME TrapFrame, OUT PULONGLONG Result, OUT PLONG ErrOffset OPTIONAL, OUT PCHAR ErrMsg OPTIONAL)
Evaluates the RPN op stack and returns the result.
Definition: kdb_expr.c:894
BOOLEAN KdbpRpnEvaluateExpression(IN PCHAR Expression, IN PKDB_KTRAP_FRAME TrapFrame, OUT PULONGLONG Result, OUT PLONG ErrOffset OPTIONAL, OUT PCHAR ErrMsg OPTIONAL)
Evaluates the given expression.
Definition: kdb_expr.c:1103
ULONGLONG RpnBinaryOperatorAdd(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:158
UCHAR Register
Definition: kdb_expr.c:64
NTSTATUS KdbpSafeReadMemory(OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes)
Definition: kdb.c:1683
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned short USHORT
Definition: pedump.c:61
PVOID KdbpRpnParseExpression(IN PCHAR Expression, OUT PLONG ErrOffset OPTIONAL, OUT PCHAR ErrMsg OPTIONAL)
Parses the given expression and returns a "handle" to it.
Definition: kdb_expr.c:1143
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
ULONGLONG RpnBinaryOperatorDiv(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:182
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
#define NULL
Definition: types.h:112
ULONGLONG RpnBinaryOperatorLessThan(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:214
ULONGLONG RpnBinaryOperatorGreaterThan(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:230
static const INT RegisterToTrapFrameCount
Definition: kdb_expr.c:153
#define DPRINT1
Definition: precomp.h:8
#define CONST_STRCPY(dst, src)
Definition: kdb_expr.c:87
#define RPN_VALUE_STACK_SIZE
Definition: kdb_expr.c:91
#define OUT
Definition: typedefs.h:40
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLfloat GLfloat p
Definition: glext.h:8902
BOOLEAN KdbpRpnEvaluateParsedExpression(IN PVOID Expression, IN PKDB_KTRAP_FRAME TrapFrame, OUT PULONGLONG Result, OUT PLONG ErrOffset OPTIONAL, OUT PCHAR ErrMsg OPTIONAL)
Evaluates the given expression and returns the result.
Definition: kdb_expr.c:1197
static VOID RpnpClearStack(OUT PRPN_STACK Stack)
Clears the given RPN stack.
Definition: kdb_expr.c:325
ULONGLONG RpnBinaryOperatorMul(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:174
signed int * PLONG
Definition: retypes.h:5
unsigned short * PUSHORT
Definition: retypes.h:2
#define KdpDprintf(...)
Definition: mmdbg.c:19
RPN_BINARY_OPERATOR BinaryOperator
Definition: kdb_expr.c:60
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68