1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,205 @@ 1.4 +// Copyright (c) 2010, Google Inc. 1.5 +// All rights reserved. 1.6 +// 1.7 +// Redistribution and use in source and binary forms, with or without 1.8 +// modification, are permitted provided that the following conditions are 1.9 +// met: 1.10 +// 1.11 +// * Redistributions of source code must retain the above copyright 1.12 +// notice, this list of conditions and the following disclaimer. 1.13 +// * Redistributions in binary form must reproduce the above 1.14 +// copyright notice, this list of conditions and the following disclaimer 1.15 +// in the documentation and/or other materials provided with the 1.16 +// distribution. 1.17 +// * Neither the name of Google Inc. nor the names of its 1.18 +// contributors may be used to endorse or promote products derived from 1.19 +// this software without specific prior written permission. 1.20 +// 1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.32 + 1.33 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 1.34 + 1.35 +// cfi_frame_info.cc: Implementation of CFIFrameInfo class. 1.36 +// See cfi_frame_info.h for details. 1.37 + 1.38 +#include "processor/cfi_frame_info.h" 1.39 + 1.40 +#include <string.h> 1.41 + 1.42 +#include <algorithm> 1.43 +#include <sstream> 1.44 + 1.45 +#include "common/scoped_ptr.h" 1.46 +#include "processor/postfix_evaluator-inl.h" 1.47 + 1.48 +namespace google_breakpad { 1.49 + 1.50 +#ifdef _WIN32 1.51 +#define strtok_r strtok_s 1.52 +#endif 1.53 + 1.54 +template<typename V> 1.55 +bool CFIFrameInfo::FindCallerRegs(const RegisterValueMap<V> ®isters, 1.56 + const MemoryRegion &memory, 1.57 + RegisterValueMap<V> *caller_registers) const { 1.58 + // If there are not rules for both .ra and .cfa in effect at this address, 1.59 + // don't use this CFI data for stack walking. 1.60 + if (cfa_rule_.isExprInvalid() || ra_rule_.isExprInvalid()) 1.61 + return false; 1.62 + 1.63 + RegisterValueMap<V> working; 1.64 + PostfixEvaluator<V> evaluator(&working, &memory); 1.65 + 1.66 + caller_registers->clear(); 1.67 + 1.68 + // First, compute the CFA. 1.69 + V cfa; 1.70 + working = registers; 1.71 + if (!evaluator.EvaluateForValue(cfa_rule_, &cfa)) 1.72 + return false; 1.73 + 1.74 + // Then, compute the return address. 1.75 + V ra; 1.76 + working = registers; 1.77 + working.set(ustr__ZDcfa(), cfa); 1.78 + if (!evaluator.EvaluateForValue(ra_rule_, &ra)) 1.79 + return false; 1.80 + 1.81 + // Now, compute values for all the registers register_rules_ mentions. 1.82 + for (RuleMap::const_iterator it = register_rules_.begin(); 1.83 + it != register_rules_.end(); it++) { 1.84 + V value; 1.85 + working = registers; 1.86 + working.set(ustr__ZDcfa(), cfa); 1.87 + if (!evaluator.EvaluateForValue(it->second, &value)) 1.88 + return false; 1.89 + caller_registers->set(it->first, value); 1.90 + } 1.91 + 1.92 + caller_registers->set(ustr__ZDra(), ra); 1.93 + caller_registers->set(ustr__ZDcfa(), cfa); 1.94 + 1.95 + return true; 1.96 +} 1.97 + 1.98 +// Explicit instantiations for 32-bit and 64-bit architectures. 1.99 +template bool CFIFrameInfo::FindCallerRegs<uint32_t>( 1.100 + const RegisterValueMap<uint32_t> ®isters, 1.101 + const MemoryRegion &memory, 1.102 + RegisterValueMap<uint32_t> *caller_registers) const; 1.103 +template bool CFIFrameInfo::FindCallerRegs<uint64_t>( 1.104 + const RegisterValueMap<uint64_t> ®isters, 1.105 + const MemoryRegion &memory, 1.106 + RegisterValueMap<uint64_t> *caller_registers) const; 1.107 + 1.108 +string CFIFrameInfo::Serialize() const { 1.109 + std::ostringstream stream; 1.110 + 1.111 + if (!cfa_rule_.isExprInvalid()) { 1.112 + stream << ".cfa: " << cfa_rule_; 1.113 + } 1.114 + if (!ra_rule_.isExprInvalid()) { 1.115 + if (static_cast<std::streamoff>(stream.tellp()) != 0) 1.116 + stream << " "; 1.117 + stream << ".ra: " << ra_rule_; 1.118 + } 1.119 + 1.120 + // Visit the register rules in alphabetical order. Because 1.121 + // register_rules_ has the elements in some arbitrary order, 1.122 + // get the names out into a vector, sort them, and visit in 1.123 + // sorted order. 1.124 + std::vector<const UniqueString*> rr_names; 1.125 + for (RuleMap::const_iterator iter = register_rules_.begin(); 1.126 + iter != register_rules_.end(); 1.127 + ++iter) { 1.128 + rr_names.push_back(iter->first); 1.129 + } 1.130 + 1.131 + std::sort(rr_names.begin(), rr_names.end(), LessThan_UniqueString); 1.132 + 1.133 + // Now visit the register rules in alphabetical order. 1.134 + for (std::vector<const UniqueString*>::const_iterator name = rr_names.begin(); 1.135 + name != rr_names.end(); 1.136 + ++name) { 1.137 + const UniqueString* nm = *name; 1.138 + Module::Expr rule = register_rules_.find(nm)->second; 1.139 + if (static_cast<std::streamoff>(stream.tellp()) != 0) 1.140 + stream << " "; 1.141 + stream << FromUniqueString(nm) << ": " << rule; 1.142 + } 1.143 + 1.144 + return stream.str(); 1.145 +} 1.146 + 1.147 +bool CFIRuleParser::Parse(const string &rule_set) { 1.148 + size_t rule_set_len = rule_set.size(); 1.149 + scoped_array<char> working_copy(new char[rule_set_len + 1]); 1.150 + memcpy(working_copy.get(), rule_set.data(), rule_set_len); 1.151 + working_copy[rule_set_len] = '\0'; 1.152 + 1.153 + name_ = ustr__empty(); 1.154 + expression_.clear(); 1.155 + 1.156 + char *cursor; 1.157 + static const char token_breaks[] = " \t\r\n"; 1.158 + char *token = strtok_r(working_copy.get(), token_breaks, &cursor); 1.159 + 1.160 + for (;;) { 1.161 + // End of rule set? 1.162 + if (!token) return Report(); 1.163 + 1.164 + // Register/pseudoregister name? 1.165 + size_t token_len = strlen(token); 1.166 + if (token_len >= 1 && token[token_len - 1] == ':') { 1.167 + // Names can't be empty. 1.168 + if (token_len < 2) return false; 1.169 + // If there is any pending content, report it. 1.170 + if (name_ != ustr__empty() || !expression_.empty()) { 1.171 + if (!Report()) return false; 1.172 + } 1.173 + name_ = ToUniqueString_n(token, token_len - 1); 1.174 + expression_.clear(); 1.175 + } else { 1.176 + // Another expression component. 1.177 + assert(token_len > 0); // strtok_r guarantees this, I think. 1.178 + if (!expression_.empty()) 1.179 + expression_ += ' '; 1.180 + expression_ += token; 1.181 + } 1.182 + token = strtok_r(NULL, token_breaks, &cursor); 1.183 + } 1.184 +} 1.185 + 1.186 +bool CFIRuleParser::Report() { 1.187 + if (name_ == ustr__empty() || expression_.empty()) return false; 1.188 + if (name_ == ustr__ZDcfa()) handler_->CFARule(expression_); 1.189 + else if (name_ == ustr__ZDra()) handler_->RARule(expression_); 1.190 + else handler_->RegisterRule(name_, expression_); 1.191 + return true; 1.192 +} 1.193 + 1.194 +void CFIFrameInfoParseHandler::CFARule(const string &expression) { 1.195 + // 'expression' is a postfix expression string. 1.196 + frame_info_->SetCFARule(Module::Expr(expression)); 1.197 +} 1.198 + 1.199 +void CFIFrameInfoParseHandler::RARule(const string &expression) { 1.200 + frame_info_->SetRARule(Module::Expr(expression)); 1.201 +} 1.202 + 1.203 +void CFIFrameInfoParseHandler::RegisterRule(const UniqueString* name, 1.204 + const string &expression) { 1.205 + frame_info_->SetRegisterRule(name, Module::Expr(expression)); 1.206 +} 1.207 + 1.208 +} // namespace google_breakpad