diff options
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h')
-rw-r--r-- | toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h | 363 |
1 files changed, 0 insertions, 363 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h deleted file mode 100644 index d7dbeac20..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h +++ /dev/null @@ -1,363 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// postfix_evaluator-inl.h: Postfix (reverse Polish) notation expression -// evaluator. -// -// Documentation in postfix_evaluator.h. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_POSTFIX_EVALUATOR_INL_H__ -#define PROCESSOR_POSTFIX_EVALUATOR_INL_H__ - -#include "processor/postfix_evaluator.h" - -#include <stdio.h> - -#include <sstream> - -#include "google_breakpad/processor/memory_region.h" -#include "processor/logging.h" - -namespace google_breakpad { - -using std::istringstream; -using std::ostringstream; - - -// A small class used in Evaluate to make sure to clean up the stack -// before returning failure. -class AutoStackClearer { - public: - explicit AutoStackClearer(vector<string> *stack) : stack_(stack) {} - ~AutoStackClearer() { stack_->clear(); } - - private: - vector<string> *stack_; -}; - - -template<typename ValueType> -bool PostfixEvaluator<ValueType>::EvaluateToken( - const string &token, - const string &expression, - DictionaryValidityType *assigned) { - // There are enough binary operations that do exactly the same thing - // (other than the specific operation, of course) that it makes sense - // to share as much code as possible. - enum BinaryOperation { - BINARY_OP_NONE = 0, - BINARY_OP_ADD, - BINARY_OP_SUBTRACT, - BINARY_OP_MULTIPLY, - BINARY_OP_DIVIDE_QUOTIENT, - BINARY_OP_DIVIDE_MODULUS, - BINARY_OP_ALIGN - }; - - BinaryOperation operation = BINARY_OP_NONE; - if (token == "+") - operation = BINARY_OP_ADD; - else if (token == "-") - operation = BINARY_OP_SUBTRACT; - else if (token == "*") - operation = BINARY_OP_MULTIPLY; - else if (token == "/") - operation = BINARY_OP_DIVIDE_QUOTIENT; - else if (token == "%") - operation = BINARY_OP_DIVIDE_MODULUS; - else if (token == "@") - operation = BINARY_OP_ALIGN; - - if (operation != BINARY_OP_NONE) { - // Get the operands. - ValueType operand1 = ValueType(); - ValueType operand2 = ValueType(); - if (!PopValues(&operand1, &operand2)) { - BPLOG(ERROR) << "Could not PopValues to get two values for binary " - "operation " << token << ": " << expression; - return false; - } - - // Perform the operation. - ValueType result; - switch (operation) { - case BINARY_OP_ADD: - result = operand1 + operand2; - break; - case BINARY_OP_SUBTRACT: - result = operand1 - operand2; - break; - case BINARY_OP_MULTIPLY: - result = operand1 * operand2; - break; - case BINARY_OP_DIVIDE_QUOTIENT: - result = operand1 / operand2; - break; - case BINARY_OP_DIVIDE_MODULUS: - result = operand1 % operand2; - break; - case BINARY_OP_ALIGN: - result = - operand1 & (static_cast<ValueType>(-1) ^ (operand2 - 1)); - break; - case BINARY_OP_NONE: - // This will not happen, but compilers will want a default or - // BINARY_OP_NONE case. - BPLOG(ERROR) << "Not reached!"; - return false; - break; - } - - // Save the result. - PushValue(result); - } else if (token == "^") { - // ^ for unary dereference. Can't dereference without memory. - if (!memory_) { - BPLOG(ERROR) << "Attempt to dereference without memory: " << - expression; - return false; - } - - ValueType address; - if (!PopValue(&address)) { - BPLOG(ERROR) << "Could not PopValue to get value to derefence: " << - expression; - return false; - } - - ValueType value; - if (!memory_->GetMemoryAtAddress(address, &value)) { - BPLOG(ERROR) << "Could not dereference memory at address " << - HexString(address) << ": " << expression; - return false; - } - - PushValue(value); - } else if (token == "=") { - // = for assignment. - ValueType value; - if (!PopValue(&value)) { - BPLOG(INFO) << "Could not PopValue to get value to assign: " << - expression; - return false; - } - - // Assignment is only meaningful when assigning into an identifier. - // The identifier must name a variable, not a constant. Variables - // begin with '$'. - string identifier; - if (PopValueOrIdentifier(NULL, &identifier) != POP_RESULT_IDENTIFIER) { - BPLOG(ERROR) << "PopValueOrIdentifier returned a value, but an " - "identifier is needed to assign " << - HexString(value) << ": " << expression; - return false; - } - if (identifier.empty() || identifier[0] != '$') { - BPLOG(ERROR) << "Can't assign " << HexString(value) << " to " << - identifier << ": " << expression; - return false; - } - - (*dictionary_)[identifier] = value; - if (assigned) - (*assigned)[identifier] = true; - } else { - // The token is not an operator, it's a literal value or an identifier. - // Push it onto the stack as-is. Use push_back instead of PushValue - // because PushValue pushes ValueType as a string, but token is already - // a string. - stack_.push_back(token); - } - return true; -} - -template<typename ValueType> -bool PostfixEvaluator<ValueType>::EvaluateInternal( - const string &expression, - DictionaryValidityType *assigned) { - // Tokenize, splitting on whitespace. - istringstream stream(expression); - string token; - while (stream >> token) { - // Normally, tokens are whitespace-separated, but occasionally, the - // assignment operator is smashed up against the next token, i.e. - // $T0 $ebp 128 + =$eip $T0 4 + ^ =$ebp $T0 ^ = - // This has been observed in program strings produced by MSVS 2010 in LTO - // mode. - if (token.size() > 1 && token[0] == '=') { - if (!EvaluateToken("=", expression, assigned)) { - return false; - } - - if (!EvaluateToken(token.substr(1), expression, assigned)) { - return false; - } - } else if (!EvaluateToken(token, expression, assigned)) { - return false; - } - } - - return true; -} - -template<typename ValueType> -bool PostfixEvaluator<ValueType>::Evaluate(const string &expression, - DictionaryValidityType *assigned) { - // Ensure that the stack is cleared before returning. - AutoStackClearer clearer(&stack_); - - if (!EvaluateInternal(expression, assigned)) - return false; - - // If there's anything left on the stack, it indicates incomplete execution. - // This is a failure case. If the stack is empty, evalution was complete - // and successful. - if (stack_.empty()) - return true; - - BPLOG(ERROR) << "Incomplete execution: " << expression; - return false; -} - -template<typename ValueType> -bool PostfixEvaluator<ValueType>::EvaluateForValue(const string &expression, - ValueType *result) { - // Ensure that the stack is cleared before returning. - AutoStackClearer clearer(&stack_); - - if (!EvaluateInternal(expression, NULL)) - return false; - - // A successful execution should leave exactly one value on the stack. - if (stack_.size() != 1) { - BPLOG(ERROR) << "Expression yielded bad number of results: " - << "'" << expression << "'"; - return false; - } - - return PopValue(result); -} - -template<typename ValueType> -typename PostfixEvaluator<ValueType>::PopResult -PostfixEvaluator<ValueType>::PopValueOrIdentifier( - ValueType *value, string *identifier) { - // There needs to be at least one element on the stack to pop. - if (!stack_.size()) - return POP_RESULT_FAIL; - - string token = stack_.back(); - stack_.pop_back(); - - // First, try to treat the value as a literal. Literals may have leading - // '-' sign, and the entire remaining string must be parseable as - // ValueType. If this isn't possible, it can't be a literal, so treat it - // as an identifier instead. - // - // Some versions of the libstdc++, the GNU standard C++ library, have - // stream extractors for unsigned integer values that permit a leading - // '-' sign (6.0.13); others do not (6.0.9). Since we require it, we - // handle it explicitly here. - istringstream token_stream(token); - ValueType literal = ValueType(); - bool negative; - if (token_stream.peek() == '-') { - negative = true; - token_stream.get(); - } else { - negative = false; - } - if (token_stream >> literal && token_stream.peek() == EOF) { - if (value) { - *value = literal; - } - if (negative) - *value = -*value; - return POP_RESULT_VALUE; - } else { - if (identifier) { - *identifier = token; - } - return POP_RESULT_IDENTIFIER; - } -} - - -template<typename ValueType> -bool PostfixEvaluator<ValueType>::PopValue(ValueType *value) { - ValueType literal = ValueType(); - string token; - PopResult result; - if ((result = PopValueOrIdentifier(&literal, &token)) == POP_RESULT_FAIL) { - return false; - } else if (result == POP_RESULT_VALUE) { - // This is the easy case. - *value = literal; - } else { // result == POP_RESULT_IDENTIFIER - // There was an identifier at the top of the stack. Resolve it to a - // value by looking it up in the dictionary. - typename DictionaryType::const_iterator iterator = - dictionary_->find(token); - if (iterator == dictionary_->end()) { - // The identifier wasn't found in the dictionary. Don't imply any - // default value, just fail. - BPLOG(INFO) << "Identifier " << token << " not in dictionary"; - return false; - } - - *value = iterator->second; - } - - return true; -} - - -template<typename ValueType> -bool PostfixEvaluator<ValueType>::PopValues(ValueType *value1, - ValueType *value2) { - return PopValue(value2) && PopValue(value1); -} - - -template<typename ValueType> -void PostfixEvaluator<ValueType>::PushValue(const ValueType &value) { - ostringstream token_stream; - token_stream << value; - stack_.push_back(token_stream.str()); -} - - -} // namespace google_breakpad - - -#endif // PROCESSOR_POSTFIX_EVALUATOR_INL_H__ |