ReactOS  0.4.15-dev-5126-g3bb451b
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_PTR i, i2;
441  ULONG64 ull;
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  ull = strtoull(p, &pend, 0);
600  if (p != pend)
601  {
602  RpnOp.Type = RpnOpImmediate;
603  RpnOp.CharacterOffset = CharacterOffset;
604  RpnOp.Data.Immediate = ull;
605  CharacterOffset += pend - p;
606  p = pend;
607  }
608  else
609  {
610  CONST_STRCPY(ErrMsg, "Operand expected");
611 
612  if (ErrOffset)
613  *ErrOffset = CharacterOffset;
614 
615  return FALSE;
616  }
617  }
618 
619  /* Push operand */
620  if (!RpnpPushStack(Stack, &RpnOp))
621  {
622  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
623 
624  if (ErrOffset)
625  *ErrOffset = -1;
626 
627  return FALSE;
628  }
629  }
630  else if (i == 0)
631  {
632  if (p[0] == '(' || p[0] == '[') /* subexpression */
633  {
634  if (!RpnpParseExpression(Stack, p + 1, &pend, CharacterOffset + 1,
635  ErrOffset, ErrMsg))
636  {
637  return FALSE;
638  }
639  else if (pend == p + 1)
640  {
641  CONST_STRCPY(ErrMsg, "Expression expected");
642 
643  if (ErrOffset)
644  *ErrOffset = CharacterOffset + 1;
645 
646  return FALSE;
647  }
648 
649  if (p[0] == '[') /* dereference */
650  {
651  ASSERT(MemorySize == 1 || MemorySize == 2 ||
652  MemorySize == 4 || MemorySize == 8);
653 
654  if (pend[0] != ']')
655  {
656  CONST_STRCPY(ErrMsg, "']' expected");
657 
658  if (ErrOffset)
659  *ErrOffset = CharacterOffset + (pend - p);
660 
661  return FALSE;
662  }
663 
664  RpnOp.Type = RpnOpDereference;
665  RpnOp.CharacterOffset = CharacterOffset;
667 
668  if (!RpnpPushStack(Stack, &RpnOp))
669  {
670  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
671 
672  if (ErrOffset)
673  *ErrOffset = -1;
674 
675  return FALSE;
676  }
677  }
678  else /* p[0] == '(' */
679  {
680  if (pend[0] != ')')
681  {
682  CONST_STRCPY(ErrMsg, "')' expected");
683 
684  if (ErrOffset)
685  *ErrOffset = CharacterOffset + (pend - p);
686 
687  return FALSE;
688  }
689  }
690 
691  /* Push a "nop" to prevent popping of the + operator (which would
692  * result in (10+10)/2 beeing evaluated as 15)
693  */
694  RpnOp.Type = RpnOpNop;
695  if (!RpnpPushStack(Stack, &RpnOp))
696  {
697  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
698 
699  if (ErrOffset)
700  *ErrOffset = -1;
701 
702  return FALSE;
703  }
704 
705  /* Skip closing brace/bracket */
706  pend++;
707 
708  CharacterOffset += pend - p;
709  p = pend;
710  }
711  else if (First && p[0] == '-') /* Allow expressions like "- eax" */
712  {
713  RpnOp.Type = RpnOpImmediate;
714  RpnOp.CharacterOffset = CharacterOffset;
715  RpnOp.Data.Immediate = 0;
716 
717  if (!RpnpPushStack(Stack, &RpnOp))
718  {
719  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
720 
721  if (ErrOffset)
722  *ErrOffset = -1;
723 
724  return FALSE;
725  }
726  }
727  else
728  {
729  CONST_STRCPY(ErrMsg, "Operand expected");
730 
731  if (ErrOffset)
732  *ErrOffset = CharacterOffset;
733 
734  return FALSE;
735  }
736  }
737  else
738  {
739  CONST_STRCPY(ErrMsg, "strcspn() failed");
740 
741  if (ErrOffset)
742  *ErrOffset = -1;
743 
744  return FALSE;
745  }
746 
747  if (!First)
748  {
749  /* Push operator */
750  RpnOp.CharacterOffset = OperatorOffset;
751  RpnOp.Type = RpnOpBinaryOperator;
752  IsComparativeOp = FALSE;
753 
754  switch (*Operator)
755  {
756  case '+':
758  break;
759 
760  case '-':
762  break;
763 
764  case '*':
766  break;
767 
768  case '/':
770  break;
771 
772  case '%':
774  break;
775 
776  case '=':
777  ASSERT(Operator[1] == '=');
778  IsComparativeOp = TRUE;
780  break;
781 
782  case '!':
783  ASSERT(Operator[1] == '=');
784  IsComparativeOp = TRUE;
786  break;
787 
788  case '<':
789  IsComparativeOp = TRUE;
790 
791  if (Operator[1] == '=')
793  else
795 
796  break;
797 
798  case '>':
799  IsComparativeOp = TRUE;
800 
801  if (Operator[1] == '=')
803  else
805 
806  break;
807 
808  default:
809  ASSERT(0);
810  break;
811  }
812 
813  if (IsComparativeOp)
814  {
815  if (ComparativeOpFilled && !RpnpPushStack(Stack, &ComparativeOp))
816  {
817  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
818 
819  if (ErrOffset)
820  *ErrOffset = -1;
821 
822  return FALSE;
823  }
824 
825  memcpy(&ComparativeOp, &RpnOp, sizeof(RPN_OP));
826  ComparativeOpFilled = TRUE;
827  }
828  else if (!RpnpPushStack(Stack, &RpnOp))
829  {
830  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
831 
832  if (ErrOffset)
833  *ErrOffset = -1;
834 
835  return FALSE;
836  }
837 
838  /* Push popped operator */
839  if (HavePoppedOperator)
840  {
841  if (!RpnpPushStack(Stack, &PoppedOperator))
842  {
843  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
844 
845  if (ErrOffset)
846  *ErrOffset = -1;
847 
848  return FALSE;
849  }
850  }
851  }
852 
853  First = FALSE;
854  }
855 
856 //end_of_expression:
857 
858  if (ComparativeOpFilled && !RpnpPushStack(Stack, &ComparativeOp))
859  {
860  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
861 
862  if (ErrOffset)
863  *ErrOffset = -1;
864 
865  return FALSE;
866  }
867 
868  /* Skip whitespace */
869  while (isspace(*p))
870  {
871  p++;
872  CharacterOffset++;
873  }
874 
875  if (End)
876  *End = p;
877 
878  return TRUE;
879 }
880 
892 static BOOLEAN
895  IN PKDB_KTRAP_FRAME TrapFrame,
897  OUT PLONG ErrOffset OPTIONAL,
898  OUT PCHAR ErrMsg OPTIONAL)
899 {
900  ULONGLONG ValueStack[RPN_VALUE_STACK_SIZE];
901  ULONG ValueStackPointer = 0;
902  ULONG index;
903  ULONGLONG ull;
904  ULONG ul;
905  USHORT us;
906  UCHAR uc;
907  PVOID p;
908  BOOLEAN Ok;
909 #ifdef DEBUG_RPN
910  ULONG ValueStackPointerMax = 0;
911 #endif
912 
913  ASSERT(Stack);
914  ASSERT(TrapFrame);
915  ASSERT(Result);
916 
917  for (index = 0; index < Stack->Sp; index++)
918  {
919  PRPN_OP Op = Stack->Ops + index;
920 
921 #ifdef DEBUG_RPN
922  ValueStackPointerMax = max(ValueStackPointerMax, ValueStackPointer);
923 #endif
924 
925  switch (Op->Type)
926  {
927  case RpnOpNop:
928  /* No operation */
929  break;
930 
931  case RpnOpImmediate:
932  if (ValueStackPointer == RPN_VALUE_STACK_SIZE)
933  {
934  CONST_STRCPY(ErrMsg, "Value stack overflow");
935 
936  if (ErrOffset)
937  *ErrOffset = -1;
938 
939  return FALSE;
940  }
941 
942  ValueStack[ValueStackPointer++] = Op->Data.Immediate;
943  break;
944 
945  case RpnOpRegister:
946  if (ValueStackPointer == RPN_VALUE_STACK_SIZE)
947  {
948  CONST_STRCPY(ErrMsg, "Value stack overflow");
949 
950  if (ErrOffset)
951  *ErrOffset = -1;
952 
953  return FALSE;
954  }
955 
956  ul = Op->Data.Register;
957  p = (PVOID)((ULONG_PTR)TrapFrame + RegisterToTrapFrame[ul].Offset);
958 
959  switch (RegisterToTrapFrame[ul].Size)
960  {
961  case 1: ull = (ULONGLONG)(*(PUCHAR)p); break;
962  case 2: ull = (ULONGLONG)(*(PUSHORT)p); break;
963  case 4: ull = (ULONGLONG)(*(PULONG)p); break;
964  case 8: ull = (ULONGLONG)(*(PULONGLONG)p); break;
965  default: ASSERT(0); return FALSE; break;
966  }
967 
968  ValueStack[ValueStackPointer++] = ull;
969  break;
970 
971  case RpnOpDereference:
972  if (ValueStackPointer < 1)
973  {
974  CONST_STRCPY(ErrMsg, "Value stack underflow");
975 
976  if (ErrOffset)
977  *ErrOffset = -1;
978 
979  return FALSE;
980  }
981 
982  /* FIXME: Print a warning when address is out of range */
983  p = (PVOID)(ULONG_PTR)ValueStack[ValueStackPointer - 1];
984  Ok = FALSE;
985 
986  switch (Op->Data.DerefMemorySize)
987  {
988  case 1:
989  if (NT_SUCCESS(KdbpSafeReadMemory(&uc, p, sizeof (uc))))
990  {
991  Ok = TRUE;
992  ull = (ULONGLONG)uc;
993  }
994  break;
995 
996  case 2:
997  if (NT_SUCCESS(KdbpSafeReadMemory(&us, p, sizeof (us))))
998  {
999  Ok = TRUE;
1000  ull = (ULONGLONG)us;
1001  }
1002  break;
1003 
1004  case 4:
1005  if (NT_SUCCESS(KdbpSafeReadMemory(&ul, p, sizeof (ul))))
1006  {
1007  Ok = TRUE;
1008  ull = (ULONGLONG)ul;
1009  }
1010  break;
1011 
1012  case 8:
1013  if (NT_SUCCESS(KdbpSafeReadMemory(&ull, p, sizeof (ull))))
1014  {
1015  Ok = TRUE;
1016  }
1017  break;
1018 
1019  default:
1020  ASSERT(0);
1021  return FALSE;
1022  break;
1023  }
1024 
1025  if (!Ok)
1026  {
1027  _snprintf(ErrMsg, 128, "Couldn't access memory at 0x%p", p);
1028 
1029  if (ErrOffset)
1030  *ErrOffset = Op->CharacterOffset;
1031 
1032  return FALSE;
1033  }
1034 
1035  ValueStack[ValueStackPointer - 1] = ull;
1036  break;
1037 
1038  case RpnOpBinaryOperator:
1039  if (ValueStackPointer < 2)
1040  {
1041  CONST_STRCPY(ErrMsg, "Value stack underflow");
1042 
1043  if (ErrOffset)
1044  *ErrOffset = -1;
1045 
1046  return FALSE;
1047  }
1048 
1049  ValueStackPointer--;
1050  ull = ValueStack[ValueStackPointer];
1051 
1052  if (ull == 0 && Op->Data.BinaryOperator == RpnBinaryOperatorDiv)
1053  {
1054  CONST_STRCPY(ErrMsg, "Division by zero");
1055 
1056  if (ErrOffset)
1057  *ErrOffset = Op->CharacterOffset;
1058 
1059  return FALSE;
1060  }
1061 
1062  ull = Op->Data.BinaryOperator(ValueStack[ValueStackPointer - 1], ull);
1063  ValueStack[ValueStackPointer - 1] = ull;
1064  break;
1065 
1066  default:
1067  ASSERT(0);
1068  return FALSE;
1069  }
1070  }
1071 
1072 #ifdef DEBUG_RPN
1073  DPRINT1("Max value stack pointer: %d\n", ValueStackPointerMax);
1074 #endif
1075 
1076  if (ValueStackPointer != 1)
1077  {
1078  CONST_STRCPY(ErrMsg, "Stack not empty after evaluation");
1079 
1080  if (ErrOffset)
1081  *ErrOffset = -1;
1082 
1083  return FALSE;
1084  }
1085 
1086  *Result = ValueStack[0];
1087  return TRUE;
1088 }
1089 
1101 BOOLEAN
1104  IN PKDB_KTRAP_FRAME TrapFrame,
1106  OUT PLONG ErrOffset OPTIONAL,
1107  OUT PCHAR ErrMsg OPTIONAL)
1108 {
1110 
1111  ASSERT(Expression);
1112  ASSERT(TrapFrame);
1113  ASSERT(Result);
1114 
1115  /* Clear the stack and parse the expression */
1117  if (!RpnpParseExpression(Stack, Expression, NULL, 0, ErrOffset, ErrMsg))
1118  return FALSE;
1119 
1120 #ifdef DEBUG_RPN
1122 #endif
1123 
1124  /* Evaluate the stack */
1125  if (!RpnpEvaluateStack(Stack, TrapFrame, Result, ErrOffset, ErrMsg))
1126  return FALSE;
1127 
1128  return TRUE;
1129 }
1130 
1141 PVOID
1144  OUT PLONG ErrOffset OPTIONAL,
1145  OUT PCHAR ErrMsg OPTIONAL)
1146 {
1147  LONG Size;
1149  PRPN_STACK NewStack;
1150 
1151  ASSERT(Expression);
1152 
1153  /* Clear the stack and parse the expression */
1155  if (!RpnpParseExpression(Stack, Expression, NULL, 0, ErrOffset, ErrMsg))
1156  return FALSE;
1157 
1158 #ifdef DEBUG_RPN
1160 #endif
1161 
1162  /* Duplicate the stack and return a pointer/handle to it */
1163  ASSERT(Stack->Sp >= 1);
1164  Size = sizeof (RPN_STACK) + (RTL_FIELD_SIZE(RPN_STACK, Ops[0]) * (Stack->Sp - 1));
1166 
1167  if (!NewStack)
1168  {
1169  CONST_STRCPY(ErrMsg, "Out of memory");
1170 
1171  if (ErrOffset)
1172  *ErrOffset = -1;
1173 
1174  return NULL;
1175  }
1176 
1177  memcpy(NewStack, Stack, Size);
1178  NewStack->Size = NewStack->Sp;
1179 
1180  return NewStack;
1181 }
1182 
1195 BOOLEAN
1198  IN PKDB_KTRAP_FRAME TrapFrame,
1200  OUT PLONG ErrOffset OPTIONAL,
1201  OUT PCHAR ErrMsg OPTIONAL)
1202 {
1204 
1205  ASSERT(Expression);
1206  ASSERT(TrapFrame);
1207  ASSERT(Result);
1208 
1209  /* Evaluate the stack */
1210  return RpnpEvaluateStack(Stack, TrapFrame, Result, ErrOffset, ErrMsg);
1211 }
1212 
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
#define TAG_KDBG
Definition: tag.h:38
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
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
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
int32_t INT_PTR
Definition: typedefs.h:64
#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
static const struct @1772 RegisterToTrapFrame[]
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 strtoull
Definition: stabs.c:58
#define ASSERT(a)
Definition: mode.c:44
static struct @1771 RpnStack
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t ULONGLONG
Definition: typedefs.h:67
ULONG Sp
Definition: kdb_expr.c:97
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 __int64 ULONG64
Definition: imports.h:198
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
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:893
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:1102
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:1690
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:1142
#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
union _RPN_OP::@1773 Data
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:1196
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