ReactOS  0.4.15-dev-1386-g5cb9f87
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 {
115  {"eflags", FIELD_OFFSET(KDB_KTRAP_FRAME, EFlags), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, EFlags)},
124  {"cs", FIELD_OFFSET(KDB_KTRAP_FRAME, SegCs), 2 }, /* Use only the lower 2 bytes */
136 };
138 
139 /* FUNCTIONS *****************************************************************/
140 
141 ULONGLONG
143  ULONGLONG a,
144  ULONGLONG b)
145 {
146  return a + b;
147 }
148 
149 ULONGLONG
151  ULONGLONG a,
152  ULONGLONG b)
153 {
154  return a - b;
155 }
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 
233 VOID
236 {
237  ULONG ul;
238 
239  ASSERT(Stack);
240  DbgPrint("\nStack size: %ld\n", Stack->Sp);
241 
242  for (ul = 0; ul < Stack->Sp; ul++)
243  {
244  PRPN_OP Op = Stack->Ops + ul;
245  switch (Op->Type)
246  {
247  case RpnOpNop:
248  DbgPrint("NOP,");
249  break;
250 
251  case RpnOpImmediate:
252  DbgPrint("0x%I64x,", Op->Data.Immediate);
253  break;
254 
255  case RpnOpBinaryOperator:
257  DbgPrint("+,");
258  else if (Op->Data.BinaryOperator == RpnBinaryOperatorSub)
259  DbgPrint("-,");
260  else if (Op->Data.BinaryOperator == RpnBinaryOperatorMul)
261  DbgPrint("*,");
262  else if (Op->Data.BinaryOperator == RpnBinaryOperatorDiv)
263  DbgPrint("/,");
264  else if (Op->Data.BinaryOperator == RpnBinaryOperatorMod)
265  DbgPrint("%%,");
267  DbgPrint("==,");
269  DbgPrint("!=,");
271  DbgPrint("<,");
273  DbgPrint("<=,");
275  DbgPrint(">,");
277  DbgPrint(">=,");
278  else
279  DbgPrint("UNKNOWN OP,");
280 
281  break;
282 
283  case RpnOpRegister:
284  DbgPrint("%s,", RegisterToTrapFrame[Op->Data.Register].Name);
285  break;
286 
287  case RpnOpDereference:
288  DbgPrint("[%s],",
289  (Op->Data.DerefMemorySize == 1) ? ("byte") :
290  ((Op->Data.DerefMemorySize == 2) ? ("word") :
291  ((Op->Data.DerefMemorySize == 4) ? ("dword") : ("qword"))));
292  break;
293 
294  default:
295  DbgPrint("\nUnsupported Type: %d\n", Op->Type);
296  ul = Stack->Sp;
297  break;
298  }
299  }
300 
301  DbgPrint("\n");
302 }
303 
308 static VOID
311 {
312  ASSERT(Stack);
313  Stack->Sp = 0;
314 }
315 
321 static BOOLEAN
324  IN PRPN_OP Op)
325 {
326  ASSERT(Stack);
327  ASSERT(Op);
328 
329  if (Stack->Sp >= Stack->Size)
330  return FALSE;
331 
332  memcpy(Stack->Ops + Stack->Sp, Op, sizeof (RPN_OP));
333  Stack->Sp++;
334 
335  return TRUE;
336 }
337 
346 static BOOLEAN
349  OUT PRPN_OP Op OPTIONAL)
350 {
351  ASSERT(Stack);
352 
353  if (Stack->Sp == 0)
354  return FALSE;
355 
356  Stack->Sp--;
357  if (Op)
358  memcpy(Op, Stack->Ops + Stack->Sp, sizeof (RPN_OP));
359 
360  return TRUE;
361 }
362 
371 static BOOLEAN
374  OUT PRPN_OP Op)
375 {
376  ASSERT(Stack);
377  ASSERT(Op);
378 
379  if (Stack->Sp == 0)
380  return FALSE;
381 
382  memcpy(Op, Stack->Ops + Stack->Sp - 1, sizeof (RPN_OP));
383 
384  return TRUE;
385 }
386 
405 static BOOLEAN
409  OUT PCHAR *End OPTIONAL,
410  IN ULONG CharacterOffset,
411  OUT PLONG ErrOffset OPTIONAL,
412  OUT PCHAR ErrMsg OPTIONAL)
413 {
414  PCHAR p = Expression;
415  PCHAR pend;
416  PCHAR Operator = NULL;
417  LONG OperatorOffset = -1;
418  RPN_OP RpnOp;
419  RPN_OP PoppedOperator;
420  BOOLEAN HavePoppedOperator = FALSE;
421  RPN_OP ComparativeOp;
422  BOOLEAN ComparativeOpFilled = FALSE;
423  BOOLEAN IsComparativeOp;
424  INT i, i2;
425  ULONG ul;
427  CHAR Buffer[16];
428  BOOLEAN First;
429 
430  ASSERT(Stack);
432 
433  First = TRUE;
434  for (;;)
435  {
436  /* Skip whitespace */
437  while (isspace(*p))
438  {
439  p++;
440  CharacterOffset++;
441  }
442 
443  /* Check for end of expression */
444  if (p[0] == '\0' || p[0] == ')' || p[0] == ']')
445  break;
446 
447  if (!First)
448  {
449  /* Remember operator */
450  Operator = p++;
451  OperatorOffset = CharacterOffset++;
452 
453  /* Pop operator (to get the right operator precedence) */
454  HavePoppedOperator = FALSE;
455  if (*Operator == '*' || *Operator == '/' || *Operator == '%')
456  {
457  if (RpnpTopStack(Stack, &PoppedOperator) &&
458  PoppedOperator.Type == RpnOpBinaryOperator &&
459  (PoppedOperator.Data.BinaryOperator == RpnBinaryOperatorAdd ||
460  PoppedOperator.Data.BinaryOperator == RpnBinaryOperatorSub))
461  {
463  HavePoppedOperator = TRUE;
464  }
465  else if (PoppedOperator.Type == RpnOpNop)
466  {
468  /* Discard the NOP - it was only pushed to indicate there was a
469  * closing brace, so the previous operator shouldn't be popped.
470  */
471  }
472  }
473  else if ((Operator[0] == '=' && Operator[1] == '=') ||
474  (Operator[0] == '!' && Operator[1] == '=') ||
475  Operator[0] == '<' || Operator[0] == '>')
476  {
477  if (Operator[0] == '=' || Operator[0] == '!' ||
478  (Operator[0] == '<' && Operator[1] == '=') ||
479  (Operator[0] == '>' && Operator[1] == '='))
480  {
481  p++;
482  CharacterOffset++;
483  }
484 #if 0
485  /* Parse rest of expression */
486  if (!RpnpParseExpression(Stack, p + 1, &pend, CharacterOffset + 1,
487  ErrOffset, ErrMsg))
488  {
489  return FALSE;
490  }
491  else if (pend == p + 1)
492  {
493  CONST_STRCPY(ErrMsg, "Expression expected");
494 
495  if (ErrOffset)
496  *ErrOffset = CharacterOffset + 1;
497 
498  return FALSE;
499  }
500 
501  goto end_of_expression; /* return */
502 #endif
503  }
504  else if (Operator[0] != '+' && Operator[0] != '-')
505  {
506  CONST_STRCPY(ErrMsg, "Operator expected");
507 
508  if (ErrOffset)
509  *ErrOffset = OperatorOffset;
510 
511  return FALSE;
512  }
513 
514  /* Skip whitespace */
515  while (isspace(*p))
516  {
517  p++;
518  CharacterOffset++;
519  }
520  }
521 
522  /* Get operand */
523  MemorySize = sizeof(ULONG_PTR); /* default to pointer size */
524 
525 get_operand:
526  i = strcspn(p, "+-*/%()[]<>!=");
527  if (i > 0)
528  {
529  i2 = i;
530 
531  /* Copy register name/memory size */
532  while (isspace(p[--i2]));
533 
534  i2 = min(i2 + 1, (INT)sizeof (Buffer) - 1);
535  strncpy(Buffer, p, i2);
536  Buffer[i2] = '\0';
537 
538  /* Memory size prefix */
539  if (p[i] == '[')
540  {
541  if (stricmp(Buffer, "byte") == 0)
542  MemorySize = 1;
543  else if (stricmp(Buffer, "word") == 0)
544  MemorySize = 2;
545  else if (stricmp(Buffer, "dword") == 0)
546  MemorySize = 4;
547  else if (stricmp(Buffer, "qword") == 0)
548  MemorySize = 8;
549  else
550  {
551  CONST_STRCPY(ErrMsg, "Invalid memory size prefix");
552 
553  if (ErrOffset)
554  *ErrOffset = CharacterOffset;
555 
556  return FALSE;
557  }
558 
559  p += i;
560  CharacterOffset += i;
561  goto get_operand;
562  }
563 
564  /* Try to find register */
565  for (i = 0; i < RegisterToTrapFrameCount; i++)
566  {
568  break;
569  }
570 
572  {
573  RpnOp.Type = RpnOpRegister;
574  RpnOp.CharacterOffset = CharacterOffset;
575  RpnOp.Data.Register = i;
577  CharacterOffset += i;
578  p += i;
579  }
580  else
581  {
582  /* Immediate value */
583  /* FIXME: Need string to ULONGLONG function */
584  ul = strtoul(p, &pend, 0);
585  if (p != pend)
586  {
587  RpnOp.Type = RpnOpImmediate;
588  RpnOp.CharacterOffset = CharacterOffset;
589  RpnOp.Data.Immediate = (ULONGLONG)ul;
590  CharacterOffset += pend - p;
591  p = pend;
592  }
593  else
594  {
595  CONST_STRCPY(ErrMsg, "Operand expected");
596 
597  if (ErrOffset)
598  *ErrOffset = CharacterOffset;
599 
600  return FALSE;
601  }
602  }
603 
604  /* Push operand */
605  if (!RpnpPushStack(Stack, &RpnOp))
606  {
607  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
608 
609  if (ErrOffset)
610  *ErrOffset = -1;
611 
612  return FALSE;
613  }
614  }
615  else if (i == 0)
616  {
617  if (p[0] == '(' || p[0] == '[') /* subexpression */
618  {
619  if (!RpnpParseExpression(Stack, p + 1, &pend, CharacterOffset + 1,
620  ErrOffset, ErrMsg))
621  {
622  return FALSE;
623  }
624  else if (pend == p + 1)
625  {
626  CONST_STRCPY(ErrMsg, "Expression expected");
627 
628  if (ErrOffset)
629  *ErrOffset = CharacterOffset + 1;
630 
631  return FALSE;
632  }
633 
634  if (p[0] == '[') /* dereference */
635  {
636  ASSERT(MemorySize == 1 || MemorySize == 2 ||
637  MemorySize == 4 || MemorySize == 8);
638 
639  if (pend[0] != ']')
640  {
641  CONST_STRCPY(ErrMsg, "']' expected");
642 
643  if (ErrOffset)
644  *ErrOffset = CharacterOffset + (pend - p);
645 
646  return FALSE;
647  }
648 
649  RpnOp.Type = RpnOpDereference;
650  RpnOp.CharacterOffset = CharacterOffset;
652 
653  if (!RpnpPushStack(Stack, &RpnOp))
654  {
655  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
656 
657  if (ErrOffset)
658  *ErrOffset = -1;
659 
660  return FALSE;
661  }
662  }
663  else /* p[0] == '(' */
664  {
665  if (pend[0] != ')')
666  {
667  CONST_STRCPY(ErrMsg, "')' expected");
668 
669  if (ErrOffset)
670  *ErrOffset = CharacterOffset + (pend - p);
671 
672  return FALSE;
673  }
674  }
675 
676  /* Push a "nop" to prevent popping of the + operator (which would
677  * result in (10+10)/2 beeing evaluated as 15)
678  */
679  RpnOp.Type = RpnOpNop;
680  if (!RpnpPushStack(Stack, &RpnOp))
681  {
682  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
683 
684  if (ErrOffset)
685  *ErrOffset = -1;
686 
687  return FALSE;
688  }
689 
690  /* Skip closing brace/bracket */
691  pend++;
692 
693  CharacterOffset += pend - p;
694  p = pend;
695  }
696  else if (First && p[0] == '-') /* Allow expressions like "- eax" */
697  {
698  RpnOp.Type = RpnOpImmediate;
699  RpnOp.CharacterOffset = CharacterOffset;
700  RpnOp.Data.Immediate = 0;
701 
702  if (!RpnpPushStack(Stack, &RpnOp))
703  {
704  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
705 
706  if (ErrOffset)
707  *ErrOffset = -1;
708 
709  return FALSE;
710  }
711  }
712  else
713  {
714  CONST_STRCPY(ErrMsg, "Operand expected");
715 
716  if (ErrOffset)
717  *ErrOffset = CharacterOffset;
718 
719  return FALSE;
720  }
721  }
722  else
723  {
724  CONST_STRCPY(ErrMsg, "strcspn() failed");
725 
726  if (ErrOffset)
727  *ErrOffset = -1;
728 
729  return FALSE;
730  }
731 
732  if (!First)
733  {
734  /* Push operator */
735  RpnOp.CharacterOffset = OperatorOffset;
736  RpnOp.Type = RpnOpBinaryOperator;
737  IsComparativeOp = FALSE;
738 
739  switch (*Operator)
740  {
741  case '+':
743  break;
744 
745  case '-':
747  break;
748 
749  case '*':
751  break;
752 
753  case '/':
755  break;
756 
757  case '%':
759  break;
760 
761  case '=':
762  ASSERT(Operator[1] == '=');
763  IsComparativeOp = TRUE;
765  break;
766 
767  case '!':
768  ASSERT(Operator[1] == '=');
769  IsComparativeOp = TRUE;
771  break;
772 
773  case '<':
774  IsComparativeOp = TRUE;
775 
776  if (Operator[1] == '=')
778  else
780 
781  break;
782 
783  case '>':
784  IsComparativeOp = TRUE;
785 
786  if (Operator[1] == '=')
788  else
790 
791  break;
792 
793  default:
794  ASSERT(0);
795  break;
796  }
797 
798  if (IsComparativeOp)
799  {
800  if (ComparativeOpFilled && !RpnpPushStack(Stack, &ComparativeOp))
801  {
802  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
803 
804  if (ErrOffset)
805  *ErrOffset = -1;
806 
807  return FALSE;
808  }
809 
810  memcpy(&ComparativeOp, &RpnOp, sizeof(RPN_OP));
811  ComparativeOpFilled = TRUE;
812  }
813  else if (!RpnpPushStack(Stack, &RpnOp))
814  {
815  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
816 
817  if (ErrOffset)
818  *ErrOffset = -1;
819 
820  return FALSE;
821  }
822 
823  /* Push popped operator */
824  if (HavePoppedOperator)
825  {
826  if (!RpnpPushStack(Stack, &PoppedOperator))
827  {
828  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
829 
830  if (ErrOffset)
831  *ErrOffset = -1;
832 
833  return FALSE;
834  }
835  }
836  }
837 
838  First = FALSE;
839  }
840 
841 //end_of_expression:
842 
843  if (ComparativeOpFilled && !RpnpPushStack(Stack, &ComparativeOp))
844  {
845  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
846 
847  if (ErrOffset)
848  *ErrOffset = -1;
849 
850  return FALSE;
851  }
852 
853  /* Skip whitespace */
854  while (isspace(*p))
855  {
856  p++;
857  CharacterOffset++;
858  }
859 
860  if (End)
861  *End = p;
862 
863  return TRUE;
864 }
865 
877 static BOOLEAN
880  IN PKDB_KTRAP_FRAME TrapFrame,
882  OUT PLONG ErrOffset OPTIONAL,
883  OUT PCHAR ErrMsg OPTIONAL)
884 {
885  ULONGLONG ValueStack[RPN_VALUE_STACK_SIZE];
886  ULONG ValueStackPointer = 0;
887  ULONG index;
888  ULONGLONG ull;
889  ULONG ul;
890  USHORT us;
891  UCHAR uc;
892  PVOID p;
893  BOOLEAN Ok;
894 #ifdef DEBUG_RPN
895  ULONG ValueStackPointerMax = 0;
896 #endif
897 
898  ASSERT(Stack);
899  ASSERT(TrapFrame);
900  ASSERT(Result);
901 
902  for (index = 0; index < Stack->Sp; index++)
903  {
904  PRPN_OP Op = Stack->Ops + index;
905 
906 #ifdef DEBUG_RPN
907  ValueStackPointerMax = max(ValueStackPointerMax, ValueStackPointer);
908 #endif
909 
910  switch (Op->Type)
911  {
912  case RpnOpNop:
913  /* No operation */
914  break;
915 
916  case RpnOpImmediate:
917  if (ValueStackPointer == RPN_VALUE_STACK_SIZE)
918  {
919  CONST_STRCPY(ErrMsg, "Value stack overflow");
920 
921  if (ErrOffset)
922  *ErrOffset = -1;
923 
924  return FALSE;
925  }
926 
927  ValueStack[ValueStackPointer++] = Op->Data.Immediate;
928  break;
929 
930  case RpnOpRegister:
931  if (ValueStackPointer == RPN_VALUE_STACK_SIZE)
932  {
933  CONST_STRCPY(ErrMsg, "Value stack overflow");
934 
935  if (ErrOffset)
936  *ErrOffset = -1;
937 
938  return FALSE;
939  }
940 
941  ul = Op->Data.Register;
942  p = (PVOID)((ULONG_PTR)TrapFrame + RegisterToTrapFrame[ul].Offset);
943 
944  switch (RegisterToTrapFrame[ul].Size)
945  {
946  case 1: ull = (ULONGLONG)(*(PUCHAR)p); break;
947  case 2: ull = (ULONGLONG)(*(PUSHORT)p); break;
948  case 4: ull = (ULONGLONG)(*(PULONG)p); break;
949  case 8: ull = (ULONGLONG)(*(PULONGLONG)p); break;
950  default: ASSERT(0); return FALSE; break;
951  }
952 
953  ValueStack[ValueStackPointer++] = ull;
954  break;
955 
956  case RpnOpDereference:
957  if (ValueStackPointer < 1)
958  {
959  CONST_STRCPY(ErrMsg, "Value stack underflow");
960 
961  if (ErrOffset)
962  *ErrOffset = -1;
963 
964  return FALSE;
965  }
966 
967  /* FIXME: Print a warning when address is out of range */
968  p = (PVOID)(ULONG_PTR)ValueStack[ValueStackPointer - 1];
969  Ok = FALSE;
970 
971  switch (Op->Data.DerefMemorySize)
972  {
973  case 1:
974  if (NT_SUCCESS(KdbpSafeReadMemory(&uc, p, sizeof (uc))))
975  {
976  Ok = TRUE;
977  ull = (ULONGLONG)uc;
978  }
979  break;
980 
981  case 2:
982  if (NT_SUCCESS(KdbpSafeReadMemory(&us, p, sizeof (us))))
983  {
984  Ok = TRUE;
985  ull = (ULONGLONG)us;
986  }
987  break;
988 
989  case 4:
990  if (NT_SUCCESS(KdbpSafeReadMemory(&ul, p, sizeof (ul))))
991  {
992  Ok = TRUE;
993  ull = (ULONGLONG)ul;
994  }
995  break;
996 
997  case 8:
998  if (NT_SUCCESS(KdbpSafeReadMemory(&ull, p, sizeof (ull))))
999  {
1000  Ok = TRUE;
1001  }
1002  break;
1003 
1004  default:
1005  ASSERT(0);
1006  return FALSE;
1007  break;
1008  }
1009 
1010  if (!Ok)
1011  {
1012  _snprintf(ErrMsg, 128, "Couldn't access memory at 0x%lx", (ULONG)p);
1013 
1014  if (ErrOffset)
1015  *ErrOffset = Op->CharacterOffset;
1016 
1017  return FALSE;
1018  }
1019 
1020  ValueStack[ValueStackPointer - 1] = ull;
1021  break;
1022 
1023  case RpnOpBinaryOperator:
1024  if (ValueStackPointer < 2)
1025  {
1026  CONST_STRCPY(ErrMsg, "Value stack underflow");
1027 
1028  if (ErrOffset)
1029  *ErrOffset = -1;
1030 
1031  return FALSE;
1032  }
1033 
1034  ValueStackPointer--;
1035  ull = ValueStack[ValueStackPointer];
1036 
1037  if (ull == 0 && Op->Data.BinaryOperator == RpnBinaryOperatorDiv)
1038  {
1039  CONST_STRCPY(ErrMsg, "Division by zero");
1040 
1041  if (ErrOffset)
1042  *ErrOffset = Op->CharacterOffset;
1043 
1044  return FALSE;
1045  }
1046 
1047  ull = Op->Data.BinaryOperator(ValueStack[ValueStackPointer - 1], ull);
1048  ValueStack[ValueStackPointer - 1] = ull;
1049  break;
1050 
1051  default:
1052  ASSERT(0);
1053  return FALSE;
1054  }
1055  }
1056 
1057 #ifdef DEBUG_RPN
1058  DPRINT1("Max value stack pointer: %d\n", ValueStackPointerMax);
1059 #endif
1060 
1061  if (ValueStackPointer != 1)
1062  {
1063  CONST_STRCPY(ErrMsg, "Stack not empty after evaluation");
1064 
1065  if (ErrOffset)
1066  *ErrOffset = -1;
1067 
1068  return FALSE;
1069  }
1070 
1071  *Result = ValueStack[0];
1072  return TRUE;
1073 }
1074 
1086 BOOLEAN
1089  IN PKDB_KTRAP_FRAME TrapFrame,
1091  OUT PLONG ErrOffset OPTIONAL,
1092  OUT PCHAR ErrMsg OPTIONAL)
1093 {
1095 
1096  ASSERT(Expression);
1097  ASSERT(TrapFrame);
1098  ASSERT(Result);
1099 
1100  /* Clear the stack and parse the expression */
1102  if (!RpnpParseExpression(Stack, Expression, NULL, 0, ErrOffset, ErrMsg))
1103  return FALSE;
1104 
1105 #ifdef DEBUG_RPN
1107 #endif
1108 
1109  /* Evaluate the stack */
1110  if (!RpnpEvaluateStack(Stack, TrapFrame, Result, ErrOffset, ErrMsg))
1111  return FALSE;
1112 
1113  return TRUE;
1114 }
1115 
1126 PVOID
1129  OUT PLONG ErrOffset OPTIONAL,
1130  OUT PCHAR ErrMsg OPTIONAL)
1131 {
1132  LONG Size;
1134  PRPN_STACK NewStack;
1135 
1136  ASSERT(Expression);
1137 
1138  /* Clear the stack and parse the expression */
1140  if (!RpnpParseExpression(Stack, Expression, NULL, 0, ErrOffset, ErrMsg))
1141  return FALSE;
1142 
1143 #ifdef DEBUG_RPN
1145 #endif
1146 
1147  /* Duplicate the stack and return a pointer/handle to it */
1148  ASSERT(Stack->Sp >= 1);
1149  Size = sizeof (RPN_STACK) + (RTL_FIELD_SIZE(RPN_STACK, Ops[0]) * (Stack->Sp - 1));
1151 
1152  if (!NewStack)
1153  {
1154  CONST_STRCPY(ErrMsg, "Out of memory");
1155 
1156  if (ErrOffset)
1157  *ErrOffset = -1;
1158 
1159  return NULL;
1160  }
1161 
1162  memcpy(NewStack, Stack, Size);
1163  NewStack->Size = NewStack->Sp;
1164 
1165  return NewStack;
1166 }
1167 
1180 BOOLEAN
1183  IN PKDB_KTRAP_FRAME TrapFrame,
1185  OUT PLONG ErrOffset OPTIONAL,
1186  OUT PCHAR ErrMsg OPTIONAL)
1187 {
1189 
1190  ASSERT(Expression);
1191  ASSERT(TrapFrame);
1192  ASSERT(Result);
1193 
1194  /* Evaluate the stack */
1195  return RpnpEvaluateStack(Stack, TrapFrame, Result, ErrOffset, ErrMsg);
1196 }
1197 
#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:372
#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:406
static BOOLEAN RpnpPopStack(IN OUT PRPN_STACK Stack, OUT PRPN_OP Op OPTIONAL)
Pops the top op from the stack.
Definition: kdb_expr.c:347
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:174
#define DbgPrint
Definition: loader.c:25
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:234
#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:222
#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:322
#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 struct @1803 RpnStack
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:45
#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:190
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:206
static CONST DWORD MemorySize[]
Definition: svga.c:32
ULONGLONG RpnBinaryOperatorEquals(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:182
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
ULONGLONG RpnBinaryOperatorSub(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:150
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:878
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:1087
ULONGLONG RpnBinaryOperatorAdd(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:142
UCHAR Register
Definition: kdb_expr.c:64
NTSTATUS KdbpSafeReadMemory(OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes)
Definition: kdb.c:1679
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:1127
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
static const struct @1804 RegisterToTrapFrame[]
ULONGLONG RpnBinaryOperatorDiv(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:166
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:198
ULONGLONG RpnBinaryOperatorGreaterThan(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:214
static const INT RegisterToTrapFrameCount
Definition: kdb_expr.c:137
#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:384
unsigned int ULONG
Definition: retypes.h:1
union _RPN_OP::@1805 Data
#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:1181
static VOID RpnpClearStack(OUT PRPN_STACK Stack)
Clears the given RPN stack.
Definition: kdb_expr.c:309
ULONGLONG RpnBinaryOperatorMul(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:158
signed int * PLONG
Definition: retypes.h:5
unsigned short * PUSHORT
Definition: retypes.h:2
RPN_BINARY_OPERATOR BinaryOperator
Definition: kdb_expr.c:60
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68