ReactOS  0.4.10-dev-486-g11b7619
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  {"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)},
140 };
142 
143 /* FUNCTIONS *****************************************************************/
144 
145 ULONGLONG
147  ULONGLONG a,
148  ULONGLONG b)
149 {
150  return a + b;
151 }
152 
153 ULONGLONG
155  ULONGLONG a,
156  ULONGLONG b)
157 {
158  return a - b;
159 }
160 
161 ULONGLONG
163  ULONGLONG a,
164  ULONGLONG b)
165 {
166  return a * b;
167 }
168 
169 ULONGLONG
171  ULONGLONG a,
172  ULONGLONG b)
173 {
174  return a / b;
175 }
176 
177 ULONGLONG
179  ULONGLONG a,
180  ULONGLONG b)
181 {
182  return a % b;
183 }
184 
185 ULONGLONG
187  ULONGLONG a,
188  ULONGLONG b)
189 {
190  return (a == b);
191 }
192 
193 ULONGLONG
195  ULONGLONG a,
196  ULONGLONG b)
197 {
198  return (a != b);
199 }
200 
201 ULONGLONG
203  ULONGLONG a,
204  ULONGLONG b)
205 {
206  return (a < b);
207 }
208 
209 ULONGLONG
211  ULONGLONG a,
212  ULONGLONG b)
213 {
214  return (a <= b);
215 }
216 
217 ULONGLONG
219  ULONGLONG a,
220  ULONGLONG b)
221 {
222  return (a > b);
223 }
224 
225 ULONGLONG
227  ULONGLONG a,
228  ULONGLONG b)
229 {
230  return (a >= b);
231 }
232 
237 VOID
239  IN PRPN_STACK Stack)
240 {
241  ULONG ul;
242 
243  ASSERT(Stack);
244  DbgPrint("\nStack size: %ld\n", Stack->Sp);
245 
246  for (ul = 0; ul < Stack->Sp; ul++)
247  {
248  PRPN_OP Op = Stack->Ops + ul;
249  switch (Op->Type)
250  {
251  case RpnOpNop:
252  DbgPrint("NOP,");
253  break;
254 
255  case RpnOpImmediate:
256  DbgPrint("0x%I64x,", Op->Data.Immediate);
257  break;
258 
259  case RpnOpBinaryOperator:
261  DbgPrint("+,");
262  else if (Op->Data.BinaryOperator == RpnBinaryOperatorSub)
263  DbgPrint("-,");
264  else if (Op->Data.BinaryOperator == RpnBinaryOperatorMul)
265  DbgPrint("*,");
266  else if (Op->Data.BinaryOperator == RpnBinaryOperatorDiv)
267  DbgPrint("/,");
268  else if (Op->Data.BinaryOperator == RpnBinaryOperatorMod)
269  DbgPrint("%%,");
271  DbgPrint("==,");
273  DbgPrint("!=,");
275  DbgPrint("<,");
277  DbgPrint("<=,");
279  DbgPrint(">,");
281  DbgPrint(">=,");
282  else
283  DbgPrint("UNKNOWN OP,");
284 
285  break;
286 
287  case RpnOpRegister:
288  DbgPrint("%s,", RegisterToTrapFrame[Op->Data.Register].Name);
289  break;
290 
291  case RpnOpDereference:
292  DbgPrint("[%s],",
293  (Op->Data.DerefMemorySize == 1) ? ("byte") :
294  ((Op->Data.DerefMemorySize == 2) ? ("word") :
295  ((Op->Data.DerefMemorySize == 4) ? ("dword") : ("qword"))));
296  break;
297 
298  default:
299  DbgPrint("\nUnsupported Type: %d\n", Op->Type);
300  ul = Stack->Sp;
301  break;
302  }
303  }
304 
305  DbgPrint("\n");
306 }
307 
312 static VOID
314  OUT PRPN_STACK Stack)
315 {
316  ASSERT(Stack);
317  Stack->Sp = 0;
318 }
319 
325 static BOOLEAN
327  IN OUT PRPN_STACK Stack,
328  IN PRPN_OP Op)
329 {
330  ASSERT(Stack);
331  ASSERT(Op);
332 
333  if (Stack->Sp >= Stack->Size)
334  return FALSE;
335 
336  memcpy(Stack->Ops + Stack->Sp, Op, sizeof (RPN_OP));
337  Stack->Sp++;
338 
339  return TRUE;
340 }
341 
350 static BOOLEAN
352  IN OUT PRPN_STACK Stack,
353  OUT PRPN_OP Op OPTIONAL)
354 {
355  ASSERT(Stack);
356 
357  if (Stack->Sp == 0)
358  return FALSE;
359 
360  Stack->Sp--;
361  if (Op)
362  memcpy(Op, Stack->Ops + Stack->Sp, sizeof (RPN_OP));
363 
364  return TRUE;
365 }
366 
375 static BOOLEAN
377  IN PRPN_STACK Stack,
378  OUT PRPN_OP Op)
379 {
380  ASSERT(Stack);
381  ASSERT(Op);
382 
383  if (Stack->Sp == 0)
384  return FALSE;
385 
386  memcpy(Op, Stack->Ops + Stack->Sp - 1, sizeof (RPN_OP));
387 
388  return TRUE;
389 }
390 
409 static BOOLEAN
411  IN PRPN_STACK Stack,
413  OUT PCHAR *End OPTIONAL,
414  IN ULONG CharacterOffset,
415  OUT PLONG ErrOffset OPTIONAL,
416  OUT PCHAR ErrMsg OPTIONAL)
417 {
418  PCHAR p = Expression;
419  PCHAR pend;
420  PCHAR Operator = NULL;
421  LONG OperatorOffset = -1;
422  RPN_OP RpnOp;
423  RPN_OP PoppedOperator;
424  BOOLEAN HavePoppedOperator = FALSE;
425  RPN_OP ComparativeOp;
426  BOOLEAN ComparativeOpFilled = FALSE;
427  BOOLEAN IsComparativeOp;
428  INT i, i2;
429  ULONG ul;
431  CHAR Buffer[16];
432  BOOLEAN First;
433 
434  ASSERT(Stack);
435  ASSERT(Expression);
436 
437  First = TRUE;
438  for (;;)
439  {
440  /* Skip whitespace */
441  while (isspace(*p))
442  {
443  p++;
444  CharacterOffset++;
445  }
446 
447  /* Check for end of expression */
448  if (p[0] == '\0' || p[0] == ')' || p[0] == ']')
449  break;
450 
451  if (!First)
452  {
453  /* Remember operator */
454  Operator = p++;
455  OperatorOffset = CharacterOffset++;
456 
457  /* Pop operator (to get the right operator precedence) */
458  HavePoppedOperator = FALSE;
459  if (*Operator == '*' || *Operator == '/' || *Operator == '%')
460  {
461  if (RpnpTopStack(Stack, &PoppedOperator) &&
462  PoppedOperator.Type == RpnOpBinaryOperator &&
463  (PoppedOperator.Data.BinaryOperator == RpnBinaryOperatorAdd ||
464  PoppedOperator.Data.BinaryOperator == RpnBinaryOperatorSub))
465  {
466  RpnpPopStack(Stack, NULL);
467  HavePoppedOperator = TRUE;
468  }
469  else if (PoppedOperator.Type == RpnOpNop)
470  {
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.
474  */
475  }
476  }
477  else if ((Operator[0] == '=' && Operator[1] == '=') ||
478  (Operator[0] == '!' && Operator[1] == '=') ||
479  Operator[0] == '<' || Operator[0] == '>')
480  {
481  if (Operator[0] == '=' || Operator[0] == '!' ||
482  (Operator[0] == '<' && Operator[1] == '=') ||
483  (Operator[0] == '>' && Operator[1] == '='))
484  {
485  p++;
486  CharacterOffset++;
487  }
488 #if 0
489  /* Parse rest of expression */
490  if (!RpnpParseExpression(Stack, p + 1, &pend, CharacterOffset + 1,
491  ErrOffset, ErrMsg))
492  {
493  return FALSE;
494  }
495  else if (pend == p + 1)
496  {
497  CONST_STRCPY(ErrMsg, "Expression expected");
498 
499  if (ErrOffset)
500  *ErrOffset = CharacterOffset + 1;
501 
502  return FALSE;
503  }
504 
505  goto end_of_expression; /* return */
506 #endif
507  }
508  else if (Operator[0] != '+' && Operator[0] != '-')
509  {
510  CONST_STRCPY(ErrMsg, "Operator expected");
511 
512  if (ErrOffset)
513  *ErrOffset = OperatorOffset;
514 
515  return FALSE;
516  }
517 
518  /* Skip whitespace */
519  while (isspace(*p))
520  {
521  p++;
522  CharacterOffset++;
523  }
524  }
525 
526  /* Get operand */
527  MemorySize = sizeof(ULONG_PTR); /* default to pointer size */
528 
529 get_operand:
530  i = strcspn(p, "+-*/%()[]<>!=");
531  if (i > 0)
532  {
533  i2 = i;
534 
535  /* Copy register name/memory size */
536  while (isspace(p[--i2]));
537 
538  i2 = min(i2 + 1, (INT)sizeof (Buffer) - 1);
539  strncpy(Buffer, p, i2);
540  Buffer[i2] = '\0';
541 
542  /* Memory size prefix */
543  if (p[i] == '[')
544  {
545  if (stricmp(Buffer, "byte") == 0)
546  MemorySize = 1;
547  else if (stricmp(Buffer, "word") == 0)
548  MemorySize = 2;
549  else if (stricmp(Buffer, "dword") == 0)
550  MemorySize = 4;
551  else if (stricmp(Buffer, "qword") == 0)
552  MemorySize = 8;
553  else
554  {
555  CONST_STRCPY(ErrMsg, "Invalid memory size prefix");
556 
557  if (ErrOffset)
558  *ErrOffset = CharacterOffset;
559 
560  return FALSE;
561  }
562 
563  p += i;
564  CharacterOffset += i;
565  goto get_operand;
566  }
567 
568  /* Try to find register */
569  for (i = 0; i < RegisterToTrapFrameCount; i++)
570  {
571  if (stricmp(RegisterToTrapFrame[i].Name, Buffer) == 0)
572  break;
573  }
574 
575  if (i < RegisterToTrapFrameCount)
576  {
577  RpnOp.Type = RpnOpRegister;
578  RpnOp.CharacterOffset = CharacterOffset;
579  RpnOp.Data.Register = i;
581  CharacterOffset += i;
582  p += i;
583  }
584  else
585  {
586  /* Immediate value */
587  /* FIXME: Need string to ULONGLONG function */
588  ul = strtoul(p, &pend, 0);
589  if (p != pend)
590  {
591  RpnOp.Type = RpnOpImmediate;
592  RpnOp.CharacterOffset = CharacterOffset;
593  RpnOp.Data.Immediate = (ULONGLONG)ul;
594  CharacterOffset += pend - p;
595  p = pend;
596  }
597  else
598  {
599  CONST_STRCPY(ErrMsg, "Operand expected");
600 
601  if (ErrOffset)
602  *ErrOffset = CharacterOffset;
603 
604  return FALSE;
605  }
606  }
607 
608  /* Push operand */
609  if (!RpnpPushStack(Stack, &RpnOp))
610  {
611  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
612 
613  if (ErrOffset)
614  *ErrOffset = -1;
615 
616  return FALSE;
617  }
618  }
619  else if (i == 0)
620  {
621  if (p[0] == '(' || p[0] == '[') /* subexpression */
622  {
623  if (!RpnpParseExpression(Stack, p + 1, &pend, CharacterOffset + 1,
624  ErrOffset, ErrMsg))
625  {
626  return FALSE;
627  }
628  else if (pend == p + 1)
629  {
630  CONST_STRCPY(ErrMsg, "Expression expected");
631 
632  if (ErrOffset)
633  *ErrOffset = CharacterOffset + 1;
634 
635  return FALSE;
636  }
637 
638  if (p[0] == '[') /* dereference */
639  {
640  ASSERT(MemorySize == 1 || MemorySize == 2 ||
641  MemorySize == 4 || MemorySize == 8);
642 
643  if (pend[0] != ']')
644  {
645  CONST_STRCPY(ErrMsg, "']' expected");
646 
647  if (ErrOffset)
648  *ErrOffset = CharacterOffset + (pend - p);
649 
650  return FALSE;
651  }
652 
653  RpnOp.Type = RpnOpDereference;
654  RpnOp.CharacterOffset = CharacterOffset;
656 
657  if (!RpnpPushStack(Stack, &RpnOp))
658  {
659  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
660 
661  if (ErrOffset)
662  *ErrOffset = -1;
663 
664  return FALSE;
665  }
666  }
667  else /* p[0] == '(' */
668  {
669  if (pend[0] != ')')
670  {
671  CONST_STRCPY(ErrMsg, "')' expected");
672 
673  if (ErrOffset)
674  *ErrOffset = CharacterOffset + (pend - p);
675 
676  return FALSE;
677  }
678  }
679 
680  /* Push a "nop" to prevent popping of the + operator (which would
681  * result in (10+10)/2 beeing evaluated as 15)
682  */
683  RpnOp.Type = RpnOpNop;
684  if (!RpnpPushStack(Stack, &RpnOp))
685  {
686  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
687 
688  if (ErrOffset)
689  *ErrOffset = -1;
690 
691  return FALSE;
692  }
693 
694  /* Skip closing brace/bracket */
695  pend++;
696 
697  CharacterOffset += pend - p;
698  p = pend;
699  }
700  else if (First && p[0] == '-') /* Allow expressions like "- eax" */
701  {
702  RpnOp.Type = RpnOpImmediate;
703  RpnOp.CharacterOffset = CharacterOffset;
704  RpnOp.Data.Immediate = 0;
705 
706  if (!RpnpPushStack(Stack, &RpnOp))
707  {
708  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
709 
710  if (ErrOffset)
711  *ErrOffset = -1;
712 
713  return FALSE;
714  }
715  }
716  else
717  {
718  CONST_STRCPY(ErrMsg, "Operand expected");
719 
720  if (ErrOffset)
721  *ErrOffset = CharacterOffset;
722 
723  return FALSE;
724  }
725  }
726  else
727  {
728  CONST_STRCPY(ErrMsg, "strcspn() failed");
729 
730  if (ErrOffset)
731  *ErrOffset = -1;
732 
733  return FALSE;
734  }
735 
736  if (!First)
737  {
738  /* Push operator */
739  RpnOp.CharacterOffset = OperatorOffset;
740  RpnOp.Type = RpnOpBinaryOperator;
741  IsComparativeOp = FALSE;
742 
743  switch (*Operator)
744  {
745  case '+':
747  break;
748 
749  case '-':
751  break;
752 
753  case '*':
755  break;
756 
757  case '/':
759  break;
760 
761  case '%':
763  break;
764 
765  case '=':
766  ASSERT(Operator[1] == '=');
767  IsComparativeOp = TRUE;
769  break;
770 
771  case '!':
772  ASSERT(Operator[1] == '=');
773  IsComparativeOp = TRUE;
775  break;
776 
777  case '<':
778  IsComparativeOp = TRUE;
779 
780  if (Operator[1] == '=')
782  else
784 
785  break;
786 
787  case '>':
788  IsComparativeOp = TRUE;
789 
790  if (Operator[1] == '=')
792  else
794 
795  break;
796 
797  default:
798  ASSERT(0);
799  break;
800  }
801 
802  if (IsComparativeOp)
803  {
804  if (ComparativeOpFilled && !RpnpPushStack(Stack, &ComparativeOp))
805  {
806  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
807 
808  if (ErrOffset)
809  *ErrOffset = -1;
810 
811  return FALSE;
812  }
813 
814  memcpy(&ComparativeOp, &RpnOp, sizeof(RPN_OP));
815  ComparativeOpFilled = TRUE;
816  }
817  else if (!RpnpPushStack(Stack, &RpnOp))
818  {
819  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
820 
821  if (ErrOffset)
822  *ErrOffset = -1;
823 
824  return FALSE;
825  }
826 
827  /* Push popped operator */
828  if (HavePoppedOperator)
829  {
830  if (!RpnpPushStack(Stack, &PoppedOperator))
831  {
832  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
833 
834  if (ErrOffset)
835  *ErrOffset = -1;
836 
837  return FALSE;
838  }
839  }
840  }
841 
842  First = FALSE;
843  }
844 
845 //end_of_expression:
846 
847  if (ComparativeOpFilled && !RpnpPushStack(Stack, &ComparativeOp))
848  {
849  CONST_STRCPY(ErrMsg, "RPN op stack overflow");
850 
851  if (ErrOffset)
852  *ErrOffset = -1;
853 
854  return FALSE;
855  }
856 
857  /* Skip whitespace */
858  while (isspace(*p))
859  {
860  p++;
861  CharacterOffset++;
862  }
863 
864  if (End)
865  *End = p;
866 
867  return TRUE;
868 }
869 
881 static BOOLEAN
883  IN PRPN_STACK Stack,
884  IN PKDB_KTRAP_FRAME TrapFrame,
886  OUT PLONG ErrOffset OPTIONAL,
887  OUT PCHAR ErrMsg OPTIONAL)
888 {
889  ULONGLONG ValueStack[RPN_VALUE_STACK_SIZE];
890  ULONG ValueStackPointer = 0;
891  ULONG index;
892  ULONGLONG ull;
893  ULONG ul;
894  USHORT us;
895  UCHAR uc;
896  PVOID p;
897  BOOLEAN Ok;
898 #ifdef DEBUG_RPN
899  ULONG ValueStackPointerMax = 0;
900 #endif
901 
902  ASSERT(Stack);
903  ASSERT(TrapFrame);
904  ASSERT(Result);
905 
906  for (index = 0; index < Stack->Sp; index++)
907  {
908  PRPN_OP Op = Stack->Ops + index;
909 
910 #ifdef DEBUG_RPN
911  ValueStackPointerMax = max(ValueStackPointerMax, ValueStackPointer);
912 #endif
913 
914  switch (Op->Type)
915  {
916  case RpnOpNop:
917  /* No operation */
918  break;
919 
920  case RpnOpImmediate:
921  if (ValueStackPointer == RPN_VALUE_STACK_SIZE)
922  {
923  CONST_STRCPY(ErrMsg, "Value stack overflow");
924 
925  if (ErrOffset)
926  *ErrOffset = -1;
927 
928  return FALSE;
929  }
930 
931  ValueStack[ValueStackPointer++] = Op->Data.Immediate;
932  break;
933 
934  case RpnOpRegister:
935  if (ValueStackPointer == RPN_VALUE_STACK_SIZE)
936  {
937  CONST_STRCPY(ErrMsg, "Value stack overflow");
938 
939  if (ErrOffset)
940  *ErrOffset = -1;
941 
942  return FALSE;
943  }
944 
945  ul = Op->Data.Register;
946  p = (PVOID)((ULONG_PTR)TrapFrame + RegisterToTrapFrame[ul].Offset);
947 
948  switch (RegisterToTrapFrame[ul].Size)
949  {
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;
955  }
956 
957  ValueStack[ValueStackPointer++] = ull;
958  break;
959 
960  case RpnOpDereference:
961  if (ValueStackPointer < 1)
962  {
963  CONST_STRCPY(ErrMsg, "Value stack underflow");
964 
965  if (ErrOffset)
966  *ErrOffset = -1;
967 
968  return FALSE;
969  }
970 
971  /* FIXME: Print a warning when address is out of range */
972  p = (PVOID)(ULONG_PTR)ValueStack[ValueStackPointer - 1];
973  Ok = FALSE;
974 
975  switch (Op->Data.DerefMemorySize)
976  {
977  case 1:
978  if (NT_SUCCESS(KdbpSafeReadMemory(&uc, p, sizeof (uc))))
979  {
980  Ok = TRUE;
981  ull = (ULONGLONG)uc;
982  }
983  break;
984 
985  case 2:
986  if (NT_SUCCESS(KdbpSafeReadMemory(&us, p, sizeof (us))))
987  {
988  Ok = TRUE;
989  ull = (ULONGLONG)us;
990  }
991  break;
992 
993  case 4:
994  if (NT_SUCCESS(KdbpSafeReadMemory(&ul, p, sizeof (ul))))
995  {
996  Ok = TRUE;
997  ull = (ULONGLONG)ul;
998  }
999  break;
1000 
1001  case 8:
1002  if (NT_SUCCESS(KdbpSafeReadMemory(&ull, p, sizeof (ull))))
1003  {
1004  Ok = TRUE;
1005  }
1006  break;
1007 
1008  default:
1009  ASSERT(0);
1010  return FALSE;
1011  break;
1012  }
1013 
1014  if (!Ok)
1015  {
1016  _snprintf(ErrMsg, 128, "Couldn't access memory at 0x%lx", (ULONG)p);
1017 
1018  if (ErrOffset)
1019  *ErrOffset = Op->CharacterOffset;
1020 
1021  return FALSE;
1022  }
1023 
1024  ValueStack[ValueStackPointer - 1] = ull;
1025  break;
1026 
1027  case RpnOpBinaryOperator:
1028  if (ValueStackPointer < 2)
1029  {
1030  CONST_STRCPY(ErrMsg, "Value stack underflow");
1031 
1032  if (ErrOffset)
1033  *ErrOffset = -1;
1034 
1035  return FALSE;
1036  }
1037 
1038  ValueStackPointer--;
1039  ull = ValueStack[ValueStackPointer];
1040 
1041  if (ull == 0 && Op->Data.BinaryOperator == RpnBinaryOperatorDiv)
1042  {
1043  CONST_STRCPY(ErrMsg, "Division by zero");
1044 
1045  if (ErrOffset)
1046  *ErrOffset = Op->CharacterOffset;
1047 
1048  return FALSE;
1049  }
1050 
1051  ull = Op->Data.BinaryOperator(ValueStack[ValueStackPointer - 1], ull);
1052  ValueStack[ValueStackPointer - 1] = ull;
1053  break;
1054 
1055  default:
1056  ASSERT(0);
1057  return FALSE;
1058  }
1059  }
1060 
1061 #ifdef DEBUG_RPN
1062  DPRINT1("Max value stack pointer: %d\n", ValueStackPointerMax);
1063 #endif
1064 
1065  if (ValueStackPointer != 1)
1066  {
1067  CONST_STRCPY(ErrMsg, "Stack not empty after evaluation");
1068 
1069  if (ErrOffset)
1070  *ErrOffset = -1;
1071 
1072  return FALSE;
1073  }
1074 
1075  *Result = ValueStack[0];
1076  return TRUE;
1077 }
1078 
1090 BOOLEAN
1093  IN PKDB_KTRAP_FRAME TrapFrame,
1095  OUT PLONG ErrOffset OPTIONAL,
1096  OUT PCHAR ErrMsg OPTIONAL)
1097 {
1098  PRPN_STACK Stack = (PRPN_STACK)&RpnStack;
1099 
1100  ASSERT(Expression);
1101  ASSERT(TrapFrame);
1102  ASSERT(Result);
1103 
1104  /* Clear the stack and parse the expression */
1105  RpnpClearStack(Stack);
1106  if (!RpnpParseExpression(Stack, Expression, NULL, 0, ErrOffset, ErrMsg))
1107  return FALSE;
1108 
1109 #ifdef DEBUG_RPN
1110  RpnpDumpStack(Stack);
1111 #endif
1112 
1113  /* Evaluate the stack */
1114  if (!RpnpEvaluateStack(Stack, TrapFrame, Result, ErrOffset, ErrMsg))
1115  return FALSE;
1116 
1117  return TRUE;
1118 }
1119 
1130 PVOID
1133  OUT PLONG ErrOffset OPTIONAL,
1134  OUT PCHAR ErrMsg OPTIONAL)
1135 {
1136  LONG Size;
1137  PRPN_STACK Stack = (PRPN_STACK)&RpnStack;
1138  PRPN_STACK NewStack;
1139 
1140  ASSERT(Expression);
1141 
1142  /* Clear the stack and parse the expression */
1143  RpnpClearStack(Stack);
1144  if (!RpnpParseExpression(Stack, Expression, NULL, 0, ErrOffset, ErrMsg))
1145  return FALSE;
1146 
1147 #ifdef DEBUG_RPN
1148  RpnpDumpStack(Stack);
1149 #endif
1150 
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);
1155 
1156  if (!NewStack)
1157  {
1158  CONST_STRCPY(ErrMsg, "Out of memory");
1159 
1160  if (ErrOffset)
1161  *ErrOffset = -1;
1162 
1163  return NULL;
1164  }
1165 
1166  memcpy(NewStack, Stack, Size);
1167  NewStack->Size = NewStack->Sp;
1168 
1169  return NewStack;
1170 }
1171 
1184 BOOLEAN
1187  IN PKDB_KTRAP_FRAME TrapFrame,
1189  OUT PLONG ErrOffset OPTIONAL,
1190  OUT PCHAR ErrMsg OPTIONAL)
1191 {
1192  PRPN_STACK Stack = (PRPN_STACK)Expression;
1193 
1194  ASSERT(Expression);
1195  ASSERT(TrapFrame);
1196  ASSERT(Result);
1197 
1198  /* Evaluate the stack */
1199  return RpnpEvaluateStack(Stack, TrapFrame, Result, ErrOffset, ErrMsg);
1200 }
1201 
DWORD *typedef PVOID
Definition: winlogon.h:60
#define TAG_KDBG
Definition: kdb.h:7
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:376
#define IN
Definition: typedefs.h:38
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
#define TRUE
Definition: types.h:120
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:410
static BOOLEAN RpnpPopStack(IN OUT PRPN_STACK Stack, OUT PRPN_OP Op OPTIONAL)
Pops the top op from the stack.
Definition: kdb_expr.c:351
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:178
#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
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
VOID RpnpDumpStack(IN PRPN_STACK Stack)
Dumps the given RPN stack content.
Definition: kdb_expr.c:238
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
_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
ULONGLONG RpnBinaryOperatorGreaterThanOrEquals(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:226
#define RPN_OP_STACK_SIZE
Definition: kdb_expr.c:90
int32_t INT
Definition: typedefs.h:56
uint32_t ULONG_PTR
Definition: typedefs.h:63
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:326
#define _snprintf
Definition: xmlstorage.h:200
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#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
smooth NULL
Definition: ftsmooth.c:416
ULONG Size
Definition: kdb_expr.c:96
Definition: bufpool.h:45
PCHAR Name
Definition: kdb_expr.c:108
struct _RPN_STACK RPN_STACK
#define b
Definition: ke_i.h:79
UINTN Size
Definition: acefiex.h:555
struct _RPN_OP RPN_OP
unsigned char BOOLEAN
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint 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 GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint i2
Definition: glfuncs.h:96
uint64_t ULONGLONG
Definition: typedefs.h:65
ULONG Sp
Definition: kdb_expr.c:97
unsigned short * PUSHORT
Definition: retypes.h:2
ULONGLONG RpnBinaryOperatorNotEquals(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:194
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
_In_ PUNICODE_STRING Name
Definition: mrx.h:218
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:210
static CONST DWORD MemorySize[]
Definition: svga.c:32
ULONGLONG RpnBinaryOperatorEquals(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:186
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
ULONGLONG RpnBinaryOperatorSub(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:154
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:882
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:1091
ULONGLONG RpnBinaryOperatorAdd(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:146
UCHAR Register
Definition: kdb_expr.c:64
NTSTATUS KdbpSafeReadMemory(OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes)
Definition: kdb.c:1734
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:1131
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
ULONGLONG RpnBinaryOperatorDiv(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:170
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
ULONGLONG RpnBinaryOperatorLessThan(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:202
ULONGLONG RpnBinaryOperatorGreaterThan(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:218
static const INT RegisterToTrapFrameCount
Definition: kdb_expr.c:141
#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:39
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:390
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
static struct @1680 RpnStack
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:1185
static VOID RpnpClearStack(OUT PRPN_STACK Stack)
Clears the given RPN stack.
Definition: kdb_expr.c:313
ULONGLONG RpnBinaryOperatorMul(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:162
signed int * PLONG
Definition: retypes.h:5
ULONGLONG(* RPN_BINARY_OPERATOR)(ULONGLONG a, ULONGLONG b)
Definition: kdb_expr.c:51
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44
union _RPN_OP::@1682 Data
RPN_BINARY_OPERATOR BinaryOperator
Definition: kdb_expr.c:60
static const struct @1681 RegisterToTrapFrame[]