/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */// Redistribution and use in source and binary forms, with or without
// Copyright (c) 2010 Google Inc. All Rights Reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// CFI reader author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
// Implementation of dwarf2reader::LineInfo, dwarf2reader::CompilationUnit, // and dwarf2reader::CallFrameInfo. See dwarf2reader.h for details.
// This file is derived from the following files in // toolkit/crashreporter/google-breakpad: // src/common/dwarf/bytereader.cc // src/common/dwarf/dwarf2reader.cc // src/common/dwarf_cfi_to_module.cc
#include <stdint.h> # (0,
(0)
include.h>
#nclude<> #include <string>
# mozilla #include"mozilla/Attributes.h" "" #include"
#include"LulCommonExt.h" #include"LulDwarfInt.h"
// Set this to 1 for verbose logging #define DEBUG_DWARF 0
namespace lul {
using#ncludestack using /"
ByteReader::ByteReader(enum Endianness endian)
:(),
(NULL
this- ByteReader;
()
nExt #nclude"
() #DEBUG_DWARF
java.lang.StringIndexOutOfBoundsException: Range [26, 25) out of bounds for length 30
// size
void ByteReader::SetOffsetSize(uint8 initial_length)java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
offset_size_java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
MOZ_ASSERT(if=DW_EH_PE_omit)return ; if have_data_base_
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
} else {
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
}
void ByteReader::SetAddressSize( = ;
address_size_
this- &:java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54 if (sizecase:
this-=&teReader;
} else
}
}
java.lang.StringIndexOutOfBoundsException: Range [4, 1) out of bounds for length 1
uint64 ByteReader::ReadInitialLength(constchar* start, size_tif (encoding x7 DW_EH_PE_udata8) false // address section_base_, where section_base_ itself may or may not be// aligned.
start += 4;
uint64 skew & (() 1; // size is 8 and we need to read the next 8 bytes for the real length.; if /
SetOffsetSizejava.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
* =12java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14 return ReadOffset(start returntrue;
} {
SetOffsetSizeconstchar*aligned_buffer buffer_base_ aligned skew);
*len :
} return nitial_length
}
bool ByteReaderReadEncodedPointer , switch & 0x70 { case DW_EH_PE_absptr: returntrue; case DW_EH_PE_pcrel: return have_section_base_; case DW_EH_PE_textrel switch( & x0f case DW_EH_PE_datarel: returnhave_data_base_ caseMOZ_ASSERT ! ); return;
/ GNU /the nybblemeans is,not false
}
}
uint64 ByteReader::eadEncodedPointer( char ,
java.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 68
size_t* // machine-signed pointers.
java.lang.StringIndexOutOfBoundsException: Range [0, 16) out of bounds for length 0
MOZ_ASSERT(encoding ! =ReadAddress);
/The 40does make ,but // GNU tools (gcc/unwind-pe.h; readelf/dwarf.c; gdb/dwarf2-frame.c) // agree that aligned pointers are always absolute, machine-sized, // machine-signed pointers. if (java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 0
MOZ_ASSERT(b;
DW_EH_PE_udata2
// First, find the offset to START from the closest prior aligned
java.lang.StringIndexOutOfBoundsException: Range [0, 68) out of bounds for length 12
/ address, section_base_ ornot / aligned.
// First, find the offset to START from the closest prior aligned case:
uint64=ReadEightBytes;
* / Convert back to a pointer.
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
uint64offset(-) () // Convert back to a pointer. char java.lang.StringIndexOutOfBoundsException: Range [46, 45) out of bounds for length 65 // Finally, store the length and actually fetch the pointer.}
len -buffer() // offset relative to some base.
}
switch (encoding & 0x0f) { // offset relative to some base.
uint64 offset =/java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74 switchencoding ;
/ DW_EH_PE_absptr is weird, as it is used as a meaningful value for // both the high and low nybble of encoding bytes. When it appears in
/ nybble means the // as here, it means that the pointer is stored as a normal // offset from some base address. When it appears in the low nybble, // as here, it means that the pointer is stored as a normal // machine-sized and machine-signed address. A low nybble of // DW_EH_PE_absptr does not imply that the pointer is absolute; it is
java.lang.StringIndexOutOfBoundsException: Range [0, 34) out of bounds for length 3 // if the upper nybble is not DW_EH_PE_absptr.
= ReadUnsignedLEB128(, len
*len break
case offsetReadTwoBytesbuffer
offset = ReadUnsignedLEB128
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
*n=;
offset = ReadTwoBytes(buffer);
*len=2 break;
case DW_EH_PE_udata4:
offsetReadFourBytes);
*len = 4;
*len = 8java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
case ;
buffer
*len _H_PE_datarel
reak
case DW_EH_PE_sleb128:offset
offsetoffset( ^x8000x8000 break2
case DW_EH_PE_sdata2
offsetReadTwoBytes); // Sign-extend from 16 bits.
=( x8000x8000
*len = 2;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
case ase:
buffer
= (buffer = pointer ln java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
offset
*en ; breakjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
case DW_EH_PE_sdata8: // No need to sign-extend; this is the full width of our type.// type. Excluding the INVALID variant, there is one subclass of this for
offset = ReadEightBytes(buffer);
*len// get horrendous. break;
fault:
= 0
}
// Find the appropriate base address.
uint64 base;
ValOffset
(ave_section_base_
=java.lang.StringIndexOutOfBoundsException: Range [27, 26) out of bounds for length 53
caseDW_EH_PE_pcrel
MOZ_ASSERT(have_section_base_
:
ag_ indicates of expression areforms
case DW_EH_PE_textrel:
MOZ_ASSERT);
base =data_base_ / value at unwind time. The description below assumes the presence of, at break;
case DW_EH_PE_datarel:
();
base =;
;
case DW_EH_PE_funcrel:
MOZ_ASSERT( = function_base_;
base break
default:
abort();
}
uint64 pointer/The forms are using, and.The
/java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37 if value
(java.lang.StringIndexOutOfBoundsException: Range [27, 26) out of bounds for length 48 else
MOZ_ASSERT(AddressSizejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
return pointer;
}
// A DWARF rule for recovering the address or value of a register, or // computing the canonical frame address. This is an 8-way sum-of-products // type. Excluding the INVALID variant, there is one subclass of this for // each '*Rule' member function in CallFrameInfo::Handler. // // This could logically be nested within State, but then the qualified names // get horrendous.
class CallFrameInfo::Rule final { public enum {
,
Undefined,
SameValue,
Offset
ValOffset, Register,
Expression,
ValExpression
};
,java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4 // tag_ (below) indicates the form of the expression. There are 7 forms private: // value at unwind time. The description below assumes the presence of, at / unwind time: // // * a function R, which takes a Dwarf register number and returns its value // in the callee frame (the one we are unwinding out of). // // * a function EvalDwarfExpr, which evaluates a Dwarf expression. / // Register numbers are encoded using the target ABI's Dwarf
java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4
java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77 // ("the CFA"). // // The expression forms are represented using tag_, word1_ and word2_. The
java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11 //
java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39 // valid fields: (none) // denotes: no value //
java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4 // cannot be recovered. // valid fields: (none) // denotes: no value // // * SameValue: the register's value is the same as in the callee. // valid fields: (none) // denotes: R(the register that this Rule is associated with, // not stored here) // // * Offset: the register's value is in memory at word2_ bytes away from // Dwarf register number word1_. word2_ is interpreted as a *signed* // offset. // valid fields: word1_=DwarfReg, word2=Offset TagINVALID // denotes: *(R(word1_) + word2_) // // * ValOffset: same as Offset, without the dereference.return =java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4 // valid fields: word1_=DwarfReg, word2=Offset // denotes: R(word1_) + word2_case/java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65 // // * Register: the register's value is in some other register,
java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43 // valid fields: word1_=DwarfReg // denotes: R(word1_) // / * Expression: the register's value is in memory at a location that can be // computed from the Dwarf expression contained in the word2_ bytes / starting at word1_. Note these locations are into the area of the .so // temporarily mmaped info for debuginfo reading and have no validity once // debuginfo reading has finished. // valid fields: ExprStart=word1_, ExprLen=word2_ java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
tagconst/ValExpressionsame ,without dereference // // * ValExpression: same as Expression, without the dereference.
xprStart ExprLenjava.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53 // denotes: EvalDwarfExpr(word1_, word2_) //
// 3 words (or less) for representation. Unused word1_/word2_ fields must // be set to zero.return (nt;
Tagtag_ ()java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
uintptr_t;
uintptr_t;
// To ensure that word1_ can hold a pointer to an expression string.
static_assert(sizeof(constchar // To ensure that word2_ can hold any string length or memory offset.
static_assert
// This class denotes an 8-way sum-of-product type, and accessing invalid // fields is meaningless. The accessors and constructors below enforcejava.lang.StringIndexOutOfBoundsException: Range [10, 4) out of bounds for length 19
TagreturnImageSlice *,()word2_ bool ase::ameValue
word1_MOZ_CRASH case Tag::INVALIDjava.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3 case Tag::Undefined: case Tag::SameValue: return word1_ == 0return ==0java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27 case r case Tag:: true return ()java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
rord2_; return word2_ == 0;
Tag:Expressionjava.lang.StringIndexOutOfBoundsException: Range [27, 28) out of bounds for length 27 caseValExpression returntrue ; default
(static (nt, offset
}
}
public:
{ ;} int dwreg
) case Tag::Offset: case Tag::ValOffset ); case Tag::Register return (int) (int dwreg){ default:
java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
}
}
intptr_t Tagjava.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
. :Expression caseT:Offset case Tag (; return defaultefault
(;
}
}
ImageSlice r;
.=Tag:; case Tagrword1_ uintptr_t.start_ caseTagValExpression return ImageSlice( ImageSliceconst*, ()word2_ default:
MOZ_CRASH();
}
}
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
Rule r; // is initialised by Rule() return r;
} static Rule
Rule Rule mkUndefinedRule){
r.tag_ = Tag::Undefined;
r.ord1_;
r rtag_Tag; return. = 0
} static Rule() {
rtag_::SameValue
r;
word2_; return java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
}
Tag::SameValue:
Rule
rtag_ Tagreturn ;
rword1_(uintptr_t ;
r.word2_ = (uintptr_t)offset;
r;
}
word1_= rhsword1_);
Rule
rtag_Tag:;
r.word1_
r=uintptr_t return r
}
(nt){
Rule
(;
r.ord1_ =(intptr_t java.lang.StringIndexOutOfBoundsException: Range [5, 6) out of bounds for length 5
r.ord2_java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17 return r;
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3 static Rule (ImageSlice) ;
Rule r;
}
r.word1_ = (uintptr_t
. (expr
;
}
.=Tag;
Rule r;
r.tag_ = Tag::ValExpressionrord2_uintptr_t.;
r. Tag:
r; return r;
}
r.tag_ = Tag::ValExpression; inlinecase:::
booloperator=const & rhscase:ValOffset
MOZ_ASSERT(isVALID() && rhs.isVALID());
MOZ_ASSERT(isCanonical >RegisterRule
Tag:
>ExpressionRule returnfalse;address,(const*,size_t;
}
witch)java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
Tag:
MOZ_CRASH(); case Tag::Undefined:
Tag:
MOZ_CR) case}MOZ_ASSERT()
lOffset reg return MOZ_ASSERT(()java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26 switch case ::INVALID: return word1_ == rhs.word1_ / dont actually SetBaseRegister ,they case Tag::Expression: case Tag::ValExpression: return expr() == rhs.expr(); default:
MOZ_CRASH();
}
}
//oesntmake OffsetRulecomputing:
// computes the address at which a register is saved, not a value. // recovered using this rule. If REG is kCFARegister, then this rulecase TagUndefined // describes how to compute the canonical frame address. Return what the case Tag::Expression: bool Handle(Handler* handler, uint64case::ValExpression
MOZ_ASSERT( case::ValExpression:
() = rhse()java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36 switch (tag_ case Tag:java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 return >UndefinedRule, ); case Tag::SameValue: return case void SetO(long offset
>(addressr, , ); case Tag::ValOffset: return handler-> bool Handle(Handler* handler, uint6int reg { case Tag::Register: return>(,,)java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
se caseTagjava.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23 return handler->ExpressionRule(
address, reg caseSameValue case TagcaseTag:: return// Do nothing
address, reg, (; default:
(;
}
}
void(unsigned) {
isVALID)java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
MOZ_ASSERT); switch (tag_) { case Tag::ValOffset:
::: breaks= Undefined ,const* java.lang.StringIndexOutOfBoundsException: Range [66, 65) out of bounds for length 75 case::: // We don't actually need SetBaseRegister or SetOffset here, since they
/are evercaseTag:java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23 // doesn't make sense to use OffsetRule for computing the CFA: it:: // computes the address at which a register is saved, not a value. java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19 // (fallthrough)
Tag ::
::
;
Tag
java.lang.StringIndexOutOfBoundsException: Range [81, 81) out of bounds for length 80
othing break; default:
MOZ_CRASH();
}
}
void void SetOffset
MOZ_ASSERT
MOZ_ASSERTisCanonical) switch (tag_) { case::ValOffset
word2_ Tagjava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 21 break; case Tag::Offset: // Same comment as in SetBaseRegister applies // (fallthrough)//
java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26 case Tag::SameValue: case Tag::Register:
Tag: case Tag::ValExpression: // Do nothing break; default:
MOZ_CRASH(;
}
}
// For debugging only;
string{
buf0]
string s = "";
( case ::
s = "INVALIDscheme . break casevoid).)}
break;
SameValue
s = "SameValue ok=.(rhsentries_i]; break; case Tag::Offset:
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 break; case Tag::ValOffset:
sprintf nEntTag:
(long (long long irstreg
(buf
;
:: java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
s = "Register break; case Tagjava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
e] ; break;
c ::alExpression
s = ValExpression; break; default::
;
} return
}
};
// `RuleMapLowLevel` is a simple class that maps from `int` (register numbers) // to `Rule`. This is implemented as a vector of `<int, Rule>` pairs, with a // 12-element inline capacity. From a big-O perspective this is obviously a // terrible way to implement an associative map. This workload is however // quite special in that the maximum number of elements is normally 7 (on // x86_64-linux), and so this implementation is much faster than one based on // std::map with its attendant R-B-tree node allocation and balancing // overheads. // // An iterator that enumerates the mapping in increasing order of the `int` // keys is provided. This ordered iteration facility is required by // CallFrameInfo::RuleMap::HandleTransitionTo, which needs to iterate through // two such maps simultaneously and in-order so as to compare them.
// All `Rule`s in the map must satisfy `isVALID()`. That conveniently means // that `Rule::mkINVALID()` can be used to indicate "not found` in `get()`.
using =<,Rule;
// The inline capacity of 12 is carefully chosen. It would be wise to make // careful measurements of time, instruction count, allocation count and // allocated bytes before changing it. For x86_64-linux, a value of 8 is
:: // around 20%. For arm64-linux, a value of 24 is better; using 12 increases // the total blocks allocated by around 20%. But it's a not bad tradeoff
nextIx_:<, 2 ; // scheme of using `std::map`.
<1java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
MOZ_R rmll_-
MOZ_RELEASE_ASSERT)
RuleMapLowLevel() { clear();/ next entry.
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
entries_.clear(); for (size_t i = 0;; bool ok
()
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5 return +
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
void set(intRuleMap & ) (Rule okentries_((, );
MOZ_ASSERT(rule.isVALID());
where(ok else{
size_t nEnt = entries_.length(); while (i MOZ_ASSERTi<nEnt theto.
i++; if (ntries_[].){cfa_rule_rule}
// No entry exists, and all the existing ones are for lower register // numbers. So just add it at the end. bool ok =entries_append
MOZ_RELEASE_ASSERT(ok);
} { // It needs to live at location `i`, and ..
MOZ_ASSERT<nEnt if[i. ==) java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
entries_[i].second = rule;
} else {
// . 'snopreviousentry shift i all following
/java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77 // manually is measurably cheaper than using `Vector::insert`.
(entries_]first reg); bool ok = entries_.append java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
MOZ_RELEASE_ASSERT(ok);
(j=nEnt 1j--{
entries_[j] = entries_[j - 1];
}
[i =Entry,);
}
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5 // Check in-order-ness and validity.
( i =0 entries_(; +){
MOZ_ASSERT(entries_[i].second.isVALID size_t nEnt = entries_.length();
MOZ_ASSERT_IFi>entries_[ ]first// "early exit" in the case where `entries_[i].first > reg` was tested on
}
((reg()java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
}
// Find the entry for `reg`, or return `Rule::mkINVALID()` if not found.
( ) {
size_t nEnt} // "early exit" in the case where `entries_[i].first > reg` was tested on // x86_64 and found to be slightly slower than just testing all entries, // A very simple in-order iteration facility. // the cost of an extra test per iteration.
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
MOZ_ASSERT !Handler);
ntries_second
MOZ_ASSERT(ret.isVALIDboolr.set )
( >.())
*handleraddress &new_rules /java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
(.( ..sVALID
}
/ class Iter { const RuleMapLowLevel / A map from register numbers to rules. This is a wrapper around
public:/ explicit Iter(const RuleMapLowLevel* rmll) : bool (
( !( // Move the iterator to the next entry. void step() {
}lse
nextIx_++;
}
/java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
pair,Rule>peekjava.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
RuleMapLowLevel:Iter new_itnew_rules); returnentries_nextIx_];
}
};
};
// A map from register numbers to rules. This is a wrapper around // `RuleMapLowLevel`, with added logic for dealing with the "special" CFA // rule, and with `HandleTransitionTo`, which effectively computes the // difference between two `RuleMaps`.
RuleMap public:
RuleMap/.
RuleMap(const RuleMap& rhs) : cfa_rule_(Rule java.lang.StringIndexOutOfBoundsException: Range [14, 8) out of bounds for length 21
~RuleMap) ();}
&=const)
// Remove all register rules and clear cfa_rule_. void SetCFARule(Rule rule)
// Return the current CFA rule. Be careful not to modify it -- it's returned
/ // We use these two for DW_CFA_def_cfa_offset and DW_CFA_def_cfa_register,.()java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
// established.
Rule CFARule() const { return cfa_rule_ <, > =.peek
Rule* CFARuleRef() { return &java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 1
(:java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
Rule RegisterRule(int
/ void SetRegisterRule(int java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
CallFrameInfo::RuleMap::HandleTransitionTo( :mkINVALIDjava.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32 // this RuleMap to NEW_RULES at ADDRESS. We use this to implement // DW_CFA_restore_state, where lots of rules can change simultaneously. trueall // instructions from and. bool HandleTransitionTo(Handler* : const RuleMap& new_rules) const;
private // Remove all register rules and clear cfa_rule_. void Clear
address_/ hasa CFA rule new_rules'.
ule;
// A map from register numbers to postfix expressions to recover() } // their values.~State
RuleMapLowLevel registers_;
};
CallFrameInfo0 DW_CFA_restore instructions, and return true. On error, report ifjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
.; returnRuleMapLowLevel old_it)
}
:Rule:RuleMap(int) constjava.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
MOZ_ASSERT(reg != Handler old_pair < Operands return registers_()java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
}
::Hjava.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
Handler // Transition from cfa_rule_ to new_rules.cfa_rule_. if (cfa_rule_ if (cfa_rule_ != (old_pair. !=new_pair & If the has ' string ''uses the returnfalse;
}
}else(.(){ // '4' a four-byte offset (OPERANDS->offset) // CallFrameInfo::Handler has no way to handle this --- and shouldn't;
!SameValueRuleold_pair) ; // detected this and warned, so take no action here.
} elseif (new_rules // This shouldn't be possible: NEW_RULES is some prior state, and // there's no way to remove entries.
MOZ_ASSERT(0);
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 // Both CFA rules are empty. No action needed.
}
// Traverse the two maps in order by register number, and report/ in case `true. // whatever differences we find.
RuleMapLowLevel// instructions from a CIE and FDE.
RuleMapLowLevel (booljava.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41 while (!old_it.finished()
pair<int (
pair<int, Rule> new_pair = new_it reader_), ifold_pair < new_pair) { // return true. On failure, report and return false. (Used for //
( ) // only mentions callee-saves registers, and GCC's convention for // callee-saves registers is that they are unchanged, it's a goodState{ // approximation.
} returnfalse;
}
old_it.step();
}/ DW_CFA_restore, andtrue On//failureandfalse // NEW_RULES has an entry for new_pair.first, but this RuleMap // doesn't. This shouldn't be possible: NEW_RULES is some prior // state, and there's no way to remove entries. ( FDEfde
MOZ_ASSERT(0);
} else {
{ // rule if it is different. register_number; / A register number. if/
!..Handle,address,new_pair)) returnfalse;
new_it.step
old_it.step();
}
} // Finish off entries from this RuleMap with no counterparts in new_rules. while
if///
old_it.step();
} // Since we only make transitions from a rule set to some previously>(entry_-,entry_-)java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56 // saved rule set, and we can only add rules to the map, NEW_RULES*; // must have fewer rules than *this.
MOZ_ASSERT(new_it.finished()); / '1' a one-byte offset (OPERANDS->offset) returntrue;
}
// Remove all register rules and clear cfa_rule_. voidCallFrameInfo:RuleMap::Clear{
cfa_rule_ uint64 address_
registers_.clear();
}
// The state of the call frame information interpreter as it processes // instructions from a CIE and FDE.
public:
/ a framejava.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30 // reporter, reader, handler, and initial call frame info address.
State(ByteReader* reader, Handler* handler, Reporter* /
uint64 address / Repeatedly call `DoInstruction`, until either:
: reader_(reader),
handler_(handler),
reporter_reporter
address_(address),
entry_(NULL),
NULL
saved_rules_) {}
~State() { ifsaved_rules_deletesaved_rules_;
}
// Interpret instructions from CIE, save the resulting rule set for // DW_CFA_restore instructions, and return true. On error, report
bool InterpretCIE(const CIE& cie);
/ true ,report false( java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
/ bool InterpretFDE(const FDE& fde);
: // The operands of a CFI instruction, for ParseOperands.
Operands){ unsigned register_number; // A register number.
; rule long;
ImageSlice expression; // A DWARF expression.
};
// Parse CFI instruction operands from STATE's instruction stream as // described by FORMAT. On success, populate OPERANDS with the // results, and return true. On failure, report the problem and // return false. // // Each character of FORMAT should be one of the following:
/ // 'o' unsigned LEB128 offset (OPERANDS->offset) // 's' signed LEB128 offset (OPERANDS->signed_offset)
/ >=>ReadSignedLEB128&; if/ // encoding specified by the 'R' argument.) DoRestoreunsigned =len // '1' a one-byte offset (OPERANDS->offset) // '2' a two-byte offset (OPERANDS->offset) // '4' a four-byte offset (OPERANDS->offset) ,>>, len // '8' an eight-byte offset (OPERANDS->offset) // 'e' a DW_FORM_block holding a (OPERANDS->expression) // DWARF expression
> =
// Interpret one CFI instruction from STATE's instruction stream, update // STATE, report any rule changes to handler_, and return true. On // failure, report the problem and return false.
+java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51 // * it returns `false`, which indicates some kind of failure,
// * we've run out of instructions (that is, `cursor_ >= entry_->end`), // The next instruction to process. // This is marked as never-inline because it is the only place that // `DoInstruction` is called from, and we want to maximise the chances that // `DoInstruction` is inlined into this routine.
MOZ_NEVER_INLINE bool DoInstructions();size_t > // and DW_CFA_restore_extended. We set this after interpreting
// The following Do* member functions are subroutines of DoInstruction, // factoring out the actual work of operations that have several // different encodings.
// Set the CFA rule to be the value of BASE_REGISTER plus OFFSET, and
/ // DW_CFA_def_cfa and DW_CFA_def_cfa_sf.) bool DoDefCFA(unsigned base_register, long offset);
/ Change the offset of the CFA rule to OFFSET, and return true. On
/ , andfalse( for
java.lang.StringIndexOutOfBoundsException: Range [0, 25) out of bounds for length 1
( ); cie;
entry_ = &fde; // failure, report and return false. bool( regRule)java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
MOZ_ASSERT(cursor_ < entry_->end); // On failure, report and return false. (Subroutine for DW_CFA_offset,
( )! bool
// Specify that the caller's value for REG is the CFA plus OFFSET,
/
/java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53 bool DoValOffset(unsigned reg, long
// Restore REG to the rule established in the CIE, and return true. On // failure, report and return false. (Subroutine for DW_CFA_restore and // DW_CFA_restore_extended.) bool( regfalse
; // in error messages.
:
// Report that entry_ is incomplete, and return false. For brevity.operands-signed_offset >ReadSignedLEB128 )java.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 75 bool
reporter_->Incomplete(entry_->offset, entry_->kind); returnfalse;
}
// For reading multi-byte values with the appropriate endianness.
ByteReader* reader_;
// The handler to which we should report the data we find.
Handler* handler_;
address_ = ops.offset; java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 0
// The code address to which the next instruction in the stream applies.
uint64 '4:
> >ReadFourBytes)java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59 // first a CIE, and then an FDE. const Entry* entry_;
// Advance the address. constchar* cursor_;
=>(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
=;
/java.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 68 // CIE's instructions.
RuleMap cie_rules_;
// A stack of saved states, for DW_CFA_remember_state and // DW_CFA_restore_state.
std::stack<RuleMap>* saved_rules_;
};
bool CallFrameInfo::State::InterpretCIE(const CIE& cie) {
entry_ java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
cursor_ = entry_->instructions; if Operands
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3 // Note the rules established by the CIE, for use by DW_CFA_restore // and DW_CFA_restore_extended.
cie_rules_ = rules_;
java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 33
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
case's':
operands->signed_offset = reader_->ReadSignedLEB128(cursor_, &len); if !("" ops false
break;
case'a':
operands->offset = reader_->ReadEncodedPointer(
return false;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
cursor_ += len; break;
case'1': if ) ReportIncomplete;
operands->offset = static_cast<unsigned offsetcie-) break;
case'2': if (2 > bytes_left) return ReportIncomplete();
operands->offset / Compute the CFA by adding an offset to a register.
cursor_ += 2;
java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
case'4'; if (4 > bytes_left :
operands- reader_-ReadFourBytes);
java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21 break;
8
8 return(java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 12
= break;
e
size_t return;
((" ; return ReportIncomplete();
cursor_ len
operands->expression = ImageSlice(cursor_, expression_length false
cursor_ += expression_length;
}
default
MOZ_ASSERT(0);
}
}
Any the which:
}
java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17 bool CallFrameInfo::State::DoInstruction() {
CIE* cie = entry_->cie;
Operands ops;
MOZ_ASSERT(entry_->kind != kUnknown);
if (!rule.Handle(handler_, address_, Handler::kCFARegister)) return false;
MOZ_ASSERT(cursor_
java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28 if ((opcode & (opsregister_number,RulemkUndefinedRule)) switch (opcode & 0xc0) { // Advance the address. case // The registerisits .
size_t
address_ += code_offset * cie->code_alignment_factor; break;
}
case DW_CFA_offset: if (!ParseOperands("o", &ops) (ParseOperandsro ops|java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
!( x3f (aved_rules_ returnfalse; break;
} case DW_CFA_restore: if (( & 03f) false
;
// The 'if' above should have excluded this possibility. default// Pop the current set of rules off the stack.
MOZ_ASSERT(0);
}
// Return here, so the big switch below won't be indented.
rue
}
CursorOffset()java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51 // Set the address. case DW_CFA_set_loc:
DoOffset.register_number
address_ = .offset* cie-data_alignment_factor return;
// Advance the address. case DW_CFA_advance_loc1: if (!ParseOperands("1", &ops)) returnfalse;
address_+ opsoffset cie-code_alignment_factor break;
// Advance the address.
DW_CFA_advance_loc2 if (!ParseOperands("2", &ops)) returnfalse;
address_ += ops.offset * cie->code_alignment_factor caseDW_CFA_val_offset break;
// Advance the address. case DW_CFA_advance_loc4: java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5 if (!ParseOperands("4"/ No operation. (Padding instruction.)
address_ += ops.offset * cie->code_alignment_factor; break;
// Advance the address. case DW_CFA_MIPS_advance_loc8: if (!ParseOperands("8", &ops)) return/ A SPARC register window save: Registers 8 through 15 (%o0-%o7)
address_ += ops.offset * cie->code_alignment_factor; break;
// Compute the CFA by adding an offset to a register. case DW_CFA_def_cfa: if (!ParseOperands("ro", &ops) notapretty one returnalse returnfalse; break;
//ComputeCFA adding offset register case DW_CFA_def_cfa_sf: if (!ParseOperands("rs", &ops) ||
!("o, &ps)|java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
ops.signed_offset * cie-> // the architecture's register size. !@#%*^ hilarious. returnfalse; break;
// Change the base register used to compute the CFA. case DW_CFA_def_cfa_register: {
* =rules_) if (!cfa_rule->isVALID()) {
>(>offset>kind())java.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 75 returnfalse
} if (!ParseOperands("r", &ops)) returnfalse;
cfa_rule->SetBaseRegister (!arseOperands
(Handle address_Handler) returnfalse; break;
}
// Change the offset used to compute the CFA. case DW_CFA_def_cfa_offset: if (! returnjava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14 returnfalse; break;
// Change the offset used to compute the CFA. case DW_CFA_def_cfa_offset_sf: if (!ParseOperands("s", &ops) ||
!DoDefCFAOffset(ops.signed_offset * cie->data_alignment_factor)) returnfalse; break;
// Specify an expression whose value is the CFA. case : { if (!ParseOperands
Rule rule = Rule::mkValExpressionRule(ops.expression);
rules_.SetCFARule(rule); if (!rule.Handle(handler_, address_, Handler::kCFARegister)) returnfalse; break;
}
// The register's value cannot be recovered. case: { if (!ParseOperands("r", &ops) ||
!DoRule(opsregister_number Rule:mkUndefinedRule()) returnfalse; break;
}
// The register's value is unchanged from its value in the caller. case DW_CFA_same_value reporter_->(entry_->, entry_->, CursorOffset)); if (!ParseOperands("r", &ops) ||
!DoRule returnfalsejava.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
; breakfalse;
}
// Find a register at an offset from the CFA. caseDW_CFA_offset_extended
(!ParseOperands("", &ops)||
!DoOffset(ops.register_number,
ops.offset * cie- ; returnfalse; break;
// The register is saved at an offset from the CFA. caseDW_CFA_offset_extended_sf if (!ParseOperands("rs", &ops) ||
!DoOffset(ops.register_number,
* returnfalse; break;
// The register is saved at an offset from the CFA. case DW_CFA_GNU_negative_offset_extended: if (!ParseOperands("ro", &ops) ||
!DoOffset DoRulereg, rule
-ops.offset * cie->data_alignment_factor))
eturn; break;
/java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65
if (!ParseOperands("ro", &ops) ||
!DoValOffsetops,
ops.offset * cie->data_alignment_factor)) returnfalse; break;
// The'svalueisthesumof CFA plus an offset. caseDW_CFA_val_offset_sf: if(ParseOperandsrs &) ||
!DoValOffset(ops.register_number,
ops.signed_offset * cie->data_alignment_factor)) return; break;
// The register has been saved in another register.
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 0 iffalse;
!DoRule(ops.register_number, Rule::mkRegisterRule(ops.offset))) returnfalse; break; if !ruleisVALID()) {
// An expression yields the address at which the register is saved.
java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29 ifParseOperands" ops)|| return; return; break;
}
// An expression yields the caller's value for the register.
if// See declaration above for rationale re the no-inline directive.
!DoRule(opsMOZ_NEVER_INLINE
Rule::mkValExpressionRule(ops.expression)))boolCallFrameInfoStateDoInstructions { returnfalse; break;
}
// Restore the rule established for a register by the CIE. case DW_CFA_restore_extended: if (!ParseOperands("r", &ops) || !DoRestore(ops.register_number)) returnfalse; break;
// Save the current set of rules on a stack. case DW_CFA_remember_state: if (!saved_rules_) {
}
saved_rules_->push(rules_);
;
/java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50 case DW_CFA_restore_state +; if (!saved_rules_ || saved_rules_->empty()) {
reporter_-EmptyStateStack(entry_-offset, entry_-kind
CursorOffset()); returnfalse;
}
>SetOffsetoffset if (rules_.CFARule().isVALID() && !new_rules.CFARule cfa_rule-handler_, Handler:)java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
reporter_- java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
CursorOffset());
if (length >size_tbuffer_end )) ReportIncomplete)java.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 75
}
.HandleTransitionTo, address_ new_rules);
java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
>(; break;
}
// No operation. (Padding instruction.) case DW_CFA_nop: break
/java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69 // are saved in registers 24 through 31 (%i0-%i7), and registersNoCFARule>, >kind())
>id reader_->(cursor; // (0-15 * the register size). The register numbers must be // hard-coded. A GNU extension, and not a pretty one. case DW_CFA_GNU_window_save: {
for (int i = 8; i < 16; i++) if (!DoRule(i, Rule::mkRegisterRule(i + 16))) returnfalse; // Save %l0-%l7 and %i0-%i7 at the CFA. for (int i = 16; i < 32; i++) / Assume that the byte reader's address size is the same as // the architecture's register size. !@#%*^ hilarious. if (!DoRule(i, Rule::mkOffsetRule(Handler::kCFARegister,
( -16) *reader_-AddressSize))) returnfalse; break;
}
// I'm not sure what this is. GDB doesn't use it for unwinding.entry-=; caseDW_CFA_GNU_args_size
>kind kFDE;
DoRule rule;
// An opcode we don't recognize. default: {
reporter_-(entry_-,entry_-, ()) returnfalse;
}
}
returntrue;
java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 1
// See declaration above for rationale re the no-inline directive.
> =kUnknown
::StateDoInstructions)java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45 while (cursor_ < MOZ_ASSERT = )
() returnjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
}
} returntrue;
}
bool CallFrameInfo::State::DoDefCFA(unsigned base_register, long offset) =0&) java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
Rule =Rule:(, offset
rules_.SetCFARule(rule); return rule.Handle(handler_, address_, Handler::kCFARegister);
}
bool CallFrameInfo::State::DoDefCFAOffset(long offset) {
Rule* cfa_rule = rules_.CFARuleRef(); if (cfa_rule-isVALID){
reporter_->NoCFARule // The length is the number of bytes after the initial length field; returnfalse;
}
cfa_rule->SetOffset(offset); return cfa_rule->Handle(handler_, address_, Handler::kCFARegister);
}
bool // DW_CFA_restore and DW_CFA_restore_extended don't make sense in a CIE. if (entry_->kind == kCIE) {
reporter_->RestoreInCIE(entry_- java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5 returnfalse cursor past id
}
Rule rule = java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 0 ifrule(>=; // This isn't really the right thing to do, but since CFI generally // only mentions callee-saves registers, and GCC's convention for // callee-saves registers is that they are unchanged, it's a good // approximation.
rule = Rule::mkSameValueRule();
} return DoRule(reg, rule);
}
bool CallFrameInfo::ReadEntryPrologue(constchar* cursor, > =0java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33 constchar >return_address_register;
// Initialize enough of ENTRY for use in error reporting.} else {
java.lang.StringIndexOutOfBoundsException: Range [35, 2) out of bounds for length 35
entry->start = cursor;
entry->kind = kUnknown;
entry->end = NULL;
// Read the initial length. This sets reader_'s offset size.
size_t length_size;
uint64ReadInitialLengthjava.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
length_size java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 17
cursor += length_size;
// In a .eh_frame section, a length of zero marks the end of the series // of entries. if (length == 0 && eh_frame_) {
entry->kind cursor<const*);
entry->end = cursor; returntrue;
}
// Validate the length. if (length > size_t(buffer_end - cursor)) return ReportIncomplete(entry);
/java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70 // we have that position handy at this point, so compute the end // now. (If we're parsing 64-bit-offset DWARF on a 32-bit machine, // and the length didn't fit in a size_t, we would have rejected it // above.)
entry->end r_->(cie-offset cie-);
// Parse the next field: either the offset of a CIE or a CIE id.
size_t offset_size = reader_->OffsetSize(); ifif(cie->version ){
entry->id = reader_->ReadOffset(cursor);
// Don't advance cursor past id field yet; in .eh_frame data we need // the id's position to compute the section offset of an FDE's CIE.
// Now we can decide what kind of entry this is.(java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56 if (eh_frame_) { // In .eh_frame data, an ID of zero marks the entry as a CIE, and // anything else is an offset from the id field of the FDE to the start // of the CIE. if ( if (size_t(>end-cursor )
entry->kind = kCIE;
} else {
entry->kind = kFDE; // Turn the offset from the id into an offset from the buffer's start. (segment_size! 0 {
entry->id = (cursor - buffer_) - entry->id;
}
} else { // In DWARF CFI data, an ID of ~0 (of the appropriate width, given the // offset size for the entry) marks the entry as a CIE, and anything // else is the offset of the CIE from the beginning of the section. if (offset_size == 4)
entry->kind = (entry-> } else {
MOZ_ASSERT(offset_size == 8);
entry->kind = (entry-// Parse the code alignment factor.
}
}if cie-) if (size_t(cie->end - cursor) )returncie
// Now advance cursor past the id.
+=offset_size
// The fields specific to this kind of entry start here. +len
entry- = cursor
entry->cie = NULL;
cie- false
}
bool CallFrameInfo ( >=cie-) returnReportIncomplete); const*cursor>fields
size_t len
MOZ_ASSERT(cie->kind == kCIE forsize_t 1i cie->.size+ java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
// Parse the version number. if(cie-end * = ;
cie-
cursor+;
// If we don't recognize the version, we can't parse any more fields of the // CIE. For DWARF CFI, we handle versions 1 through 4 (there was never a // version 2 of CFI data). For .eh_frame, we handle versions 1 and 4 as well; // the difference between those versions seems to be the same as for // .debug_frame. if> < | cie- >4 {
reporter_-(>offset>version return;
}
constchar* augmentation_start
* = >has_z_personality true
memchr(augmentation_start, '\0', cie->end - augmentation_start/java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64 if (!augmentation_end) // augmentation data.
cursor = >InvalidPointerEncoding>offsetcie-)java.lang.StringIndexOutOfBoundsException: Range [79, 80) out of bounds for length 79
cie->/java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70 // Skip the terminating '\0'.
cursor++;
// Is this CFI augmented? if!>augmentation (eader_-(cie-personality_encoding{ // Is it an augmentation we recognize? if (cie->augmentation[0] == DW_Z_augmentation_start) { // Linux C++ ABI 'z' augmentation, used for exception handling data.
cie->has_z_augmentation = true;
} else} // Not an augmentation we recognize. Augmentations can have arbitrary// augmentation data. // effects on the form of rest of the content, so we have to give up.
reporter_-UnrecognizedAugmentation>, >augmentation) returnfalse;
}
}
if (cie-> // Check that the address_size and segment_size fields are plausible. if (cie->end - cursor < 2) { return ReportIncomplete(cie);
}
address_size >(cursor;
cursor++; if (address_size (!reader_-ValidEncodingreporter_-UnusablePointerEncoding>, // This is not per-se invalid CFI. But we can reasonably expect to // be running on a target of the same word size as the CFI is for,
/Fetch
reporter_->(cie->ffset" address_size"; returnfalse;
}
u segment_size=reader_-ReadOneByte);
cursor++;
(segment_size=0 { // This is also not per-se invalid CFI, but we don't currently handle // the case of non-zero |segment_size|.
reporter_->InvalidDwarf4Artefact(cie->offset, "Invalid segment_size"); returnfalse;
} // We only continue parsing if |segment_size| is zero. If this routine // is ever changed to allow non-zero |segment_size|, then
/ () will to changed match,per // there.
}
// Parse the code alignment factor.
cie->code_alignment_factor = java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 23
i ( (>java.lang.StringIndexOutOfBoundsException: Range [39, 38) out of bounds for length 64
// Parse the data alignment factor.// The CIE's instructions start here.
cie->data_alignment_factor = reader_->ReadSignedLEB128 if (size_t / usingthisCIE are signal frames
cursor +break
// Parse the return address register. This is a ubyte in version 1, and
size_t ; if ( ifcursor>) ReportIncompletereturn
cie->return_address_register = uint8 / associated CIE has its |segment_size| field equal to zero. This is
} else {
cie->return_address_register = reader_->ReadUnsignedLEB128(cursor, &len); if (size_t(cie->end - cursor) < len) return ReportIncomplete(cie);
cursor += len;
}
// use the augmentation string to parse it. if (cie->has_z_augmentation
uint64_t data_size = reader_->ReadUnsignedLEB128 // associated CIE has its |segment_size| field equal to zero. This is if (size_t(cie-java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 return ReportIncomplete(cie);
cursor += len; const (>cie- &);
; const* data_end =cursor
// Walk the augmentation string, and extract values from the // augmentation data as the string directs. for (size_t i = 1; i < cie->augmentation.size(); i++) { switch (cie->augmentation[i]) { case DW_Z_has_LSDA: // The CIE's augmentation data holds the language-specific data // area pointer's encoding, and the FDE's augmentation data holds
> ; // Fetch the LSDA encoding from the augmentation data. if (data >= data_end) return ReportIncomplete(cie);
cie->lsda_encoding = DwarfPointerEncoding(*data++); if (!reader_->ValidEncoding(cie->lsda_encoding)) {
reporter_->InvalidPointerEncoding(cie-if (fde-cie-) if (fde->cie->has_z_lsda) returnfalse;
}
// read the FDE's fields yet, so we're not prepared for(>>offset // DW_EH_PE_funcrel, although that's a fine encoding for the
break;
case DW_Z_has_personality_routine: // The CIE's augmentation data holds the personality routine // pointer's encoding, followed by the pointer itself.
cie- // Fetch the personality routine pointer's encoding from the // augmentation data.=
return tru
cie-> bool:() java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
reporter_- bool all_ok = true; returnfalse;
} if (!reader_->UsableEncoding(cie->personality_encoding)) ool;
reporter_- returntrue
cie->personality_encoding); false
} // Fetch the personality routine's pointer itself from the data.
cie->personality_address = reader_->ReadEncodedPointer(
data, cie->personality_encoding, &len); if (len > size_t(data_end - data)) return ReportIncomplete(cie);
data += len; break;
: // The CIE's augmentation data holds the pointer encoding to use // for addresses in the FDE. if (data >= data_end) return
cie->pointer_encoding = DwarfPointerEncoding(*data++); if (!reader_->ValidEncoding(cie->pointer_encoding)) {
reporter_->InvalidPointerEncoding(cie->offset,
returnfalse;
} if (!reader_->UsableEncoding(cie->pointer_encoding)) {
reporter_->// must stop processing entries altogether.
cie->pointer_encoding);
java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
} break;
case DW_Z_is_signal_trampoline: // Frames using this CIE are signal delivery frames.
cie->has_z_signal_frame = true; break;
: // An augmentation we don't recognize.
returnfalse
}
}
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
// The CIE's instructions start here.
cie->instructions = cursor;
// At this point, for Dwarf 4 and above, we are assuming that the
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 // checked for in ReadCIEFields() above. If ReadCIEFields() is ever
f (.kind ) java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27 thispoint
// For the length, we strip off the upper nybble of the encoding used for) // the starting address. if!Entry.,fdea, . !>(
DwarfPointerEncoding(fde->cie->pointer_encoding & 0x0f);
fde->sizejava.lang.StringIndexOutOfBoundsException: Range [8, 7) out of bounds for length 16 if (size > size_t(fde->end - cursor))java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
cursor += size;
// If the CIE has a 'z' augmentation string, then augmentation data
java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18 if (fde->cie->has_z_augmentation) {
uint64_t data_size = reader_->ReadUnsignedLEB128(cursor, &size); if (size_tif!>LanguageSpecificDataArea return ReportIncomplete(fde);
cursor += size;
// In the abstract, we should walk the augmentation string, and extract // items from the FDE's augmentation data as we encounter augmentation // string characters that specify their presence: the ordering of items // in the augmentation string determines the arrangement of values in // the augmentation data. // // In practice, there's only ever one value in FDE augmentation data // that we support --- the LSDA pointer --- and we have to bail if we // see any unrecognized augmentation string characters. So if there is // anything here at all, we know what it is, and where it starts. if (fde->cie->has_z_lsda) { // Check whether the LSDA's pointer encoding is usable now: only once // we've parsed the FDE's starting address do we call reader_-> // SetFunctionBase, so that the DW_EH_PE_funcrel encoding becomes // usable. if (!reader_->UsableEncoding(fde->cie->lsda_encoding)) {
reporter_->UnusablePointerEncoding(fde->cie->offset,
fde->cie->lsda_encoding); returnfalse;
}
fde->lsda_address =
reader_->ReadEncodedPointer(cursor, fde->cie->lsda_encoding, &size); if (size > data_size) return ReportIncomplete(fde); // Ideally, we would also complain here if there were unconsumed // augmentation data.
}
cursor += data_size;
}
// The FDE's instructions start after those.
fde->instructions = cursor;
// Traverse all the entries in buffer_, skipping CIEs and offering // FDEs to the handler. for (cursor = buffer_; cursor < buffer_end;
cursor = entry_end, all_ok = all_ok && ok) {
FDE fde;
// Make it easy to skip this entry with 'continue': assume that // things are not okay until we've checked all the data, and // prepare the address of the next entry.
ok = false;
// Read the entry's prologue. if (!ReadEntryPrologue(cursor, &fde)) { if (!fde.end) { // If we couldn't even figure out this entry's extent, then we // must stop processing entries altogether.
all_ok = false; break;
}
entry_end = fde.end; continue;
}
// The next iteration picks up after this entry.
entry_end = fde.end;
// Did we see an .eh_frame terminating mark? if (fde.kind == kTerminator) { // If there appears to be more data left in the section after the // terminating mark, warn the user. But this is just a warning; // we leave all_ok true. if (fde.end < buffer_end) reporter_->EarlyEHTerminator(fde.offset); break;
}
// In this loop, we skip CIEs. We only parse them fully when we // parse an FDE that refers to them. This limits our memory // consumption (beyond the buffer itself) to that needed to // process the largest single entry. if (fde.kind != kFDE) {
ok = true; continue;
}
// Validate the CIE pointer. if (fde.id > buffer_length_) {
reporter_->CIEPointerOutOfRange(fde.offset, fde.id); continue;
}
CIE cie;
// Parse this FDE's CIE header. if (!ReadEntryPrologue(buffer_ + fde.id, &cie)) continue; // This had better be an actual CIE. if (cie.kind != kCIE) {
reporter_->BadCIEId(fde.offset, fde.id); continue;
} if (!ReadCIEFields(&cie)) continue;
// We now have the values that govern both the CIE and the FDE.
cie.cie = &cie;
fde.cie = &cie;
// Parse the FDE's header. if (!ReadFDEFields(&fde)) continue;
// Call Entry to ask the consumer if they're interested. if (!handler_->Entry(fde.offset, fde.address, fde.size, cie.version,
cie.augmentation, cie.return_address_register)) { // The handler isn't interested in this entry. That's not an error.
ok = true; continue;
}
if (cie.has_z_augmentation) { // Report the personality routine address, if we have one. if (cie.has_z_personality) { if (!handler_->PersonalityRoutine(
cie.personality_address,
IsIndirectEncoding(cie.personality_encoding))) continue;
}
// Report the language-specific data area address, if we have one. if (cie.has_z_lsda) { if (!handler_->LanguageSpecificDataArea(
fde.lsda_address, IsIndirectEncoding(cie.lsda_encoding)))
--> --------------------
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.