LCOV - code coverage report
Current view: top level - tools/profiler/lul - LulDwarf.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 941 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 136 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : 
       4             : // Copyright (c) 2010 Google Inc. All Rights Reserved.
       5             : //
       6             : // Redistribution and use in source and binary forms, with or without
       7             : // modification, are permitted provided that the following conditions are
       8             : // met:
       9             : //
      10             : //     * Redistributions of source code must retain the above copyright
      11             : // notice, this list of conditions and the following disclaimer.
      12             : //     * Redistributions in binary form must reproduce the above
      13             : // copyright notice, this list of conditions and the following disclaimer
      14             : // in the documentation and/or other materials provided with the
      15             : // distribution.
      16             : //     * Neither the name of Google Inc. nor the names of its
      17             : // contributors may be used to endorse or promote products derived from
      18             : // this software without specific prior written permission.
      19             : //
      20             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      22             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      23             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      24             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      25             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      26             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      27             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      28             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      29             : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      30             : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      31             : 
      32             : // CFI reader author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
      33             : // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
      34             : 
      35             : // Implementation of dwarf2reader::LineInfo, dwarf2reader::CompilationUnit,
      36             : // and dwarf2reader::CallFrameInfo. See dwarf2reader.h for details.
      37             : 
      38             : // This file is derived from the following files in
      39             : // toolkit/crashreporter/google-breakpad:
      40             : //   src/common/dwarf/bytereader.cc
      41             : //   src/common/dwarf/dwarf2reader.cc
      42             : //   src/common/dwarf_cfi_to_module.cc
      43             : 
      44             : #include <stdint.h>
      45             : #include <stdio.h>
      46             : #include <string.h>
      47             : #include <stdlib.h>
      48             : 
      49             : #include <map>
      50             : #include <stack>
      51             : #include <string>
      52             : 
      53             : #include "mozilla/Assertions.h"
      54             : #include "mozilla/Sprintf.h"
      55             : 
      56             : #include "LulCommonExt.h"
      57             : #include "LulDwarfInt.h"
      58             : 
      59             : 
      60             : // Set this to 1 for verbose logging
      61             : #define DEBUG_DWARF 0
      62             : 
      63             : 
      64             : namespace lul {
      65             : 
      66             : using std::string;
      67             : 
      68           0 : ByteReader::ByteReader(enum Endianness endian)
      69             :     :offset_reader_(NULL), address_reader_(NULL), endian_(endian),
      70             :      address_size_(0), offset_size_(0),
      71             :      have_section_base_(), have_text_base_(), have_data_base_(),
      72           0 :      have_function_base_() { }
      73             : 
      74           0 : ByteReader::~ByteReader() { }
      75             : 
      76           0 : void ByteReader::SetOffsetSize(uint8 size) {
      77           0 :   offset_size_ = size;
      78           0 :   MOZ_ASSERT(size == 4 || size == 8);
      79           0 :   if (size == 4) {
      80           0 :     this->offset_reader_ = &ByteReader::ReadFourBytes;
      81             :   } else {
      82           0 :     this->offset_reader_ = &ByteReader::ReadEightBytes;
      83             :   }
      84           0 : }
      85             : 
      86           0 : void ByteReader::SetAddressSize(uint8 size) {
      87           0 :   address_size_ = size;
      88           0 :   MOZ_ASSERT(size == 4 || size == 8);
      89           0 :   if (size == 4) {
      90           0 :     this->address_reader_ = &ByteReader::ReadFourBytes;
      91             :   } else {
      92           0 :     this->address_reader_ = &ByteReader::ReadEightBytes;
      93             :   }
      94           0 : }
      95             : 
      96           0 : uint64 ByteReader::ReadInitialLength(const char* start, size_t* len) {
      97           0 :   const uint64 initial_length = ReadFourBytes(start);
      98           0 :   start += 4;
      99             : 
     100             :   // In DWARF2/3, if the initial length is all 1 bits, then the offset
     101             :   // size is 8 and we need to read the next 8 bytes for the real length.
     102           0 :   if (initial_length == 0xffffffff) {
     103           0 :     SetOffsetSize(8);
     104           0 :     *len = 12;
     105           0 :     return ReadOffset(start);
     106             :   } else {
     107           0 :     SetOffsetSize(4);
     108           0 :     *len = 4;
     109             :   }
     110           0 :   return initial_length;
     111             : }
     112             : 
     113           0 : bool ByteReader::ValidEncoding(DwarfPointerEncoding encoding) const {
     114           0 :   if (encoding == DW_EH_PE_omit) return true;
     115           0 :   if (encoding == DW_EH_PE_aligned) return true;
     116           0 :   if ((encoding & 0x7) > DW_EH_PE_udata8)
     117           0 :     return false;
     118           0 :   if ((encoding & 0x70) > DW_EH_PE_funcrel)
     119           0 :     return false;
     120           0 :   return true;
     121             : }
     122             : 
     123           0 : bool ByteReader::UsableEncoding(DwarfPointerEncoding encoding) const {
     124           0 :   switch (encoding & 0x70) {
     125           0 :     case DW_EH_PE_absptr:  return true;
     126           0 :     case DW_EH_PE_pcrel:   return have_section_base_;
     127           0 :     case DW_EH_PE_textrel: return have_text_base_;
     128           0 :     case DW_EH_PE_datarel: return have_data_base_;
     129           0 :     case DW_EH_PE_funcrel: return have_function_base_;
     130           0 :     default:               return false;
     131             :   }
     132             : }
     133             : 
     134           0 : uint64 ByteReader::ReadEncodedPointer(const char *buffer,
     135             :                                       DwarfPointerEncoding encoding,
     136             :                                       size_t *len) const {
     137             :   // UsableEncoding doesn't approve of DW_EH_PE_omit, so we shouldn't
     138             :   // see it here.
     139           0 :   MOZ_ASSERT(encoding != DW_EH_PE_omit);
     140             : 
     141             :   // The Linux Standards Base 4.0 does not make this clear, but the
     142             :   // GNU tools (gcc/unwind-pe.h; readelf/dwarf.c; gdb/dwarf2-frame.c)
     143             :   // agree that aligned pointers are always absolute, machine-sized,
     144             :   // machine-signed pointers.
     145           0 :   if (encoding == DW_EH_PE_aligned) {
     146           0 :     MOZ_ASSERT(have_section_base_);
     147             : 
     148             :     // We don't need to align BUFFER in *our* address space. Rather, we
     149             :     // need to find the next position in our buffer that would be aligned
     150             :     // when the .eh_frame section the buffer contains is loaded into the
     151             :     // program's memory. So align assuming that buffer_base_ gets loaded at
     152             :     // address section_base_, where section_base_ itself may or may not be
     153             :     // aligned.
     154             : 
     155             :     // First, find the offset to START from the closest prior aligned
     156             :     // address.
     157           0 :     uint64 skew = section_base_ & (AddressSize() - 1);
     158             :     // Now find the offset from that aligned address to buffer.
     159           0 :     uint64 offset = skew + (buffer - buffer_base_);
     160             :     // Round up to the next boundary.
     161           0 :     uint64 aligned = (offset + AddressSize() - 1) & -AddressSize();
     162             :     // Convert back to a pointer.
     163           0 :     const char *aligned_buffer = buffer_base_ + (aligned - skew);
     164             :     // Finally, store the length and actually fetch the pointer.
     165           0 :     *len = aligned_buffer - buffer + AddressSize();
     166           0 :     return ReadAddress(aligned_buffer);
     167             :   }
     168             : 
     169             :   // Extract the value first, ignoring whether it's a pointer or an
     170             :   // offset relative to some base.
     171             :   uint64 offset;
     172           0 :   switch (encoding & 0x0f) {
     173             :     case DW_EH_PE_absptr:
     174             :       // DW_EH_PE_absptr is weird, as it is used as a meaningful value for
     175             :       // both the high and low nybble of encoding bytes. When it appears in
     176             :       // the high nybble, it means that the pointer is absolute, not an
     177             :       // offset from some base address. When it appears in the low nybble,
     178             :       // as here, it means that the pointer is stored as a normal
     179             :       // machine-sized and machine-signed address. A low nybble of
     180             :       // DW_EH_PE_absptr does not imply that the pointer is absolute; it is
     181             :       // correct for us to treat the value as an offset from a base address
     182             :       // if the upper nybble is not DW_EH_PE_absptr.
     183           0 :       offset = ReadAddress(buffer);
     184           0 :       *len = AddressSize();
     185           0 :       break;
     186             : 
     187             :     case DW_EH_PE_uleb128:
     188           0 :       offset = ReadUnsignedLEB128(buffer, len);
     189           0 :       break;
     190             : 
     191             :     case DW_EH_PE_udata2:
     192           0 :       offset = ReadTwoBytes(buffer);
     193           0 :       *len = 2;
     194           0 :       break;
     195             : 
     196             :     case DW_EH_PE_udata4:
     197           0 :       offset = ReadFourBytes(buffer);
     198           0 :       *len = 4;
     199           0 :       break;
     200             : 
     201             :     case DW_EH_PE_udata8:
     202           0 :       offset = ReadEightBytes(buffer);
     203           0 :       *len = 8;
     204           0 :       break;
     205             : 
     206             :     case DW_EH_PE_sleb128:
     207           0 :       offset = ReadSignedLEB128(buffer, len);
     208           0 :       break;
     209             : 
     210             :     case DW_EH_PE_sdata2:
     211           0 :       offset = ReadTwoBytes(buffer);
     212             :       // Sign-extend from 16 bits.
     213           0 :       offset = (offset ^ 0x8000) - 0x8000;
     214           0 :       *len = 2;
     215           0 :       break;
     216             : 
     217             :     case DW_EH_PE_sdata4:
     218           0 :       offset = ReadFourBytes(buffer);
     219             :       // Sign-extend from 32 bits.
     220           0 :       offset = (offset ^ 0x80000000ULL) - 0x80000000ULL;
     221           0 :       *len = 4;
     222           0 :       break;
     223             : 
     224             :     case DW_EH_PE_sdata8:
     225             :       // No need to sign-extend; this is the full width of our type.
     226           0 :       offset = ReadEightBytes(buffer);
     227           0 :       *len = 8;
     228           0 :       break;
     229             : 
     230             :     default:
     231           0 :       abort();
     232             :   }
     233             : 
     234             :   // Find the appropriate base address.
     235             :   uint64 base;
     236           0 :   switch (encoding & 0x70) {
     237             :     case DW_EH_PE_absptr:
     238           0 :       base = 0;
     239           0 :       break;
     240             : 
     241             :     case DW_EH_PE_pcrel:
     242           0 :       MOZ_ASSERT(have_section_base_);
     243           0 :       base = section_base_ + (buffer - buffer_base_);
     244           0 :       break;
     245             : 
     246             :     case DW_EH_PE_textrel:
     247           0 :       MOZ_ASSERT(have_text_base_);
     248           0 :       base = text_base_;
     249           0 :       break;
     250             : 
     251             :     case DW_EH_PE_datarel:
     252           0 :       MOZ_ASSERT(have_data_base_);
     253           0 :       base = data_base_;
     254           0 :       break;
     255             : 
     256             :     case DW_EH_PE_funcrel:
     257           0 :       MOZ_ASSERT(have_function_base_);
     258           0 :       base = function_base_;
     259           0 :       break;
     260             : 
     261             :     default:
     262           0 :       abort();
     263             :   }
     264             : 
     265           0 :   uint64 pointer = base + offset;
     266             : 
     267             :   // Remove inappropriate upper bits.
     268           0 :   if (AddressSize() == 4)
     269           0 :     pointer = pointer & 0xffffffff;
     270             :   else
     271           0 :     MOZ_ASSERT(AddressSize() == sizeof(uint64));
     272             : 
     273           0 :   return pointer;
     274             : }
     275             : 
     276             : 
     277             : // A DWARF rule for recovering the address or value of a register, or
     278             : // computing the canonical frame address. There is one subclass of this for
     279             : // each '*Rule' member function in CallFrameInfo::Handler.
     280             : //
     281             : // It's annoying that we have to handle Rules using pointers (because
     282             : // the concrete instances can have an arbitrary size). They're small,
     283             : // so it would be much nicer if we could just handle them by value
     284             : // instead of fretting about ownership and destruction.
     285             : //
     286             : // It seems like all these could simply be instances of std::tr1::bind,
     287             : // except that we need instances to be EqualityComparable, too.
     288             : //
     289             : // This could logically be nested within State, but then the qualified names
     290             : // get horrendous.
     291           0 : class CallFrameInfo::Rule {
     292             :  public:
     293           0 :   virtual ~Rule() { }
     294             : 
     295             :   // Tell HANDLER that, at ADDRESS in the program, REGISTER can be
     296             :   // recovered using this rule. If REGISTER is kCFARegister, then this rule
     297             :   // describes how to compute the canonical frame address. Return what the
     298             :   // HANDLER member function returned.
     299             :   virtual bool Handle(Handler *handler, uint64 address, int register) const = 0;
     300             : 
     301             :   // Equality on rules. We use these to decide which rules we need
     302             :   // to report after a DW_CFA_restore_state instruction.
     303             :   virtual bool operator==(const Rule &rhs) const = 0;
     304             : 
     305           0 :   bool operator!=(const Rule &rhs) const { return ! (*this == rhs); }
     306             : 
     307             :   // Return a pointer to a copy of this rule.
     308             :   virtual Rule *Copy() const = 0;
     309             : 
     310             :   // If this is a base+offset rule, change its base register to REG.
     311             :   // Otherwise, do nothing. (Ugly, but required for DW_CFA_def_cfa_register.)
     312           0 :   virtual void SetBaseRegister(unsigned reg) { }
     313             : 
     314             :   // If this is a base+offset rule, change its offset to OFFSET. Otherwise,
     315             :   // do nothing. (Ugly, but required for DW_CFA_def_cfa_offset.)
     316           0 :   virtual void SetOffset(long long offset) { }
     317             : 
     318             :   // A RTTI workaround, to make it possible to implement equality
     319             :   // comparisons on classes derived from this one.
     320             :   enum CFIRTag {
     321             :     CFIR_UNDEFINED_RULE,
     322             :     CFIR_SAME_VALUE_RULE,
     323             :     CFIR_OFFSET_RULE,
     324             :     CFIR_VAL_OFFSET_RULE,
     325             :     CFIR_REGISTER_RULE,
     326             :     CFIR_EXPRESSION_RULE,
     327             :     CFIR_VAL_EXPRESSION_RULE
     328             :   };
     329             : 
     330             :   // Produce the tag that identifies the child class of this object.
     331             :   virtual CFIRTag getTag() const = 0;
     332             : };
     333             : 
     334             : // Rule: the value the register had in the caller cannot be recovered.
     335           0 : class CallFrameInfo::UndefinedRule: public CallFrameInfo::Rule {
     336             :  public:
     337           0 :   UndefinedRule() { }
     338           0 :   ~UndefinedRule() { }
     339           0 :   CFIRTag getTag() const { return CFIR_UNDEFINED_RULE; }
     340           0 :   bool Handle(Handler *handler, uint64 address, int reg) const {
     341           0 :     return handler->UndefinedRule(address, reg);
     342             :   }
     343           0 :   bool operator==(const Rule &rhs) const {
     344           0 :     if (rhs.getTag() != CFIR_UNDEFINED_RULE) return false;
     345           0 :     return true;
     346             :   }
     347           0 :   Rule *Copy() const { return new UndefinedRule(*this); }
     348             : };
     349             : 
     350             : // Rule: the register's value is the same as that it had in the caller.
     351           0 : class CallFrameInfo::SameValueRule: public CallFrameInfo::Rule {
     352             :  public:
     353           0 :   SameValueRule() { }
     354           0 :   ~SameValueRule() { }
     355           0 :   CFIRTag getTag() const { return CFIR_SAME_VALUE_RULE; }
     356           0 :   bool Handle(Handler *handler, uint64 address, int reg) const {
     357           0 :     return handler->SameValueRule(address, reg);
     358             :   }
     359           0 :   bool operator==(const Rule &rhs) const {
     360           0 :     if (rhs.getTag() != CFIR_SAME_VALUE_RULE) return false;
     361           0 :     return true;
     362             :   }
     363           0 :   Rule *Copy() const { return new SameValueRule(*this); }
     364             : };
     365             : 
     366             : // Rule: the register is saved at OFFSET from BASE_REGISTER.  BASE_REGISTER
     367             : // may be CallFrameInfo::Handler::kCFARegister.
     368           0 : class CallFrameInfo::OffsetRule: public CallFrameInfo::Rule {
     369             :  public:
     370           0 :   OffsetRule(int base_register, long offset)
     371           0 :       : base_register_(base_register), offset_(offset) { }
     372           0 :   ~OffsetRule() { }
     373           0 :   CFIRTag getTag() const { return CFIR_OFFSET_RULE; }
     374           0 :   bool Handle(Handler *handler, uint64 address, int reg) const {
     375           0 :     return handler->OffsetRule(address, reg, base_register_, offset_);
     376             :   }
     377           0 :   bool operator==(const Rule &rhs) const {
     378           0 :     if (rhs.getTag() != CFIR_OFFSET_RULE) return false;
     379           0 :     const OffsetRule *our_rhs = static_cast<const OffsetRule *>(&rhs);
     380           0 :     return (base_register_ == our_rhs->base_register_ &&
     381           0 :             offset_ == our_rhs->offset_);
     382             :   }
     383           0 :   Rule *Copy() const { return new OffsetRule(*this); }
     384             :   // We don't actually need SetBaseRegister or SetOffset here, since they
     385             :   // are only ever applied to CFA rules, for DW_CFA_def_cfa_offset, and it
     386             :   // doesn't make sense to use OffsetRule for computing the CFA: it
     387             :   // computes the address at which a register is saved, not a value.
     388             :  private:
     389             :   int base_register_;
     390             :   long offset_;
     391             : };
     392             : 
     393             : // Rule: the value the register had in the caller is the value of
     394             : // BASE_REGISTER plus offset. BASE_REGISTER may be
     395             : // CallFrameInfo::Handler::kCFARegister.
     396           0 : class CallFrameInfo::ValOffsetRule: public CallFrameInfo::Rule {
     397             :  public:
     398           0 :   ValOffsetRule(int base_register, long offset)
     399           0 :       : base_register_(base_register), offset_(offset) { }
     400           0 :   ~ValOffsetRule() { }
     401           0 :   CFIRTag getTag() const { return CFIR_VAL_OFFSET_RULE; }
     402           0 :   bool Handle(Handler *handler, uint64 address, int reg) const {
     403           0 :     return handler->ValOffsetRule(address, reg, base_register_, offset_);
     404             :   }
     405           0 :   bool operator==(const Rule &rhs) const {
     406           0 :     if (rhs.getTag() != CFIR_VAL_OFFSET_RULE) return false;
     407           0 :     const ValOffsetRule *our_rhs = static_cast<const ValOffsetRule *>(&rhs);
     408           0 :     return (base_register_ == our_rhs->base_register_ &&
     409           0 :             offset_ == our_rhs->offset_);
     410             :   }
     411           0 :   Rule *Copy() const { return new ValOffsetRule(*this); }
     412           0 :   void SetBaseRegister(unsigned reg) { base_register_ = reg; }
     413           0 :   void SetOffset(long long offset) { offset_ = offset; }
     414             :  private:
     415             :   int base_register_;
     416             :   long offset_;
     417             : };
     418             : 
     419             : // Rule: the register has been saved in another register REGISTER_NUMBER_.
     420           0 : class CallFrameInfo::RegisterRule: public CallFrameInfo::Rule {
     421             :  public:
     422           0 :   explicit RegisterRule(int register_number)
     423           0 :       : register_number_(register_number) { }
     424           0 :   ~RegisterRule() { }
     425           0 :   CFIRTag getTag() const { return CFIR_REGISTER_RULE; }
     426           0 :   bool Handle(Handler *handler, uint64 address, int reg) const {
     427           0 :     return handler->RegisterRule(address, reg, register_number_);
     428             :   }
     429           0 :   bool operator==(const Rule &rhs) const {
     430           0 :     if (rhs.getTag() != CFIR_REGISTER_RULE) return false;
     431           0 :     const RegisterRule *our_rhs = static_cast<const RegisterRule *>(&rhs);
     432           0 :     return (register_number_ == our_rhs->register_number_);
     433             :   }
     434           0 :   Rule *Copy() const { return new RegisterRule(*this); }
     435             :  private:
     436             :   int register_number_;
     437             : };
     438             : 
     439             : // Rule: EXPRESSION evaluates to the address at which the register is saved.
     440           0 : class CallFrameInfo::ExpressionRule: public CallFrameInfo::Rule {
     441             :  public:
     442           0 :   explicit ExpressionRule(const string &expression)
     443           0 :       : expression_(expression) { }
     444           0 :   ~ExpressionRule() { }
     445           0 :   CFIRTag getTag() const { return CFIR_EXPRESSION_RULE; }
     446           0 :   bool Handle(Handler *handler, uint64 address, int reg) const {
     447           0 :     return handler->ExpressionRule(address, reg, expression_);
     448             :   }
     449           0 :   bool operator==(const Rule &rhs) const {
     450           0 :     if (rhs.getTag() != CFIR_EXPRESSION_RULE) return false;
     451           0 :     const ExpressionRule *our_rhs = static_cast<const ExpressionRule *>(&rhs);
     452           0 :     return (expression_ == our_rhs->expression_);
     453             :   }
     454           0 :   Rule *Copy() const { return new ExpressionRule(*this); }
     455             :  private:
     456             :   string expression_;
     457             : };
     458             : 
     459             : // Rule: EXPRESSION evaluates to the previous value of the register.
     460           0 : class CallFrameInfo::ValExpressionRule: public CallFrameInfo::Rule {
     461             :  public:
     462           0 :   explicit ValExpressionRule(const string &expression)
     463           0 :       : expression_(expression) { }
     464           0 :   ~ValExpressionRule() { }
     465           0 :   CFIRTag getTag() const { return CFIR_VAL_EXPRESSION_RULE; }
     466           0 :   bool Handle(Handler *handler, uint64 address, int reg) const {
     467           0 :     return handler->ValExpressionRule(address, reg, expression_);
     468             :   }
     469           0 :   bool operator==(const Rule &rhs) const {
     470           0 :     if (rhs.getTag() != CFIR_VAL_EXPRESSION_RULE) return false;
     471             :     const ValExpressionRule *our_rhs =
     472           0 :         static_cast<const ValExpressionRule *>(&rhs);
     473           0 :     return (expression_ == our_rhs->expression_);
     474             :   }
     475           0 :   Rule *Copy() const { return new ValExpressionRule(*this); }
     476             :  private:
     477             :   string expression_;
     478             : };
     479             : 
     480             : // A map from register numbers to rules.
     481             : class CallFrameInfo::RuleMap {
     482             :  public:
     483           0 :   RuleMap() : cfa_rule_(NULL) { }
     484           0 :   RuleMap(const RuleMap &rhs) : cfa_rule_(NULL) { *this = rhs; }
     485           0 :   ~RuleMap() { Clear(); }
     486             : 
     487             :   RuleMap &operator=(const RuleMap &rhs);
     488             : 
     489             :   // Set the rule for computing the CFA to RULE. Take ownership of RULE.
     490           0 :   void SetCFARule(Rule *rule) { delete cfa_rule_; cfa_rule_ = rule; }
     491             : 
     492             :   // Return the current CFA rule. Unlike RegisterRule, this RuleMap retains
     493             :   // ownership of the rule. We use this for DW_CFA_def_cfa_offset and
     494             :   // DW_CFA_def_cfa_register, and for detecting references to the CFA before
     495             :   // a rule for it has been established.
     496           0 :   Rule *CFARule() const { return cfa_rule_; }
     497             : 
     498             :   // Return the rule for REG, or NULL if there is none. The caller takes
     499             :   // ownership of the result.
     500             :   Rule *RegisterRule(int reg) const;
     501             : 
     502             :   // Set the rule for computing REG to RULE. Take ownership of RULE.
     503             :   void SetRegisterRule(int reg, Rule *rule);
     504             : 
     505             :   // Make all the appropriate calls to HANDLER as if we were changing from
     506             :   // this RuleMap to NEW_RULES at ADDRESS. We use this to implement
     507             :   // DW_CFA_restore_state, where lots of rules can change simultaneously.
     508             :   // Return true if all handlers returned true; otherwise, return false.
     509             :   bool HandleTransitionTo(Handler *handler, uint64 address,
     510             :                           const RuleMap &new_rules) const;
     511             : 
     512             :  private:
     513             :   // A map from register numbers to Rules.
     514             :   typedef std::map<int, Rule *> RuleByNumber;
     515             : 
     516             :   // Remove all register rules and clear cfa_rule_.
     517             :   void Clear();
     518             : 
     519             :   // The rule for computing the canonical frame address. This RuleMap owns
     520             :   // this rule.
     521             :   Rule *cfa_rule_;
     522             : 
     523             :   // A map from register numbers to postfix expressions to recover
     524             :   // their values. This RuleMap owns the Rules the map refers to.
     525             :   RuleByNumber registers_;
     526             : };
     527             : 
     528           0 : CallFrameInfo::RuleMap &CallFrameInfo::RuleMap::operator=(const RuleMap &rhs) {
     529           0 :   Clear();
     530             :   // Since each map owns the rules it refers to, assignment must copy them.
     531           0 :   if (rhs.cfa_rule_) cfa_rule_ = rhs.cfa_rule_->Copy();
     532           0 :   for (RuleByNumber::const_iterator it = rhs.registers_.begin();
     533           0 :        it != rhs.registers_.end(); it++)
     534           0 :     registers_[it->first] = it->second->Copy();
     535           0 :   return *this;
     536             : }
     537             : 
     538           0 : CallFrameInfo::Rule *CallFrameInfo::RuleMap::RegisterRule(int reg) const {
     539           0 :   MOZ_ASSERT(reg != Handler::kCFARegister);
     540           0 :   RuleByNumber::const_iterator it = registers_.find(reg);
     541           0 :   if (it != registers_.end())
     542           0 :     return it->second->Copy();
     543             :   else
     544           0 :     return NULL;
     545             : }
     546             : 
     547           0 : void CallFrameInfo::RuleMap::SetRegisterRule(int reg, Rule *rule) {
     548           0 :   MOZ_ASSERT(reg != Handler::kCFARegister);
     549           0 :   MOZ_ASSERT(rule);
     550           0 :   Rule **slot = &registers_[reg];
     551           0 :   delete *slot;
     552           0 :   *slot = rule;
     553           0 : }
     554             : 
     555           0 : bool CallFrameInfo::RuleMap::HandleTransitionTo(
     556             :     Handler *handler,
     557             :     uint64 address,
     558             :     const RuleMap &new_rules) const {
     559             :   // Transition from cfa_rule_ to new_rules.cfa_rule_.
     560           0 :   if (cfa_rule_ && new_rules.cfa_rule_) {
     561           0 :     if (*cfa_rule_ != *new_rules.cfa_rule_ &&
     562           0 :         !new_rules.cfa_rule_->Handle(handler, address, Handler::kCFARegister))
     563           0 :       return false;
     564           0 :   } else if (cfa_rule_) {
     565             :     // this RuleMap has a CFA rule but new_rules doesn't.
     566             :     // CallFrameInfo::Handler has no way to handle this --- and shouldn't;
     567             :     // it's garbage input. The instruction interpreter should have
     568             :     // detected this and warned, so take no action here.
     569           0 :   } else if (new_rules.cfa_rule_) {
     570             :     // This shouldn't be possible: NEW_RULES is some prior state, and
     571             :     // there's no way to remove entries.
     572           0 :     MOZ_ASSERT(0);
     573             :   } else {
     574             :     // Both CFA rules are empty.  No action needed.
     575             :   }
     576             : 
     577             :   // Traverse the two maps in order by register number, and report
     578             :   // whatever differences we find.
     579           0 :   RuleByNumber::const_iterator old_it = registers_.begin();
     580           0 :   RuleByNumber::const_iterator new_it = new_rules.registers_.begin();
     581           0 :   while (old_it != registers_.end() && new_it != new_rules.registers_.end()) {
     582           0 :     if (old_it->first < new_it->first) {
     583             :       // This RuleMap has an entry for old_it->first, but NEW_RULES
     584             :       // doesn't.
     585             :       //
     586             :       // This isn't really the right thing to do, but since CFI generally
     587             :       // only mentions callee-saves registers, and GCC's convention for
     588             :       // callee-saves registers is that they are unchanged, it's a good
     589             :       // approximation.
     590           0 :       if (!handler->SameValueRule(address, old_it->first))
     591           0 :         return false;
     592           0 :       old_it++;
     593           0 :     } else if (old_it->first > new_it->first) {
     594             :       // NEW_RULES has entry for new_it->first, but this RuleMap
     595             :       // doesn't. This shouldn't be possible: NEW_RULES is some prior
     596             :       // state, and there's no way to remove entries.
     597           0 :       MOZ_ASSERT(0);
     598             :     } else {
     599             :       // Both maps have an entry for this register. Report the new
     600             :       // rule if it is different.
     601           0 :       if (*old_it->second != *new_it->second &&
     602           0 :           !new_it->second->Handle(handler, address, new_it->first))
     603           0 :         return false;
     604           0 :       new_it++; old_it++;
     605             :     }
     606             :   }
     607             :   // Finish off entries from this RuleMap with no counterparts in new_rules.
     608           0 :   while (old_it != registers_.end()) {
     609           0 :     if (!handler->SameValueRule(address, old_it->first))
     610           0 :       return false;
     611           0 :     old_it++;
     612             :   }
     613             :   // Since we only make transitions from a rule set to some previously
     614             :   // saved rule set, and we can only add rules to the map, NEW_RULES
     615             :   // must have fewer rules than *this.
     616           0 :   MOZ_ASSERT(new_it == new_rules.registers_.end());
     617             : 
     618           0 :   return true;
     619             : }
     620             : 
     621             : // Remove all register rules and clear cfa_rule_.
     622           0 : void CallFrameInfo::RuleMap::Clear() {
     623           0 :   delete cfa_rule_;
     624           0 :   cfa_rule_ = NULL;
     625           0 :   for (RuleByNumber::iterator it = registers_.begin();
     626           0 :        it != registers_.end(); it++)
     627           0 :     delete it->second;
     628           0 :   registers_.clear();
     629           0 : }
     630             : 
     631             : // The state of the call frame information interpreter as it processes
     632             : // instructions from a CIE and FDE.
     633             : class CallFrameInfo::State {
     634             :  public:
     635             :   // Create a call frame information interpreter state with the given
     636             :   // reporter, reader, handler, and initial call frame info address.
     637           0 :   State(ByteReader *reader, Handler *handler, Reporter *reporter,
     638             :         uint64 address)
     639           0 :       : reader_(reader), handler_(handler), reporter_(reporter),
     640             :         address_(address), entry_(NULL), cursor_(NULL),
     641           0 :         saved_rules_(NULL) { }
     642             : 
     643           0 :   ~State() {
     644           0 :     if (saved_rules_)
     645           0 :       delete saved_rules_;
     646           0 :   }
     647             : 
     648             :   // Interpret instructions from CIE, save the resulting rule set for
     649             :   // DW_CFA_restore instructions, and return true. On error, report
     650             :   // the problem to reporter_ and return false.
     651             :   bool InterpretCIE(const CIE &cie);
     652             : 
     653             :   // Interpret instructions from FDE, and return true. On error,
     654             :   // report the problem to reporter_ and return false.
     655             :   bool InterpretFDE(const FDE &fde);
     656             : 
     657             :  private:
     658             :   // The operands of a CFI instruction, for ParseOperands.
     659           0 :   struct Operands {
     660             :     unsigned register_number;  // A register number.
     661             :     uint64 offset;             // An offset or address.
     662             :     long signed_offset;        // A signed offset.
     663             :     string expression;         // A DWARF expression.
     664             :   };
     665             : 
     666             :   // Parse CFI instruction operands from STATE's instruction stream as
     667             :   // described by FORMAT. On success, populate OPERANDS with the
     668             :   // results, and return true. On failure, report the problem and
     669             :   // return false.
     670             :   //
     671             :   // Each character of FORMAT should be one of the following:
     672             :   //
     673             :   //   'r'  unsigned LEB128 register number (OPERANDS->register_number)
     674             :   //   'o'  unsigned LEB128 offset          (OPERANDS->offset)
     675             :   //   's'  signed LEB128 offset            (OPERANDS->signed_offset)
     676             :   //   'a'  machine-size address            (OPERANDS->offset)
     677             :   //        (If the CIE has a 'z' augmentation string, 'a' uses the
     678             :   //        encoding specified by the 'R' argument.)
     679             :   //   '1'  a one-byte offset               (OPERANDS->offset)
     680             :   //   '2'  a two-byte offset               (OPERANDS->offset)
     681             :   //   '4'  a four-byte offset              (OPERANDS->offset)
     682             :   //   '8'  an eight-byte offset            (OPERANDS->offset)
     683             :   //   'e'  a DW_FORM_block holding a       (OPERANDS->expression)
     684             :   //        DWARF expression
     685             :   bool ParseOperands(const char *format, Operands *operands);
     686             : 
     687             :   // Interpret one CFI instruction from STATE's instruction stream, update
     688             :   // STATE, report any rule changes to handler_, and return true. On
     689             :   // failure, report the problem and return false.
     690             :   bool DoInstruction();
     691             : 
     692             :   // The following Do* member functions are subroutines of DoInstruction,
     693             :   // factoring out the actual work of operations that have several
     694             :   // different encodings.
     695             : 
     696             :   // Set the CFA rule to be the value of BASE_REGISTER plus OFFSET, and
     697             :   // return true. On failure, report and return false. (Used for
     698             :   // DW_CFA_def_cfa and DW_CFA_def_cfa_sf.)
     699             :   bool DoDefCFA(unsigned base_register, long offset);
     700             : 
     701             :   // Change the offset of the CFA rule to OFFSET, and return true. On
     702             :   // failure, report and return false. (Subroutine for
     703             :   // DW_CFA_def_cfa_offset and DW_CFA_def_cfa_offset_sf.)
     704             :   bool DoDefCFAOffset(long offset);
     705             : 
     706             :   // Specify that REG can be recovered using RULE, and return true. On
     707             :   // failure, report and return false.
     708             :   bool DoRule(unsigned reg, Rule *rule);
     709             : 
     710             :   // Specify that REG can be found at OFFSET from the CFA, and return true.
     711             :   // On failure, report and return false. (Subroutine for DW_CFA_offset,
     712             :   // DW_CFA_offset_extended, and DW_CFA_offset_extended_sf.)
     713             :   bool DoOffset(unsigned reg, long offset);
     714             : 
     715             :   // Specify that the caller's value for REG is the CFA plus OFFSET,
     716             :   // and return true. On failure, report and return false. (Subroutine
     717             :   // for DW_CFA_val_offset and DW_CFA_val_offset_sf.)
     718             :   bool DoValOffset(unsigned reg, long offset);
     719             : 
     720             :   // Restore REG to the rule established in the CIE, and return true. On
     721             :   // failure, report and return false. (Subroutine for DW_CFA_restore and
     722             :   // DW_CFA_restore_extended.)
     723             :   bool DoRestore(unsigned reg);
     724             : 
     725             :   // Return the section offset of the instruction at cursor. For use
     726             :   // in error messages.
     727           0 :   uint64 CursorOffset() { return entry_->offset + (cursor_ - entry_->start); }
     728             : 
     729             :   // Report that entry_ is incomplete, and return false. For brevity.
     730           0 :   bool ReportIncomplete() {
     731           0 :     reporter_->Incomplete(entry_->offset, entry_->kind);
     732           0 :     return false;
     733             :   }
     734             : 
     735             :   // For reading multi-byte values with the appropriate endianness.
     736             :   ByteReader *reader_;
     737             : 
     738             :   // The handler to which we should report the data we find.
     739             :   Handler *handler_;
     740             : 
     741             :   // For reporting problems in the info we're parsing.
     742             :   Reporter *reporter_;
     743             : 
     744             :   // The code address to which the next instruction in the stream applies.
     745             :   uint64 address_;
     746             : 
     747             :   // The entry whose instructions we are currently processing. This is
     748             :   // first a CIE, and then an FDE.
     749             :   const Entry *entry_;
     750             : 
     751             :   // The next instruction to process.
     752             :   const char *cursor_;
     753             : 
     754             :   // The current set of rules.
     755             :   RuleMap rules_;
     756             : 
     757             :   // The set of rules established by the CIE, used by DW_CFA_restore
     758             :   // and DW_CFA_restore_extended. We set this after interpreting the
     759             :   // CIE's instructions.
     760             :   RuleMap cie_rules_;
     761             : 
     762             :   // A stack of saved states, for DW_CFA_remember_state and
     763             :   // DW_CFA_restore_state.
     764             :   std::stack<RuleMap>* saved_rules_;
     765             : };
     766             : 
     767           0 : bool CallFrameInfo::State::InterpretCIE(const CIE &cie) {
     768           0 :   entry_ = &cie;
     769           0 :   cursor_ = entry_->instructions;
     770           0 :   while (cursor_ < entry_->end)
     771           0 :     if (!DoInstruction())
     772           0 :       return false;
     773             :   // Note the rules established by the CIE, for use by DW_CFA_restore
     774             :   // and DW_CFA_restore_extended.
     775           0 :   cie_rules_ = rules_;
     776           0 :   return true;
     777             : }
     778             : 
     779           0 : bool CallFrameInfo::State::InterpretFDE(const FDE &fde) {
     780           0 :   entry_ = &fde;
     781           0 :   cursor_ = entry_->instructions;
     782           0 :   while (cursor_ < entry_->end)
     783           0 :     if (!DoInstruction())
     784           0 :       return false;
     785           0 :   return true;
     786             : }
     787             : 
     788           0 : bool CallFrameInfo::State::ParseOperands(const char *format,
     789             :                                          Operands *operands) {
     790             :   size_t len;
     791             :   const char *operand;
     792             : 
     793           0 :   for (operand = format; *operand; operand++) {
     794           0 :     size_t bytes_left = entry_->end - cursor_;
     795           0 :     switch (*operand) {
     796             :       case 'r':
     797           0 :         operands->register_number = reader_->ReadUnsignedLEB128(cursor_, &len);
     798           0 :         if (len > bytes_left) return ReportIncomplete();
     799           0 :         cursor_ += len;
     800           0 :         break;
     801             : 
     802             :       case 'o':
     803           0 :         operands->offset = reader_->ReadUnsignedLEB128(cursor_, &len);
     804           0 :         if (len > bytes_left) return ReportIncomplete();
     805           0 :         cursor_ += len;
     806           0 :         break;
     807             : 
     808             :       case 's':
     809           0 :         operands->signed_offset = reader_->ReadSignedLEB128(cursor_, &len);
     810           0 :         if (len > bytes_left) return ReportIncomplete();
     811           0 :         cursor_ += len;
     812           0 :         break;
     813             : 
     814             :       case 'a':
     815           0 :         operands->offset =
     816           0 :           reader_->ReadEncodedPointer(cursor_, entry_->cie->pointer_encoding,
     817             :                                       &len);
     818           0 :         if (len > bytes_left) return ReportIncomplete();
     819           0 :         cursor_ += len;
     820           0 :         break;
     821             : 
     822             :       case '1':
     823           0 :         if (1 > bytes_left) return ReportIncomplete();
     824           0 :         operands->offset = static_cast<unsigned char>(*cursor_++);
     825           0 :         break;
     826             : 
     827             :       case '2':
     828           0 :         if (2 > bytes_left) return ReportIncomplete();
     829           0 :         operands->offset = reader_->ReadTwoBytes(cursor_);
     830           0 :         cursor_ += 2;
     831           0 :         break;
     832             : 
     833             :       case '4':
     834           0 :         if (4 > bytes_left) return ReportIncomplete();
     835           0 :         operands->offset = reader_->ReadFourBytes(cursor_);
     836           0 :         cursor_ += 4;
     837           0 :         break;
     838             : 
     839             :       case '8':
     840           0 :         if (8 > bytes_left) return ReportIncomplete();
     841           0 :         operands->offset = reader_->ReadEightBytes(cursor_);
     842           0 :         cursor_ += 8;
     843           0 :         break;
     844             : 
     845             :       case 'e': {
     846           0 :         size_t expression_length = reader_->ReadUnsignedLEB128(cursor_, &len);
     847           0 :         if (len > bytes_left || expression_length > bytes_left - len)
     848           0 :           return ReportIncomplete();
     849           0 :         cursor_ += len;
     850           0 :         operands->expression = string(cursor_, expression_length);
     851           0 :         cursor_ += expression_length;
     852           0 :         break;
     853             :       }
     854             : 
     855             :       default:
     856           0 :         MOZ_ASSERT(0);
     857             :     }
     858             :   }
     859             : 
     860           0 :   return true;
     861             : }
     862             : 
     863           0 : bool CallFrameInfo::State::DoInstruction() {
     864           0 :   CIE *cie = entry_->cie;
     865           0 :   Operands ops;
     866             : 
     867             :   // Our entry's kind should have been set by now.
     868           0 :   MOZ_ASSERT(entry_->kind != kUnknown);
     869             : 
     870             :   // We shouldn't have been invoked unless there were more
     871             :   // instructions to parse.
     872           0 :   MOZ_ASSERT(cursor_ < entry_->end);
     873             : 
     874           0 :   unsigned opcode = *cursor_++;
     875           0 :   if ((opcode & 0xc0) != 0) {
     876           0 :     switch (opcode & 0xc0) {
     877             :       // Advance the address.
     878             :       case DW_CFA_advance_loc: {
     879           0 :         size_t code_offset = opcode & 0x3f;
     880           0 :         address_ += code_offset * cie->code_alignment_factor;
     881           0 :         break;
     882             :       }
     883             : 
     884             :       // Find a register at an offset from the CFA.
     885             :       case DW_CFA_offset:
     886           0 :         if (!ParseOperands("o", &ops) ||
     887           0 :             !DoOffset(opcode & 0x3f, ops.offset * cie->data_alignment_factor))
     888           0 :           return false;
     889           0 :         break;
     890             : 
     891             :       // Restore the rule established for a register by the CIE.
     892             :       case DW_CFA_restore:
     893           0 :         if (!DoRestore(opcode & 0x3f)) return false;
     894           0 :         break;
     895             : 
     896             :       // The 'if' above should have excluded this possibility.
     897             :       default:
     898           0 :         MOZ_ASSERT(0);
     899             :     }
     900             : 
     901             :     // Return here, so the big switch below won't be indented.
     902           0 :     return true;
     903             :   }
     904             : 
     905           0 :   switch (opcode) {
     906             :     // Set the address.
     907             :     case DW_CFA_set_loc:
     908           0 :       if (!ParseOperands("a", &ops)) return false;
     909           0 :       address_ = ops.offset;
     910           0 :       break;
     911             : 
     912             :     // Advance the address.
     913             :     case DW_CFA_advance_loc1:
     914           0 :       if (!ParseOperands("1", &ops)) return false;
     915           0 :       address_ += ops.offset * cie->code_alignment_factor;
     916           0 :       break;
     917             : 
     918             :     // Advance the address.
     919             :     case DW_CFA_advance_loc2:
     920           0 :       if (!ParseOperands("2", &ops)) return false;
     921           0 :       address_ += ops.offset * cie->code_alignment_factor;
     922           0 :       break;
     923             : 
     924             :     // Advance the address.
     925             :     case DW_CFA_advance_loc4:
     926           0 :       if (!ParseOperands("4", &ops)) return false;
     927           0 :       address_ += ops.offset * cie->code_alignment_factor;
     928           0 :       break;
     929             : 
     930             :     // Advance the address.
     931             :     case DW_CFA_MIPS_advance_loc8:
     932           0 :       if (!ParseOperands("8", &ops)) return false;
     933           0 :       address_ += ops.offset * cie->code_alignment_factor;
     934           0 :       break;
     935             : 
     936             :     // Compute the CFA by adding an offset to a register.
     937             :     case DW_CFA_def_cfa:
     938           0 :       if (!ParseOperands("ro", &ops) ||
     939           0 :           !DoDefCFA(ops.register_number, ops.offset))
     940           0 :         return false;
     941           0 :       break;
     942             : 
     943             :     // Compute the CFA by adding an offset to a register.
     944             :     case DW_CFA_def_cfa_sf:
     945           0 :       if (!ParseOperands("rs", &ops) ||
     946           0 :           !DoDefCFA(ops.register_number,
     947           0 :                     ops.signed_offset * cie->data_alignment_factor))
     948           0 :         return false;
     949           0 :       break;
     950             : 
     951             :     // Change the base register used to compute the CFA.
     952             :     case DW_CFA_def_cfa_register: {
     953           0 :       Rule *cfa_rule = rules_.CFARule();
     954           0 :       if (!cfa_rule) {
     955           0 :         reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset());
     956           0 :         return false;
     957             :       }
     958           0 :       if (!ParseOperands("r", &ops)) return false;
     959           0 :       cfa_rule->SetBaseRegister(ops.register_number);
     960           0 :       if (!cfa_rule->Handle(handler_, address_, Handler::kCFARegister))
     961           0 :         return false;
     962           0 :       break;
     963             :     }
     964             : 
     965             :     // Change the offset used to compute the CFA.
     966             :     case DW_CFA_def_cfa_offset:
     967           0 :       if (!ParseOperands("o", &ops) ||
     968           0 :           !DoDefCFAOffset(ops.offset))
     969           0 :         return false;
     970           0 :       break;
     971             : 
     972             :     // Change the offset used to compute the CFA.
     973             :     case DW_CFA_def_cfa_offset_sf:
     974           0 :       if (!ParseOperands("s", &ops) ||
     975           0 :           !DoDefCFAOffset(ops.signed_offset * cie->data_alignment_factor))
     976           0 :         return false;
     977           0 :       break;
     978             : 
     979             :     // Specify an expression whose value is the CFA.
     980             :     case DW_CFA_def_cfa_expression: {
     981           0 :       if (!ParseOperands("e", &ops))
     982           0 :         return false;
     983           0 :       Rule *rule = new ValExpressionRule(ops.expression);
     984           0 :       rules_.SetCFARule(rule);
     985           0 :       if (!rule->Handle(handler_, address_, Handler::kCFARegister))
     986           0 :         return false;
     987           0 :       break;
     988             :     }
     989             : 
     990             :     // The register's value cannot be recovered.
     991             :     case DW_CFA_undefined: {
     992           0 :       if (!ParseOperands("r", &ops) ||
     993           0 :           !DoRule(ops.register_number, new UndefinedRule()))
     994           0 :         return false;
     995           0 :       break;
     996             :     }
     997             : 
     998             :     // The register's value is unchanged from its value in the caller.
     999             :     case DW_CFA_same_value: {
    1000           0 :       if (!ParseOperands("r", &ops) ||
    1001           0 :           !DoRule(ops.register_number, new SameValueRule()))
    1002           0 :         return false;
    1003           0 :       break;
    1004             :     }
    1005             : 
    1006             :     // Find a register at an offset from the CFA.
    1007             :     case DW_CFA_offset_extended:
    1008           0 :       if (!ParseOperands("ro", &ops) ||
    1009           0 :           !DoOffset(ops.register_number,
    1010           0 :                     ops.offset * cie->data_alignment_factor))
    1011           0 :         return false;
    1012           0 :       break;
    1013             : 
    1014             :     // The register is saved at an offset from the CFA.
    1015             :     case DW_CFA_offset_extended_sf:
    1016           0 :       if (!ParseOperands("rs", &ops) ||
    1017           0 :           !DoOffset(ops.register_number,
    1018           0 :                     ops.signed_offset * cie->data_alignment_factor))
    1019           0 :         return false;
    1020           0 :       break;
    1021             : 
    1022             :     // The register is saved at an offset from the CFA.
    1023             :     case DW_CFA_GNU_negative_offset_extended:
    1024           0 :       if (!ParseOperands("ro", &ops) ||
    1025           0 :           !DoOffset(ops.register_number,
    1026           0 :                     -ops.offset * cie->data_alignment_factor))
    1027           0 :         return false;
    1028           0 :       break;
    1029             : 
    1030             :     // The register's value is the sum of the CFA plus an offset.
    1031             :     case DW_CFA_val_offset:
    1032           0 :       if (!ParseOperands("ro", &ops) ||
    1033           0 :           !DoValOffset(ops.register_number,
    1034           0 :                        ops.offset * cie->data_alignment_factor))
    1035           0 :         return false;
    1036           0 :       break;
    1037             : 
    1038             :     // The register's value is the sum of the CFA plus an offset.
    1039             :     case DW_CFA_val_offset_sf:
    1040           0 :       if (!ParseOperands("rs", &ops) ||
    1041           0 :           !DoValOffset(ops.register_number,
    1042           0 :                        ops.signed_offset * cie->data_alignment_factor))
    1043           0 :         return false;
    1044           0 :       break;
    1045             : 
    1046             :     // The register has been saved in another register.
    1047             :     case DW_CFA_register: {
    1048           0 :       if (!ParseOperands("ro", &ops) ||
    1049           0 :           !DoRule(ops.register_number, new RegisterRule(ops.offset)))
    1050           0 :         return false;
    1051           0 :       break;
    1052             :     }
    1053             : 
    1054             :     // An expression yields the address at which the register is saved.
    1055             :     case DW_CFA_expression: {
    1056           0 :       if (!ParseOperands("re", &ops) ||
    1057           0 :           !DoRule(ops.register_number, new ExpressionRule(ops.expression)))
    1058           0 :         return false;
    1059           0 :       break;
    1060             :     }
    1061             : 
    1062             :     // An expression yields the caller's value for the register.
    1063             :     case DW_CFA_val_expression: {
    1064           0 :       if (!ParseOperands("re", &ops) ||
    1065           0 :           !DoRule(ops.register_number, new ValExpressionRule(ops.expression)))
    1066           0 :         return false;
    1067           0 :       break;
    1068             :     }
    1069             : 
    1070             :     // Restore the rule established for a register by the CIE.
    1071             :     case DW_CFA_restore_extended:
    1072           0 :       if (!ParseOperands("r", &ops) ||
    1073           0 :           !DoRestore( ops.register_number))
    1074           0 :         return false;
    1075           0 :       break;
    1076             : 
    1077             :     // Save the current set of rules on a stack.
    1078             :     case DW_CFA_remember_state:
    1079           0 :       if (!saved_rules_) {
    1080           0 :         saved_rules_ = new std::stack<RuleMap>();
    1081             :       }
    1082           0 :       saved_rules_->push(rules_);
    1083           0 :       break;
    1084             : 
    1085             :     // Pop the current set of rules off the stack.
    1086             :     case DW_CFA_restore_state: {
    1087           0 :       if (!saved_rules_ || saved_rules_->empty()) {
    1088           0 :         reporter_->EmptyStateStack(entry_->offset, entry_->kind,
    1089           0 :                                    CursorOffset());
    1090           0 :         return false;
    1091             :       }
    1092           0 :       const RuleMap &new_rules = saved_rules_->top();
    1093           0 :       if (rules_.CFARule() && !new_rules.CFARule()) {
    1094           0 :         reporter_->ClearingCFARule(entry_->offset, entry_->kind,
    1095           0 :                                    CursorOffset());
    1096           0 :         return false;
    1097             :       }
    1098           0 :       rules_.HandleTransitionTo(handler_, address_, new_rules);
    1099           0 :       rules_ = new_rules;
    1100           0 :       saved_rules_->pop();
    1101           0 :       break;
    1102             :     }
    1103             : 
    1104             :     // No operation.  (Padding instruction.)
    1105             :     case DW_CFA_nop:
    1106           0 :       break;
    1107             : 
    1108             :     // A SPARC register window save: Registers 8 through 15 (%o0-%o7)
    1109             :     // are saved in registers 24 through 31 (%i0-%i7), and registers
    1110             :     // 16 through 31 (%l0-%l7 and %i0-%i7) are saved at CFA offsets
    1111             :     // (0-15 * the register size). The register numbers must be
    1112             :     // hard-coded. A GNU extension, and not a pretty one.
    1113             :     case DW_CFA_GNU_window_save: {
    1114             :       // Save %o0-%o7 in %i0-%i7.
    1115           0 :       for (int i = 8; i < 16; i++)
    1116           0 :         if (!DoRule(i, new RegisterRule(i + 16)))
    1117           0 :           return false;
    1118             :       // Save %l0-%l7 and %i0-%i7 at the CFA.
    1119           0 :       for (int i = 16; i < 32; i++)
    1120             :         // Assume that the byte reader's address size is the same as
    1121             :         // the architecture's register size. !@#%*^ hilarious.
    1122           0 :         if (!DoRule(i, new OffsetRule(Handler::kCFARegister,
    1123           0 :                                       (i - 16) * reader_->AddressSize())))
    1124           0 :           return false;
    1125           0 :       break;
    1126             :     }
    1127             : 
    1128             :     // I'm not sure what this is. GDB doesn't use it for unwinding.
    1129             :     case DW_CFA_GNU_args_size:
    1130           0 :       if (!ParseOperands("o", &ops)) return false;
    1131           0 :       break;
    1132             : 
    1133             :     // An opcode we don't recognize.
    1134             :     default: {
    1135           0 :       reporter_->BadInstruction(entry_->offset, entry_->kind, CursorOffset());
    1136           0 :       return false;
    1137             :     }
    1138             :   }
    1139             : 
    1140           0 :   return true;
    1141             : }
    1142             : 
    1143           0 : bool CallFrameInfo::State::DoDefCFA(unsigned base_register, long offset) {
    1144           0 :   Rule *rule = new ValOffsetRule(base_register, offset);
    1145           0 :   rules_.SetCFARule(rule);
    1146           0 :   return rule->Handle(handler_, address_, Handler::kCFARegister);
    1147             : }
    1148             : 
    1149           0 : bool CallFrameInfo::State::DoDefCFAOffset(long offset) {
    1150           0 :   Rule *cfa_rule = rules_.CFARule();
    1151           0 :   if (!cfa_rule) {
    1152           0 :     reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset());
    1153           0 :     return false;
    1154             :   }
    1155           0 :   cfa_rule->SetOffset(offset);
    1156           0 :   return cfa_rule->Handle(handler_, address_, Handler::kCFARegister);
    1157             : }
    1158             : 
    1159           0 : bool CallFrameInfo::State::DoRule(unsigned reg, Rule *rule) {
    1160           0 :   rules_.SetRegisterRule(reg, rule);
    1161           0 :   return rule->Handle(handler_, address_, reg);
    1162             : }
    1163             : 
    1164           0 : bool CallFrameInfo::State::DoOffset(unsigned reg, long offset) {
    1165           0 :   if (!rules_.CFARule()) {
    1166           0 :     reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset());
    1167           0 :     return false;
    1168             :   }
    1169             :   return DoRule(reg,
    1170           0 :                 new OffsetRule(Handler::kCFARegister, offset));
    1171             : }
    1172             : 
    1173           0 : bool CallFrameInfo::State::DoValOffset(unsigned reg, long offset) {
    1174           0 :   if (!rules_.CFARule()) {
    1175           0 :     reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset());
    1176           0 :     return false;
    1177             :   }
    1178             :   return DoRule(reg,
    1179           0 :                 new ValOffsetRule(Handler::kCFARegister, offset));
    1180             : }
    1181             : 
    1182           0 : bool CallFrameInfo::State::DoRestore(unsigned reg) {
    1183             :   // DW_CFA_restore and DW_CFA_restore_extended don't make sense in a CIE.
    1184           0 :   if (entry_->kind == kCIE) {
    1185           0 :     reporter_->RestoreInCIE(entry_->offset, CursorOffset());
    1186           0 :     return false;
    1187             :   }
    1188           0 :   Rule *rule = cie_rules_.RegisterRule(reg);
    1189           0 :   if (!rule) {
    1190             :     // This isn't really the right thing to do, but since CFI generally
    1191             :     // only mentions callee-saves registers, and GCC's convention for
    1192             :     // callee-saves registers is that they are unchanged, it's a good
    1193             :     // approximation.
    1194           0 :     rule = new SameValueRule();
    1195             :   }
    1196           0 :   return DoRule(reg, rule);
    1197             : }
    1198             : 
    1199           0 : bool CallFrameInfo::ReadEntryPrologue(const char *cursor, Entry *entry) {
    1200           0 :   const char *buffer_end = buffer_ + buffer_length_;
    1201             : 
    1202             :   // Initialize enough of ENTRY for use in error reporting.
    1203           0 :   entry->offset = cursor - buffer_;
    1204           0 :   entry->start = cursor;
    1205           0 :   entry->kind = kUnknown;
    1206           0 :   entry->end = NULL;
    1207             : 
    1208             :   // Read the initial length. This sets reader_'s offset size.
    1209             :   size_t length_size;
    1210           0 :   uint64 length = reader_->ReadInitialLength(cursor, &length_size);
    1211           0 :   if (length_size > size_t(buffer_end - cursor))
    1212           0 :     return ReportIncomplete(entry);
    1213           0 :   cursor += length_size;
    1214             : 
    1215             :   // In a .eh_frame section, a length of zero marks the end of the series
    1216             :   // of entries.
    1217           0 :   if (length == 0 && eh_frame_) {
    1218           0 :     entry->kind = kTerminator;
    1219           0 :     entry->end = cursor;
    1220           0 :     return true;
    1221             :   }
    1222             : 
    1223             :   // Validate the length.
    1224           0 :   if (length > size_t(buffer_end - cursor))
    1225           0 :     return ReportIncomplete(entry);
    1226             : 
    1227             :   // The length is the number of bytes after the initial length field;
    1228             :   // we have that position handy at this point, so compute the end
    1229             :   // now. (If we're parsing 64-bit-offset DWARF on a 32-bit machine,
    1230             :   // and the length didn't fit in a size_t, we would have rejected it
    1231             :   // above.)
    1232           0 :   entry->end = cursor + length;
    1233             : 
    1234             :   // Parse the next field: either the offset of a CIE or a CIE id.
    1235           0 :   size_t offset_size = reader_->OffsetSize();
    1236           0 :   if (offset_size > size_t(entry->end - cursor)) return ReportIncomplete(entry);
    1237           0 :   entry->id = reader_->ReadOffset(cursor);
    1238             : 
    1239             :   // Don't advance cursor past id field yet; in .eh_frame data we need
    1240             :   // the id's position to compute the section offset of an FDE's CIE.
    1241             : 
    1242             :   // Now we can decide what kind of entry this is.
    1243           0 :   if (eh_frame_) {
    1244             :     // In .eh_frame data, an ID of zero marks the entry as a CIE, and
    1245             :     // anything else is an offset from the id field of the FDE to the start
    1246             :     // of the CIE.
    1247           0 :     if (entry->id == 0) {
    1248           0 :       entry->kind = kCIE;
    1249             :     } else {
    1250           0 :       entry->kind = kFDE;
    1251             :       // Turn the offset from the id into an offset from the buffer's start.
    1252           0 :       entry->id = (cursor - buffer_) - entry->id;
    1253             :     }
    1254             :   } else {
    1255             :     // In DWARF CFI data, an ID of ~0 (of the appropriate width, given the
    1256             :     // offset size for the entry) marks the entry as a CIE, and anything
    1257             :     // else is the offset of the CIE from the beginning of the section.
    1258           0 :     if (offset_size == 4)
    1259           0 :       entry->kind = (entry->id == 0xffffffff) ? kCIE : kFDE;
    1260             :     else {
    1261           0 :       MOZ_ASSERT(offset_size == 8);
    1262           0 :       entry->kind = (entry->id == 0xffffffffffffffffULL) ? kCIE : kFDE;
    1263             :     }
    1264             :   }
    1265             : 
    1266             :   // Now advance cursor past the id.
    1267           0 :    cursor += offset_size;
    1268             : 
    1269             :   // The fields specific to this kind of entry start here.
    1270           0 :   entry->fields = cursor;
    1271             : 
    1272           0 :   entry->cie = NULL;
    1273             : 
    1274           0 :   return true;
    1275             : }
    1276             : 
    1277           0 : bool CallFrameInfo::ReadCIEFields(CIE *cie) {
    1278           0 :   const char *cursor = cie->fields;
    1279             :   size_t len;
    1280             : 
    1281           0 :   MOZ_ASSERT(cie->kind == kCIE);
    1282             : 
    1283             :   // Prepare for early exit.
    1284           0 :   cie->version = 0;
    1285           0 :   cie->augmentation.clear();
    1286           0 :   cie->code_alignment_factor = 0;
    1287           0 :   cie->data_alignment_factor = 0;
    1288           0 :   cie->return_address_register = 0;
    1289           0 :   cie->has_z_augmentation = false;
    1290           0 :   cie->pointer_encoding = DW_EH_PE_absptr;
    1291           0 :   cie->instructions = 0;
    1292             : 
    1293             :   // Parse the version number.
    1294           0 :   if (cie->end - cursor < 1)
    1295           0 :     return ReportIncomplete(cie);
    1296           0 :   cie->version = reader_->ReadOneByte(cursor);
    1297           0 :   cursor++;
    1298             : 
    1299             :   // If we don't recognize the version, we can't parse any more fields of the
    1300             :   // CIE. For DWARF CFI, we handle versions 1 through 3 (there was never a
    1301             :   // version 2 of CFI data). For .eh_frame, we handle versions 1 and 3 as well;
    1302             :   // the difference between those versions seems to be the same as for
    1303             :   // .debug_frame.
    1304           0 :   if (cie->version < 1 || cie->version > 3) {
    1305           0 :     reporter_->UnrecognizedVersion(cie->offset, cie->version);
    1306           0 :     return false;
    1307             :   }
    1308             : 
    1309           0 :   const char *augmentation_start = cursor;
    1310             :   const void *augmentation_end =
    1311           0 :       memchr(augmentation_start, '\0', cie->end - augmentation_start);
    1312           0 :   if (! augmentation_end) return ReportIncomplete(cie);
    1313           0 :   cursor = static_cast<const char *>(augmentation_end);
    1314           0 :   cie->augmentation = string(augmentation_start,
    1315           0 :                                   cursor - augmentation_start);
    1316             :   // Skip the terminating '\0'.
    1317           0 :   cursor++;
    1318             : 
    1319             :   // Is this CFI augmented?
    1320           0 :   if (!cie->augmentation.empty()) {
    1321             :     // Is it an augmentation we recognize?
    1322           0 :     if (cie->augmentation[0] == DW_Z_augmentation_start) {
    1323             :       // Linux C++ ABI 'z' augmentation, used for exception handling data.
    1324           0 :       cie->has_z_augmentation = true;
    1325             :     } else {
    1326             :       // Not an augmentation we recognize. Augmentations can have arbitrary
    1327             :       // effects on the form of rest of the content, so we have to give up.
    1328           0 :       reporter_->UnrecognizedAugmentation(cie->offset, cie->augmentation);
    1329           0 :       return false;
    1330             :     }
    1331             :   }
    1332             : 
    1333             :   // Parse the code alignment factor.
    1334           0 :   cie->code_alignment_factor = reader_->ReadUnsignedLEB128(cursor, &len);
    1335           0 :   if (size_t(cie->end - cursor) < len) return ReportIncomplete(cie);
    1336           0 :   cursor += len;
    1337             : 
    1338             :   // Parse the data alignment factor.
    1339           0 :   cie->data_alignment_factor = reader_->ReadSignedLEB128(cursor, &len);
    1340           0 :   if (size_t(cie->end - cursor) < len) return ReportIncomplete(cie);
    1341           0 :   cursor += len;
    1342             : 
    1343             :   // Parse the return address register. This is a ubyte in version 1, and
    1344             :   // a ULEB128 in version 3.
    1345           0 :   if (cie->version == 1) {
    1346           0 :     if (cursor >= cie->end) return ReportIncomplete(cie);
    1347           0 :     cie->return_address_register = uint8(*cursor++);
    1348             :   } else {
    1349           0 :     cie->return_address_register = reader_->ReadUnsignedLEB128(cursor, &len);
    1350           0 :     if (size_t(cie->end - cursor) < len) return ReportIncomplete(cie);
    1351           0 :     cursor += len;
    1352             :   }
    1353             : 
    1354             :   // If we have a 'z' augmentation string, find the augmentation data and
    1355             :   // use the augmentation string to parse it.
    1356           0 :   if (cie->has_z_augmentation) {
    1357           0 :     uint64_t data_size = reader_->ReadUnsignedLEB128(cursor, &len);
    1358           0 :     if (size_t(cie->end - cursor) < len + data_size)
    1359           0 :       return ReportIncomplete(cie);
    1360           0 :     cursor += len;
    1361           0 :     const char *data = cursor;
    1362           0 :     cursor += data_size;
    1363           0 :     const char *data_end = cursor;
    1364             : 
    1365           0 :     cie->has_z_lsda = false;
    1366           0 :     cie->has_z_personality = false;
    1367           0 :     cie->has_z_signal_frame = false;
    1368             : 
    1369             :     // Walk the augmentation string, and extract values from the
    1370             :     // augmentation data as the string directs.
    1371           0 :     for (size_t i = 1; i < cie->augmentation.size(); i++) {
    1372           0 :       switch (cie->augmentation[i]) {
    1373             :         case DW_Z_has_LSDA:
    1374             :           // The CIE's augmentation data holds the language-specific data
    1375             :           // area pointer's encoding, and the FDE's augmentation data holds
    1376             :           // the pointer itself.
    1377           0 :           cie->has_z_lsda = true;
    1378             :           // Fetch the LSDA encoding from the augmentation data.
    1379           0 :           if (data >= data_end) return ReportIncomplete(cie);
    1380           0 :           cie->lsda_encoding = DwarfPointerEncoding(*data++);
    1381           0 :           if (!reader_->ValidEncoding(cie->lsda_encoding)) {
    1382           0 :             reporter_->InvalidPointerEncoding(cie->offset, cie->lsda_encoding);
    1383           0 :             return false;
    1384             :           }
    1385             :           // Don't check if the encoding is usable here --- we haven't
    1386             :           // read the FDE's fields yet, so we're not prepared for
    1387             :           // DW_EH_PE_funcrel, although that's a fine encoding for the
    1388             :           // LSDA to use, since it appears in the FDE.
    1389           0 :           break;
    1390             : 
    1391             :         case DW_Z_has_personality_routine:
    1392             :           // The CIE's augmentation data holds the personality routine
    1393             :           // pointer's encoding, followed by the pointer itself.
    1394           0 :           cie->has_z_personality = true;
    1395             :           // Fetch the personality routine pointer's encoding from the
    1396             :           // augmentation data.
    1397           0 :           if (data >= data_end) return ReportIncomplete(cie);
    1398           0 :           cie->personality_encoding = DwarfPointerEncoding(*data++);
    1399           0 :           if (!reader_->ValidEncoding(cie->personality_encoding)) {
    1400           0 :             reporter_->InvalidPointerEncoding(cie->offset,
    1401           0 :                                               cie->personality_encoding);
    1402           0 :             return false;
    1403             :           }
    1404           0 :           if (!reader_->UsableEncoding(cie->personality_encoding)) {
    1405           0 :             reporter_->UnusablePointerEncoding(cie->offset,
    1406           0 :                                                cie->personality_encoding);
    1407           0 :             return false;
    1408             :           }
    1409             :           // Fetch the personality routine's pointer itself from the data.
    1410           0 :           cie->personality_address =
    1411           0 :             reader_->ReadEncodedPointer(data, cie->personality_encoding,
    1412             :                                         &len);
    1413           0 :           if (len > size_t(data_end - data))
    1414           0 :             return ReportIncomplete(cie);
    1415           0 :           data += len;
    1416           0 :           break;
    1417             : 
    1418             :         case DW_Z_has_FDE_address_encoding:
    1419             :           // The CIE's augmentation data holds the pointer encoding to use
    1420             :           // for addresses in the FDE.
    1421           0 :           if (data >= data_end) return ReportIncomplete(cie);
    1422           0 :           cie->pointer_encoding = DwarfPointerEncoding(*data++);
    1423           0 :           if (!reader_->ValidEncoding(cie->pointer_encoding)) {
    1424           0 :             reporter_->InvalidPointerEncoding(cie->offset,
    1425           0 :                                               cie->pointer_encoding);
    1426           0 :             return false;
    1427             :           }
    1428           0 :           if (!reader_->UsableEncoding(cie->pointer_encoding)) {
    1429           0 :             reporter_->UnusablePointerEncoding(cie->offset,
    1430           0 :                                                cie->pointer_encoding);
    1431           0 :             return false;
    1432             :           }
    1433           0 :           break;
    1434             : 
    1435             :         case DW_Z_is_signal_trampoline:
    1436             :           // Frames using this CIE are signal delivery frames.
    1437           0 :           cie->has_z_signal_frame = true;
    1438           0 :           break;
    1439             : 
    1440             :         default:
    1441             :           // An augmentation we don't recognize.
    1442           0 :           reporter_->UnrecognizedAugmentation(cie->offset, cie->augmentation);
    1443           0 :           return false;
    1444             :       }
    1445             :     }
    1446             :   }
    1447             : 
    1448             :   // The CIE's instructions start here.
    1449           0 :   cie->instructions = cursor;
    1450             : 
    1451           0 :   return true;
    1452             : }
    1453             : 
    1454           0 : bool CallFrameInfo::ReadFDEFields(FDE *fde) {
    1455           0 :   const char *cursor = fde->fields;
    1456             :   size_t size;
    1457             : 
    1458           0 :   fde->address = reader_->ReadEncodedPointer(cursor, fde->cie->pointer_encoding,
    1459             :                                              &size);
    1460           0 :   if (size > size_t(fde->end - cursor))
    1461           0 :     return ReportIncomplete(fde);
    1462           0 :   cursor += size;
    1463           0 :   reader_->SetFunctionBase(fde->address);
    1464             : 
    1465             :   // For the length, we strip off the upper nybble of the encoding used for
    1466             :   // the starting address.
    1467             :   DwarfPointerEncoding length_encoding =
    1468           0 :     DwarfPointerEncoding(fde->cie->pointer_encoding & 0x0f);
    1469           0 :   fde->size = reader_->ReadEncodedPointer(cursor, length_encoding, &size);
    1470           0 :   if (size > size_t(fde->end - cursor))
    1471           0 :     return ReportIncomplete(fde);
    1472           0 :   cursor += size;
    1473             : 
    1474             :   // If the CIE has a 'z' augmentation string, then augmentation data
    1475             :   // appears here.
    1476           0 :   if (fde->cie->has_z_augmentation) {
    1477           0 :     uint64_t data_size = reader_->ReadUnsignedLEB128(cursor, &size);
    1478           0 :     if (size_t(fde->end - cursor) < size + data_size)
    1479           0 :       return ReportIncomplete(fde);
    1480           0 :     cursor += size;
    1481             : 
    1482             :     // In the abstract, we should walk the augmentation string, and extract
    1483             :     // items from the FDE's augmentation data as we encounter augmentation
    1484             :     // string characters that specify their presence: the ordering of items
    1485             :     // in the augmentation string determines the arrangement of values in
    1486             :     // the augmentation data.
    1487             :     //
    1488             :     // In practice, there's only ever one value in FDE augmentation data
    1489             :     // that we support --- the LSDA pointer --- and we have to bail if we
    1490             :     // see any unrecognized augmentation string characters. So if there is
    1491             :     // anything here at all, we know what it is, and where it starts.
    1492           0 :     if (fde->cie->has_z_lsda) {
    1493             :       // Check whether the LSDA's pointer encoding is usable now: only once
    1494             :       // we've parsed the FDE's starting address do we call reader_->
    1495             :       // SetFunctionBase, so that the DW_EH_PE_funcrel encoding becomes
    1496             :       // usable.
    1497           0 :       if (!reader_->UsableEncoding(fde->cie->lsda_encoding)) {
    1498           0 :         reporter_->UnusablePointerEncoding(fde->cie->offset,
    1499           0 :                                            fde->cie->lsda_encoding);
    1500           0 :         return false;
    1501             :       }
    1502             : 
    1503           0 :       fde->lsda_address =
    1504           0 :         reader_->ReadEncodedPointer(cursor, fde->cie->lsda_encoding, &size);
    1505           0 :       if (size > data_size)
    1506           0 :         return ReportIncomplete(fde);
    1507             :       // Ideally, we would also complain here if there were unconsumed
    1508             :       // augmentation data.
    1509             :     }
    1510             : 
    1511           0 :     cursor += data_size;
    1512             :   }
    1513             : 
    1514             :   // The FDE's instructions start after those.
    1515           0 :   fde->instructions = cursor;
    1516             : 
    1517           0 :   return true;
    1518             : }
    1519             : 
    1520           0 : bool CallFrameInfo::Start() {
    1521           0 :   const char *buffer_end = buffer_ + buffer_length_;
    1522             :   const char *cursor;
    1523           0 :   bool all_ok = true;
    1524             :   const char *entry_end;
    1525             :   bool ok;
    1526             : 
    1527             :   // Traverse all the entries in buffer_, skipping CIEs and offering
    1528             :   // FDEs to the handler.
    1529           0 :   for (cursor = buffer_; cursor < buffer_end;
    1530           0 :        cursor = entry_end, all_ok = all_ok && ok) {
    1531             :     FDE fde;
    1532             : 
    1533             :     // Make it easy to skip this entry with 'continue': assume that
    1534             :     // things are not okay until we've checked all the data, and
    1535             :     // prepare the address of the next entry.
    1536           0 :     ok = false;
    1537             : 
    1538             :     // Read the entry's prologue.
    1539           0 :     if (!ReadEntryPrologue(cursor, &fde)) {
    1540           0 :       if (!fde.end) {
    1541             :         // If we couldn't even figure out this entry's extent, then we
    1542             :         // must stop processing entries altogether.
    1543           0 :         all_ok = false;
    1544           0 :         break;
    1545             :       }
    1546           0 :       entry_end = fde.end;
    1547           0 :       continue;
    1548             :     }
    1549             : 
    1550             :     // The next iteration picks up after this entry.
    1551           0 :     entry_end = fde.end;
    1552             : 
    1553             :     // Did we see an .eh_frame terminating mark?
    1554           0 :     if (fde.kind == kTerminator) {
    1555             :       // If there appears to be more data left in the section after the
    1556             :       // terminating mark, warn the user. But this is just a warning;
    1557             :       // we leave all_ok true.
    1558           0 :       if (fde.end < buffer_end) reporter_->EarlyEHTerminator(fde.offset);
    1559           0 :       break;
    1560             :     }
    1561             : 
    1562             :     // In this loop, we skip CIEs. We only parse them fully when we
    1563             :     // parse an FDE that refers to them. This limits our memory
    1564             :     // consumption (beyond the buffer itself) to that needed to
    1565             :     // process the largest single entry.
    1566           0 :     if (fde.kind != kFDE) {
    1567           0 :       ok = true;
    1568           0 :       continue;
    1569             :     }
    1570             : 
    1571             :     // Validate the CIE pointer.
    1572           0 :     if (fde.id > buffer_length_) {
    1573           0 :       reporter_->CIEPointerOutOfRange(fde.offset, fde.id);
    1574           0 :       continue;
    1575             :     }
    1576             : 
    1577           0 :     CIE cie;
    1578             : 
    1579             :     // Parse this FDE's CIE header.
    1580           0 :     if (!ReadEntryPrologue(buffer_ + fde.id, &cie))
    1581           0 :       continue;
    1582             :     // This had better be an actual CIE.
    1583           0 :     if (cie.kind != kCIE) {
    1584           0 :       reporter_->BadCIEId(fde.offset, fde.id);
    1585           0 :       continue;
    1586             :     }
    1587           0 :     if (!ReadCIEFields(&cie))
    1588           0 :       continue;
    1589             : 
    1590             :     // We now have the values that govern both the CIE and the FDE.
    1591           0 :     cie.cie = &cie;
    1592           0 :     fde.cie = &cie;
    1593             : 
    1594             :     // Parse the FDE's header.
    1595           0 :     if (!ReadFDEFields(&fde))
    1596           0 :       continue;
    1597             : 
    1598             :     // Call Entry to ask the consumer if they're interested.
    1599           0 :     if (!handler_->Entry(fde.offset, fde.address, fde.size,
    1600           0 :                          cie.version, cie.augmentation,
    1601           0 :                          cie.return_address_register)) {
    1602             :       // The handler isn't interested in this entry. That's not an error.
    1603           0 :       ok = true;
    1604           0 :       continue;
    1605             :     }
    1606             : 
    1607           0 :     if (cie.has_z_augmentation) {
    1608             :       // Report the personality routine address, if we have one.
    1609           0 :       if (cie.has_z_personality) {
    1610           0 :         if (!handler_
    1611           0 :             ->PersonalityRoutine(cie.personality_address,
    1612           0 :                                  IsIndirectEncoding(cie.personality_encoding)))
    1613           0 :           continue;
    1614             :       }
    1615             : 
    1616             :       // Report the language-specific data area address, if we have one.
    1617           0 :       if (cie.has_z_lsda) {
    1618           0 :         if (!handler_
    1619           0 :             ->LanguageSpecificDataArea(fde.lsda_address,
    1620           0 :                                        IsIndirectEncoding(cie.lsda_encoding)))
    1621           0 :           continue;
    1622             :       }
    1623             : 
    1624             :       // If this is a signal-handling frame, report that.
    1625           0 :       if (cie.has_z_signal_frame) {
    1626           0 :         if (!handler_->SignalHandler())
    1627           0 :           continue;
    1628             :       }
    1629             :     }
    1630             : 
    1631             :     // Interpret the CIE's instructions, and then the FDE's instructions.
    1632           0 :     State state(reader_, handler_, reporter_, fde.address);
    1633           0 :     ok = state.InterpretCIE(cie) && state.InterpretFDE(fde);
    1634             : 
    1635             :     // Tell the ByteReader that the function start address from the
    1636             :     // FDE header is no longer valid.
    1637           0 :     reader_->ClearFunctionBase();
    1638             : 
    1639             :     // Report the end of the entry.
    1640           0 :     handler_->End();
    1641             :   }
    1642             : 
    1643           0 :   return all_ok;
    1644             : }
    1645             : 
    1646           0 : const char *CallFrameInfo::KindName(EntryKind kind) {
    1647           0 :   if (kind == CallFrameInfo::kUnknown)
    1648           0 :     return "entry";
    1649           0 :   else if (kind == CallFrameInfo::kCIE)
    1650           0 :     return "common information entry";
    1651           0 :   else if (kind == CallFrameInfo::kFDE)
    1652           0 :     return "frame description entry";
    1653             :   else {
    1654           0 :     MOZ_ASSERT (kind == CallFrameInfo::kTerminator);
    1655           0 :     return ".eh_frame sequence terminator";
    1656             :   }
    1657             : }
    1658             : 
    1659           0 : bool CallFrameInfo::ReportIncomplete(Entry *entry) {
    1660           0 :   reporter_->Incomplete(entry->offset, entry->kind);
    1661           0 :   return false;
    1662             : }
    1663             : 
    1664           0 : void CallFrameInfo::Reporter::Incomplete(uint64 offset,
    1665             :                                          CallFrameInfo::EntryKind kind) {
    1666             :   char buf[300];
    1667           0 :   SprintfLiteral(buf,
    1668             :                  "%s: CFI %s at offset 0x%llx in '%s': entry ends early\n",
    1669             :                  filename_.c_str(), CallFrameInfo::KindName(kind), offset,
    1670           0 :                  section_.c_str());
    1671           0 :   log_(buf);
    1672           0 : }
    1673             : 
    1674           0 : void CallFrameInfo::Reporter::EarlyEHTerminator(uint64 offset) {
    1675             :   char buf[300];
    1676           0 :   SprintfLiteral(buf,
    1677             :                  "%s: CFI at offset 0x%llx in '%s': saw end-of-data marker"
    1678             :                  " before end of section contents\n",
    1679           0 :                  filename_.c_str(), offset, section_.c_str());
    1680           0 :   log_(buf);
    1681           0 : }
    1682             : 
    1683           0 : void CallFrameInfo::Reporter::CIEPointerOutOfRange(uint64 offset,
    1684             :                                                    uint64 cie_offset) {
    1685             :   char buf[300];
    1686           0 :   SprintfLiteral(buf,
    1687             :                  "%s: CFI frame description entry at offset 0x%llx in '%s':"
    1688             :                  " CIE pointer is out of range: 0x%llx\n",
    1689           0 :                  filename_.c_str(), offset, section_.c_str(), cie_offset);
    1690           0 :   log_(buf);
    1691           0 : }
    1692             : 
    1693           0 : void CallFrameInfo::Reporter::BadCIEId(uint64 offset, uint64 cie_offset) {
    1694             :   char buf[300];
    1695           0 :   SprintfLiteral(buf,
    1696             :                  "%s: CFI frame description entry at offset 0x%llx in '%s':"
    1697             :                  " CIE pointer does not point to a CIE: 0x%llx\n",
    1698           0 :                  filename_.c_str(), offset, section_.c_str(), cie_offset);
    1699           0 :   log_(buf);
    1700           0 : }
    1701             : 
    1702           0 : void CallFrameInfo::Reporter::UnrecognizedVersion(uint64 offset, int version) {
    1703             :   char buf[300];
    1704           0 :   SprintfLiteral(buf,
    1705             :                  "%s: CFI frame description entry at offset 0x%llx in '%s':"
    1706             :                  " CIE specifies unrecognized version: %d\n",
    1707           0 :                  filename_.c_str(), offset, section_.c_str(), version);
    1708           0 :   log_(buf);
    1709           0 : }
    1710             : 
    1711           0 : void CallFrameInfo::Reporter::UnrecognizedAugmentation(uint64 offset,
    1712             :                                                        const string &aug) {
    1713             :   char buf[300];
    1714           0 :   SprintfLiteral(buf,
    1715             :                  "%s: CFI frame description entry at offset 0x%llx in '%s':"
    1716             :                  " CIE specifies unrecognized augmentation: '%s'\n",
    1717           0 :                  filename_.c_str(), offset, section_.c_str(), aug.c_str());
    1718           0 :   log_(buf);
    1719           0 : }
    1720             : 
    1721           0 : void CallFrameInfo::Reporter::InvalidPointerEncoding(uint64 offset,
    1722             :                                                      uint8 encoding) {
    1723             :   char buf[300];
    1724           0 :   SprintfLiteral(buf,
    1725             :                  "%s: CFI common information entry at offset 0x%llx in '%s':"
    1726             :                  " 'z' augmentation specifies invalid pointer encoding: "
    1727             :                  "0x%02x\n",
    1728           0 :                  filename_.c_str(), offset, section_.c_str(), encoding);
    1729           0 :   log_(buf);
    1730           0 : }
    1731             : 
    1732           0 : void CallFrameInfo::Reporter::UnusablePointerEncoding(uint64 offset,
    1733             :                                                       uint8 encoding) {
    1734             :   char buf[300];
    1735           0 :   SprintfLiteral(buf,
    1736             :                  "%s: CFI common information entry at offset 0x%llx in '%s':"
    1737             :                  " 'z' augmentation specifies a pointer encoding for which"
    1738             :                  " we have no base address: 0x%02x\n",
    1739           0 :                  filename_.c_str(), offset, section_.c_str(), encoding);
    1740           0 :   log_(buf);
    1741           0 : }
    1742             : 
    1743           0 : void CallFrameInfo::Reporter::RestoreInCIE(uint64 offset, uint64 insn_offset) {
    1744             :   char buf[300];
    1745           0 :   SprintfLiteral(buf,
    1746             :                  "%s: CFI common information entry at offset 0x%llx in '%s':"
    1747             :                  " the DW_CFA_restore instruction at offset 0x%llx"
    1748             :                  " cannot be used in a common information entry\n",
    1749           0 :                  filename_.c_str(), offset, section_.c_str(), insn_offset);
    1750           0 :   log_(buf);
    1751           0 : }
    1752             : 
    1753           0 : void CallFrameInfo::Reporter::BadInstruction(uint64 offset,
    1754             :                                              CallFrameInfo::EntryKind kind,
    1755             :                                              uint64 insn_offset) {
    1756             :   char buf[300];
    1757           0 :   SprintfLiteral(buf,
    1758             :                  "%s: CFI %s at offset 0x%llx in section '%s':"
    1759             :                  " the instruction at offset 0x%llx is unrecognized\n",
    1760             :                  filename_.c_str(), CallFrameInfo::KindName(kind),
    1761           0 :                  offset, section_.c_str(), insn_offset);
    1762           0 :   log_(buf);
    1763           0 : }
    1764             : 
    1765           0 : void CallFrameInfo::Reporter::NoCFARule(uint64 offset,
    1766             :                                         CallFrameInfo::EntryKind kind,
    1767             :                                         uint64 insn_offset) {
    1768             :   char buf[300];
    1769           0 :   SprintfLiteral(buf,
    1770             :                  "%s: CFI %s at offset 0x%llx in section '%s':"
    1771             :                  " the instruction at offset 0x%llx assumes that a CFA rule "
    1772             :                  "has been set, but none has been set\n",
    1773             :                  filename_.c_str(), CallFrameInfo::KindName(kind), offset,
    1774           0 :                  section_.c_str(), insn_offset);
    1775           0 :   log_(buf);
    1776           0 : }
    1777             : 
    1778           0 : void CallFrameInfo::Reporter::EmptyStateStack(uint64 offset,
    1779             :                                               CallFrameInfo::EntryKind kind,
    1780             :                                               uint64 insn_offset) {
    1781             :   char buf[300];
    1782           0 :   SprintfLiteral(buf,
    1783             :                  "%s: CFI %s at offset 0x%llx in section '%s':"
    1784             :                  " the DW_CFA_restore_state instruction at offset 0x%llx"
    1785             :                  " should pop a saved state from the stack, but the stack "
    1786             :                  "is empty\n",
    1787             :                  filename_.c_str(), CallFrameInfo::KindName(kind), offset,
    1788           0 :                  section_.c_str(), insn_offset);
    1789           0 :   log_(buf);
    1790           0 : }
    1791             : 
    1792           0 : void CallFrameInfo::Reporter::ClearingCFARule(uint64 offset,
    1793             :                                               CallFrameInfo::EntryKind kind,
    1794             :                                               uint64 insn_offset) {
    1795             :   char buf[300];
    1796           0 :   SprintfLiteral(buf,
    1797             :                  "%s: CFI %s at offset 0x%llx in section '%s':"
    1798             :                  " the DW_CFA_restore_state instruction at offset 0x%llx"
    1799             :                  " would clear the CFA rule in effect\n",
    1800             :                  filename_.c_str(), CallFrameInfo::KindName(kind), offset,
    1801           0 :                  section_.c_str(), insn_offset);
    1802           0 :   log_(buf);
    1803           0 : }
    1804             : 
    1805             : 
    1806           0 : unsigned int DwarfCFIToModule::RegisterNames::I386() {
    1807             :   /*
    1808             :    8 "$eax", "$ecx", "$edx", "$ebx", "$esp", "$ebp", "$esi", "$edi",
    1809             :    3 "$eip", "$eflags", "$unused1",
    1810             :    8 "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
    1811             :    2 "$unused2", "$unused3",
    1812             :    8 "$xmm0", "$xmm1", "$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
    1813             :    8 "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
    1814             :    3 "$fcw", "$fsw", "$mxcsr",
    1815             :    8 "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused4", "$unused5",
    1816             :    2 "$tr", "$ldtr"
    1817             :   */
    1818           0 :   return 8 + 3 + 8 + 2 + 8 + 8 + 3 + 8 + 2;
    1819             : }
    1820             : 
    1821           0 : unsigned int DwarfCFIToModule::RegisterNames::X86_64() {
    1822             :   /*
    1823             :    8 "$rax", "$rdx", "$rcx", "$rbx", "$rsi", "$rdi", "$rbp", "$rsp",
    1824             :    8 "$r8",  "$r9",  "$r10", "$r11", "$r12", "$r13", "$r14", "$r15",
    1825             :    1 "$rip",
    1826             :    8 "$xmm0","$xmm1","$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
    1827             :    8 "$xmm8","$xmm9","$xmm10","$xmm11","$xmm12","$xmm13","$xmm14","$xmm15",
    1828             :    8 "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
    1829             :    8 "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
    1830             :    1 "$rflags",
    1831             :    8 "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused1", "$unused2",
    1832             :    4 "$fs.base", "$gs.base", "$unused3", "$unused4",
    1833             :    2 "$tr", "$ldtr",
    1834             :    3 "$mxcsr", "$fcw", "$fsw"
    1835             :   */
    1836           0 :   return 8 + 8 + 1 + 8 + 8 + 8 + 8 + 1 + 8 + 4 + 2 + 3;
    1837             : }
    1838             : 
    1839             : // Per ARM IHI 0040A, section 3.1
    1840           0 : unsigned int DwarfCFIToModule::RegisterNames::ARM() {
    1841             :   /*
    1842             :    8 "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
    1843             :    8 "r8",  "r9",  "r10", "r11", "r12", "sp",  "lr",  "pc",
    1844             :    8 "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
    1845             :    8 "fps", "cpsr", "",   "",    "",    "",    "",    "",
    1846             :    8 "",    "",    "",    "",    "",    "",    "",    "",
    1847             :    8 "",    "",    "",    "",    "",    "",    "",    "",
    1848             :    8 "",    "",    "",    "",    "",    "",    "",    "",
    1849             :    8 "",    "",    "",    "",    "",    "",    "",    "",
    1850             :    8 "s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",
    1851             :    8 "s8",  "s9",  "s10", "s11", "s12", "s13", "s14", "s15",
    1852             :    8 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
    1853             :    8 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
    1854             :    8 "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7"
    1855             :   */
    1856           0 :   return 13 * 8;
    1857             : }
    1858             : 
    1859             : // See prototype for comments.
    1860           0 : int32_t parseDwarfExpr(Summariser* summ, const ByteReader* reader,
    1861             :                        string expr, bool debug,
    1862             :                        bool pushCfaAtStart, bool derefAtEnd)
    1863             : {
    1864           0 :   const char* cursor = expr.c_str();
    1865           0 :   const char* end1   = cursor + expr.length();
    1866             : 
    1867             :   char buf[100];
    1868           0 :   if (debug) {
    1869           0 :     SprintfLiteral(buf, "LUL.DW  << DwarfExpr, len is %d\n",
    1870           0 :                    (int)(end1 - cursor));
    1871           0 :     summ->Log(buf);
    1872             :   }
    1873             : 
    1874             :   // Add a marker for the start of this expression.  In it, indicate
    1875             :   // whether or not the CFA should be pushed onto the stack prior to
    1876             :   // evaluation.
    1877             :   int32_t start_ix
    1878           0 :     = summ->AddPfxInstr(PfxInstr(PX_Start, pushCfaAtStart ? 1 : 0));
    1879           0 :   MOZ_ASSERT(start_ix >= 0);
    1880             : 
    1881           0 :   while (cursor < end1) {
    1882             : 
    1883           0 :     uint8 opc = reader->ReadOneByte(cursor);
    1884           0 :     cursor++;
    1885             : 
    1886           0 :     const char* nm   = nullptr;
    1887           0 :     PfxExprOp   pxop = PX_End;
    1888             : 
    1889           0 :     switch (opc) {
    1890             : 
    1891             :       case DW_OP_lit0 ... DW_OP_lit31: {
    1892           0 :         int32_t simm32 = (int32_t)(opc - DW_OP_lit0);
    1893           0 :         if (debug) {
    1894           0 :           SprintfLiteral(buf, "LUL.DW   DW_OP_lit%d\n", (int)simm32);
    1895           0 :           summ->Log(buf);
    1896             :         }
    1897           0 :         (void) summ->AddPfxInstr(PfxInstr(PX_SImm32, simm32));
    1898           0 :         break;
    1899             :       }
    1900             : 
    1901             :       case DW_OP_breg0 ... DW_OP_breg31: {
    1902             :         size_t len;
    1903           0 :         int64_t n = reader->ReadSignedLEB128(cursor, &len);
    1904           0 :         cursor += len;
    1905           0 :         DW_REG_NUMBER reg = (DW_REG_NUMBER)(opc - DW_OP_breg0);
    1906           0 :         if (debug) {
    1907             :           SprintfLiteral(buf, "LUL.DW   DW_OP_breg%d %lld\n",
    1908           0 :                          (int)reg, (long long int)n);
    1909           0 :           summ->Log(buf);
    1910             :         }
    1911             :         // PfxInstr only allows a 32 bit signed offset.  So we
    1912             :         // must fail if the immediate is out of range.
    1913           0 :         if (n < INT32_MIN || INT32_MAX < n)
    1914             :           goto fail;
    1915           0 :         (void) summ->AddPfxInstr(PfxInstr(PX_DwReg, reg));
    1916           0 :         (void) summ->AddPfxInstr(PfxInstr(PX_SImm32, (int32_t)n));
    1917           0 :         (void) summ->AddPfxInstr(PfxInstr(PX_Add));
    1918           0 :         break;
    1919             :       }
    1920             : 
    1921             :       case DW_OP_const4s: {
    1922           0 :         uint64_t u64 = reader->ReadFourBytes(cursor);
    1923           0 :         cursor += 4;
    1924             :         // u64 is guaranteed by |ReadFourBytes| to be in the
    1925             :         // range 0 .. FFFFFFFF inclusive.  But to be safe:
    1926           0 :         uint32_t u32 = (uint32_t)(u64 & 0xFFFFFFFF);
    1927           0 :         int32_t  s32 = (int32_t)u32;
    1928           0 :         if (debug) {
    1929           0 :           SprintfLiteral(buf, "LUL.DW   DW_OP_const4s %d\n", (int)s32);
    1930           0 :           summ->Log(buf);
    1931             :         }
    1932           0 :         (void) summ->AddPfxInstr(PfxInstr(PX_SImm32, s32));
    1933           0 :         break;
    1934             :       }
    1935             : 
    1936           0 :       case DW_OP_deref: nm = "deref"; pxop = PX_Deref;  goto no_operands;
    1937           0 :       case DW_OP_and:   nm = "and";   pxop = PX_And;    goto no_operands;
    1938           0 :       case DW_OP_plus:  nm = "plus";  pxop = PX_Add;    goto no_operands;
    1939           0 :       case DW_OP_minus: nm = "minus"; pxop = PX_Sub;    goto no_operands;
    1940           0 :       case DW_OP_shl:   nm = "shl";   pxop = PX_Shl;    goto no_operands;
    1941           0 :       case DW_OP_ge:    nm = "ge";    pxop = PX_CmpGES; goto no_operands;
    1942             :       no_operands:
    1943           0 :         MOZ_ASSERT(nm && pxop != PX_End);
    1944           0 :         if (debug) {
    1945           0 :           SprintfLiteral(buf, "LUL.DW   DW_OP_%s\n", nm);
    1946           0 :           summ->Log(buf);
    1947             :         }
    1948           0 :         (void) summ->AddPfxInstr(PfxInstr(pxop));
    1949           0 :         break;
    1950             : 
    1951             :       default:
    1952           0 :         if (debug) {
    1953           0 :           SprintfLiteral(buf, "LUL.DW   unknown opc %d\n", (int)opc);
    1954           0 :           summ->Log(buf);
    1955             :         }
    1956           0 :         goto fail;
    1957             : 
    1958             :     } // switch (opc)
    1959             : 
    1960             :   } // while (cursor < end1)
    1961             : 
    1962           0 :   MOZ_ASSERT(cursor >= end1);
    1963             : 
    1964           0 :   if (cursor > end1) {
    1965             :     // We overran the Dwarf expression.  Give up.
    1966           0 :     goto fail;
    1967             :   }
    1968             : 
    1969             :   // For DW_CFA_expression, what the expression denotes is the address
    1970             :   // of where the previous value is located.  The caller of this routine
    1971             :   // may therefore request one last dereference before the end marker is
    1972             :   // inserted.
    1973           0 :   if (derefAtEnd) {
    1974           0 :     (void) summ->AddPfxInstr(PfxInstr(PX_Deref));
    1975             :   }
    1976             : 
    1977             :   // Insert an end marker, and declare success.
    1978           0 :   (void) summ->AddPfxInstr(PfxInstr(PX_End));
    1979           0 :   if (debug) {
    1980             :     SprintfLiteral(buf, "LUL.DW   conversion of dwarf expression succeeded, "
    1981           0 :                         "ix = %d\n", (int)start_ix);
    1982           0 :     summ->Log(buf);
    1983           0 :     summ->Log("LUL.DW  >>\n");
    1984             :   }
    1985           0 :   return start_ix;
    1986             : 
    1987             :  fail:
    1988           0 :   if (debug) {
    1989           0 :     summ->Log("LUL.DW   conversion of dwarf expression failed\n");
    1990           0 :     summ->Log("LUL.DW  >>\n");
    1991             :   }
    1992           0 :   return -1;
    1993             : }
    1994             : 
    1995             : 
    1996           0 : bool DwarfCFIToModule::Entry(size_t offset, uint64 address, uint64 length,
    1997             :                              uint8 version, const string &augmentation,
    1998             :                              unsigned return_address) {
    1999             :   if (DEBUG_DWARF) {
    2000             :     char buf[100];
    2001             :     SprintfLiteral(buf, "LUL.DW DwarfCFIToModule::Entry 0x%llx,+%lld\n",
    2002             :                    address, length);
    2003             :     summ_->Log(buf);
    2004             :   }
    2005             : 
    2006           0 :   summ_->Entry(address, length);
    2007             : 
    2008             :   // If dwarf2reader::CallFrameInfo can handle this version and
    2009             :   // augmentation, then we should be okay with that, so there's no
    2010             :   // need to check them here.
    2011             : 
    2012             :   // Get ready to collect entries.
    2013           0 :   return_address_ = return_address;
    2014             : 
    2015             :   // Breakpad STACK CFI records must provide a .ra rule, but DWARF CFI
    2016             :   // may not establish any rule for .ra if the return address column
    2017             :   // is an ordinary register, and that register holds the return
    2018             :   // address on entry to the function. So establish an initial .ra
    2019             :   // rule citing the return address register.
    2020           0 :   if (return_address_ < num_dw_regs_) {
    2021           0 :     summ_->Rule(address, return_address_, NODEREF, return_address, 0);
    2022             :   }
    2023             : 
    2024           0 :   return true;
    2025             : }
    2026             : 
    2027           0 : const UniqueString* DwarfCFIToModule::RegisterName(int i) {
    2028           0 :   if (i < 0) {
    2029           0 :     MOZ_ASSERT(i == kCFARegister);
    2030           0 :     return usu_->ToUniqueString(".cfa");
    2031             :   }
    2032           0 :   unsigned reg = i;
    2033           0 :   if (reg == return_address_)
    2034           0 :     return usu_->ToUniqueString(".ra");
    2035             : 
    2036             :   char buf[30];
    2037           0 :   SprintfLiteral(buf, "dwarf_reg_%u", reg);
    2038           0 :   return usu_->ToUniqueString(buf);
    2039             : }
    2040             : 
    2041           0 : bool DwarfCFIToModule::UndefinedRule(uint64 address, int reg) {
    2042           0 :   reporter_->UndefinedNotSupported(entry_offset_, RegisterName(reg));
    2043             :   // Treat this as a non-fatal error.
    2044           0 :   return true;
    2045             : }
    2046             : 
    2047           0 : bool DwarfCFIToModule::SameValueRule(uint64 address, int reg) {
    2048             :   if (DEBUG_DWARF) {
    2049             :     char buf[100];
    2050             :     SprintfLiteral(buf, "LUL.DW  0x%llx: old r%d = Same\n", address, reg);
    2051             :     summ_->Log(buf);
    2052             :   }
    2053             :   // reg + 0
    2054           0 :   summ_->Rule(address, reg, NODEREF, reg, 0);
    2055           0 :   return true;
    2056             : }
    2057             : 
    2058           0 : bool DwarfCFIToModule::OffsetRule(uint64 address, int reg,
    2059             :                                   int base_register, long offset) {
    2060             :   if (DEBUG_DWARF) {
    2061             :     char buf[100];
    2062             :     SprintfLiteral(buf, "LUL.DW  0x%llx: old r%d = *(r%d + %ld)\n",
    2063             :                    address, reg, base_register, offset);
    2064             :     summ_->Log(buf);
    2065             :   }
    2066             :   // *(base_register + offset)
    2067           0 :   summ_->Rule(address, reg, DEREF, base_register, offset);
    2068           0 :   return true;
    2069             : }
    2070             : 
    2071           0 : bool DwarfCFIToModule::ValOffsetRule(uint64 address, int reg,
    2072             :                                      int base_register, long offset) {
    2073             :   if (DEBUG_DWARF) {
    2074             :     char buf[100];
    2075             :     SprintfLiteral(buf, "LUL.DW  0x%llx: old r%d = r%d + %ld\n",
    2076             :                    address, reg, base_register, offset);
    2077             :     summ_->Log(buf);
    2078             :   }
    2079             :   // base_register + offset
    2080           0 :   summ_->Rule(address, reg, NODEREF, base_register, offset);
    2081           0 :   return true;
    2082             : }
    2083             : 
    2084           0 : bool DwarfCFIToModule::RegisterRule(uint64 address, int reg,
    2085             :                                     int base_register) {
    2086             :   if (DEBUG_DWARF) {
    2087             :     char buf[100];
    2088             :     SprintfLiteral(buf, "LUL.DW  0x%llx: old r%d = r%d\n",
    2089             :                    address, reg, base_register);
    2090             :     summ_->Log(buf);
    2091             :   }
    2092             :   // base_register + 0
    2093           0 :   summ_->Rule(address, reg, NODEREF, base_register, 0);
    2094           0 :   return true;
    2095             : }
    2096             : 
    2097           0 : bool DwarfCFIToModule::ExpressionRule(uint64 address, int reg,
    2098             :                                       const string &expression)
    2099             : {
    2100           0 :   bool debug = !!DEBUG_DWARF;
    2101           0 :   int32_t start_ix = parseDwarfExpr(summ_, reader_, expression, debug,
    2102             :                                     true/*pushCfaAtStart*/,
    2103           0 :                                     true/*derefAtEnd*/);
    2104           0 :   if (start_ix >= 0) {
    2105           0 :     summ_->Rule(address, reg, PFXEXPR, 0, start_ix);
    2106             :   } else {
    2107             :     // Parsing of the Dwarf expression failed.  Treat this as a
    2108             :     // non-fatal error, hence return |true| even on this path.
    2109           0 :     reporter_->ExpressionCouldNotBeSummarised(entry_offset_, RegisterName(reg));
    2110             :   }
    2111           0 :   return true;
    2112             : }
    2113             : 
    2114           0 : bool DwarfCFIToModule::ValExpressionRule(uint64 address, int reg,
    2115             :                                          const string &expression)
    2116             : {
    2117           0 :   bool debug = !!DEBUG_DWARF;
    2118           0 :   int32_t start_ix = parseDwarfExpr(summ_, reader_, expression, debug,
    2119             :                                     true/*pushCfaAtStart*/,
    2120           0 :                                     false/*!derefAtEnd*/);
    2121           0 :   if (start_ix >= 0) {
    2122           0 :     summ_->Rule(address, reg, PFXEXPR, 0, start_ix);
    2123             :   } else {
    2124             :     // Parsing of the Dwarf expression failed.  Treat this as a
    2125             :     // non-fatal error, hence return |true| even on this path.
    2126           0 :     reporter_->ExpressionCouldNotBeSummarised(entry_offset_, RegisterName(reg));
    2127             :   }
    2128           0 :   return true;
    2129             : }
    2130             : 
    2131           0 : bool DwarfCFIToModule::End() {
    2132             :   //module_->AddStackFrameEntry(entry_);
    2133             :   if (DEBUG_DWARF) {
    2134             :     summ_->Log("LUL.DW DwarfCFIToModule::End()\n");
    2135             :   }
    2136           0 :   summ_->End();
    2137           0 :   return true;
    2138             : }
    2139             : 
    2140           0 : void DwarfCFIToModule::Reporter::UndefinedNotSupported(
    2141             :     size_t offset,
    2142             :     const UniqueString* reg) {
    2143             :   char buf[300];
    2144           0 :   SprintfLiteral(buf, "DwarfCFIToModule::Reporter::UndefinedNotSupported()\n");
    2145           0 :   log_(buf);
    2146             :   //BPLOG(INFO) << file_ << ", section '" << section_
    2147             :   //  << "': the call frame entry at offset 0x"
    2148             :   //  << std::setbase(16) << offset << std::setbase(10)
    2149             :   //  << " sets the rule for register '" << FromUniqueString(reg)
    2150             :   //  << "' to 'undefined', but the Breakpad symbol file format cannot "
    2151             :   //  << " express this";
    2152           0 : }
    2153             : 
    2154             : // FIXME: move this somewhere sensible
    2155           0 : static bool is_power_of_2(uint64_t n)
    2156             : {
    2157           0 :   int i, nSetBits = 0;
    2158           0 :   for (i = 0; i < 8*(int)sizeof(n); i++) {
    2159           0 :     if ((n & ((uint64_t)1) << i) != 0)
    2160           0 :       nSetBits++;
    2161             :   }
    2162           0 :   return nSetBits <= 1;
    2163             : }
    2164             : 
    2165           0 : void DwarfCFIToModule::Reporter::ExpressionCouldNotBeSummarised(
    2166             :     size_t offset,
    2167             :     const UniqueString* reg) {
    2168             :   static uint64_t n_complaints = 0; // This isn't threadsafe
    2169           0 :   n_complaints++;
    2170           0 :   if (!is_power_of_2(n_complaints))
    2171           0 :     return;
    2172             :   char buf[300];
    2173           0 :   SprintfLiteral(buf,
    2174             :                  "DwarfCFIToModule::Reporter::"
    2175             :                  "ExpressionCouldNotBeSummarised(shown %llu times)\n",
    2176           0 :                  (unsigned long long int)n_complaints);
    2177           0 :   log_(buf);
    2178             : }
    2179             : 
    2180             : } // namespace lul

Generated by: LCOV version 1.13