1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,276 @@ 1.4 +// -*- mode: C++ -*- 1.5 + 1.6 +// Copyright (c) 2010, Google Inc. 1.7 +// All rights reserved. 1.8 +// 1.9 +// Redistribution and use in source and binary forms, with or without 1.10 +// modification, are permitted provided that the following conditions are 1.11 +// met: 1.12 +// 1.13 +// * Redistributions of source code must retain the above copyright 1.14 +// notice, this list of conditions and the following disclaimer. 1.15 +// * Redistributions in binary form must reproduce the above 1.16 +// copyright notice, this list of conditions and the following disclaimer 1.17 +// in the documentation and/or other materials provided with the 1.18 +// distribution. 1.19 +// * Neither the name of Google Inc. nor the names of its 1.20 +// contributors may be used to endorse or promote products derived from 1.21 +// this software without specific prior written permission. 1.22 +// 1.23 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.24 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.25 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.26 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.27 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.28 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.29 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.30 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.31 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.32 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.33 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.34 + 1.35 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 1.36 + 1.37 +// cfi_frame_info.h: Define the CFIFrameInfo class, which holds the 1.38 +// set of 'STACK CFI'-derived register recovery rules that apply at a 1.39 +// given instruction. 1.40 + 1.41 +#ifndef PROCESSOR_CFI_FRAME_INFO_H_ 1.42 +#define PROCESSOR_CFI_FRAME_INFO_H_ 1.43 + 1.44 +#include <map> 1.45 +#include <string> 1.46 + 1.47 +#include "common/using_std_string.h" 1.48 +#include "common/unique_string.h" 1.49 +#include "google_breakpad/common/breakpad_types.h" 1.50 +#include "common/module.h" 1.51 + 1.52 +namespace google_breakpad { 1.53 + 1.54 +using std::map; 1.55 + 1.56 +class MemoryRegion; 1.57 + 1.58 +// A set of rules for recovering the calling frame's registers' 1.59 +// values, when the PC is at a given address in the current frame's 1.60 +// function. See the description of 'STACK CFI' records at: 1.61 +// 1.62 +// http://code.google.com/p/google-breakpad/wiki/SymbolFiles 1.63 +// 1.64 +// To prepare an instance of CFIFrameInfo for use at a given 1.65 +// instruction, first populate it with the rules from the 'STACK CFI 1.66 +// INIT' record that covers that instruction, and then apply the 1.67 +// changes given by the 'STACK CFI' records up to our instruction's 1.68 +// address. Then, use the FindCallerRegs member function to apply the 1.69 +// rules to the callee frame's register values, yielding the caller 1.70 +// frame's register values. 1.71 +class CFIFrameInfo { 1.72 + public: 1.73 + // A map from register names onto values. 1.74 + template<typename ValueType> class RegisterValueMap: 1.75 + public UniqueStringMap<ValueType> { }; 1.76 + 1.77 + // Set the expression for computing a call frame address, return 1.78 + // address, or register's value. At least the CFA rule and the RA 1.79 + // rule must be set before calling FindCallerRegs. 1.80 + void SetCFARule(const Module::Expr& rule) { cfa_rule_ = rule; } 1.81 + void SetRARule(const Module::Expr& rule) { ra_rule_ = rule; } 1.82 + void SetRegisterRule(const UniqueString* register_name, 1.83 + const Module::Expr& rule) { 1.84 + register_rules_[register_name] = rule; 1.85 + } 1.86 + 1.87 + // Compute the values of the calling frame's registers, according to 1.88 + // this rule set. Use ValueType in expression evaluation; this 1.89 + // should be uint32_t on machines with 32-bit addresses, or 1.90 + // uint64_t on machines with 64-bit addresses. 1.91 + // 1.92 + // Return true on success, false otherwise. 1.93 + // 1.94 + // MEMORY provides access to the contents of the stack. REGISTERS is 1.95 + // a dictionary mapping the names of registers whose values are 1.96 + // known in the current frame to their values. CALLER_REGISTERS is 1.97 + // populated with the values of the recoverable registers in the 1.98 + // frame that called the current frame. 1.99 + // 1.100 + // In addition, CALLER_REGISTERS[".ra"] will be the return address, 1.101 + // and CALLER_REGISTERS[".cfa"] will be the call frame address. 1.102 + // These may be helpful in computing the caller's PC and stack 1.103 + // pointer, if their values are not explicitly specified. 1.104 + template<typename ValueType> 1.105 + bool FindCallerRegs(const RegisterValueMap<ValueType> ®isters, 1.106 + const MemoryRegion &memory, 1.107 + RegisterValueMap<ValueType> *caller_registers) const; 1.108 + 1.109 + // Serialize the rules in this object into a string in the format 1.110 + // of STACK CFI records. 1.111 + string Serialize() const; 1.112 + 1.113 + private: 1.114 + 1.115 + // A map from register names onto evaluation rules. 1.116 + typedef map<const UniqueString*, Module::Expr> RuleMap; 1.117 + 1.118 + // An expression for computing the current frame's CFA (call 1.119 + // frame address). The CFA is a reference address for the frame that 1.120 + // remains unchanged throughout the frame's lifetime. You should 1.121 + // evaluate this expression with a dictionary initially populated 1.122 + // with the values of the current frame's known registers. 1.123 + Module::Expr cfa_rule_; 1.124 + 1.125 + // The following expressions should be evaluated with a dictionary 1.126 + // initially populated with the values of the current frame's known 1.127 + // registers, and with ".cfa" set to the result of evaluating the 1.128 + // cfa_rule expression, above. 1.129 + 1.130 + // An expression for computing the current frame's return address. 1.131 + Module::Expr ra_rule_; 1.132 + 1.133 + // For a register named REG, rules[REG] is a postfix expression 1.134 + // which leaves the value of REG in the calling frame on the top of 1.135 + // the stack. You should evaluate this expression 1.136 + RuleMap register_rules_; 1.137 +}; 1.138 + 1.139 +// A parser for STACK CFI-style rule sets. 1.140 +// This may seem bureaucratic: there's no legitimate run-time reason 1.141 +// to use a parser/handler pattern for this, as it's not a likely 1.142 +// reuse boundary. But doing so makes finer-grained unit testing 1.143 +// possible. 1.144 +class CFIRuleParser { 1.145 + public: 1.146 + 1.147 + class Handler { 1.148 + public: 1.149 + Handler() { } 1.150 + virtual ~Handler() { } 1.151 + 1.152 + // The input specifies EXPRESSION as the CFA/RA computation rule. 1.153 + virtual void CFARule(const string &expression) = 0; 1.154 + virtual void RARule(const string &expression) = 0; 1.155 + 1.156 + // The input specifies EXPRESSION as the recovery rule for register NAME. 1.157 + virtual void RegisterRule(const UniqueString* name, 1.158 + const string &expression) = 0; 1.159 + }; 1.160 + 1.161 + // Construct a parser which feeds its results to HANDLER. 1.162 + CFIRuleParser(Handler *handler) : handler_(handler) { } 1.163 + 1.164 + // Parse RULE_SET as a set of CFA computation and RA/register 1.165 + // recovery rules, as appearing in STACK CFI records. Report the 1.166 + // results of parsing by making the appropriate calls to handler_. 1.167 + // Return true if parsing was successful, false otherwise. 1.168 + bool Parse(const string &rule_set); 1.169 + 1.170 + private: 1.171 + // Report any accumulated rule to handler_ 1.172 + bool Report(); 1.173 + 1.174 + // The handler to which the parser reports its findings. 1.175 + Handler *handler_; 1.176 + 1.177 + // Working data. 1.178 + const UniqueString* name_; 1.179 + string expression_; 1.180 +}; 1.181 + 1.182 +// A handler for rule set parsing that populates a CFIFrameInfo with 1.183 +// the results. 1.184 +class CFIFrameInfoParseHandler: public CFIRuleParser::Handler { 1.185 + public: 1.186 + // Populate FRAME_INFO with the results of parsing. 1.187 + CFIFrameInfoParseHandler(CFIFrameInfo *frame_info) 1.188 + : frame_info_(frame_info) { } 1.189 + 1.190 + void CFARule(const string &expression); 1.191 + void RARule(const string &expression); 1.192 + void RegisterRule(const UniqueString* name, const string &expression); 1.193 + 1.194 + private: 1.195 + CFIFrameInfo *frame_info_; 1.196 +}; 1.197 + 1.198 +// A utility class template for simple 'STACK CFI'-driven stack walkers. 1.199 +// Given a CFIFrameInfo instance, a table describing the architecture's 1.200 +// register set, and a context holding the last frame's registers, an 1.201 +// instance of this class can populate a new context with the caller's 1.202 +// registers. 1.203 +// 1.204 +// This class template doesn't use any internal knowledge of CFIFrameInfo 1.205 +// or the other stack walking structures; it just uses the public interface 1.206 +// of CFIFrameInfo to do the usual things. But the logic it handles should 1.207 +// be common to many different architectures' stack walkers, so wrapping it 1.208 +// up in a class should allow the walkers to share code. 1.209 +// 1.210 +// RegisterType should be the type of this architecture's registers, either 1.211 +// uint32_t or uint64_t. RawContextType should be the raw context 1.212 +// structure type for this architecture. 1.213 +template <typename RegisterType, class RawContextType> 1.214 +class SimpleCFIWalker { 1.215 + public: 1.216 + // A structure describing one architecture register. 1.217 + struct RegisterSet { 1.218 + // The register name, as it appears in STACK CFI rules. 1.219 + const UniqueString* name; 1.220 + 1.221 + // An alternate name that the register's value might be found 1.222 + // under in a register value dictionary, or NULL. When generating 1.223 + // names, prefer NAME to this value. It's common to list ".cfa" as 1.224 + // an alternative name for the stack pointer, and ".ra" as an 1.225 + // alternative name for the instruction pointer. 1.226 + const UniqueString* alternate_name; 1.227 + 1.228 + // True if the callee is expected to preserve the value of this 1.229 + // register. If this flag is true for some register R, and the STACK 1.230 + // CFI records provide no rule to recover R, then SimpleCFIWalker 1.231 + // assumes that the callee has not changed R's value, and the caller's 1.232 + // value for R is that currently in the callee's context. 1.233 + bool callee_saves; 1.234 + 1.235 + // The ContextValidity flag representing the register's presence. 1.236 + int validity_flag; 1.237 + 1.238 + // A pointer to the RawContextType member that holds the 1.239 + // register's value. 1.240 + RegisterType RawContextType::*context_member; 1.241 + }; 1.242 + 1.243 + // Create a simple CFI-based frame walker, given a description of the 1.244 + // architecture's register set. REGISTER_MAP is an array of 1.245 + // RegisterSet structures; MAP_SIZE is the number of elements in the 1.246 + // array. 1.247 + SimpleCFIWalker(const RegisterSet *register_map, size_t map_size) 1.248 + : register_map_(register_map), map_size_(map_size) { } 1.249 + 1.250 + // Compute the calling frame's raw context given the callee's raw 1.251 + // context. 1.252 + // 1.253 + // Given: 1.254 + // 1.255 + // - MEMORY, holding the stack's contents, 1.256 + // - CFI_FRAME_INFO, describing the called function, 1.257 + // - CALLEE_CONTEXT, holding the called frame's registers, and 1.258 + // - CALLEE_VALIDITY, indicating which registers in CALLEE_CONTEXT are valid, 1.259 + // 1.260 + // fill in CALLER_CONTEXT with the caller's register values, and set 1.261 + // CALLER_VALIDITY to indicate which registers are valid in 1.262 + // CALLER_CONTEXT. Return true on success, or false on failure. 1.263 + bool FindCallerRegisters(const MemoryRegion &memory, 1.264 + const CFIFrameInfo &cfi_frame_info, 1.265 + const RawContextType &callee_context, 1.266 + int callee_validity, 1.267 + RawContextType *caller_context, 1.268 + int *caller_validity) const; 1.269 + 1.270 + private: 1.271 + const RegisterSet *register_map_; 1.272 + size_t map_size_; 1.273 +}; 1.274 + 1.275 +} // namespace google_breakpad 1.276 + 1.277 +#include "cfi_frame_info-inl.h" 1.278 + 1.279 +#endif // PROCESSOR_CFI_FRAME_INFO_H_