Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenkdb_expr.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS kernel 00003 * Copyright (C) 2005 ReactOS Team 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along 00016 * with this program; if not, write to the Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00018 */ 00019 /* 00020 * PROJECT: ReactOS kernel 00021 * FILE: ntoskrnl/dbg/kdb_expr.c 00022 * PURPOSE: Kernel debugger expression evaluation 00023 * PROGRAMMER: Gregor Anich (blight@blight.eu.org) 00024 * UPDATE HISTORY: 00025 * Created 15/01/2005 00026 */ 00027 00028 /* Note: 00029 * 00030 * The given expression is parsed and stored in reverse polish notation, 00031 * then it is evaluated and the result is returned. 00032 */ 00033 00034 /* INCLUDES ******************************************************************/ 00035 00036 #include <ntoskrnl.h> 00037 #define NDEBUG 00038 #include <debug.h> 00039 00040 /* TYPES *********************************************************************/ 00041 typedef enum _RPN_OP_TYPE 00042 { 00043 RpnOpNop, 00044 RpnOpBinaryOperator, 00045 RpnOpUnaryOperator, 00046 RpnOpImmediate, 00047 RpnOpRegister, 00048 RpnOpDereference 00049 } RPN_OP_TYPE; 00050 00051 typedef ULONGLONG (*RPN_BINARY_OPERATOR)(ULONGLONG a, ULONGLONG b); 00052 00053 typedef struct _RPN_OP 00054 { 00055 RPN_OP_TYPE Type; 00056 ULONG CharacterOffset; 00057 union 00058 { 00059 /* RpnOpBinaryOperator */ 00060 RPN_BINARY_OPERATOR BinaryOperator; 00061 /* RpnOpImmediate */ 00062 ULONGLONG Immediate; 00063 /* RpnOpRegister */ 00064 UCHAR Register; 00065 /* RpnOpDereference */ 00066 UCHAR DerefMemorySize; 00067 } 00068 Data; 00069 } 00070 RPN_OP, *PRPN_OP; 00071 00072 typedef struct _RPN_STACK 00073 { 00074 ULONG Size; /* Number of RPN_OPs on Ops */ 00075 ULONG Sp; /* Stack pointer */ 00076 RPN_OP Ops[1]; /* Array of RPN_OPs */ 00077 } 00078 RPN_STACK, *PRPN_STACK; 00079 00080 /* DEFINES *******************************************************************/ 00081 #define stricmp _stricmp 00082 00083 #ifndef RTL_FIELD_SIZE 00084 # define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field)) 00085 #endif 00086 00087 #define CONST_STRCPY(dst, src) \ 00088 do { if ((dst)) { memcpy(dst, src, sizeof(src)); } } while (0); 00089 00090 #define RPN_OP_STACK_SIZE 256 00091 #define RPN_VALUE_STACK_SIZE 256 00092 00093 /* GLOBALS *******************************************************************/ 00094 static struct 00095 { 00096 ULONG Size; 00097 ULONG Sp; 00098 RPN_OP Ops[RPN_OP_STACK_SIZE]; 00099 } 00100 RpnStack = 00101 { 00102 RPN_OP_STACK_SIZE, 00103 0 00104 }; 00105 00106 static const struct 00107 { 00108 PCHAR Name; 00109 UCHAR Offset; 00110 UCHAR Size; 00111 } 00112 RegisterToTrapFrame[] = 00113 { 00114 {"eip", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Eip), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Eip)}, 00115 {"eflags", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.EFlags), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.EFlags)}, 00116 {"eax", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Eax), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Eax)}, 00117 {"ebx", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Ebx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Ebx)}, 00118 {"ecx", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Ecx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Ecx)}, 00119 {"edx", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Edx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Edx)}, 00120 {"esi", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Esi), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Esi)}, 00121 {"edi", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Edi), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Edi)}, 00122 {"esp", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.HardwareEsp), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.HardwareEsp)}, 00123 {"ebp", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Ebp), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Ebp)}, 00124 {"cs", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegCs), 2 }, /* Use only the lower 2 bytes */ 00125 {"ds", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegDs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.SegDs)}, 00126 {"es", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegEs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.SegEs)}, 00127 {"fs", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegFs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.SegFs)}, 00128 {"gs", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegGs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.SegGs)}, 00129 {"ss", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.HardwareSegSs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.HardwareSegSs)}, 00130 {"dr0", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr0), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr0)}, 00131 {"dr1", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr1), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr1)}, 00132 {"dr2", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr2), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr2)}, 00133 {"dr3", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr3), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr3)}, 00134 {"dr6", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr6), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr6)}, 00135 {"dr7", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr7), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr7)}, 00136 {"cr0", FIELD_OFFSET(KDB_KTRAP_FRAME, Cr0), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Cr0)}, 00137 {"cr2", FIELD_OFFSET(KDB_KTRAP_FRAME, Cr2), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Cr2)}, 00138 {"cr3", FIELD_OFFSET(KDB_KTRAP_FRAME, Cr3), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Cr3)}, 00139 {"cr4", FIELD_OFFSET(KDB_KTRAP_FRAME, Cr4), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Cr4)} 00140 }; 00141 static const INT RegisterToTrapFrameCount = sizeof (RegisterToTrapFrame) / sizeof (RegisterToTrapFrame[0]); 00142 00143 /* FUNCTIONS *****************************************************************/ 00144 00145 ULONGLONG 00146 RpnBinaryOperatorAdd( 00147 ULONGLONG a, 00148 ULONGLONG b) 00149 { 00150 return a + b; 00151 } 00152 00153 ULONGLONG 00154 RpnBinaryOperatorSub( 00155 ULONGLONG a, 00156 ULONGLONG b) 00157 { 00158 return a - b; 00159 } 00160 00161 ULONGLONG 00162 RpnBinaryOperatorMul( 00163 ULONGLONG a, 00164 ULONGLONG b) 00165 { 00166 return a * b; 00167 } 00168 00169 ULONGLONG 00170 RpnBinaryOperatorDiv( 00171 ULONGLONG a, 00172 ULONGLONG b) 00173 { 00174 return a / b; 00175 } 00176 00177 ULONGLONG 00178 RpnBinaryOperatorMod( 00179 ULONGLONG a, 00180 ULONGLONG b) 00181 { 00182 return a % b; 00183 } 00184 00185 ULONGLONG 00186 RpnBinaryOperatorEquals( 00187 ULONGLONG a, 00188 ULONGLONG b) 00189 { 00190 return (a == b); 00191 } 00192 00193 ULONGLONG 00194 RpnBinaryOperatorNotEquals( 00195 ULONGLONG a, 00196 ULONGLONG b) 00197 { 00198 return (a != b); 00199 } 00200 00201 ULONGLONG 00202 RpnBinaryOperatorLessThan( 00203 ULONGLONG a, 00204 ULONGLONG b) 00205 { 00206 return (a < b); 00207 } 00208 00209 ULONGLONG 00210 RpnBinaryOperatorLessThanOrEquals( 00211 ULONGLONG a, 00212 ULONGLONG b) 00213 { 00214 return (a <= b); 00215 } 00216 00217 ULONGLONG 00218 RpnBinaryOperatorGreaterThan( 00219 ULONGLONG a, 00220 ULONGLONG b) 00221 { 00222 return (a > b); 00223 } 00224 00225 ULONGLONG 00226 RpnBinaryOperatorGreaterThanOrEquals( 00227 ULONGLONG a, 00228 ULONGLONG b) 00229 { 00230 return (a >= b); 00231 } 00232 00237 VOID 00238 RpnpDumpStack( 00239 IN PRPN_STACK Stack) 00240 { 00241 ULONG ul; 00242 00243 ASSERT(Stack); 00244 DbgPrint("\nStack size: %ld\n", Stack->Sp); 00245 00246 for (ul = 0; ul < Stack->Sp; ul++) 00247 { 00248 PRPN_OP Op = Stack->Ops + ul; 00249 switch (Op->Type) 00250 { 00251 case RpnOpNop: 00252 DbgPrint("NOP,"); 00253 break; 00254 00255 case RpnOpImmediate: 00256 DbgPrint("0x%I64x,", Op->Data.Immediate); 00257 break; 00258 00259 case RpnOpBinaryOperator: 00260 if (Op->Data.BinaryOperator == RpnBinaryOperatorAdd) 00261 DbgPrint("+,"); 00262 else if (Op->Data.BinaryOperator == RpnBinaryOperatorSub) 00263 DbgPrint("-,"); 00264 else if (Op->Data.BinaryOperator == RpnBinaryOperatorMul) 00265 DbgPrint("*,"); 00266 else if (Op->Data.BinaryOperator == RpnBinaryOperatorDiv) 00267 DbgPrint("/,"); 00268 else if (Op->Data.BinaryOperator == RpnBinaryOperatorMod) 00269 DbgPrint("%%,"); 00270 else if (Op->Data.BinaryOperator == RpnBinaryOperatorEquals) 00271 DbgPrint("==,"); 00272 else if (Op->Data.BinaryOperator == RpnBinaryOperatorNotEquals) 00273 DbgPrint("!=,"); 00274 else if (Op->Data.BinaryOperator == RpnBinaryOperatorLessThan) 00275 DbgPrint("<,"); 00276 else if (Op->Data.BinaryOperator == RpnBinaryOperatorLessThanOrEquals) 00277 DbgPrint("<=,"); 00278 else if (Op->Data.BinaryOperator == RpnBinaryOperatorGreaterThan) 00279 DbgPrint(">,"); 00280 else if (Op->Data.BinaryOperator == RpnBinaryOperatorGreaterThanOrEquals) 00281 DbgPrint(">=,"); 00282 else 00283 DbgPrint("UNKNOWN OP,"); 00284 00285 break; 00286 00287 case RpnOpRegister: 00288 DbgPrint("%s,", RegisterToTrapFrame[Op->Data.Register].Name); 00289 break; 00290 00291 case RpnOpDereference: 00292 DbgPrint("[%s],", 00293 (Op->Data.DerefMemorySize == 1) ? ("byte") : 00294 ((Op->Data.DerefMemorySize == 2) ? ("word") : 00295 ((Op->Data.DerefMemorySize == 4) ? ("dword") : ("qword")))); 00296 break; 00297 00298 default: 00299 DbgPrint("\nUnsupported Type: %d\n", Op->Type); 00300 ul = Stack->Sp; 00301 break; 00302 } 00303 } 00304 00305 DbgPrint("\n"); 00306 } 00307 00312 static VOID 00313 RpnpClearStack( 00314 OUT PRPN_STACK Stack) 00315 { 00316 ASSERT(Stack); 00317 Stack->Sp = 0; 00318 } 00319 00325 static BOOLEAN 00326 RpnpPushStack( 00327 IN OUT PRPN_STACK Stack, 00328 IN PRPN_OP Op) 00329 { 00330 ASSERT(Stack); 00331 ASSERT(Op); 00332 00333 if (Stack->Sp >= Stack->Size) 00334 return FALSE; 00335 00336 memcpy(Stack->Ops + Stack->Sp, Op, sizeof (RPN_OP)); 00337 Stack->Sp++; 00338 00339 return TRUE; 00340 } 00341 00350 static BOOLEAN 00351 RpnpPopStack( 00352 IN OUT PRPN_STACK Stack, 00353 OUT PRPN_OP Op OPTIONAL) 00354 { 00355 ASSERT(Stack); 00356 00357 if (Stack->Sp == 0) 00358 return FALSE; 00359 00360 Stack->Sp--; 00361 if (Op) 00362 memcpy(Op, Stack->Ops + Stack->Sp, sizeof (RPN_OP)); 00363 00364 return TRUE; 00365 } 00366 00375 static BOOLEAN 00376 RpnpTopStack( 00377 IN PRPN_STACK Stack, 00378 OUT PRPN_OP Op) 00379 { 00380 ASSERT(Stack); 00381 ASSERT(Op); 00382 00383 if (Stack->Sp == 0) 00384 return FALSE; 00385 00386 memcpy(Op, Stack->Ops + Stack->Sp - 1, sizeof (RPN_OP)); 00387 00388 return TRUE; 00389 } 00390 00409 static BOOLEAN 00410 RpnpParseExpression( 00411 IN PRPN_STACK Stack, 00412 IN PCHAR Expression, 00413 OUT PCHAR *End OPTIONAL, 00414 IN ULONG CharacterOffset, 00415 OUT PLONG ErrOffset OPTIONAL, 00416 OUT PCHAR ErrMsg OPTIONAL) 00417 { 00418 PCHAR p = Expression; 00419 PCHAR pend; 00420 PCHAR Operator = NULL; 00421 LONG OperatorOffset = -1; 00422 RPN_OP RpnOp; 00423 RPN_OP PoppedOperator; 00424 BOOLEAN HavePoppedOperator = FALSE; 00425 RPN_OP ComparativeOp; 00426 BOOLEAN ComparativeOpFilled = FALSE; 00427 BOOLEAN IsComparativeOp; 00428 INT i, i2; 00429 ULONG ul; 00430 UCHAR MemorySize; 00431 CHAR Buffer[16]; 00432 BOOLEAN First; 00433 00434 ASSERT(Stack); 00435 ASSERT(Expression); 00436 00437 First = TRUE; 00438 for (;;) 00439 { 00440 /* Skip whitespace */ 00441 while (isspace(*p)) 00442 { 00443 p++; 00444 CharacterOffset++; 00445 } 00446 00447 /* Check for end of expression */ 00448 if (p[0] == '\0' || p[0] == ')' || p[0] == ']') 00449 break; 00450 00451 if (!First) 00452 { 00453 /* Remember operator */ 00454 Operator = p++; 00455 OperatorOffset = CharacterOffset++; 00456 00457 /* Pop operator (to get the right operator precedence) */ 00458 HavePoppedOperator = FALSE; 00459 if (*Operator == '*' || *Operator == '/' || *Operator == '%') 00460 { 00461 if (RpnpTopStack(Stack, &PoppedOperator) && 00462 PoppedOperator.Type == RpnOpBinaryOperator && 00463 (PoppedOperator.Data.BinaryOperator == RpnBinaryOperatorAdd || 00464 PoppedOperator.Data.BinaryOperator == RpnBinaryOperatorSub)) 00465 { 00466 RpnpPopStack(Stack, NULL); 00467 HavePoppedOperator = TRUE; 00468 } 00469 else if (PoppedOperator.Type == RpnOpNop) 00470 { 00471 RpnpPopStack(Stack, NULL); 00472 /* Discard the NOP - it was only pushed to indicate there was a 00473 * closing brace, so the previous operator shouldn't be popped. 00474 */ 00475 } 00476 } 00477 else if ((Operator[0] == '=' && Operator[1] == '=') || 00478 (Operator[0] == '!' && Operator[1] == '=') || 00479 Operator[0] == '<' || Operator[0] == '>') 00480 { 00481 if (Operator[0] == '=' || Operator[0] == '!' || 00482 (Operator[0] == '<' && Operator[1] == '=') || 00483 (Operator[0] == '>' && Operator[1] == '=')) 00484 { 00485 p++; 00486 CharacterOffset++; 00487 } 00488 #if 0 00489 /* Parse rest of expression */ 00490 if (!RpnpParseExpression(Stack, p + 1, &pend, CharacterOffset + 1, 00491 ErrOffset, ErrMsg)) 00492 { 00493 return FALSE; 00494 } 00495 else if (pend == p + 1) 00496 { 00497 CONST_STRCPY(ErrMsg, "Expression expected"); 00498 00499 if (ErrOffset) 00500 *ErrOffset = CharacterOffset + 1; 00501 00502 return FALSE; 00503 } 00504 00505 goto end_of_expression; /* return */ 00506 #endif 00507 } 00508 else if (Operator[0] != '+' && Operator[0] != '-') 00509 { 00510 CONST_STRCPY(ErrMsg, "Operator expected"); 00511 00512 if (ErrOffset) 00513 *ErrOffset = OperatorOffset; 00514 00515 return FALSE; 00516 } 00517 00518 /* Skip whitespace */ 00519 while (isspace(*p)) 00520 { 00521 p++; 00522 CharacterOffset++; 00523 } 00524 } 00525 00526 /* Get operand */ 00527 MemorySize = sizeof(ULONG_PTR); /* default to pointer size */ 00528 00529 get_operand: 00530 i = strcspn(p, "+-*/%()[]<>!="); 00531 if (i > 0) 00532 { 00533 i2 = i; 00534 00535 /* Copy register name/memory size */ 00536 while (isspace(p[--i2])); 00537 00538 i2 = min(i2 + 1, (INT)sizeof (Buffer) - 1); 00539 strncpy(Buffer, p, i2); 00540 Buffer[i2] = '\0'; 00541 00542 /* Memory size prefix */ 00543 if (p[i] == '[') 00544 { 00545 if (stricmp(Buffer, "byte") == 0) 00546 MemorySize = 1; 00547 else if (stricmp(Buffer, "word") == 0) 00548 MemorySize = 2; 00549 else if (stricmp(Buffer, "dword") == 0) 00550 MemorySize = 4; 00551 else if (stricmp(Buffer, "qword") == 0) 00552 MemorySize = 8; 00553 else 00554 { 00555 CONST_STRCPY(ErrMsg, "Invalid memory size prefix"); 00556 00557 if (ErrOffset) 00558 *ErrOffset = CharacterOffset; 00559 00560 return FALSE; 00561 } 00562 00563 p += i; 00564 CharacterOffset += i; 00565 goto get_operand; 00566 } 00567 00568 /* Try to find register */ 00569 for (i = 0; i < RegisterToTrapFrameCount; i++) 00570 { 00571 if (stricmp(RegisterToTrapFrame[i].Name, Buffer) == 0) 00572 break; 00573 } 00574 00575 if (i < RegisterToTrapFrameCount) 00576 { 00577 RpnOp.Type = RpnOpRegister; 00578 RpnOp.CharacterOffset = CharacterOffset; 00579 RpnOp.Data.Register = i; 00580 i = strlen(RegisterToTrapFrame[i].Name); 00581 CharacterOffset += i; 00582 p += i; 00583 } 00584 else 00585 { 00586 /* Immediate value */ 00587 /* FIXME: Need string to ULONGLONG function */ 00588 ul = strtoul(p, &pend, 0); 00589 if (p != pend) 00590 { 00591 RpnOp.Type = RpnOpImmediate; 00592 RpnOp.CharacterOffset = CharacterOffset; 00593 RpnOp.Data.Immediate = (ULONGLONG)ul; 00594 CharacterOffset += pend - p; 00595 p = pend; 00596 } 00597 else 00598 { 00599 CONST_STRCPY(ErrMsg, "Operand expected"); 00600 00601 if (ErrOffset) 00602 *ErrOffset = CharacterOffset; 00603 00604 return FALSE; 00605 } 00606 } 00607 00608 /* Push operand */ 00609 if (!RpnpPushStack(Stack, &RpnOp)) 00610 { 00611 CONST_STRCPY(ErrMsg, "RPN op stack overflow"); 00612 00613 if (ErrOffset) 00614 *ErrOffset = -1; 00615 00616 return FALSE; 00617 } 00618 } 00619 else if (i == 0) 00620 { 00621 if (p[0] == '(' || p[0] == '[') /* subexpression */ 00622 { 00623 if (!RpnpParseExpression(Stack, p + 1, &pend, CharacterOffset + 1, 00624 ErrOffset, ErrMsg)) 00625 { 00626 return FALSE; 00627 } 00628 else if (pend == p + 1) 00629 { 00630 CONST_STRCPY(ErrMsg, "Expression expected"); 00631 00632 if (ErrOffset) 00633 *ErrOffset = CharacterOffset + 1; 00634 00635 return FALSE; 00636 } 00637 00638 if (p[0] == '[') /* dereference */ 00639 { 00640 ASSERT(MemorySize == 1 || MemorySize == 2 || 00641 MemorySize == 4 || MemorySize == 8); 00642 00643 if (pend[0] != ']') 00644 { 00645 CONST_STRCPY(ErrMsg, "']' expected"); 00646 00647 if (ErrOffset) 00648 *ErrOffset = CharacterOffset + (pend - p); 00649 00650 return FALSE; 00651 } 00652 00653 RpnOp.Type = RpnOpDereference; 00654 RpnOp.CharacterOffset = CharacterOffset; 00655 RpnOp.Data.DerefMemorySize = MemorySize; 00656 00657 if (!RpnpPushStack(Stack, &RpnOp)) 00658 { 00659 CONST_STRCPY(ErrMsg, "RPN op stack overflow"); 00660 00661 if (ErrOffset) 00662 *ErrOffset = -1; 00663 00664 return FALSE; 00665 } 00666 } 00667 else /* p[0] == '(' */ 00668 { 00669 if (pend[0] != ')') 00670 { 00671 CONST_STRCPY(ErrMsg, "')' expected"); 00672 00673 if (ErrOffset) 00674 *ErrOffset = CharacterOffset + (pend - p); 00675 00676 return FALSE; 00677 } 00678 } 00679 00680 /* Push a "nop" to prevent popping of the + operator (which would 00681 * result in (10+10)/2 beeing evaluated as 15) 00682 */ 00683 RpnOp.Type = RpnOpNop; 00684 if (!RpnpPushStack(Stack, &RpnOp)) 00685 { 00686 CONST_STRCPY(ErrMsg, "RPN op stack overflow"); 00687 00688 if (ErrOffset) 00689 *ErrOffset = -1; 00690 00691 return FALSE; 00692 } 00693 00694 /* Skip closing brace/bracket */ 00695 pend++; 00696 00697 CharacterOffset += pend - p; 00698 p = pend; 00699 } 00700 else if (First && p[0] == '-') /* Allow expressions like "- eax" */ 00701 { 00702 RpnOp.Type = RpnOpImmediate; 00703 RpnOp.CharacterOffset = CharacterOffset; 00704 RpnOp.Data.Immediate = 0; 00705 00706 if (!RpnpPushStack(Stack, &RpnOp)) 00707 { 00708 CONST_STRCPY(ErrMsg, "RPN op stack overflow"); 00709 00710 if (ErrOffset) 00711 *ErrOffset = -1; 00712 00713 return FALSE; 00714 } 00715 } 00716 else 00717 { 00718 CONST_STRCPY(ErrMsg, "Operand expected"); 00719 00720 if (ErrOffset) 00721 *ErrOffset = CharacterOffset; 00722 00723 return FALSE; 00724 } 00725 } 00726 else 00727 { 00728 CONST_STRCPY(ErrMsg, "strcspn() failed"); 00729 00730 if (ErrOffset) 00731 *ErrOffset = -1; 00732 00733 return FALSE; 00734 } 00735 00736 if (!First) 00737 { 00738 /* Push operator */ 00739 RpnOp.CharacterOffset = OperatorOffset; 00740 RpnOp.Type = RpnOpBinaryOperator; 00741 IsComparativeOp = FALSE; 00742 00743 switch (*Operator) 00744 { 00745 case '+': 00746 RpnOp.Data.BinaryOperator = RpnBinaryOperatorAdd; 00747 break; 00748 00749 case '-': 00750 RpnOp.Data.BinaryOperator = RpnBinaryOperatorSub; 00751 break; 00752 00753 case '*': 00754 RpnOp.Data.BinaryOperator = RpnBinaryOperatorMul; 00755 break; 00756 00757 case '/': 00758 RpnOp.Data.BinaryOperator = RpnBinaryOperatorDiv; 00759 break; 00760 00761 case '%': 00762 RpnOp.Data.BinaryOperator = RpnBinaryOperatorMod; 00763 break; 00764 00765 case '=': 00766 ASSERT(Operator[1] == '='); 00767 IsComparativeOp = TRUE; 00768 RpnOp.Data.BinaryOperator = RpnBinaryOperatorEquals; 00769 break; 00770 00771 case '!': 00772 ASSERT(Operator[1] == '='); 00773 IsComparativeOp = TRUE; 00774 RpnOp.Data.BinaryOperator = RpnBinaryOperatorNotEquals; 00775 break; 00776 00777 case '<': 00778 IsComparativeOp = TRUE; 00779 00780 if (Operator[1] == '=') 00781 RpnOp.Data.BinaryOperator = RpnBinaryOperatorLessThanOrEquals; 00782 else 00783 RpnOp.Data.BinaryOperator = RpnBinaryOperatorLessThan; 00784 00785 break; 00786 00787 case '>': 00788 IsComparativeOp = TRUE; 00789 00790 if (Operator[1] == '=') 00791 RpnOp.Data.BinaryOperator = RpnBinaryOperatorGreaterThanOrEquals; 00792 else 00793 RpnOp.Data.BinaryOperator = RpnBinaryOperatorGreaterThan; 00794 00795 break; 00796 00797 default: 00798 ASSERT(0); 00799 break; 00800 } 00801 00802 if (IsComparativeOp) 00803 { 00804 if (ComparativeOpFilled && !RpnpPushStack(Stack, &ComparativeOp)) 00805 { 00806 CONST_STRCPY(ErrMsg, "RPN op stack overflow"); 00807 00808 if (ErrOffset) 00809 *ErrOffset = -1; 00810 00811 return FALSE; 00812 } 00813 00814 memcpy(&ComparativeOp, &RpnOp, sizeof(RPN_OP)); 00815 ComparativeOpFilled = TRUE; 00816 } 00817 else if (!RpnpPushStack(Stack, &RpnOp)) 00818 { 00819 CONST_STRCPY(ErrMsg, "RPN op stack overflow"); 00820 00821 if (ErrOffset) 00822 *ErrOffset = -1; 00823 00824 return FALSE; 00825 } 00826 00827 /* Push popped operator */ 00828 if (HavePoppedOperator) 00829 { 00830 if (!RpnpPushStack(Stack, &PoppedOperator)) 00831 { 00832 CONST_STRCPY(ErrMsg, "RPN op stack overflow"); 00833 00834 if (ErrOffset) 00835 *ErrOffset = -1; 00836 00837 return FALSE; 00838 } 00839 } 00840 } 00841 00842 First = FALSE; 00843 } 00844 00845 //end_of_expression: 00846 00847 if (ComparativeOpFilled && !RpnpPushStack(Stack, &ComparativeOp)) 00848 { 00849 CONST_STRCPY(ErrMsg, "RPN op stack overflow"); 00850 00851 if (ErrOffset) 00852 *ErrOffset = -1; 00853 00854 return FALSE; 00855 } 00856 00857 /* Skip whitespace */ 00858 while (isspace(*p)) 00859 { 00860 p++; 00861 CharacterOffset++; 00862 } 00863 00864 if (End) 00865 *End = p; 00866 00867 return TRUE; 00868 } 00869 00881 static BOOLEAN 00882 RpnpEvaluateStack( 00883 IN PRPN_STACK Stack, 00884 IN PKDB_KTRAP_FRAME TrapFrame, 00885 OUT PULONGLONG Result, 00886 OUT PLONG ErrOffset OPTIONAL, 00887 OUT PCHAR ErrMsg OPTIONAL) 00888 { 00889 ULONGLONG ValueStack[RPN_VALUE_STACK_SIZE]; 00890 ULONG ValueStackPointer = 0; 00891 ULONG index; 00892 ULONGLONG ull; 00893 ULONG ul; 00894 USHORT us; 00895 UCHAR uc; 00896 PVOID p; 00897 BOOLEAN Ok; 00898 #ifdef DEBUG_RPN 00899 ULONG ValueStackPointerMax = 0; 00900 #endif 00901 00902 ASSERT(Stack); 00903 ASSERT(TrapFrame); 00904 ASSERT(Result); 00905 00906 for (index = 0; index < Stack->Sp; index++) 00907 { 00908 PRPN_OP Op = Stack->Ops + index; 00909 00910 #ifdef DEBUG_RPN 00911 ValueStackPointerMax = max(ValueStackPointerMax, ValueStackPointer); 00912 #endif 00913 00914 switch (Op->Type) 00915 { 00916 case RpnOpNop: 00917 /* No operation */ 00918 break; 00919 00920 case RpnOpImmediate: 00921 if (ValueStackPointer == RPN_VALUE_STACK_SIZE) 00922 { 00923 CONST_STRCPY(ErrMsg, "Value stack overflow"); 00924 00925 if (ErrOffset) 00926 *ErrOffset = -1; 00927 00928 return FALSE; 00929 } 00930 00931 ValueStack[ValueStackPointer++] = Op->Data.Immediate; 00932 break; 00933 00934 case RpnOpRegister: 00935 if (ValueStackPointer == RPN_VALUE_STACK_SIZE) 00936 { 00937 CONST_STRCPY(ErrMsg, "Value stack overflow"); 00938 00939 if (ErrOffset) 00940 *ErrOffset = -1; 00941 00942 return FALSE; 00943 } 00944 00945 ul = Op->Data.Register; 00946 p = (PVOID)((ULONG_PTR)TrapFrame + RegisterToTrapFrame[ul].Offset); 00947 00948 switch (RegisterToTrapFrame[ul].Size) 00949 { 00950 case 1: ull = (ULONGLONG)(*(PUCHAR)p); break; 00951 case 2: ull = (ULONGLONG)(*(PUSHORT)p); break; 00952 case 4: ull = (ULONGLONG)(*(PULONG)p); break; 00953 case 8: ull = (ULONGLONG)(*(PULONGLONG)p); break; 00954 default: ASSERT(0); return FALSE; break; 00955 } 00956 00957 ValueStack[ValueStackPointer++] = ull; 00958 break; 00959 00960 case RpnOpDereference: 00961 if (ValueStackPointer < 1) 00962 { 00963 CONST_STRCPY(ErrMsg, "Value stack underflow"); 00964 00965 if (ErrOffset) 00966 *ErrOffset = -1; 00967 00968 return FALSE; 00969 } 00970 00971 /* FIXME: Print a warning when address is out of range */ 00972 p = (PVOID)(ULONG_PTR)ValueStack[ValueStackPointer - 1]; 00973 Ok = FALSE; 00974 00975 switch (Op->Data.DerefMemorySize) 00976 { 00977 case 1: 00978 if (NT_SUCCESS(KdbpSafeReadMemory(&uc, p, sizeof (uc)))) 00979 { 00980 Ok = TRUE; 00981 ull = (ULONGLONG)uc; 00982 } 00983 break; 00984 00985 case 2: 00986 if (NT_SUCCESS(KdbpSafeReadMemory(&us, p, sizeof (us)))) 00987 { 00988 Ok = TRUE; 00989 ull = (ULONGLONG)us; 00990 } 00991 break; 00992 00993 case 4: 00994 if (NT_SUCCESS(KdbpSafeReadMemory(&ul, p, sizeof (ul)))) 00995 { 00996 Ok = TRUE; 00997 ull = (ULONGLONG)ul; 00998 } 00999 break; 01000 01001 case 8: 01002 if (NT_SUCCESS(KdbpSafeReadMemory(&ull, p, sizeof (ull)))) 01003 { 01004 Ok = TRUE; 01005 } 01006 break; 01007 01008 default: 01009 ASSERT(0); 01010 return FALSE; 01011 break; 01012 } 01013 01014 if (!Ok) 01015 { 01016 _snprintf(ErrMsg, 128, "Couldn't access memory at 0x%lx", (ULONG)p); 01017 01018 if (ErrOffset) 01019 *ErrOffset = Op->CharacterOffset; 01020 01021 return FALSE; 01022 } 01023 01024 ValueStack[ValueStackPointer - 1] = ull; 01025 break; 01026 01027 case RpnOpBinaryOperator: 01028 if (ValueStackPointer < 2) 01029 { 01030 CONST_STRCPY(ErrMsg, "Value stack underflow"); 01031 01032 if (ErrOffset) 01033 *ErrOffset = -1; 01034 01035 return FALSE; 01036 } 01037 01038 ValueStackPointer--; 01039 ull = ValueStack[ValueStackPointer]; 01040 01041 if (ull == 0 && Op->Data.BinaryOperator == RpnBinaryOperatorDiv) 01042 { 01043 CONST_STRCPY(ErrMsg, "Division by zero"); 01044 01045 if (ErrOffset) 01046 *ErrOffset = Op->CharacterOffset; 01047 01048 return FALSE; 01049 } 01050 01051 ull = Op->Data.BinaryOperator(ValueStack[ValueStackPointer - 1], ull); 01052 ValueStack[ValueStackPointer - 1] = ull; 01053 break; 01054 01055 default: 01056 ASSERT(0); 01057 return FALSE; 01058 } 01059 } 01060 01061 #ifdef DEBUG_RPN 01062 DPRINT1("Max value stack pointer: %d\n", ValueStackPointerMax); 01063 #endif 01064 01065 if (ValueStackPointer != 1) 01066 { 01067 CONST_STRCPY(ErrMsg, "Stack not empty after evaluation"); 01068 01069 if (ErrOffset) 01070 *ErrOffset = -1; 01071 01072 return FALSE; 01073 } 01074 01075 *Result = ValueStack[0]; 01076 return TRUE; 01077 } 01078 01090 BOOLEAN 01091 KdbpRpnEvaluateExpression( 01092 IN PCHAR Expression, 01093 IN PKDB_KTRAP_FRAME TrapFrame, 01094 OUT PULONGLONG Result, 01095 OUT PLONG ErrOffset OPTIONAL, 01096 OUT PCHAR ErrMsg OPTIONAL) 01097 { 01098 PRPN_STACK Stack = (PRPN_STACK)&RpnStack; 01099 01100 ASSERT(Expression); 01101 ASSERT(TrapFrame); 01102 ASSERT(Result); 01103 01104 /* Clear the stack and parse the expression */ 01105 RpnpClearStack(Stack); 01106 if (!RpnpParseExpression(Stack, Expression, NULL, 0, ErrOffset, ErrMsg)) 01107 return FALSE; 01108 01109 #ifdef DEBUG_RPN 01110 RpnpDumpStack(Stack); 01111 #endif 01112 01113 /* Evaluate the stack */ 01114 if (!RpnpEvaluateStack(Stack, TrapFrame, Result, ErrOffset, ErrMsg)) 01115 return FALSE; 01116 01117 return TRUE; 01118 } 01119 01130 PVOID 01131 KdbpRpnParseExpression( 01132 IN PCHAR Expression, 01133 OUT PLONG ErrOffset OPTIONAL, 01134 OUT PCHAR ErrMsg OPTIONAL) 01135 { 01136 LONG Size; 01137 PRPN_STACK Stack = (PRPN_STACK)&RpnStack; 01138 PRPN_STACK NewStack; 01139 01140 ASSERT(Expression); 01141 01142 /* Clear the stack and parse the expression */ 01143 RpnpClearStack(Stack); 01144 if (!RpnpParseExpression(Stack, Expression, NULL, 0, ErrOffset, ErrMsg)) 01145 return FALSE; 01146 01147 #ifdef DEBUG_RPN 01148 RpnpDumpStack(Stack); 01149 #endif 01150 01151 /* Duplicate the stack and return a pointer/handle to it */ 01152 ASSERT(Stack->Sp >= 1); 01153 Size = sizeof (RPN_STACK) + (RTL_FIELD_SIZE(RPN_STACK, Ops[0]) * (Stack->Sp - 1)); 01154 NewStack = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_KDBG); 01155 01156 if (!NewStack) 01157 { 01158 CONST_STRCPY(ErrMsg, "Out of memory"); 01159 01160 if (ErrOffset) 01161 *ErrOffset = -1; 01162 01163 return NULL; 01164 } 01165 01166 memcpy(NewStack, Stack, Size); 01167 NewStack->Size = NewStack->Sp; 01168 01169 return NewStack; 01170 } 01171 01184 BOOLEAN 01185 KdbpRpnEvaluateParsedExpression( 01186 IN PVOID Expression, 01187 IN PKDB_KTRAP_FRAME TrapFrame, 01188 OUT PULONGLONG Result, 01189 OUT PLONG ErrOffset OPTIONAL, 01190 OUT PCHAR ErrMsg OPTIONAL) 01191 { 01192 PRPN_STACK Stack = (PRPN_STACK)Expression; 01193 01194 ASSERT(Expression); 01195 ASSERT(TrapFrame); 01196 ASSERT(Result); 01197 01198 /* Evaluate the stack */ 01199 return RpnpEvaluateStack(Stack, TrapFrame, Result, ErrOffset, ErrMsg); 01200 } 01201 Generated on Sun May 27 2012 04:37:29 for ReactOS by
1.7.6.1
|