1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/profiler/LulDwarf.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2010 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 + 1.7 +// Copyright (c) 2010 Google Inc. 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 +// CFI reader author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 1.36 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 1.37 + 1.38 +// Implementation of dwarf2reader::LineInfo, dwarf2reader::CompilationUnit, 1.39 +// and dwarf2reader::CallFrameInfo. See dwarf2reader.h for details. 1.40 + 1.41 +// This file is derived from the following files in 1.42 +// toolkit/crashreporter/google-breakpad: 1.43 +// src/common/dwarf/bytereader.cc 1.44 +// src/common/dwarf/dwarf2reader.cc 1.45 +// src/common/dwarf_cfi_to_module.cc 1.46 + 1.47 +#include <stdint.h> 1.48 +#include <stdio.h> 1.49 +#include <string.h> 1.50 +#include <stdlib.h> 1.51 + 1.52 +#include <map> 1.53 +#include <stack> 1.54 +#include <string> 1.55 + 1.56 +#include "mozilla/Assertions.h" 1.57 + 1.58 +#include "LulCommonExt.h" 1.59 +#include "LulDwarfInt.h" 1.60 + 1.61 +// Set this to 1 for verbose logging 1.62 +#define DEBUG_DWARF 0 1.63 + 1.64 + 1.65 +namespace lul { 1.66 + 1.67 +using std::string; 1.68 + 1.69 +ByteReader::ByteReader(enum Endianness endian) 1.70 + :offset_reader_(NULL), address_reader_(NULL), endian_(endian), 1.71 + address_size_(0), offset_size_(0), 1.72 + have_section_base_(), have_text_base_(), have_data_base_(), 1.73 + have_function_base_() { } 1.74 + 1.75 +ByteReader::~ByteReader() { } 1.76 + 1.77 +void ByteReader::SetOffsetSize(uint8 size) { 1.78 + offset_size_ = size; 1.79 + MOZ_ASSERT(size == 4 || size == 8); 1.80 + if (size == 4) { 1.81 + this->offset_reader_ = &ByteReader::ReadFourBytes; 1.82 + } else { 1.83 + this->offset_reader_ = &ByteReader::ReadEightBytes; 1.84 + } 1.85 +} 1.86 + 1.87 +void ByteReader::SetAddressSize(uint8 size) { 1.88 + address_size_ = size; 1.89 + MOZ_ASSERT(size == 4 || size == 8); 1.90 + if (size == 4) { 1.91 + this->address_reader_ = &ByteReader::ReadFourBytes; 1.92 + } else { 1.93 + this->address_reader_ = &ByteReader::ReadEightBytes; 1.94 + } 1.95 +} 1.96 + 1.97 +uint64 ByteReader::ReadInitialLength(const char* start, size_t* len) { 1.98 + const uint64 initial_length = ReadFourBytes(start); 1.99 + start += 4; 1.100 + 1.101 + // In DWARF2/3, if the initial length is all 1 bits, then the offset 1.102 + // size is 8 and we need to read the next 8 bytes for the real length. 1.103 + if (initial_length == 0xffffffff) { 1.104 + SetOffsetSize(8); 1.105 + *len = 12; 1.106 + return ReadOffset(start); 1.107 + } else { 1.108 + SetOffsetSize(4); 1.109 + *len = 4; 1.110 + } 1.111 + return initial_length; 1.112 +} 1.113 + 1.114 +bool ByteReader::ValidEncoding(DwarfPointerEncoding encoding) const { 1.115 + if (encoding == DW_EH_PE_omit) return true; 1.116 + if (encoding == DW_EH_PE_aligned) return true; 1.117 + if ((encoding & 0x7) > DW_EH_PE_udata8) 1.118 + return false; 1.119 + if ((encoding & 0x70) > DW_EH_PE_funcrel) 1.120 + return false; 1.121 + return true; 1.122 +} 1.123 + 1.124 +bool ByteReader::UsableEncoding(DwarfPointerEncoding encoding) const { 1.125 + switch (encoding & 0x70) { 1.126 + case DW_EH_PE_absptr: return true; 1.127 + case DW_EH_PE_pcrel: return have_section_base_; 1.128 + case DW_EH_PE_textrel: return have_text_base_; 1.129 + case DW_EH_PE_datarel: return have_data_base_; 1.130 + case DW_EH_PE_funcrel: return have_function_base_; 1.131 + default: return false; 1.132 + } 1.133 +} 1.134 + 1.135 +uint64 ByteReader::ReadEncodedPointer(const char *buffer, 1.136 + DwarfPointerEncoding encoding, 1.137 + size_t *len) const { 1.138 + // UsableEncoding doesn't approve of DW_EH_PE_omit, so we shouldn't 1.139 + // see it here. 1.140 + MOZ_ASSERT(encoding != DW_EH_PE_omit); 1.141 + 1.142 + // The Linux Standards Base 4.0 does not make this clear, but the 1.143 + // GNU tools (gcc/unwind-pe.h; readelf/dwarf.c; gdb/dwarf2-frame.c) 1.144 + // agree that aligned pointers are always absolute, machine-sized, 1.145 + // machine-signed pointers. 1.146 + if (encoding == DW_EH_PE_aligned) { 1.147 + MOZ_ASSERT(have_section_base_); 1.148 + 1.149 + // We don't need to align BUFFER in *our* address space. Rather, we 1.150 + // need to find the next position in our buffer that would be aligned 1.151 + // when the .eh_frame section the buffer contains is loaded into the 1.152 + // program's memory. So align assuming that buffer_base_ gets loaded at 1.153 + // address section_base_, where section_base_ itself may or may not be 1.154 + // aligned. 1.155 + 1.156 + // First, find the offset to START from the closest prior aligned 1.157 + // address. 1.158 + uint64 skew = section_base_ & (AddressSize() - 1); 1.159 + // Now find the offset from that aligned address to buffer. 1.160 + uint64 offset = skew + (buffer - buffer_base_); 1.161 + // Round up to the next boundary. 1.162 + uint64 aligned = (offset + AddressSize() - 1) & -AddressSize(); 1.163 + // Convert back to a pointer. 1.164 + const char *aligned_buffer = buffer_base_ + (aligned - skew); 1.165 + // Finally, store the length and actually fetch the pointer. 1.166 + *len = aligned_buffer - buffer + AddressSize(); 1.167 + return ReadAddress(aligned_buffer); 1.168 + } 1.169 + 1.170 + // Extract the value first, ignoring whether it's a pointer or an 1.171 + // offset relative to some base. 1.172 + uint64 offset; 1.173 + switch (encoding & 0x0f) { 1.174 + case DW_EH_PE_absptr: 1.175 + // DW_EH_PE_absptr is weird, as it is used as a meaningful value for 1.176 + // both the high and low nybble of encoding bytes. When it appears in 1.177 + // the high nybble, it means that the pointer is absolute, not an 1.178 + // offset from some base address. When it appears in the low nybble, 1.179 + // as here, it means that the pointer is stored as a normal 1.180 + // machine-sized and machine-signed address. A low nybble of 1.181 + // DW_EH_PE_absptr does not imply that the pointer is absolute; it is 1.182 + // correct for us to treat the value as an offset from a base address 1.183 + // if the upper nybble is not DW_EH_PE_absptr. 1.184 + offset = ReadAddress(buffer); 1.185 + *len = AddressSize(); 1.186 + break; 1.187 + 1.188 + case DW_EH_PE_uleb128: 1.189 + offset = ReadUnsignedLEB128(buffer, len); 1.190 + break; 1.191 + 1.192 + case DW_EH_PE_udata2: 1.193 + offset = ReadTwoBytes(buffer); 1.194 + *len = 2; 1.195 + break; 1.196 + 1.197 + case DW_EH_PE_udata4: 1.198 + offset = ReadFourBytes(buffer); 1.199 + *len = 4; 1.200 + break; 1.201 + 1.202 + case DW_EH_PE_udata8: 1.203 + offset = ReadEightBytes(buffer); 1.204 + *len = 8; 1.205 + break; 1.206 + 1.207 + case DW_EH_PE_sleb128: 1.208 + offset = ReadSignedLEB128(buffer, len); 1.209 + break; 1.210 + 1.211 + case DW_EH_PE_sdata2: 1.212 + offset = ReadTwoBytes(buffer); 1.213 + // Sign-extend from 16 bits. 1.214 + offset = (offset ^ 0x8000) - 0x8000; 1.215 + *len = 2; 1.216 + break; 1.217 + 1.218 + case DW_EH_PE_sdata4: 1.219 + offset = ReadFourBytes(buffer); 1.220 + // Sign-extend from 32 bits. 1.221 + offset = (offset ^ 0x80000000ULL) - 0x80000000ULL; 1.222 + *len = 4; 1.223 + break; 1.224 + 1.225 + case DW_EH_PE_sdata8: 1.226 + // No need to sign-extend; this is the full width of our type. 1.227 + offset = ReadEightBytes(buffer); 1.228 + *len = 8; 1.229 + break; 1.230 + 1.231 + default: 1.232 + abort(); 1.233 + } 1.234 + 1.235 + // Find the appropriate base address. 1.236 + uint64 base; 1.237 + switch (encoding & 0x70) { 1.238 + case DW_EH_PE_absptr: 1.239 + base = 0; 1.240 + break; 1.241 + 1.242 + case DW_EH_PE_pcrel: 1.243 + MOZ_ASSERT(have_section_base_); 1.244 + base = section_base_ + (buffer - buffer_base_); 1.245 + break; 1.246 + 1.247 + case DW_EH_PE_textrel: 1.248 + MOZ_ASSERT(have_text_base_); 1.249 + base = text_base_; 1.250 + break; 1.251 + 1.252 + case DW_EH_PE_datarel: 1.253 + MOZ_ASSERT(have_data_base_); 1.254 + base = data_base_; 1.255 + break; 1.256 + 1.257 + case DW_EH_PE_funcrel: 1.258 + MOZ_ASSERT(have_function_base_); 1.259 + base = function_base_; 1.260 + break; 1.261 + 1.262 + default: 1.263 + abort(); 1.264 + } 1.265 + 1.266 + uint64 pointer = base + offset; 1.267 + 1.268 + // Remove inappropriate upper bits. 1.269 + if (AddressSize() == 4) 1.270 + pointer = pointer & 0xffffffff; 1.271 + else 1.272 + MOZ_ASSERT(AddressSize() == sizeof(uint64)); 1.273 + 1.274 + return pointer; 1.275 +} 1.276 + 1.277 + 1.278 +// A DWARF rule for recovering the address or value of a register, or 1.279 +// computing the canonical frame address. There is one subclass of this for 1.280 +// each '*Rule' member function in CallFrameInfo::Handler. 1.281 +// 1.282 +// It's annoying that we have to handle Rules using pointers (because 1.283 +// the concrete instances can have an arbitrary size). They're small, 1.284 +// so it would be much nicer if we could just handle them by value 1.285 +// instead of fretting about ownership and destruction. 1.286 +// 1.287 +// It seems like all these could simply be instances of std::tr1::bind, 1.288 +// except that we need instances to be EqualityComparable, too. 1.289 +// 1.290 +// This could logically be nested within State, but then the qualified names 1.291 +// get horrendous. 1.292 +class CallFrameInfo::Rule { 1.293 + public: 1.294 + virtual ~Rule() { } 1.295 + 1.296 + // Tell HANDLER that, at ADDRESS in the program, REGISTER can be 1.297 + // recovered using this rule. If REGISTER is kCFARegister, then this rule 1.298 + // describes how to compute the canonical frame address. Return what the 1.299 + // HANDLER member function returned. 1.300 + virtual bool Handle(Handler *handler, 1.301 + uint64 address, int register) const = 0; 1.302 + 1.303 + // Equality on rules. We use these to decide which rules we need 1.304 + // to report after a DW_CFA_restore_state instruction. 1.305 + virtual bool operator==(const Rule &rhs) const = 0; 1.306 + 1.307 + bool operator!=(const Rule &rhs) const { return ! (*this == rhs); } 1.308 + 1.309 + // Return a pointer to a copy of this rule. 1.310 + virtual Rule *Copy() const = 0; 1.311 + 1.312 + // If this is a base+offset rule, change its base register to REG. 1.313 + // Otherwise, do nothing. (Ugly, but required for DW_CFA_def_cfa_register.) 1.314 + virtual void SetBaseRegister(unsigned reg) { } 1.315 + 1.316 + // If this is a base+offset rule, change its offset to OFFSET. Otherwise, 1.317 + // do nothing. (Ugly, but required for DW_CFA_def_cfa_offset.) 1.318 + virtual void SetOffset(long long offset) { } 1.319 + 1.320 + // A RTTI workaround, to make it possible to implement equality 1.321 + // comparisons on classes derived from this one. 1.322 + enum CFIRTag { 1.323 + CFIR_UNDEFINED_RULE, 1.324 + CFIR_SAME_VALUE_RULE, 1.325 + CFIR_OFFSET_RULE, 1.326 + CFIR_VAL_OFFSET_RULE, 1.327 + CFIR_REGISTER_RULE, 1.328 + CFIR_EXPRESSION_RULE, 1.329 + CFIR_VAL_EXPRESSION_RULE 1.330 + }; 1.331 + 1.332 + // Produce the tag that identifies the child class of this object. 1.333 + virtual CFIRTag getTag() const = 0; 1.334 +}; 1.335 + 1.336 +// Rule: the value the register had in the caller cannot be recovered. 1.337 +class CallFrameInfo::UndefinedRule: public CallFrameInfo::Rule { 1.338 + public: 1.339 + UndefinedRule() { } 1.340 + ~UndefinedRule() { } 1.341 + CFIRTag getTag() const { return CFIR_UNDEFINED_RULE; } 1.342 + bool Handle(Handler *handler, uint64 address, int reg) const { 1.343 + return handler->UndefinedRule(address, reg); 1.344 + } 1.345 + bool operator==(const Rule &rhs) const { 1.346 + if (rhs.getTag() != CFIR_UNDEFINED_RULE) return false; 1.347 + return true; 1.348 + } 1.349 + Rule *Copy() const { return new UndefinedRule(*this); } 1.350 +}; 1.351 + 1.352 +// Rule: the register's value is the same as that it had in the caller. 1.353 +class CallFrameInfo::SameValueRule: public CallFrameInfo::Rule { 1.354 + public: 1.355 + SameValueRule() { } 1.356 + ~SameValueRule() { } 1.357 + CFIRTag getTag() const { return CFIR_SAME_VALUE_RULE; } 1.358 + bool Handle(Handler *handler, uint64 address, int reg) const { 1.359 + return handler->SameValueRule(address, reg); 1.360 + } 1.361 + bool operator==(const Rule &rhs) const { 1.362 + if (rhs.getTag() != CFIR_SAME_VALUE_RULE) return false; 1.363 + return true; 1.364 + } 1.365 + Rule *Copy() const { return new SameValueRule(*this); } 1.366 +}; 1.367 + 1.368 +// Rule: the register is saved at OFFSET from BASE_REGISTER. BASE_REGISTER 1.369 +// may be CallFrameInfo::Handler::kCFARegister. 1.370 +class CallFrameInfo::OffsetRule: public CallFrameInfo::Rule { 1.371 + public: 1.372 + OffsetRule(int base_register, long offset) 1.373 + : base_register_(base_register), offset_(offset) { } 1.374 + ~OffsetRule() { } 1.375 + CFIRTag getTag() const { return CFIR_OFFSET_RULE; } 1.376 + bool Handle(Handler *handler, uint64 address, int reg) const { 1.377 + return handler->OffsetRule(address, reg, base_register_, offset_); 1.378 + } 1.379 + bool operator==(const Rule &rhs) const { 1.380 + if (rhs.getTag() != CFIR_OFFSET_RULE) return false; 1.381 + const OffsetRule *our_rhs = static_cast<const OffsetRule *>(&rhs); 1.382 + return (base_register_ == our_rhs->base_register_ && 1.383 + offset_ == our_rhs->offset_); 1.384 + } 1.385 + Rule *Copy() const { return new OffsetRule(*this); } 1.386 + // We don't actually need SetBaseRegister or SetOffset here, since they 1.387 + // are only ever applied to CFA rules, for DW_CFA_def_cfa_offset, and it 1.388 + // doesn't make sense to use OffsetRule for computing the CFA: it 1.389 + // computes the address at which a register is saved, not a value. 1.390 + private: 1.391 + int base_register_; 1.392 + long offset_; 1.393 +}; 1.394 + 1.395 +// Rule: the value the register had in the caller is the value of 1.396 +// BASE_REGISTER plus offset. BASE_REGISTER may be 1.397 +// CallFrameInfo::Handler::kCFARegister. 1.398 +class CallFrameInfo::ValOffsetRule: public CallFrameInfo::Rule { 1.399 + public: 1.400 + ValOffsetRule(int base_register, long offset) 1.401 + : base_register_(base_register), offset_(offset) { } 1.402 + ~ValOffsetRule() { } 1.403 + CFIRTag getTag() const { return CFIR_VAL_OFFSET_RULE; } 1.404 + bool Handle(Handler *handler, uint64 address, int reg) const { 1.405 + return handler->ValOffsetRule(address, reg, base_register_, offset_); 1.406 + } 1.407 + bool operator==(const Rule &rhs) const { 1.408 + if (rhs.getTag() != CFIR_VAL_OFFSET_RULE) return false; 1.409 + const ValOffsetRule *our_rhs = static_cast<const ValOffsetRule *>(&rhs); 1.410 + return (base_register_ == our_rhs->base_register_ && 1.411 + offset_ == our_rhs->offset_); 1.412 + } 1.413 + Rule *Copy() const { return new ValOffsetRule(*this); } 1.414 + void SetBaseRegister(unsigned reg) { base_register_ = reg; } 1.415 + void SetOffset(long long offset) { offset_ = offset; } 1.416 + private: 1.417 + int base_register_; 1.418 + long offset_; 1.419 +}; 1.420 + 1.421 +// Rule: the register has been saved in another register REGISTER_NUMBER_. 1.422 +class CallFrameInfo::RegisterRule: public CallFrameInfo::Rule { 1.423 + public: 1.424 + explicit RegisterRule(int register_number) 1.425 + : register_number_(register_number) { } 1.426 + ~RegisterRule() { } 1.427 + CFIRTag getTag() const { return CFIR_REGISTER_RULE; } 1.428 + bool Handle(Handler *handler, uint64 address, int reg) const { 1.429 + return handler->RegisterRule(address, reg, register_number_); 1.430 + } 1.431 + bool operator==(const Rule &rhs) const { 1.432 + if (rhs.getTag() != CFIR_REGISTER_RULE) return false; 1.433 + const RegisterRule *our_rhs = static_cast<const RegisterRule *>(&rhs); 1.434 + return (register_number_ == our_rhs->register_number_); 1.435 + } 1.436 + Rule *Copy() const { return new RegisterRule(*this); } 1.437 + private: 1.438 + int register_number_; 1.439 +}; 1.440 + 1.441 +// Rule: EXPRESSION evaluates to the address at which the register is saved. 1.442 +class CallFrameInfo::ExpressionRule: public CallFrameInfo::Rule { 1.443 + public: 1.444 + explicit ExpressionRule(const string &expression) 1.445 + : expression_(expression) { } 1.446 + ~ExpressionRule() { } 1.447 + CFIRTag getTag() const { return CFIR_EXPRESSION_RULE; } 1.448 + bool Handle(Handler *handler, uint64 address, int reg) const { 1.449 + return handler->ExpressionRule(address, reg, expression_); 1.450 + } 1.451 + bool operator==(const Rule &rhs) const { 1.452 + if (rhs.getTag() != CFIR_EXPRESSION_RULE) return false; 1.453 + const ExpressionRule *our_rhs = static_cast<const ExpressionRule *>(&rhs); 1.454 + return (expression_ == our_rhs->expression_); 1.455 + } 1.456 + Rule *Copy() const { return new ExpressionRule(*this); } 1.457 + private: 1.458 + string expression_; 1.459 +}; 1.460 + 1.461 +// Rule: EXPRESSION evaluates to the previous value of the register. 1.462 +class CallFrameInfo::ValExpressionRule: public CallFrameInfo::Rule { 1.463 + public: 1.464 + explicit ValExpressionRule(const string &expression) 1.465 + : expression_(expression) { } 1.466 + ~ValExpressionRule() { } 1.467 + CFIRTag getTag() const { return CFIR_VAL_EXPRESSION_RULE; } 1.468 + bool Handle(Handler *handler, uint64 address, int reg) const { 1.469 + return handler->ValExpressionRule(address, reg, expression_); 1.470 + } 1.471 + bool operator==(const Rule &rhs) const { 1.472 + if (rhs.getTag() != CFIR_VAL_EXPRESSION_RULE) return false; 1.473 + const ValExpressionRule *our_rhs = 1.474 + static_cast<const ValExpressionRule *>(&rhs); 1.475 + return (expression_ == our_rhs->expression_); 1.476 + } 1.477 + Rule *Copy() const { return new ValExpressionRule(*this); } 1.478 + private: 1.479 + string expression_; 1.480 +}; 1.481 + 1.482 +// A map from register numbers to rules. 1.483 +class CallFrameInfo::RuleMap { 1.484 + public: 1.485 + RuleMap() : cfa_rule_(NULL) { } 1.486 + RuleMap(const RuleMap &rhs) : cfa_rule_(NULL) { *this = rhs; } 1.487 + ~RuleMap() { Clear(); } 1.488 + 1.489 + RuleMap &operator=(const RuleMap &rhs); 1.490 + 1.491 + // Set the rule for computing the CFA to RULE. Take ownership of RULE. 1.492 + void SetCFARule(Rule *rule) { delete cfa_rule_; cfa_rule_ = rule; } 1.493 + 1.494 + // Return the current CFA rule. Unlike RegisterRule, this RuleMap retains 1.495 + // ownership of the rule. We use this for DW_CFA_def_cfa_offset and 1.496 + // DW_CFA_def_cfa_register, and for detecting references to the CFA before 1.497 + // a rule for it has been established. 1.498 + Rule *CFARule() const { return cfa_rule_; } 1.499 + 1.500 + // Return the rule for REG, or NULL if there is none. The caller takes 1.501 + // ownership of the result. 1.502 + Rule *RegisterRule(int reg) const; 1.503 + 1.504 + // Set the rule for computing REG to RULE. Take ownership of RULE. 1.505 + void SetRegisterRule(int reg, Rule *rule); 1.506 + 1.507 + // Make all the appropriate calls to HANDLER as if we were changing from 1.508 + // this RuleMap to NEW_RULES at ADDRESS. We use this to implement 1.509 + // DW_CFA_restore_state, where lots of rules can change simultaneously. 1.510 + // Return true if all handlers returned true; otherwise, return false. 1.511 + bool HandleTransitionTo(Handler *handler, uint64 address, 1.512 + const RuleMap &new_rules) const; 1.513 + 1.514 + private: 1.515 + // A map from register numbers to Rules. 1.516 + typedef std::map<int, Rule *> RuleByNumber; 1.517 + 1.518 + // Remove all register rules and clear cfa_rule_. 1.519 + void Clear(); 1.520 + 1.521 + // The rule for computing the canonical frame address. This RuleMap owns 1.522 + // this rule. 1.523 + Rule *cfa_rule_; 1.524 + 1.525 + // A map from register numbers to postfix expressions to recover 1.526 + // their values. This RuleMap owns the Rules the map refers to. 1.527 + RuleByNumber registers_; 1.528 +}; 1.529 + 1.530 +CallFrameInfo::RuleMap &CallFrameInfo::RuleMap::operator=(const RuleMap &rhs) { 1.531 + Clear(); 1.532 + // Since each map owns the rules it refers to, assignment must copy them. 1.533 + if (rhs.cfa_rule_) cfa_rule_ = rhs.cfa_rule_->Copy(); 1.534 + for (RuleByNumber::const_iterator it = rhs.registers_.begin(); 1.535 + it != rhs.registers_.end(); it++) 1.536 + registers_[it->first] = it->second->Copy(); 1.537 + return *this; 1.538 +} 1.539 + 1.540 +CallFrameInfo::Rule *CallFrameInfo::RuleMap::RegisterRule(int reg) const { 1.541 + MOZ_ASSERT(reg != Handler::kCFARegister); 1.542 + RuleByNumber::const_iterator it = registers_.find(reg); 1.543 + if (it != registers_.end()) 1.544 + return it->second->Copy(); 1.545 + else 1.546 + return NULL; 1.547 +} 1.548 + 1.549 +void CallFrameInfo::RuleMap::SetRegisterRule(int reg, Rule *rule) { 1.550 + MOZ_ASSERT(reg != Handler::kCFARegister); 1.551 + MOZ_ASSERT(rule); 1.552 + Rule **slot = ®isters_[reg]; 1.553 + delete *slot; 1.554 + *slot = rule; 1.555 +} 1.556 + 1.557 +bool CallFrameInfo::RuleMap::HandleTransitionTo( 1.558 + Handler *handler, 1.559 + uint64 address, 1.560 + const RuleMap &new_rules) const { 1.561 + // Transition from cfa_rule_ to new_rules.cfa_rule_. 1.562 + if (cfa_rule_ && new_rules.cfa_rule_) { 1.563 + if (*cfa_rule_ != *new_rules.cfa_rule_ && 1.564 + !new_rules.cfa_rule_->Handle(handler, address, Handler::kCFARegister)) 1.565 + return false; 1.566 + } else if (cfa_rule_) { 1.567 + // this RuleMap has a CFA rule but new_rules doesn't. 1.568 + // CallFrameInfo::Handler has no way to handle this --- and shouldn't; 1.569 + // it's garbage input. The instruction interpreter should have 1.570 + // detected this and warned, so take no action here. 1.571 + } else if (new_rules.cfa_rule_) { 1.572 + // This shouldn't be possible: NEW_RULES is some prior state, and 1.573 + // there's no way to remove entries. 1.574 + MOZ_ASSERT(0); 1.575 + } else { 1.576 + // Both CFA rules are empty. No action needed. 1.577 + } 1.578 + 1.579 + // Traverse the two maps in order by register number, and report 1.580 + // whatever differences we find. 1.581 + RuleByNumber::const_iterator old_it = registers_.begin(); 1.582 + RuleByNumber::const_iterator new_it = new_rules.registers_.begin(); 1.583 + while (old_it != registers_.end() && new_it != new_rules.registers_.end()) { 1.584 + if (old_it->first < new_it->first) { 1.585 + // This RuleMap has an entry for old_it->first, but NEW_RULES 1.586 + // doesn't. 1.587 + // 1.588 + // This isn't really the right thing to do, but since CFI generally 1.589 + // only mentions callee-saves registers, and GCC's convention for 1.590 + // callee-saves registers is that they are unchanged, it's a good 1.591 + // approximation. 1.592 + if (!handler->SameValueRule(address, old_it->first)) 1.593 + return false; 1.594 + old_it++; 1.595 + } else if (old_it->first > new_it->first) { 1.596 + // NEW_RULES has entry for new_it->first, but this RuleMap 1.597 + // doesn't. This shouldn't be possible: NEW_RULES is some prior 1.598 + // state, and there's no way to remove entries. 1.599 + MOZ_ASSERT(0); 1.600 + } else { 1.601 + // Both maps have an entry for this register. Report the new 1.602 + // rule if it is different. 1.603 + if (*old_it->second != *new_it->second && 1.604 + !new_it->second->Handle(handler, address, new_it->first)) 1.605 + return false; 1.606 + new_it++, old_it++; 1.607 + } 1.608 + } 1.609 + // Finish off entries from this RuleMap with no counterparts in new_rules. 1.610 + while (old_it != registers_.end()) { 1.611 + if (!handler->SameValueRule(address, old_it->first)) 1.612 + return false; 1.613 + old_it++; 1.614 + } 1.615 + // Since we only make transitions from a rule set to some previously 1.616 + // saved rule set, and we can only add rules to the map, NEW_RULES 1.617 + // must have fewer rules than *this. 1.618 + MOZ_ASSERT(new_it == new_rules.registers_.end()); 1.619 + 1.620 + return true; 1.621 +} 1.622 + 1.623 +// Remove all register rules and clear cfa_rule_. 1.624 +void CallFrameInfo::RuleMap::Clear() { 1.625 + delete cfa_rule_; 1.626 + cfa_rule_ = NULL; 1.627 + for (RuleByNumber::iterator it = registers_.begin(); 1.628 + it != registers_.end(); it++) 1.629 + delete it->second; 1.630 + registers_.clear(); 1.631 +} 1.632 + 1.633 +// The state of the call frame information interpreter as it processes 1.634 +// instructions from a CIE and FDE. 1.635 +class CallFrameInfo::State { 1.636 + public: 1.637 + // Create a call frame information interpreter state with the given 1.638 + // reporter, reader, handler, and initial call frame info address. 1.639 + State(ByteReader *reader, Handler *handler, Reporter *reporter, 1.640 + uint64 address) 1.641 + : reader_(reader), handler_(handler), reporter_(reporter), 1.642 + address_(address), entry_(NULL), cursor_(NULL), 1.643 + saved_rules_(NULL) { } 1.644 + 1.645 + ~State() { 1.646 + if (saved_rules_) 1.647 + delete saved_rules_; 1.648 + } 1.649 + 1.650 + // Interpret instructions from CIE, save the resulting rule set for 1.651 + // DW_CFA_restore instructions, and return true. On error, report 1.652 + // the problem to reporter_ and return false. 1.653 + bool InterpretCIE(const CIE &cie); 1.654 + 1.655 + // Interpret instructions from FDE, and return true. On error, 1.656 + // report the problem to reporter_ and return false. 1.657 + bool InterpretFDE(const FDE &fde); 1.658 + 1.659 + private: 1.660 + // The operands of a CFI instruction, for ParseOperands. 1.661 + struct Operands { 1.662 + unsigned register_number; // A register number. 1.663 + uint64 offset; // An offset or address. 1.664 + long signed_offset; // A signed offset. 1.665 + string expression; // A DWARF expression. 1.666 + }; 1.667 + 1.668 + // Parse CFI instruction operands from STATE's instruction stream as 1.669 + // described by FORMAT. On success, populate OPERANDS with the 1.670 + // results, and return true. On failure, report the problem and 1.671 + // return false. 1.672 + // 1.673 + // Each character of FORMAT should be one of the following: 1.674 + // 1.675 + // 'r' unsigned LEB128 register number (OPERANDS->register_number) 1.676 + // 'o' unsigned LEB128 offset (OPERANDS->offset) 1.677 + // 's' signed LEB128 offset (OPERANDS->signed_offset) 1.678 + // 'a' machine-size address (OPERANDS->offset) 1.679 + // (If the CIE has a 'z' augmentation string, 'a' uses the 1.680 + // encoding specified by the 'R' argument.) 1.681 + // '1' a one-byte offset (OPERANDS->offset) 1.682 + // '2' a two-byte offset (OPERANDS->offset) 1.683 + // '4' a four-byte offset (OPERANDS->offset) 1.684 + // '8' an eight-byte offset (OPERANDS->offset) 1.685 + // 'e' a DW_FORM_block holding a (OPERANDS->expression) 1.686 + // DWARF expression 1.687 + bool ParseOperands(const char *format, Operands *operands); 1.688 + 1.689 + // Interpret one CFI instruction from STATE's instruction stream, update 1.690 + // STATE, report any rule changes to handler_, and return true. On 1.691 + // failure, report the problem and return false. 1.692 + bool DoInstruction(); 1.693 + 1.694 + // The following Do* member functions are subroutines of DoInstruction, 1.695 + // factoring out the actual work of operations that have several 1.696 + // different encodings. 1.697 + 1.698 + // Set the CFA rule to be the value of BASE_REGISTER plus OFFSET, and 1.699 + // return true. On failure, report and return false. (Used for 1.700 + // DW_CFA_def_cfa and DW_CFA_def_cfa_sf.) 1.701 + bool DoDefCFA(unsigned base_register, long offset); 1.702 + 1.703 + // Change the offset of the CFA rule to OFFSET, and return true. On 1.704 + // failure, report and return false. (Subroutine for 1.705 + // DW_CFA_def_cfa_offset and DW_CFA_def_cfa_offset_sf.) 1.706 + bool DoDefCFAOffset(long offset); 1.707 + 1.708 + // Specify that REG can be recovered using RULE, and return true. On 1.709 + // failure, report and return false. 1.710 + bool DoRule(unsigned reg, Rule *rule); 1.711 + 1.712 + // Specify that REG can be found at OFFSET from the CFA, and return true. 1.713 + // On failure, report and return false. (Subroutine for DW_CFA_offset, 1.714 + // DW_CFA_offset_extended, and DW_CFA_offset_extended_sf.) 1.715 + bool DoOffset(unsigned reg, long offset); 1.716 + 1.717 + // Specify that the caller's value for REG is the CFA plus OFFSET, 1.718 + // and return true. On failure, report and return false. (Subroutine 1.719 + // for DW_CFA_val_offset and DW_CFA_val_offset_sf.) 1.720 + bool DoValOffset(unsigned reg, long offset); 1.721 + 1.722 + // Restore REG to the rule established in the CIE, and return true. On 1.723 + // failure, report and return false. (Subroutine for DW_CFA_restore and 1.724 + // DW_CFA_restore_extended.) 1.725 + bool DoRestore(unsigned reg); 1.726 + 1.727 + // Return the section offset of the instruction at cursor. For use 1.728 + // in error messages. 1.729 + uint64 CursorOffset() { return entry_->offset + (cursor_ - entry_->start); } 1.730 + 1.731 + // Report that entry_ is incomplete, and return false. For brevity. 1.732 + bool ReportIncomplete() { 1.733 + reporter_->Incomplete(entry_->offset, entry_->kind); 1.734 + return false; 1.735 + } 1.736 + 1.737 + // For reading multi-byte values with the appropriate endianness. 1.738 + ByteReader *reader_; 1.739 + 1.740 + // The handler to which we should report the data we find. 1.741 + Handler *handler_; 1.742 + 1.743 + // For reporting problems in the info we're parsing. 1.744 + Reporter *reporter_; 1.745 + 1.746 + // The code address to which the next instruction in the stream applies. 1.747 + uint64 address_; 1.748 + 1.749 + // The entry whose instructions we are currently processing. This is 1.750 + // first a CIE, and then an FDE. 1.751 + const Entry *entry_; 1.752 + 1.753 + // The next instruction to process. 1.754 + const char *cursor_; 1.755 + 1.756 + // The current set of rules. 1.757 + RuleMap rules_; 1.758 + 1.759 + // The set of rules established by the CIE, used by DW_CFA_restore 1.760 + // and DW_CFA_restore_extended. We set this after interpreting the 1.761 + // CIE's instructions. 1.762 + RuleMap cie_rules_; 1.763 + 1.764 + // A stack of saved states, for DW_CFA_remember_state and 1.765 + // DW_CFA_restore_state. 1.766 + std::stack<RuleMap>* saved_rules_; 1.767 +}; 1.768 + 1.769 +bool CallFrameInfo::State::InterpretCIE(const CIE &cie) { 1.770 + entry_ = &cie; 1.771 + cursor_ = entry_->instructions; 1.772 + while (cursor_ < entry_->end) 1.773 + if (!DoInstruction()) 1.774 + return false; 1.775 + // Note the rules established by the CIE, for use by DW_CFA_restore 1.776 + // and DW_CFA_restore_extended. 1.777 + cie_rules_ = rules_; 1.778 + return true; 1.779 +} 1.780 + 1.781 +bool CallFrameInfo::State::InterpretFDE(const FDE &fde) { 1.782 + entry_ = &fde; 1.783 + cursor_ = entry_->instructions; 1.784 + while (cursor_ < entry_->end) 1.785 + if (!DoInstruction()) 1.786 + return false; 1.787 + return true; 1.788 +} 1.789 + 1.790 +bool CallFrameInfo::State::ParseOperands(const char *format, 1.791 + Operands *operands) { 1.792 + size_t len; 1.793 + const char *operand; 1.794 + 1.795 + for (operand = format; *operand; operand++) { 1.796 + size_t bytes_left = entry_->end - cursor_; 1.797 + switch (*operand) { 1.798 + case 'r': 1.799 + operands->register_number = reader_->ReadUnsignedLEB128(cursor_, &len); 1.800 + if (len > bytes_left) return ReportIncomplete(); 1.801 + cursor_ += len; 1.802 + break; 1.803 + 1.804 + case 'o': 1.805 + operands->offset = reader_->ReadUnsignedLEB128(cursor_, &len); 1.806 + if (len > bytes_left) return ReportIncomplete(); 1.807 + cursor_ += len; 1.808 + break; 1.809 + 1.810 + case 's': 1.811 + operands->signed_offset = reader_->ReadSignedLEB128(cursor_, &len); 1.812 + if (len > bytes_left) return ReportIncomplete(); 1.813 + cursor_ += len; 1.814 + break; 1.815 + 1.816 + case 'a': 1.817 + operands->offset = 1.818 + reader_->ReadEncodedPointer(cursor_, entry_->cie->pointer_encoding, 1.819 + &len); 1.820 + if (len > bytes_left) return ReportIncomplete(); 1.821 + cursor_ += len; 1.822 + break; 1.823 + 1.824 + case '1': 1.825 + if (1 > bytes_left) return ReportIncomplete(); 1.826 + operands->offset = static_cast<unsigned char>(*cursor_++); 1.827 + break; 1.828 + 1.829 + case '2': 1.830 + if (2 > bytes_left) return ReportIncomplete(); 1.831 + operands->offset = reader_->ReadTwoBytes(cursor_); 1.832 + cursor_ += 2; 1.833 + break; 1.834 + 1.835 + case '4': 1.836 + if (4 > bytes_left) return ReportIncomplete(); 1.837 + operands->offset = reader_->ReadFourBytes(cursor_); 1.838 + cursor_ += 4; 1.839 + break; 1.840 + 1.841 + case '8': 1.842 + if (8 > bytes_left) return ReportIncomplete(); 1.843 + operands->offset = reader_->ReadEightBytes(cursor_); 1.844 + cursor_ += 8; 1.845 + break; 1.846 + 1.847 + case 'e': { 1.848 + size_t expression_length = reader_->ReadUnsignedLEB128(cursor_, &len); 1.849 + if (len > bytes_left || expression_length > bytes_left - len) 1.850 + return ReportIncomplete(); 1.851 + cursor_ += len; 1.852 + operands->expression = string(cursor_, expression_length); 1.853 + cursor_ += expression_length; 1.854 + break; 1.855 + } 1.856 + 1.857 + default: 1.858 + MOZ_ASSERT(0); 1.859 + } 1.860 + } 1.861 + 1.862 + return true; 1.863 +} 1.864 + 1.865 +bool CallFrameInfo::State::DoInstruction() { 1.866 + CIE *cie = entry_->cie; 1.867 + Operands ops; 1.868 + 1.869 + // Our entry's kind should have been set by now. 1.870 + MOZ_ASSERT(entry_->kind != kUnknown); 1.871 + 1.872 + // We shouldn't have been invoked unless there were more 1.873 + // instructions to parse. 1.874 + MOZ_ASSERT(cursor_ < entry_->end); 1.875 + 1.876 + unsigned opcode = *cursor_++; 1.877 + if ((opcode & 0xc0) != 0) { 1.878 + switch (opcode & 0xc0) { 1.879 + // Advance the address. 1.880 + case DW_CFA_advance_loc: { 1.881 + size_t code_offset = opcode & 0x3f; 1.882 + address_ += code_offset * cie->code_alignment_factor; 1.883 + break; 1.884 + } 1.885 + 1.886 + // Find a register at an offset from the CFA. 1.887 + case DW_CFA_offset: 1.888 + if (!ParseOperands("o", &ops) || 1.889 + !DoOffset(opcode & 0x3f, ops.offset * cie->data_alignment_factor)) 1.890 + return false; 1.891 + break; 1.892 + 1.893 + // Restore the rule established for a register by the CIE. 1.894 + case DW_CFA_restore: 1.895 + if (!DoRestore(opcode & 0x3f)) return false; 1.896 + break; 1.897 + 1.898 + // The 'if' above should have excluded this possibility. 1.899 + default: 1.900 + MOZ_ASSERT(0); 1.901 + } 1.902 + 1.903 + // Return here, so the big switch below won't be indented. 1.904 + return true; 1.905 + } 1.906 + 1.907 + switch (opcode) { 1.908 + // Set the address. 1.909 + case DW_CFA_set_loc: 1.910 + if (!ParseOperands("a", &ops)) return false; 1.911 + address_ = ops.offset; 1.912 + break; 1.913 + 1.914 + // Advance the address. 1.915 + case DW_CFA_advance_loc1: 1.916 + if (!ParseOperands("1", &ops)) return false; 1.917 + address_ += ops.offset * cie->code_alignment_factor; 1.918 + break; 1.919 + 1.920 + // Advance the address. 1.921 + case DW_CFA_advance_loc2: 1.922 + if (!ParseOperands("2", &ops)) return false; 1.923 + address_ += ops.offset * cie->code_alignment_factor; 1.924 + break; 1.925 + 1.926 + // Advance the address. 1.927 + case DW_CFA_advance_loc4: 1.928 + if (!ParseOperands("4", &ops)) return false; 1.929 + address_ += ops.offset * cie->code_alignment_factor; 1.930 + break; 1.931 + 1.932 + // Advance the address. 1.933 + case DW_CFA_MIPS_advance_loc8: 1.934 + if (!ParseOperands("8", &ops)) return false; 1.935 + address_ += ops.offset * cie->code_alignment_factor; 1.936 + break; 1.937 + 1.938 + // Compute the CFA by adding an offset to a register. 1.939 + case DW_CFA_def_cfa: 1.940 + if (!ParseOperands("ro", &ops) || 1.941 + !DoDefCFA(ops.register_number, ops.offset)) 1.942 + return false; 1.943 + break; 1.944 + 1.945 + // Compute the CFA by adding an offset to a register. 1.946 + case DW_CFA_def_cfa_sf: 1.947 + if (!ParseOperands("rs", &ops) || 1.948 + !DoDefCFA(ops.register_number, 1.949 + ops.signed_offset * cie->data_alignment_factor)) 1.950 + return false; 1.951 + break; 1.952 + 1.953 + // Change the base register used to compute the CFA. 1.954 + case DW_CFA_def_cfa_register: { 1.955 + Rule *cfa_rule = rules_.CFARule(); 1.956 + if (!cfa_rule) { 1.957 + reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset()); 1.958 + return false; 1.959 + } 1.960 + if (!ParseOperands("r", &ops)) return false; 1.961 + cfa_rule->SetBaseRegister(ops.register_number); 1.962 + if (!cfa_rule->Handle(handler_, address_, Handler::kCFARegister)) 1.963 + return false; 1.964 + break; 1.965 + } 1.966 + 1.967 + // Change the offset used to compute the CFA. 1.968 + case DW_CFA_def_cfa_offset: 1.969 + if (!ParseOperands("o", &ops) || 1.970 + !DoDefCFAOffset(ops.offset)) 1.971 + return false; 1.972 + break; 1.973 + 1.974 + // Change the offset used to compute the CFA. 1.975 + case DW_CFA_def_cfa_offset_sf: 1.976 + if (!ParseOperands("s", &ops) || 1.977 + !DoDefCFAOffset(ops.signed_offset * cie->data_alignment_factor)) 1.978 + return false; 1.979 + break; 1.980 + 1.981 + // Specify an expression whose value is the CFA. 1.982 + case DW_CFA_def_cfa_expression: { 1.983 + if (!ParseOperands("e", &ops)) 1.984 + return false; 1.985 + Rule *rule = new ValExpressionRule(ops.expression); 1.986 + rules_.SetCFARule(rule); 1.987 + if (!rule->Handle(handler_, address_, Handler::kCFARegister)) 1.988 + return false; 1.989 + break; 1.990 + } 1.991 + 1.992 + // The register's value cannot be recovered. 1.993 + case DW_CFA_undefined: { 1.994 + if (!ParseOperands("r", &ops) || 1.995 + !DoRule(ops.register_number, new UndefinedRule())) 1.996 + return false; 1.997 + break; 1.998 + } 1.999 + 1.1000 + // The register's value is unchanged from its value in the caller. 1.1001 + case DW_CFA_same_value: { 1.1002 + if (!ParseOperands("r", &ops) || 1.1003 + !DoRule(ops.register_number, new SameValueRule())) 1.1004 + return false; 1.1005 + break; 1.1006 + } 1.1007 + 1.1008 + // Find a register at an offset from the CFA. 1.1009 + case DW_CFA_offset_extended: 1.1010 + if (!ParseOperands("ro", &ops) || 1.1011 + !DoOffset(ops.register_number, 1.1012 + ops.offset * cie->data_alignment_factor)) 1.1013 + return false; 1.1014 + break; 1.1015 + 1.1016 + // The register is saved at an offset from the CFA. 1.1017 + case DW_CFA_offset_extended_sf: 1.1018 + if (!ParseOperands("rs", &ops) || 1.1019 + !DoOffset(ops.register_number, 1.1020 + ops.signed_offset * cie->data_alignment_factor)) 1.1021 + return false; 1.1022 + break; 1.1023 + 1.1024 + // The register is saved at an offset from the CFA. 1.1025 + case DW_CFA_GNU_negative_offset_extended: 1.1026 + if (!ParseOperands("ro", &ops) || 1.1027 + !DoOffset(ops.register_number, 1.1028 + -ops.offset * cie->data_alignment_factor)) 1.1029 + return false; 1.1030 + break; 1.1031 + 1.1032 + // The register's value is the sum of the CFA plus an offset. 1.1033 + case DW_CFA_val_offset: 1.1034 + if (!ParseOperands("ro", &ops) || 1.1035 + !DoValOffset(ops.register_number, 1.1036 + ops.offset * cie->data_alignment_factor)) 1.1037 + return false; 1.1038 + break; 1.1039 + 1.1040 + // The register's value is the sum of the CFA plus an offset. 1.1041 + case DW_CFA_val_offset_sf: 1.1042 + if (!ParseOperands("rs", &ops) || 1.1043 + !DoValOffset(ops.register_number, 1.1044 + ops.signed_offset * cie->data_alignment_factor)) 1.1045 + return false; 1.1046 + break; 1.1047 + 1.1048 + // The register has been saved in another register. 1.1049 + case DW_CFA_register: { 1.1050 + if (!ParseOperands("ro", &ops) || 1.1051 + !DoRule(ops.register_number, new RegisterRule(ops.offset))) 1.1052 + return false; 1.1053 + break; 1.1054 + } 1.1055 + 1.1056 + // An expression yields the address at which the register is saved. 1.1057 + case DW_CFA_expression: { 1.1058 + if (!ParseOperands("re", &ops) || 1.1059 + !DoRule(ops.register_number, new ExpressionRule(ops.expression))) 1.1060 + return false; 1.1061 + break; 1.1062 + } 1.1063 + 1.1064 + // An expression yields the caller's value for the register. 1.1065 + case DW_CFA_val_expression: { 1.1066 + if (!ParseOperands("re", &ops) || 1.1067 + !DoRule(ops.register_number, new ValExpressionRule(ops.expression))) 1.1068 + return false; 1.1069 + break; 1.1070 + } 1.1071 + 1.1072 + // Restore the rule established for a register by the CIE. 1.1073 + case DW_CFA_restore_extended: 1.1074 + if (!ParseOperands("r", &ops) || 1.1075 + !DoRestore( ops.register_number)) 1.1076 + return false; 1.1077 + break; 1.1078 + 1.1079 + // Save the current set of rules on a stack. 1.1080 + case DW_CFA_remember_state: 1.1081 + if (!saved_rules_) { 1.1082 + saved_rules_ = new std::stack<RuleMap>(); 1.1083 + } 1.1084 + saved_rules_->push(rules_); 1.1085 + break; 1.1086 + 1.1087 + // Pop the current set of rules off the stack. 1.1088 + case DW_CFA_restore_state: { 1.1089 + if (!saved_rules_ || saved_rules_->empty()) { 1.1090 + reporter_->EmptyStateStack(entry_->offset, entry_->kind, 1.1091 + CursorOffset()); 1.1092 + return false; 1.1093 + } 1.1094 + const RuleMap &new_rules = saved_rules_->top(); 1.1095 + if (rules_.CFARule() && !new_rules.CFARule()) { 1.1096 + reporter_->ClearingCFARule(entry_->offset, entry_->kind, 1.1097 + CursorOffset()); 1.1098 + return false; 1.1099 + } 1.1100 + rules_.HandleTransitionTo(handler_, address_, new_rules); 1.1101 + rules_ = new_rules; 1.1102 + saved_rules_->pop(); 1.1103 + break; 1.1104 + } 1.1105 + 1.1106 + // No operation. (Padding instruction.) 1.1107 + case DW_CFA_nop: 1.1108 + break; 1.1109 + 1.1110 + // A SPARC register window save: Registers 8 through 15 (%o0-%o7) 1.1111 + // are saved in registers 24 through 31 (%i0-%i7), and registers 1.1112 + // 16 through 31 (%l0-%l7 and %i0-%i7) are saved at CFA offsets 1.1113 + // (0-15 * the register size). The register numbers must be 1.1114 + // hard-coded. A GNU extension, and not a pretty one. 1.1115 + case DW_CFA_GNU_window_save: { 1.1116 + // Save %o0-%o7 in %i0-%i7. 1.1117 + for (int i = 8; i < 16; i++) 1.1118 + if (!DoRule(i, new RegisterRule(i + 16))) 1.1119 + return false; 1.1120 + // Save %l0-%l7 and %i0-%i7 at the CFA. 1.1121 + for (int i = 16; i < 32; i++) 1.1122 + // Assume that the byte reader's address size is the same as 1.1123 + // the architecture's register size. !@#%*^ hilarious. 1.1124 + if (!DoRule(i, new OffsetRule(Handler::kCFARegister, 1.1125 + (i - 16) * reader_->AddressSize()))) 1.1126 + return false; 1.1127 + break; 1.1128 + } 1.1129 + 1.1130 + // I'm not sure what this is. GDB doesn't use it for unwinding. 1.1131 + case DW_CFA_GNU_args_size: 1.1132 + if (!ParseOperands("o", &ops)) return false; 1.1133 + break; 1.1134 + 1.1135 + // An opcode we don't recognize. 1.1136 + default: { 1.1137 + reporter_->BadInstruction(entry_->offset, entry_->kind, CursorOffset()); 1.1138 + return false; 1.1139 + } 1.1140 + } 1.1141 + 1.1142 + return true; 1.1143 +} 1.1144 + 1.1145 +bool CallFrameInfo::State::DoDefCFA(unsigned base_register, long offset) { 1.1146 + Rule *rule = new ValOffsetRule(base_register, offset); 1.1147 + rules_.SetCFARule(rule); 1.1148 + return rule->Handle(handler_, address_, Handler::kCFARegister); 1.1149 +} 1.1150 + 1.1151 +bool CallFrameInfo::State::DoDefCFAOffset(long offset) { 1.1152 + Rule *cfa_rule = rules_.CFARule(); 1.1153 + if (!cfa_rule) { 1.1154 + reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset()); 1.1155 + return false; 1.1156 + } 1.1157 + cfa_rule->SetOffset(offset); 1.1158 + return cfa_rule->Handle(handler_, address_, Handler::kCFARegister); 1.1159 +} 1.1160 + 1.1161 +bool CallFrameInfo::State::DoRule(unsigned reg, Rule *rule) { 1.1162 + rules_.SetRegisterRule(reg, rule); 1.1163 + return rule->Handle(handler_, address_, reg); 1.1164 +} 1.1165 + 1.1166 +bool CallFrameInfo::State::DoOffset(unsigned reg, long offset) { 1.1167 + if (!rules_.CFARule()) { 1.1168 + reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset()); 1.1169 + return false; 1.1170 + } 1.1171 + return DoRule(reg, 1.1172 + new OffsetRule(Handler::kCFARegister, offset)); 1.1173 +} 1.1174 + 1.1175 +bool CallFrameInfo::State::DoValOffset(unsigned reg, long offset) { 1.1176 + if (!rules_.CFARule()) { 1.1177 + reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset()); 1.1178 + return false; 1.1179 + } 1.1180 + return DoRule(reg, 1.1181 + new ValOffsetRule(Handler::kCFARegister, offset)); 1.1182 +} 1.1183 + 1.1184 +bool CallFrameInfo::State::DoRestore(unsigned reg) { 1.1185 + // DW_CFA_restore and DW_CFA_restore_extended don't make sense in a CIE. 1.1186 + if (entry_->kind == kCIE) { 1.1187 + reporter_->RestoreInCIE(entry_->offset, CursorOffset()); 1.1188 + return false; 1.1189 + } 1.1190 + Rule *rule = cie_rules_.RegisterRule(reg); 1.1191 + if (!rule) { 1.1192 + // This isn't really the right thing to do, but since CFI generally 1.1193 + // only mentions callee-saves registers, and GCC's convention for 1.1194 + // callee-saves registers is that they are unchanged, it's a good 1.1195 + // approximation. 1.1196 + rule = new SameValueRule(); 1.1197 + } 1.1198 + return DoRule(reg, rule); 1.1199 +} 1.1200 + 1.1201 +bool CallFrameInfo::ReadEntryPrologue(const char *cursor, Entry *entry) { 1.1202 + const char *buffer_end = buffer_ + buffer_length_; 1.1203 + 1.1204 + // Initialize enough of ENTRY for use in error reporting. 1.1205 + entry->offset = cursor - buffer_; 1.1206 + entry->start = cursor; 1.1207 + entry->kind = kUnknown; 1.1208 + entry->end = NULL; 1.1209 + 1.1210 + // Read the initial length. This sets reader_'s offset size. 1.1211 + size_t length_size; 1.1212 + uint64 length = reader_->ReadInitialLength(cursor, &length_size); 1.1213 + if (length_size > size_t(buffer_end - cursor)) 1.1214 + return ReportIncomplete(entry); 1.1215 + cursor += length_size; 1.1216 + 1.1217 + // In a .eh_frame section, a length of zero marks the end of the series 1.1218 + // of entries. 1.1219 + if (length == 0 && eh_frame_) { 1.1220 + entry->kind = kTerminator; 1.1221 + entry->end = cursor; 1.1222 + return true; 1.1223 + } 1.1224 + 1.1225 + // Validate the length. 1.1226 + if (length > size_t(buffer_end - cursor)) 1.1227 + return ReportIncomplete(entry); 1.1228 + 1.1229 + // The length is the number of bytes after the initial length field; 1.1230 + // we have that position handy at this point, so compute the end 1.1231 + // now. (If we're parsing 64-bit-offset DWARF on a 32-bit machine, 1.1232 + // and the length didn't fit in a size_t, we would have rejected it 1.1233 + // above.) 1.1234 + entry->end = cursor + length; 1.1235 + 1.1236 + // Parse the next field: either the offset of a CIE or a CIE id. 1.1237 + size_t offset_size = reader_->OffsetSize(); 1.1238 + if (offset_size > size_t(entry->end - cursor)) return ReportIncomplete(entry); 1.1239 + entry->id = reader_->ReadOffset(cursor); 1.1240 + 1.1241 + // Don't advance cursor past id field yet; in .eh_frame data we need 1.1242 + // the id's position to compute the section offset of an FDE's CIE. 1.1243 + 1.1244 + // Now we can decide what kind of entry this is. 1.1245 + if (eh_frame_) { 1.1246 + // In .eh_frame data, an ID of zero marks the entry as a CIE, and 1.1247 + // anything else is an offset from the id field of the FDE to the start 1.1248 + // of the CIE. 1.1249 + if (entry->id == 0) { 1.1250 + entry->kind = kCIE; 1.1251 + } else { 1.1252 + entry->kind = kFDE; 1.1253 + // Turn the offset from the id into an offset from the buffer's start. 1.1254 + entry->id = (cursor - buffer_) - entry->id; 1.1255 + } 1.1256 + } else { 1.1257 + // In DWARF CFI data, an ID of ~0 (of the appropriate width, given the 1.1258 + // offset size for the entry) marks the entry as a CIE, and anything 1.1259 + // else is the offset of the CIE from the beginning of the section. 1.1260 + if (offset_size == 4) 1.1261 + entry->kind = (entry->id == 0xffffffff) ? kCIE : kFDE; 1.1262 + else { 1.1263 + MOZ_ASSERT(offset_size == 8); 1.1264 + entry->kind = (entry->id == 0xffffffffffffffffULL) ? kCIE : kFDE; 1.1265 + } 1.1266 + } 1.1267 + 1.1268 + // Now advance cursor past the id. 1.1269 + cursor += offset_size; 1.1270 + 1.1271 + // The fields specific to this kind of entry start here. 1.1272 + entry->fields = cursor; 1.1273 + 1.1274 + entry->cie = NULL; 1.1275 + 1.1276 + return true; 1.1277 +} 1.1278 + 1.1279 +bool CallFrameInfo::ReadCIEFields(CIE *cie) { 1.1280 + const char *cursor = cie->fields; 1.1281 + size_t len; 1.1282 + 1.1283 + MOZ_ASSERT(cie->kind == kCIE); 1.1284 + 1.1285 + // Prepare for early exit. 1.1286 + cie->version = 0; 1.1287 + cie->augmentation.clear(); 1.1288 + cie->code_alignment_factor = 0; 1.1289 + cie->data_alignment_factor = 0; 1.1290 + cie->return_address_register = 0; 1.1291 + cie->has_z_augmentation = false; 1.1292 + cie->pointer_encoding = DW_EH_PE_absptr; 1.1293 + cie->instructions = 0; 1.1294 + 1.1295 + // Parse the version number. 1.1296 + if (cie->end - cursor < 1) 1.1297 + return ReportIncomplete(cie); 1.1298 + cie->version = reader_->ReadOneByte(cursor); 1.1299 + cursor++; 1.1300 + 1.1301 + // If we don't recognize the version, we can't parse any more fields of the 1.1302 + // CIE. For DWARF CFI, we handle versions 1 through 3 (there was never a 1.1303 + // version 2 of CFI data). For .eh_frame, we handle versions 1 and 3 as well; 1.1304 + // the difference between those versions seems to be the same as for 1.1305 + // .debug_frame. 1.1306 + if (cie->version < 1 || cie->version > 3) { 1.1307 + reporter_->UnrecognizedVersion(cie->offset, cie->version); 1.1308 + return false; 1.1309 + } 1.1310 + 1.1311 + const char *augmentation_start = cursor; 1.1312 + const void *augmentation_end = 1.1313 + memchr(augmentation_start, '\0', cie->end - augmentation_start); 1.1314 + if (! augmentation_end) return ReportIncomplete(cie); 1.1315 + cursor = static_cast<const char *>(augmentation_end); 1.1316 + cie->augmentation = string(augmentation_start, 1.1317 + cursor - augmentation_start); 1.1318 + // Skip the terminating '\0'. 1.1319 + cursor++; 1.1320 + 1.1321 + // Is this CFI augmented? 1.1322 + if (!cie->augmentation.empty()) { 1.1323 + // Is it an augmentation we recognize? 1.1324 + if (cie->augmentation[0] == DW_Z_augmentation_start) { 1.1325 + // Linux C++ ABI 'z' augmentation, used for exception handling data. 1.1326 + cie->has_z_augmentation = true; 1.1327 + } else { 1.1328 + // Not an augmentation we recognize. Augmentations can have arbitrary 1.1329 + // effects on the form of rest of the content, so we have to give up. 1.1330 + reporter_->UnrecognizedAugmentation(cie->offset, cie->augmentation); 1.1331 + return false; 1.1332 + } 1.1333 + } 1.1334 + 1.1335 + // Parse the code alignment factor. 1.1336 + cie->code_alignment_factor = reader_->ReadUnsignedLEB128(cursor, &len); 1.1337 + if (size_t(cie->end - cursor) < len) return ReportIncomplete(cie); 1.1338 + cursor += len; 1.1339 + 1.1340 + // Parse the data alignment factor. 1.1341 + cie->data_alignment_factor = reader_->ReadSignedLEB128(cursor, &len); 1.1342 + if (size_t(cie->end - cursor) < len) return ReportIncomplete(cie); 1.1343 + cursor += len; 1.1344 + 1.1345 + // Parse the return address register. This is a ubyte in version 1, and 1.1346 + // a ULEB128 in version 3. 1.1347 + if (cie->version == 1) { 1.1348 + if (cursor >= cie->end) return ReportIncomplete(cie); 1.1349 + cie->return_address_register = uint8(*cursor++); 1.1350 + } else { 1.1351 + cie->return_address_register = reader_->ReadUnsignedLEB128(cursor, &len); 1.1352 + if (size_t(cie->end - cursor) < len) return ReportIncomplete(cie); 1.1353 + cursor += len; 1.1354 + } 1.1355 + 1.1356 + // If we have a 'z' augmentation string, find the augmentation data and 1.1357 + // use the augmentation string to parse it. 1.1358 + if (cie->has_z_augmentation) { 1.1359 + uint64_t data_size = reader_->ReadUnsignedLEB128(cursor, &len); 1.1360 + if (size_t(cie->end - cursor) < len + data_size) 1.1361 + return ReportIncomplete(cie); 1.1362 + cursor += len; 1.1363 + const char *data = cursor; 1.1364 + cursor += data_size; 1.1365 + const char *data_end = cursor; 1.1366 + 1.1367 + cie->has_z_lsda = false; 1.1368 + cie->has_z_personality = false; 1.1369 + cie->has_z_signal_frame = false; 1.1370 + 1.1371 + // Walk the augmentation string, and extract values from the 1.1372 + // augmentation data as the string directs. 1.1373 + for (size_t i = 1; i < cie->augmentation.size(); i++) { 1.1374 + switch (cie->augmentation[i]) { 1.1375 + case DW_Z_has_LSDA: 1.1376 + // The CIE's augmentation data holds the language-specific data 1.1377 + // area pointer's encoding, and the FDE's augmentation data holds 1.1378 + // the pointer itself. 1.1379 + cie->has_z_lsda = true; 1.1380 + // Fetch the LSDA encoding from the augmentation data. 1.1381 + if (data >= data_end) return ReportIncomplete(cie); 1.1382 + cie->lsda_encoding = DwarfPointerEncoding(*data++); 1.1383 + if (!reader_->ValidEncoding(cie->lsda_encoding)) { 1.1384 + reporter_->InvalidPointerEncoding(cie->offset, cie->lsda_encoding); 1.1385 + return false; 1.1386 + } 1.1387 + // Don't check if the encoding is usable here --- we haven't 1.1388 + // read the FDE's fields yet, so we're not prepared for 1.1389 + // DW_EH_PE_funcrel, although that's a fine encoding for the 1.1390 + // LSDA to use, since it appears in the FDE. 1.1391 + break; 1.1392 + 1.1393 + case DW_Z_has_personality_routine: 1.1394 + // The CIE's augmentation data holds the personality routine 1.1395 + // pointer's encoding, followed by the pointer itself. 1.1396 + cie->has_z_personality = true; 1.1397 + // Fetch the personality routine pointer's encoding from the 1.1398 + // augmentation data. 1.1399 + if (data >= data_end) return ReportIncomplete(cie); 1.1400 + cie->personality_encoding = DwarfPointerEncoding(*data++); 1.1401 + if (!reader_->ValidEncoding(cie->personality_encoding)) { 1.1402 + reporter_->InvalidPointerEncoding(cie->offset, 1.1403 + cie->personality_encoding); 1.1404 + return false; 1.1405 + } 1.1406 + if (!reader_->UsableEncoding(cie->personality_encoding)) { 1.1407 + reporter_->UnusablePointerEncoding(cie->offset, 1.1408 + cie->personality_encoding); 1.1409 + return false; 1.1410 + } 1.1411 + // Fetch the personality routine's pointer itself from the data. 1.1412 + cie->personality_address = 1.1413 + reader_->ReadEncodedPointer(data, cie->personality_encoding, 1.1414 + &len); 1.1415 + if (len > size_t(data_end - data)) 1.1416 + return ReportIncomplete(cie); 1.1417 + data += len; 1.1418 + break; 1.1419 + 1.1420 + case DW_Z_has_FDE_address_encoding: 1.1421 + // The CIE's augmentation data holds the pointer encoding to use 1.1422 + // for addresses in the FDE. 1.1423 + if (data >= data_end) return ReportIncomplete(cie); 1.1424 + cie->pointer_encoding = DwarfPointerEncoding(*data++); 1.1425 + if (!reader_->ValidEncoding(cie->pointer_encoding)) { 1.1426 + reporter_->InvalidPointerEncoding(cie->offset, 1.1427 + cie->pointer_encoding); 1.1428 + return false; 1.1429 + } 1.1430 + if (!reader_->UsableEncoding(cie->pointer_encoding)) { 1.1431 + reporter_->UnusablePointerEncoding(cie->offset, 1.1432 + cie->pointer_encoding); 1.1433 + return false; 1.1434 + } 1.1435 + break; 1.1436 + 1.1437 + case DW_Z_is_signal_trampoline: 1.1438 + // Frames using this CIE are signal delivery frames. 1.1439 + cie->has_z_signal_frame = true; 1.1440 + break; 1.1441 + 1.1442 + default: 1.1443 + // An augmentation we don't recognize. 1.1444 + reporter_->UnrecognizedAugmentation(cie->offset, cie->augmentation); 1.1445 + return false; 1.1446 + } 1.1447 + } 1.1448 + } 1.1449 + 1.1450 + // The CIE's instructions start here. 1.1451 + cie->instructions = cursor; 1.1452 + 1.1453 + return true; 1.1454 +} 1.1455 + 1.1456 +bool CallFrameInfo::ReadFDEFields(FDE *fde) { 1.1457 + const char *cursor = fde->fields; 1.1458 + size_t size; 1.1459 + 1.1460 + fde->address = reader_->ReadEncodedPointer(cursor, fde->cie->pointer_encoding, 1.1461 + &size); 1.1462 + if (size > size_t(fde->end - cursor)) 1.1463 + return ReportIncomplete(fde); 1.1464 + cursor += size; 1.1465 + reader_->SetFunctionBase(fde->address); 1.1466 + 1.1467 + // For the length, we strip off the upper nybble of the encoding used for 1.1468 + // the starting address. 1.1469 + DwarfPointerEncoding length_encoding = 1.1470 + DwarfPointerEncoding(fde->cie->pointer_encoding & 0x0f); 1.1471 + fde->size = reader_->ReadEncodedPointer(cursor, length_encoding, &size); 1.1472 + if (size > size_t(fde->end - cursor)) 1.1473 + return ReportIncomplete(fde); 1.1474 + cursor += size; 1.1475 + 1.1476 + // If the CIE has a 'z' augmentation string, then augmentation data 1.1477 + // appears here. 1.1478 + if (fde->cie->has_z_augmentation) { 1.1479 + uint64_t data_size = reader_->ReadUnsignedLEB128(cursor, &size); 1.1480 + if (size_t(fde->end - cursor) < size + data_size) 1.1481 + return ReportIncomplete(fde); 1.1482 + cursor += size; 1.1483 + 1.1484 + // In the abstract, we should walk the augmentation string, and extract 1.1485 + // items from the FDE's augmentation data as we encounter augmentation 1.1486 + // string characters that specify their presence: the ordering of items 1.1487 + // in the augmentation string determines the arrangement of values in 1.1488 + // the augmentation data. 1.1489 + // 1.1490 + // In practice, there's only ever one value in FDE augmentation data 1.1491 + // that we support --- the LSDA pointer --- and we have to bail if we 1.1492 + // see any unrecognized augmentation string characters. So if there is 1.1493 + // anything here at all, we know what it is, and where it starts. 1.1494 + if (fde->cie->has_z_lsda) { 1.1495 + // Check whether the LSDA's pointer encoding is usable now: only once 1.1496 + // we've parsed the FDE's starting address do we call reader_-> 1.1497 + // SetFunctionBase, so that the DW_EH_PE_funcrel encoding becomes 1.1498 + // usable. 1.1499 + if (!reader_->UsableEncoding(fde->cie->lsda_encoding)) { 1.1500 + reporter_->UnusablePointerEncoding(fde->cie->offset, 1.1501 + fde->cie->lsda_encoding); 1.1502 + return false; 1.1503 + } 1.1504 + 1.1505 + fde->lsda_address = 1.1506 + reader_->ReadEncodedPointer(cursor, fde->cie->lsda_encoding, &size); 1.1507 + if (size > data_size) 1.1508 + return ReportIncomplete(fde); 1.1509 + // Ideally, we would also complain here if there were unconsumed 1.1510 + // augmentation data. 1.1511 + } 1.1512 + 1.1513 + cursor += data_size; 1.1514 + } 1.1515 + 1.1516 + // The FDE's instructions start after those. 1.1517 + fde->instructions = cursor; 1.1518 + 1.1519 + return true; 1.1520 +} 1.1521 + 1.1522 +bool CallFrameInfo::Start() { 1.1523 + const char *buffer_end = buffer_ + buffer_length_; 1.1524 + const char *cursor; 1.1525 + bool all_ok = true; 1.1526 + const char *entry_end; 1.1527 + bool ok; 1.1528 + 1.1529 + // Traverse all the entries in buffer_, skipping CIEs and offering 1.1530 + // FDEs to the handler. 1.1531 + for (cursor = buffer_; cursor < buffer_end; 1.1532 + cursor = entry_end, all_ok = all_ok && ok) { 1.1533 + FDE fde; 1.1534 + 1.1535 + // Make it easy to skip this entry with 'continue': assume that 1.1536 + // things are not okay until we've checked all the data, and 1.1537 + // prepare the address of the next entry. 1.1538 + ok = false; 1.1539 + 1.1540 + // Read the entry's prologue. 1.1541 + if (!ReadEntryPrologue(cursor, &fde)) { 1.1542 + if (!fde.end) { 1.1543 + // If we couldn't even figure out this entry's extent, then we 1.1544 + // must stop processing entries altogether. 1.1545 + all_ok = false; 1.1546 + break; 1.1547 + } 1.1548 + entry_end = fde.end; 1.1549 + continue; 1.1550 + } 1.1551 + 1.1552 + // The next iteration picks up after this entry. 1.1553 + entry_end = fde.end; 1.1554 + 1.1555 + // Did we see an .eh_frame terminating mark? 1.1556 + if (fde.kind == kTerminator) { 1.1557 + // If there appears to be more data left in the section after the 1.1558 + // terminating mark, warn the user. But this is just a warning; 1.1559 + // we leave all_ok true. 1.1560 + if (fde.end < buffer_end) reporter_->EarlyEHTerminator(fde.offset); 1.1561 + break; 1.1562 + } 1.1563 + 1.1564 + // In this loop, we skip CIEs. We only parse them fully when we 1.1565 + // parse an FDE that refers to them. This limits our memory 1.1566 + // consumption (beyond the buffer itself) to that needed to 1.1567 + // process the largest single entry. 1.1568 + if (fde.kind != kFDE) { 1.1569 + ok = true; 1.1570 + continue; 1.1571 + } 1.1572 + 1.1573 + // Validate the CIE pointer. 1.1574 + if (fde.id > buffer_length_) { 1.1575 + reporter_->CIEPointerOutOfRange(fde.offset, fde.id); 1.1576 + continue; 1.1577 + } 1.1578 + 1.1579 + CIE cie; 1.1580 + 1.1581 + // Parse this FDE's CIE header. 1.1582 + if (!ReadEntryPrologue(buffer_ + fde.id, &cie)) 1.1583 + continue; 1.1584 + // This had better be an actual CIE. 1.1585 + if (cie.kind != kCIE) { 1.1586 + reporter_->BadCIEId(fde.offset, fde.id); 1.1587 + continue; 1.1588 + } 1.1589 + if (!ReadCIEFields(&cie)) 1.1590 + continue; 1.1591 + 1.1592 + // We now have the values that govern both the CIE and the FDE. 1.1593 + cie.cie = &cie; 1.1594 + fde.cie = &cie; 1.1595 + 1.1596 + // Parse the FDE's header. 1.1597 + if (!ReadFDEFields(&fde)) 1.1598 + continue; 1.1599 + 1.1600 + // Call Entry to ask the consumer if they're interested. 1.1601 + if (!handler_->Entry(fde.offset, fde.address, fde.size, 1.1602 + cie.version, cie.augmentation, 1.1603 + cie.return_address_register)) { 1.1604 + // The handler isn't interested in this entry. That's not an error. 1.1605 + ok = true; 1.1606 + continue; 1.1607 + } 1.1608 + 1.1609 + if (cie.has_z_augmentation) { 1.1610 + // Report the personality routine address, if we have one. 1.1611 + if (cie.has_z_personality) { 1.1612 + if (!handler_ 1.1613 + ->PersonalityRoutine(cie.personality_address, 1.1614 + IsIndirectEncoding(cie.personality_encoding))) 1.1615 + continue; 1.1616 + } 1.1617 + 1.1618 + // Report the language-specific data area address, if we have one. 1.1619 + if (cie.has_z_lsda) { 1.1620 + if (!handler_ 1.1621 + ->LanguageSpecificDataArea(fde.lsda_address, 1.1622 + IsIndirectEncoding(cie.lsda_encoding))) 1.1623 + continue; 1.1624 + } 1.1625 + 1.1626 + // If this is a signal-handling frame, report that. 1.1627 + if (cie.has_z_signal_frame) { 1.1628 + if (!handler_->SignalHandler()) 1.1629 + continue; 1.1630 + } 1.1631 + } 1.1632 + 1.1633 + // Interpret the CIE's instructions, and then the FDE's instructions. 1.1634 + State state(reader_, handler_, reporter_, fde.address); 1.1635 + ok = state.InterpretCIE(cie) && state.InterpretFDE(fde); 1.1636 + 1.1637 + // Tell the ByteReader that the function start address from the 1.1638 + // FDE header is no longer valid. 1.1639 + reader_->ClearFunctionBase(); 1.1640 + 1.1641 + // Report the end of the entry. 1.1642 + handler_->End(); 1.1643 + } 1.1644 + 1.1645 + return all_ok; 1.1646 +} 1.1647 + 1.1648 +const char *CallFrameInfo::KindName(EntryKind kind) { 1.1649 + if (kind == CallFrameInfo::kUnknown) 1.1650 + return "entry"; 1.1651 + else if (kind == CallFrameInfo::kCIE) 1.1652 + return "common information entry"; 1.1653 + else if (kind == CallFrameInfo::kFDE) 1.1654 + return "frame description entry"; 1.1655 + else { 1.1656 + MOZ_ASSERT (kind == CallFrameInfo::kTerminator); 1.1657 + return ".eh_frame sequence terminator"; 1.1658 + } 1.1659 +} 1.1660 + 1.1661 +bool CallFrameInfo::ReportIncomplete(Entry *entry) { 1.1662 + reporter_->Incomplete(entry->offset, entry->kind); 1.1663 + return false; 1.1664 +} 1.1665 + 1.1666 +void CallFrameInfo::Reporter::Incomplete(uint64 offset, 1.1667 + CallFrameInfo::EntryKind kind) { 1.1668 + char buf[300]; 1.1669 + snprintf(buf, sizeof(buf), 1.1670 + "%s: CFI %s at offset 0x%llx in '%s': entry ends early\n", 1.1671 + filename_.c_str(), CallFrameInfo::KindName(kind), offset, 1.1672 + section_.c_str()); 1.1673 + log_(buf); 1.1674 +} 1.1675 + 1.1676 +void CallFrameInfo::Reporter::EarlyEHTerminator(uint64 offset) { 1.1677 + char buf[300]; 1.1678 + snprintf(buf, sizeof(buf), 1.1679 + "%s: CFI at offset 0x%llx in '%s': saw end-of-data marker" 1.1680 + " before end of section contents\n", 1.1681 + filename_.c_str(), offset, section_.c_str()); 1.1682 + log_(buf); 1.1683 +} 1.1684 + 1.1685 +void CallFrameInfo::Reporter::CIEPointerOutOfRange(uint64 offset, 1.1686 + uint64 cie_offset) { 1.1687 + char buf[300]; 1.1688 + snprintf(buf, sizeof(buf), 1.1689 + "%s: CFI frame description entry at offset 0x%llx in '%s':" 1.1690 + " CIE pointer is out of range: 0x%llx\n", 1.1691 + filename_.c_str(), offset, section_.c_str(), cie_offset); 1.1692 + log_(buf); 1.1693 +} 1.1694 + 1.1695 +void CallFrameInfo::Reporter::BadCIEId(uint64 offset, uint64 cie_offset) { 1.1696 + char buf[300]; 1.1697 + snprintf(buf, sizeof(buf), 1.1698 + "%s: CFI frame description entry at offset 0x%llx in '%s':" 1.1699 + " CIE pointer does not point to a CIE: 0x%llx\n", 1.1700 + filename_.c_str(), offset, section_.c_str(), cie_offset); 1.1701 + log_(buf); 1.1702 +} 1.1703 + 1.1704 +void CallFrameInfo::Reporter::UnrecognizedVersion(uint64 offset, int version) { 1.1705 + char buf[300]; 1.1706 + snprintf(buf, sizeof(buf), 1.1707 + "%s: CFI frame description entry at offset 0x%llx in '%s':" 1.1708 + " CIE specifies unrecognized version: %d\n", 1.1709 + filename_.c_str(), offset, section_.c_str(), version); 1.1710 + log_(buf); 1.1711 +} 1.1712 + 1.1713 +void CallFrameInfo::Reporter::UnrecognizedAugmentation(uint64 offset, 1.1714 + const string &aug) { 1.1715 + char buf[300]; 1.1716 + snprintf(buf, sizeof(buf), 1.1717 + "%s: CFI frame description entry at offset 0x%llx in '%s':" 1.1718 + " CIE specifies unrecognized augmentation: '%s'\n", 1.1719 + filename_.c_str(), offset, section_.c_str(), aug.c_str()); 1.1720 + log_(buf); 1.1721 +} 1.1722 + 1.1723 +void CallFrameInfo::Reporter::InvalidPointerEncoding(uint64 offset, 1.1724 + uint8 encoding) { 1.1725 + char buf[300]; 1.1726 + snprintf(buf, sizeof(buf), 1.1727 + "%s: CFI common information entry at offset 0x%llx in '%s':" 1.1728 + " 'z' augmentation specifies invalid pointer encoding: 0x%02x\n", 1.1729 + filename_.c_str(), offset, section_.c_str(), encoding); 1.1730 + log_(buf); 1.1731 +} 1.1732 + 1.1733 +void CallFrameInfo::Reporter::UnusablePointerEncoding(uint64 offset, 1.1734 + uint8 encoding) { 1.1735 + char buf[300]; 1.1736 + snprintf(buf, sizeof(buf), 1.1737 + "%s: CFI common information entry at offset 0x%llx in '%s':" 1.1738 + " 'z' augmentation specifies a pointer encoding for which" 1.1739 + " we have no base address: 0x%02x\n", 1.1740 + filename_.c_str(), offset, section_.c_str(), encoding); 1.1741 + log_(buf); 1.1742 +} 1.1743 + 1.1744 +void CallFrameInfo::Reporter::RestoreInCIE(uint64 offset, uint64 insn_offset) { 1.1745 + char buf[300]; 1.1746 + snprintf(buf, sizeof(buf), 1.1747 + "%s: CFI common information entry at offset 0x%llx in '%s':" 1.1748 + " the DW_CFA_restore instruction at offset 0x%llx" 1.1749 + " cannot be used in a common information entry\n", 1.1750 + filename_.c_str(), offset, section_.c_str(), insn_offset); 1.1751 + log_(buf); 1.1752 +} 1.1753 + 1.1754 +void CallFrameInfo::Reporter::BadInstruction(uint64 offset, 1.1755 + CallFrameInfo::EntryKind kind, 1.1756 + uint64 insn_offset) { 1.1757 + char buf[300]; 1.1758 + snprintf(buf, sizeof(buf), 1.1759 + "%s: CFI %s at offset 0x%llx in section '%s':" 1.1760 + " the instruction at offset 0x%llx is unrecognized\n", 1.1761 + filename_.c_str(), CallFrameInfo::KindName(kind), 1.1762 + offset, section_.c_str(), insn_offset); 1.1763 + log_(buf); 1.1764 +} 1.1765 + 1.1766 +void CallFrameInfo::Reporter::NoCFARule(uint64 offset, 1.1767 + CallFrameInfo::EntryKind kind, 1.1768 + uint64 insn_offset) { 1.1769 + char buf[300]; 1.1770 + snprintf(buf, sizeof(buf), 1.1771 + "%s: CFI %s at offset 0x%llx in section '%s':" 1.1772 + " the instruction at offset 0x%llx assumes that a CFA rule has" 1.1773 + " been set, but none has been set\n", 1.1774 + filename_.c_str(), CallFrameInfo::KindName(kind), offset, 1.1775 + section_.c_str(), insn_offset); 1.1776 + log_(buf); 1.1777 +} 1.1778 + 1.1779 +void CallFrameInfo::Reporter::EmptyStateStack(uint64 offset, 1.1780 + CallFrameInfo::EntryKind kind, 1.1781 + uint64 insn_offset) { 1.1782 + char buf[300]; 1.1783 + snprintf(buf, sizeof(buf), 1.1784 + "%s: CFI %s at offset 0x%llx in section '%s':" 1.1785 + " the DW_CFA_restore_state instruction at offset 0x%llx" 1.1786 + " should pop a saved state from the stack, but the stack is empty\n", 1.1787 + filename_.c_str(), CallFrameInfo::KindName(kind), offset, 1.1788 + section_.c_str(), insn_offset); 1.1789 + log_(buf); 1.1790 +} 1.1791 + 1.1792 +void CallFrameInfo::Reporter::ClearingCFARule(uint64 offset, 1.1793 + CallFrameInfo::EntryKind kind, 1.1794 + uint64 insn_offset) { 1.1795 + char buf[300]; 1.1796 + snprintf(buf, sizeof(buf), 1.1797 + "%s: CFI %s at offset 0x%llx in section '%s':" 1.1798 + " the DW_CFA_restore_state instruction at offset 0x%llx" 1.1799 + " would clear the CFA rule in effect\n", 1.1800 + filename_.c_str(), CallFrameInfo::KindName(kind), offset, 1.1801 + section_.c_str(), insn_offset); 1.1802 + log_(buf); 1.1803 +} 1.1804 + 1.1805 + 1.1806 +const unsigned int DwarfCFIToModule::RegisterNames::I386() { 1.1807 + /* 1.1808 + 8 "$eax", "$ecx", "$edx", "$ebx", "$esp", "$ebp", "$esi", "$edi", 1.1809 + 3 "$eip", "$eflags", "$unused1", 1.1810 + 8 "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7", 1.1811 + 2 "$unused2", "$unused3", 1.1812 + 8 "$xmm0", "$xmm1", "$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7", 1.1813 + 8 "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7", 1.1814 + 3 "$fcw", "$fsw", "$mxcsr", 1.1815 + 8 "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused4", "$unused5", 1.1816 + 2 "$tr", "$ldtr" 1.1817 + */ 1.1818 + return 8 + 3 + 8 + 2 + 8 + 8 + 3 + 8 + 2; 1.1819 +} 1.1820 + 1.1821 +const unsigned int DwarfCFIToModule::RegisterNames::X86_64() { 1.1822 + /* 1.1823 + 8 "$rax", "$rdx", "$rcx", "$rbx", "$rsi", "$rdi", "$rbp", "$rsp", 1.1824 + 8 "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", 1.1825 + 1 "$rip", 1.1826 + 8 "$xmm0","$xmm1","$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7", 1.1827 + 8 "$xmm8","$xmm9","$xmm10","$xmm11","$xmm12","$xmm13","$xmm14","$xmm15", 1.1828 + 8 "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7", 1.1829 + 8 "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7", 1.1830 + 1 "$rflags", 1.1831 + 8 "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused1", "$unused2", 1.1832 + 4 "$fs.base", "$gs.base", "$unused3", "$unused4", 1.1833 + 2 "$tr", "$ldtr", 1.1834 + 3 "$mxcsr", "$fcw", "$fsw" 1.1835 + */ 1.1836 + return 8 + 8 + 1 + 8 + 8 + 8 + 8 + 1 + 8 + 4 + 2 + 3; 1.1837 +} 1.1838 + 1.1839 +// Per ARM IHI 0040A, section 3.1 1.1840 +const unsigned int DwarfCFIToModule::RegisterNames::ARM() { 1.1841 + /* 1.1842 + 8 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 1.1843 + 8 "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", 1.1844 + 8 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 1.1845 + 8 "fps", "cpsr", "", "", "", "", "", "", 1.1846 + 8 "", "", "", "", "", "", "", "", 1.1847 + 8 "", "", "", "", "", "", "", "", 1.1848 + 8 "", "", "", "", "", "", "", "", 1.1849 + 8 "", "", "", "", "", "", "", "", 1.1850 + 8 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", 1.1851 + 8 "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", 1.1852 + 8 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", 1.1853 + 8 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", 1.1854 + 8 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7" 1.1855 + */ 1.1856 + return 13 * 8; 1.1857 +} 1.1858 + 1.1859 +bool DwarfCFIToModule::Entry(size_t offset, uint64 address, uint64 length, 1.1860 + uint8 version, const string &augmentation, 1.1861 + unsigned return_address) { 1.1862 + if (DEBUG_DWARF) 1.1863 + printf("LUL.DW DwarfCFIToModule::Entry 0x%llx,+%lld\n", address, length); 1.1864 + 1.1865 + summ_->Entry(address, length); 1.1866 + 1.1867 + // If dwarf2reader::CallFrameInfo can handle this version and 1.1868 + // augmentation, then we should be okay with that, so there's no 1.1869 + // need to check them here. 1.1870 + 1.1871 + // Get ready to collect entries. 1.1872 + return_address_ = return_address; 1.1873 + 1.1874 + // Breakpad STACK CFI records must provide a .ra rule, but DWARF CFI 1.1875 + // may not establish any rule for .ra if the return address column 1.1876 + // is an ordinary register, and that register holds the return 1.1877 + // address on entry to the function. So establish an initial .ra 1.1878 + // rule citing the return address register. 1.1879 + if (return_address_ < num_dw_regs_) { 1.1880 + summ_->Rule(address, return_address_, return_address, 0, false); 1.1881 + } 1.1882 + 1.1883 + return true; 1.1884 +} 1.1885 + 1.1886 +const UniqueString* DwarfCFIToModule::RegisterName(int i) { 1.1887 + if (i < 0) { 1.1888 + MOZ_ASSERT(i == kCFARegister); 1.1889 + return ustr__ZDcfa(); 1.1890 + } 1.1891 + unsigned reg = i; 1.1892 + if (reg == return_address_) 1.1893 + return ustr__ZDra(); 1.1894 + 1.1895 + char buf[30]; 1.1896 + sprintf(buf, "dwarf_reg_%u", reg); 1.1897 + return ToUniqueString(buf); 1.1898 +} 1.1899 + 1.1900 +bool DwarfCFIToModule::UndefinedRule(uint64 address, int reg) { 1.1901 + reporter_->UndefinedNotSupported(entry_offset_, RegisterName(reg)); 1.1902 + // Treat this as a non-fatal error. 1.1903 + return true; 1.1904 +} 1.1905 + 1.1906 +bool DwarfCFIToModule::SameValueRule(uint64 address, int reg) { 1.1907 + if (DEBUG_DWARF) 1.1908 + printf("LUL.DW 0x%llx: old r%d = Same\n", address, reg); 1.1909 + // reg + 0 1.1910 + summ_->Rule(address, reg, reg, 0, false); 1.1911 + return true; 1.1912 +} 1.1913 + 1.1914 +bool DwarfCFIToModule::OffsetRule(uint64 address, int reg, 1.1915 + int base_register, long offset) { 1.1916 + if (DEBUG_DWARF) 1.1917 + printf("LUL.DW 0x%llx: old r%d = *(r%d + %ld)\n", 1.1918 + address, reg, base_register, offset); 1.1919 + // *(base_register + offset) 1.1920 + summ_->Rule(address, reg, base_register, offset, true); 1.1921 + return true; 1.1922 +} 1.1923 + 1.1924 +bool DwarfCFIToModule::ValOffsetRule(uint64 address, int reg, 1.1925 + int base_register, long offset) { 1.1926 + if (DEBUG_DWARF) 1.1927 + printf("LUL.DW 0x%llx: old r%d = r%d + %ld\n", 1.1928 + address, reg, base_register, offset); 1.1929 + // base_register + offset 1.1930 + summ_->Rule(address, reg, base_register, offset, false); 1.1931 + return true; 1.1932 +} 1.1933 + 1.1934 +bool DwarfCFIToModule::RegisterRule(uint64 address, int reg, 1.1935 + int base_register) { 1.1936 + if (DEBUG_DWARF) 1.1937 + printf("LUL.DW 0x%llx: old r%d = r%d\n", address, reg, base_register); 1.1938 + // base_register + 0 1.1939 + summ_->Rule(address, reg, base_register, 0, false); 1.1940 + return true; 1.1941 +} 1.1942 + 1.1943 +bool DwarfCFIToModule::ExpressionRule(uint64 address, int reg, 1.1944 + const string &expression) { 1.1945 + reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg)); 1.1946 + // Treat this as a non-fatal error. 1.1947 + return true; 1.1948 +} 1.1949 + 1.1950 +bool DwarfCFIToModule::ValExpressionRule(uint64 address, int reg, 1.1951 + const string &expression) { 1.1952 + reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg)); 1.1953 + // Treat this as a non-fatal error. 1.1954 + return true; 1.1955 +} 1.1956 + 1.1957 +bool DwarfCFIToModule::End() { 1.1958 + //module_->AddStackFrameEntry(entry_); 1.1959 + if (DEBUG_DWARF) 1.1960 + printf("LUL.DW DwarfCFIToModule::End()\n"); 1.1961 + summ_->End(); 1.1962 + return true; 1.1963 +} 1.1964 + 1.1965 +void DwarfCFIToModule::Reporter::UndefinedNotSupported( 1.1966 + size_t offset, 1.1967 + const UniqueString* reg) { 1.1968 + char buf[300]; 1.1969 + snprintf(buf, sizeof(buf), 1.1970 + "DwarfCFIToModule::Reporter::UndefinedNotSupported()\n"); 1.1971 + log_(buf); 1.1972 + //BPLOG(INFO) << file_ << ", section '" << section_ 1.1973 + // << "': the call frame entry at offset 0x" 1.1974 + // << std::setbase(16) << offset << std::setbase(10) 1.1975 + // << " sets the rule for register '" << FromUniqueString(reg) 1.1976 + // << "' to 'undefined', but the Breakpad symbol file format cannot " 1.1977 + // << " express this"; 1.1978 +} 1.1979 + 1.1980 +// FIXME: move this somewhere sensible 1.1981 +static bool is_power_of_2(uint64_t n) 1.1982 +{ 1.1983 + int i, nSetBits = 0; 1.1984 + for (i = 0; i < 8*(int)sizeof(n); i++) { 1.1985 + if ((n & ((uint64_t)1) << i) != 0) 1.1986 + nSetBits++; 1.1987 + } 1.1988 + return nSetBits <= 1; 1.1989 +} 1.1990 + 1.1991 +void DwarfCFIToModule::Reporter::ExpressionsNotSupported( 1.1992 + size_t offset, 1.1993 + const UniqueString* reg) { 1.1994 + static uint64_t n_complaints = 0; // This isn't threadsafe 1.1995 + n_complaints++; 1.1996 + if (!is_power_of_2(n_complaints)) 1.1997 + return; 1.1998 + char buf[300]; 1.1999 + snprintf(buf, sizeof(buf), 1.2000 + "DwarfCFIToModule::Reporter::" 1.2001 + "ExpressionsNotSupported(shown %llu times)\n", 1.2002 + (unsigned long long int)n_complaints); 1.2003 + log_(buf); 1.2004 + //BPLOG(INFO) << file_ << ", section '" << section_ 1.2005 + // << "': the call frame entry at offset 0x" 1.2006 + // << std::setbase(16) << offset << std::setbase(10) 1.2007 + // << " uses a DWARF expression to describe how to recover register '" 1.2008 + // << FromUniqueString(reg) << "', but this translator cannot yet " 1.2009 + // << "translate DWARF expressions to Breakpad postfix expressions (shown " 1.2010 + // << n_complaints << " times)"; 1.2011 +} 1.2012 + 1.2013 +} // namespace lul