|
1 // -*- mode: C++ -*- |
|
2 |
|
3 // Copyright (c) 2010 Google Inc. |
|
4 // All rights reserved. |
|
5 // |
|
6 // Redistribution and use in source and binary forms, with or without |
|
7 // modification, are permitted provided that the following conditions are |
|
8 // met: |
|
9 // |
|
10 // * Redistributions of source code must retain the above copyright |
|
11 // notice, this list of conditions and the following disclaimer. |
|
12 // * Redistributions in binary form must reproduce the above |
|
13 // copyright notice, this list of conditions and the following disclaimer |
|
14 // in the documentation and/or other materials provided with the |
|
15 // distribution. |
|
16 // * Neither the name of Google Inc. nor the names of its |
|
17 // contributors may be used to endorse or promote products derived from |
|
18 // this software without specific prior written permission. |
|
19 // |
|
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
31 |
|
32 // postfix_evaluator.h: Postfix (reverse Polish) notation expression evaluator. |
|
33 // |
|
34 // PostfixEvaluator evaluates an expression, using the expression itself |
|
35 // in postfix (reverse Polish) notation and a dictionary mapping constants |
|
36 // and variables to their values. The evaluator supports standard |
|
37 // arithmetic operations, assignment into variables, and when an optional |
|
38 // MemoryRange is provided, dereferencing. (Any unary key-to-value operation |
|
39 // may be used with a MemoryRange implementation that returns the appropriate |
|
40 // values, but PostfixEvaluator was written with dereferencing in mind.) |
|
41 // |
|
42 // The expression language is simple. Expressions are supplied as strings, |
|
43 // with operands and operators delimited by whitespace. Operands may be |
|
44 // either literal values suitable for ValueType, or constants or variables, |
|
45 // which reference the dictionary. The supported binary operators are + |
|
46 // (addition), - (subtraction), * (multiplication), / (quotient of division), |
|
47 // % (modulus of division), and @ (data alignment). The alignment operator (@) |
|
48 // accepts a value and an alignment size, and produces a result that is a |
|
49 // multiple of the alignment size by truncating the input value. |
|
50 // The unary ^ (dereference) operator is also provided. These operators |
|
51 // allow any operand to be either a literal value, constant, or variable. |
|
52 // Assignment (=) of any type of operand into a variable is also supported. |
|
53 // |
|
54 // The dictionary is provided as a map with string keys. Keys beginning |
|
55 // with the '$' character are treated as variables. All other keys are |
|
56 // treated as constants. Any results must be assigned into variables in the |
|
57 // dictionary. These variables do not need to exist prior to calling |
|
58 // Evaluate, unless used in an expression prior to being assigned to. The |
|
59 // internal stack state is not made available after evaluation, and any |
|
60 // values remaining on the stack are treated as evidence of incomplete |
|
61 // execution and cause the evaluator to indicate failure. |
|
62 // |
|
63 // PostfixEvaluator is intended to support evaluation of "program strings" |
|
64 // obtained from MSVC frame data debugging information in pdb files as |
|
65 // returned by the DIA APIs. |
|
66 // |
|
67 // Author: Mark Mentovai |
|
68 |
|
69 #ifndef PROCESSOR_POSTFIX_EVALUATOR_H__ |
|
70 #define PROCESSOR_POSTFIX_EVALUATOR_H__ |
|
71 |
|
72 |
|
73 #include <map> |
|
74 #include <string> |
|
75 #include <vector> |
|
76 |
|
77 #include "common/using_std_string.h" |
|
78 #include "common/unique_string.h" |
|
79 #include "common/module.h" |
|
80 |
|
81 namespace google_breakpad { |
|
82 |
|
83 using std::map; |
|
84 using std::vector; |
|
85 |
|
86 class MemoryRegion; |
|
87 |
|
88 // A union type for elements in the postfix evaluator's stack. |
|
89 template<typename ValueType> |
|
90 class StackElem { |
|
91 public: |
|
92 StackElem(ValueType val) { isValue = true; u.val = val; } |
|
93 StackElem(const UniqueString* ustr) { isValue = false; u.ustr = ustr; } |
|
94 bool isValue; |
|
95 union { ValueType val; const UniqueString* ustr; } u; |
|
96 }; |
|
97 |
|
98 template<typename ValueType> |
|
99 class PostfixEvaluator { |
|
100 public: |
|
101 typedef UniqueStringMap<ValueType> DictionaryType; |
|
102 typedef UniqueStringMap<bool> DictionaryValidityType; |
|
103 |
|
104 // Create a PostfixEvaluator object that may be used (with Evaluate) on |
|
105 // one or more expressions. PostfixEvaluator does not take ownership of |
|
106 // either argument. |memory| may be NULL, in which case dereferencing |
|
107 // (^) will not be supported. |dictionary| may be NULL, but evaluation |
|
108 // will fail in that case unless set_dictionary is used before calling |
|
109 // Evaluate. |
|
110 PostfixEvaluator(DictionaryType *dictionary, const MemoryRegion *memory) |
|
111 : dictionary_(dictionary), memory_(memory), stack_() {} |
|
112 |
|
113 // Evaluate the expression, starting with an empty stack. The results of |
|
114 // execution will be stored in one (or more) variables in the dictionary. |
|
115 // Returns false if any failures occur during execution, leaving |
|
116 // variables in the dictionary in an indeterminate state. If assigned is |
|
117 // non-NULL, any keys set in the dictionary as a result of evaluation |
|
118 // will also be set to true in assigned, providing a way to determine if |
|
119 // an expression modifies any of its input variables. |
|
120 bool Evaluate(const Module::Expr &expr, DictionaryValidityType *assigned); |
|
121 |
|
122 // Like Evaluate, but expects the expression to denote a value. |
|
123 // If evaluation succeeds and (in the case of a postfix expression) |
|
124 // leaves exactly one value on the stack, pop that value, store it in |
|
125 // *result, and return true. Otherwise, return false. |
|
126 bool EvaluateForValue(const Module::Expr& expression, ValueType* result); |
|
127 |
|
128 DictionaryType* dictionary() const { return dictionary_; } |
|
129 |
|
130 // Reset the dictionary. PostfixEvaluator does not take ownership. |
|
131 void set_dictionary(DictionaryType *dictionary) {dictionary_ = dictionary; } |
|
132 |
|
133 private: |
|
134 // Return values for PopValueOrIdentifier |
|
135 enum PopResult { |
|
136 POP_RESULT_FAIL = 0, |
|
137 POP_RESULT_VALUE, |
|
138 POP_RESULT_IDENTIFIER |
|
139 }; |
|
140 |
|
141 // Retrieves the topmost literal value, constant, or variable from the |
|
142 // stack. Returns POP_RESULT_VALUE if the topmost entry is a literal |
|
143 // value, and sets |value| accordingly. Returns POP_RESULT_IDENTIFIER |
|
144 // if the topmost entry is a constant or variable identifier, and sets |
|
145 // |identifier| accordingly. Returns POP_RESULT_FAIL on failure, such |
|
146 // as when the stack is empty. |
|
147 PopResult PopValueOrIdentifier(ValueType *value, |
|
148 const UniqueString** identifier); |
|
149 |
|
150 // Retrieves the topmost value on the stack. If the topmost entry is |
|
151 // an identifier, the dictionary is queried for the identifier's value. |
|
152 // Returns false on failure, such as when the stack is empty or when |
|
153 // a nonexistent identifier is named. |
|
154 bool PopValue(ValueType *value); |
|
155 |
|
156 // Pushes a UniqueString* on the stack. |
|
157 void PushIdentifier(const UniqueString* ustr); |
|
158 |
|
159 // Retrieves the top two values on the stack, in the style of PopValue. |
|
160 // value2 is popped before value1, so that value1 corresponds to the |
|
161 // entry that was pushed prior to value2. Returns false on failure. |
|
162 bool PopValues(ValueType *value1, ValueType *value2); |
|
163 |
|
164 // Pushes a new value onto the stack. |
|
165 void PushValue(const ValueType &value); |
|
166 |
|
167 // Evaluate expression, updating *assigned if it is non-zero. Return |
|
168 // true if evaluation completes successfully. Do not clear the stack |
|
169 // upon successful evaluation. |
|
170 bool EvaluateInternal(const string &expression, |
|
171 DictionaryValidityType *assigned); |
|
172 |
|
173 bool EvaluateToken(const string &token, |
|
174 const string &expression, |
|
175 DictionaryValidityType *assigned); |
|
176 |
|
177 // The dictionary mapping constant and variable identifiers (strings) to |
|
178 // values. Keys beginning with '$' are treated as variable names, and |
|
179 // PostfixEvaluator is free to create and modify these keys. Weak pointer. |
|
180 DictionaryType *dictionary_; |
|
181 |
|
182 // If non-NULL, the MemoryRegion used for dereference (^) operations. |
|
183 // If NULL, dereferencing is unsupported and will fail. Weak pointer. |
|
184 const MemoryRegion *memory_; |
|
185 |
|
186 // The stack contains state information as execution progresses. Values |
|
187 // are pushed on to it as the expression string is read and as operations |
|
188 // yield values; values are popped when used as operands to operators. |
|
189 vector<StackElem<ValueType> > stack_; |
|
190 }; |
|
191 |
|
192 } // namespace google_breakpad |
|
193 |
|
194 |
|
195 #endif // PROCESSOR_POSTFIX_EVALUATOR_H__ |