//---------------------------------------------------------------------------- // // Expression evaluation. // // Copyright (C) Microsoft Corporation, 1997-2002. // //---------------------------------------------------------------------------- #ifndef _EXPR_H_ #define _EXPR_H_ #include #define DEFAULT_RANGE_LIMIT 0x100000 // Evaluator indices are in dbgeng.h:DEBUG_EXPR_*. #define EVAL_COUNT 2 class EvalExpression; extern ULONG g_EvalSyntax; extern EvalExpression* g_EvalReleaseChain; extern TypedData g_LastEvalResult; EvalExpression* GetEvaluator(ULONG Syntax, BOOL RetFail); #define GetCurEvaluator() GetEvaluator(g_EvalSyntax, FALSE) void ReleaseEvaluator(EvalExpression* Eval); void ReleaseEvaluators(void); HRESULT GetEvaluatorByName(PCSTR AbbrevName, BOOL RetFail, EvalExpression** EvalRet); CHAR PeekChar(void); BOOL GetRange(PADDR Addr, PULONG64 Value, ULONG Size, ULONG SegReg, ULONG SizeLimit); ULONG64 EvalStringNumAndCatch(PCSTR String); ULONG64 GetExpression(void); ULONG64 GetExpressionDesc(PCSTR Desc); ULONG64 GetTermExpression(PCSTR Desc); void GetAddrExpression(ULONG SegReg, PADDR Addr); // The recursive descent parsers can take a considerable amount // of stack for just a simple expression due to the many layers // of calls on the stack. As most of the layers have trivial // frames they respond well to optimization and fastcall to // avoid using stack. However, we don't currently build // optimized binaries so this is useless and just makes the // code harder to understand. #if 1 #define EECALL #else #define EECALL FASTCALL #endif //---------------------------------------------------------------------------- // // TypedDataStackAllocator. // // Specialized allocator for getting TypedData during evaluation. // This is much more space-efficient than using the stack as // many layers of the recursive decent will not need results of // their own. // // Allocator throws NOMEMORY when out of memory. // //---------------------------------------------------------------------------- class TypedDataStackAllocator : public FixedSizeStackAllocator { public: TypedDataStackAllocator(EvalExpression* Eval) : FixedSizeStackAllocator(sizeof(TypedData), 64, TRUE) { m_Eval = Eval; } private: virtual void* RawAlloc(ULONG Bytes); EvalExpression* m_Eval; }; //---------------------------------------------------------------------------- // // EvalExpression. // //---------------------------------------------------------------------------- enum EVAL_RESULT_KIND { ERES_UNKNOWN, ERES_SYMBOL, ERES_TYPE, ERES_EXPRESSION, }; #define EXPRF_DEFAULT 0x000000000 // In the MASM evaluator this indicates whether to evaluate // symbols as their values or their addresses. No effect // on the C++ evaluator. #define EXPRF_PREFER_SYMBOL_VALUES 0x000000001 // Evaluate just a single term. Currently the term // is always bracketed by '[' and ']'. #define EXPRF_SINGLE_TERM 0x000000002 #define EvalCheck(Expr) \ if (m_Err = (Expr)) EvalError(m_Err); else 0 class EvalExpression { public: EvalExpression(ULONG Syntax, PCSTR FullName, PCSTR AbbrevName); virtual ~EvalExpression(void); virtual PCSTR Evaluate(PCSTR Expr, PCSTR Desc, ULONG Flags, TypedData* Result) = 0; virtual PCSTR EvaluateAddr(PCSTR Expr, PCSTR Desc, ULONG SegReg, PADDR Addr) = 0; PCSTR EvalString(PCSTR String, TypedData* Result) { return Evaluate(String, NULL, EXPRF_DEFAULT, Result); } void EvalCurrent(TypedData* Result); void EvalCurAddrDesc(ULONG SegReg, PCSTR Desc, PADDR Addr); void EvalCurAddr(ULONG SegReg, PADDR Addr) { EvalCurAddrDesc(SegReg, NULL, Addr); } ULONG64 EvalStringNum(PCSTR String); ULONG64 EvalCurNumDesc(PCSTR Desc); ULONG64 EvalCurNum(void) { return EvalCurNumDesc(NULL); } ULONG64 EvalCurTermNumDesc(PCSTR Desc); void DECLSPEC_NORETURN EvalErrorDesc(ULONG Error, PCSTR Desc); void DECLSPEC_NORETURN EvalError(ULONG Error) { EvalErrorDesc(Error, NULL); } void Reset(void); void InheritStart(EvalExpression* Parent); void InheritEnd(EvalExpression* Parent); ULONG m_Syntax; PCSTR m_FullName; PCSTR m_AbbrevName; ULONG m_ParseOnly; ULONG m_AllowUnresolvedSymbols; ULONG m_NumUnresolvedSymbols; EvalExpression* m_ReleaseChain; BOOL m_ChainTop; protected: void StartLexer(PCSTR Expr); void Start(PCSTR Expr, PCSTR Desc, ULONG Flags); void End(TypedData* Result); void StartLexeme(void) { m_LexemeStart = m_LexemeRestart; m_LexemeChar = m_LexemeStart; *m_LexemeChar = 0; } void AddLexeme(char Ch); TypedData* NewResult(void) { return (TypedData*)m_ResultAlloc.Alloc(); } void DelResult(TypedData* Result) { m_ResultAlloc.Free(Result); } PCSTR m_ExprDesc; ULONG m_Flags; ProcessInfo* m_Process; MachineInfo* m_Machine; PCSTR m_Lex; char m_LexemeBuffer[1024]; PSTR m_LexemeRestart; PSTR m_LexemeStart; PSTR m_LexemeChar; PCSTR m_LexemeSourceStart; TypedData m_TokenValue; BOOL m_AllowUnaryOp; ULONG m_PtrSize; TypedDataStackAllocator m_ResultAlloc; // Temporary local storage to avoid using space // for short-lived data. TypedData m_Tmp; ULONG m_Err; }; //---------------------------------------------------------------------------- // // MasmEvalExpression. // //---------------------------------------------------------------------------- class MasmEvalExpression : public EvalExpression { public: MasmEvalExpression(void); virtual ~MasmEvalExpression(void); virtual PCSTR Evaluate(PCSTR Expr, PCSTR Desc, ULONG Flags, TypedData* Result); virtual PCSTR EvaluateAddr(PCSTR Expr, PCSTR Desc, ULONG SegReg, PADDR Addr); private: void ForceAddrExpression(ULONG SegReg, PADDR Address, ULONG64 Value); LONG64 GetTypedExpression(void); BOOL GetSymValue(PSTR Symbol, PULONG64 Value); char Peek(void); ULONG64 GetCommonExpression(void); LONG64 StartExpr(void); LONG64 GetLRterm(void); LONG64 GetLterm(void); LONG64 GetShiftTerm(void); LONG64 GetAterm(void); LONG64 GetMterm(void); LONG64 GetTerm(void); ULONG GetRegToken(PCHAR Str, PULONG64 Value); ULONG PeekToken(PLONG64 Value); void AcceptToken(void); ULONG GetTokenSym(PLONG64 Value); ULONG EvalSymbol(PSTR Name, PULONG64 Value); ULONG NextToken(PLONG64 Value); ULONG m_SavedClass; LONG64 m_SavedValue; PCSTR m_SavedCommand; BOOL m_ForcePositiveNumber; USHORT m_AddrExprType; ADDR m_TempAddr; // Syms in a expression evaluate to values rather than address BOOL m_TypedExpr; }; //---------------------------------------------------------------------------- // // CppEvalExpression. // //---------------------------------------------------------------------------- #define CPP_TOKEN_MULTI 256 #define CPP_KEYWORD_FIRST CppTokenSizeof #define CPP_KEYWORD_LAST CppTokenTypeid enum CppToken { CppTokenError = 0, // Single-character tokens use the character value. CppTokenPeriod = '.', CppTokenQuestionMark = '?', CppTokenColon = ':', CppTokenComma = ',', CppTokenOpenParen = '(', CppTokenCloseParen = ')', CppTokenOpenBracket = '[', CppTokenCloseBracket = ']', CppTokenOpenAngle = '<', CppTokenCloseAngle = '>', CppTokenEof = CPP_TOKEN_MULTI, // Literals. CppTokenIdentifier, CppTokenInteger, CppTokenFloat, CppTokenCharString, CppTokenChar, CppTokenWcharString, CppTokenWchar, CppTokenDebugRegister, CppTokenModule, CppTokenSwitchEvalExpression, CppTokenPreprocFunction, // Relational operators. CppTokenEqual, CppTokenNotEqual, CppTokenLessEqual, CppTokenGreaterEqual, // Logical operators. CppTokenLogicalAnd, CppTokenLogicalOr, // Unary operators. CppTokenUnaryPlus, CppTokenUnaryMinus, // Shifts. CppTokenLeftShift, CppTokenRightShift, // Addresses. CppTokenAddressOf, CppTokenDereference, CppTokenPointerMember, CppTokenClassDereference, CppTokenClassPointerMember, // Assignment operators. CppTokenDivideAssign, CppTokenMultiplyAssign, CppTokenModuloAssign, CppTokenAddAssign, CppTokenSubtractAssign, CppTokenLeftShiftAssign, CppTokenRightShiftAssign, CppTokenAndAssign, CppTokenOrAssign, CppTokenExclusiveOrAssign, // Increments and decrements. CppTokenPreIncrement, CppTokenPreDecrement, CppTokenPostIncrement, CppTokenPostDecrement, // Namespaces. CppTokenNameQualifier, CppTokenDestructor, // Keywords. CppTokenSizeof, CppTokenThis, CppTokenOperator, CppTokenNew, CppTokenDelete, // Keep type keywords together for easy identification. CppTokenConst, CppTokenStruct, CppTokenClass, CppTokenUnion, CppTokenEnum, CppTokenVolatile, CppTokenSigned, CppTokenUnsigned, CppTokenDynamicCast, CppTokenStaticCast, CppTokenConstCast, CppTokenReinterpretCast, CppTokenTypeid, CppTokenCount }; class CppEvalExpression : public EvalExpression { public: CppEvalExpression(void); virtual ~CppEvalExpression(void); PCSTR TokenImage(CppToken Token); CppToken Lex(void); virtual PCSTR Evaluate(PCSTR Expr, PCSTR Desc, ULONG Flags, TypedData* Result); virtual PCSTR EvaluateAddr(PCSTR Expr, PCSTR Desc, ULONG SegReg, PADDR Addr); private: char GetStringChar(PBOOL Escaped); void FinishFloat(LONG64 IntPart, int Sign); CppToken ReadNumber(int Sign); void NextToken(void); void Match(CppToken Token); void Accept(void) { Match(m_Token); } void EECALL Expression(TypedData* Result); void EECALL Assignment(TypedData* Result); void EECALL Conditional(TypedData* Result); void EECALL LogicalOr(TypedData* Result); void EECALL LogicalAnd(TypedData* Result); void EECALL BitwiseOr(TypedData* Result); void EECALL BitwiseXor(TypedData* Result); void EECALL BitwiseAnd(TypedData* Result); void EECALL Equality(TypedData* Result); void EECALL Relational(TypedData* Result); void EECALL Shift(TypedData* Result); void EECALL Additive(TypedData* Result); void EECALL Multiplicative(TypedData* Result); void EECALL ClassMemberRef(TypedData* Result); void EECALL Cast(TypedData* Result); void EECALL Unary(TypedData* Result); void EECALL Postfix(TypedData* Result); void EECALL Term(TypedData* Result); EVAL_RESULT_KIND EECALL TryTypeName(TypedData* Result); EVAL_RESULT_KIND EECALL CollectTypeOrSymbolName(TypedData* Result); EVAL_RESULT_KIND EECALL CollectTemplateName(void); void EECALL CollectOperatorName(void); void EECALL UdtMember(TypedData* Result); void EECALL PreprocFunction(TypedData* Result); BOOL IsTypeKeyword(CppToken Token) { return Token >= CppTokenConst && Token <= CppTokenUnsigned; } BOOL IsAssignOp(CppToken Token) { return Token == '=' || (Token >= CppTokenDivideAssign && Token <= CppTokenExclusiveOrAssign); } TypedDataAccess CurrentAccess(void) { if (m_ParseOnly > 0) { return TDACC_NONE; } else if (m_PreprocEval) { return TDACC_ATTEMPT; } else { return TDACC_REQUIRE; } } static char s_EscapeChars[]; static char s_EscapeCharValues[]; static PCSTR s_MultiTokens[]; CppToken m_Token; ULONG m_SwitchEvalSyntax; BOOL m_PreprocEval; }; #endif // #ifndef _EXPR_H_