[llvm] r326932 - [DebugInfo] Support DWARF expressions in eh_frame

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 7 14:18:10 PST 2018


I'm going to revert this for now since the tree has been broken for two
hours.


On Wed, Mar 7, 2018 at 2:15 PM Rui Ueyama <ruiu at google.com> wrote:

> Looks like this change broke an lld test.
>
> $ bin/llvm-lit -v
> /ssd/llvm-project/lld/test/ELF/eh-frame-hdr-augmentation.s
> ninja: no work to do.
> -- Testing: 1 tests, 1 threads --
> FAIL: lld :: ELF/eh-frame-hdr-augmentation.s (1 of 1)
> ******************** TEST 'lld :: ELF/eh-frame-hdr-augmentation.s' FAILED
> ********************
> Script:
> --
> /ssd/b/bin/llvm-mc -filetype=obj -triple=x86_64-pc-linux
> /ssd/llvm-project/lld/test/ELF/eh-frame-hdr-augmentation.s -o
> /ssd/b/tools/lld/test/ELF/Output/eh-frame-hdr-augmentation.s.tmp.o
> /ssd/b/bin/ld.lld --hash-style=sysv --eh-frame-hdr
> /ssd/b/tools/lld/test/ELF/Output/eh-frame-hdr-augmentation.s.tmp.o -o
> /ssd/b/tools/lld/test/ELF/Output/eh-frame-hdr-augmentation.s.tmp -shared
> /ssd/b/bin/llvm-objdump --dwarf=frames
> /ssd/b/tools/lld/test/ELF/Output/eh-frame-hdr-augmentation.s.tmp |
> /ssd/b/bin/FileCheck
> /ssd/llvm-project/lld/test/ELF/eh-frame-hdr-augmentation.s
> --
> Exit Code: 1
>
> Command Output (stderr):
> --
> /ssd/llvm-project/lld/test/ELF/eh-frame-hdr-augmentation.s:14:16: error:
> CHECK-NEXT: is not on the line after the previous match
> // CHECK-NEXT: Augmentation data:
>                ^
> <stdin>:17:2: note: 'next' match was here
>  Augmentation data: 9B AD 0D 00 00 1B 1B
>  ^
> <stdin>:15:27: note: previous match ended here
>  Return address column: 16
>                           ^
> <stdin>:16:1: note: non-matching line after previous match is here
>  Personality Address: 00000dad
> ^
>
> --
>
> ********************
> Testing Time: 0.10s
> ********************
> Failing Tests (1):
>     lld :: ELF/eh-frame-hdr-augmentation.s
>
>   Unexpected Failures: 1
>
>
> On Wed, Mar 7, 2018 at 11:22 AM Rafael Auler via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>> Author: rafauler
>> Date: Wed Mar  7 11:19:51 2018
>> New Revision: 326932
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=326932&view=rev
>> Log:
>> [DebugInfo] Support DWARF expressions in eh_frame
>>
>> This patch enhances DWARFDebugFrame with the capability of parsing and
>> printing DWARF expressions in CFI instructions. It also makes FDEs and
>> CIEs accessible to lib users, so they can process them in client tools
>> that rely on LLVM. To make it self-contained with a test case, it
>> teaches llvm-readobj to be able to dump EH frames and checks they are
>> correct in a unit test. The llvm-readobj code is Maksim Panchenko's work
>> (maksfb).
>>
>> Reviewers: JDevlieghere, espindola
>>
>> Reviewed By: JDevlieghere
>>
>> Differential Revision: https://reviews.llvm.org/D43313
>>
>> Added:
>>     llvm/trunk/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml
>>     llvm/trunk/test/tools/llvm-readobj/unwind.test
>>     llvm/trunk/tools/llvm-readobj/DwarfCFIEHPrinter.h
>> Modified:
>>     llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
>>     llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
>>     llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFExpression.h
>>     llvm/trunk/include/llvm/Support/ScopedPrinter.h
>>     llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
>>     llvm/trunk/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
>>     llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
>>     llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp
>>     llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
>>     llvm/trunk/tools/llvm-readobj/CMakeLists.txt
>>     llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
>>
>> Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h?rev=326932&r1=326931&r2=326932&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
>> (original)
>> +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h Wed Mar
>> 7 11:19:51 2018
>> @@ -44,6 +44,13 @@ public:
>>    uint64_t getRelocatedAddress(uint32_t *Off, uint64_t *SecIx = nullptr)
>> const {
>>      return getRelocatedValue(getAddressSize(), Off, SecIx);
>>    }
>> +
>> +  /// Extracts a DWARF-encoded pointer in \p Offset using \p Encoding.
>> +  /// There is a DWARF encoding that uses a PC-relative adjustment.
>> +  /// For these values, \p AbsPosOffset is used to fix them, which should
>> +  /// reflect the absolute address of this pointer.
>> +  Optional<uint64_t> getEncodedPointer(uint32_t *Offset, uint8_t
>> Encoding,
>> +                                       uint64_t AbsPosOffset = 0) const;
>>  };
>>
>>  } // end namespace llvm
>>
>> Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h?rev=326932&r1=326931&r2=326932&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h (original)
>> +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h Wed Mar  7
>> 11:19:51 2018
>> @@ -10,40 +10,290 @@
>>  #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
>>  #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
>>
>> -#include "llvm/Support/DataExtractor.h"
>> +#include "llvm/ADT/ArrayRef.h"
>> +#include "llvm/ADT/iterator.h"
>> +#include "llvm/ADT/SmallString.h"
>> +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
>> +#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
>> +#include "llvm/Support/Error.h"
>>  #include <memory>
>>  #include <vector>
>>
>>  namespace llvm {
>>
>> -class FrameEntry;
>>  class raw_ostream;
>>
>> -/// \brief A parsed .debug_frame or .eh_frame section
>> -///
>> +namespace dwarf {
>> +
>> +/// Represent a sequence of Call Frame Information instructions that,
>> when read
>> +/// in order, construct a table mapping PC to frame state. This can also
>> be
>> +/// referred to as "CFI rules" in DWARF literature to avoid confusion
>> with
>> +/// computer programs in the broader sense, and in this context each
>> instruction
>> +/// would be a rule to establish the mapping. Refer to pg. 172 in the
>> DWARF5
>> +/// manual, "6.4.1 Structure of Call Frame Information".
>> +class CFIProgram {
>> +public:
>> +  typedef SmallVector<uint64_t, 2> Operands;
>> +
>> +  /// An instruction consists of a DWARF CFI opcode and an optional
>> sequence of
>> +  /// operands. If it refers to an expression, then this expression has
>> its own
>> +  /// sequence of operations and operands handled separately by
>> DWARFExpression.
>> +  struct Instruction {
>> +    Instruction(uint8_t Opcode) : Opcode(Opcode) {}
>> +
>> +    uint8_t Opcode;
>> +    Operands Ops;
>> +    // Associated DWARF expression in case this instruction refers to one
>> +    Optional<DWARFExpression> Expression;
>> +  };
>> +
>> +  using InstrList = std::vector<Instruction>;
>> +  using iterator = InstrList::iterator;
>> +  using const_iterator = InstrList::const_iterator;
>> +
>> +  iterator begin() { return Instructions.begin(); }
>> +  const_iterator begin() const { return Instructions.begin(); }
>> +  iterator end() { return Instructions.end(); }
>> +  const_iterator end() const { return Instructions.end(); }
>> +
>> +  unsigned size() const { return (unsigned)Instructions.size(); }
>> +  bool empty() const { return Instructions.empty(); }
>> +
>> +  CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor)
>> +      : CodeAlignmentFactor(CodeAlignmentFactor),
>> +        DataAlignmentFactor(DataAlignmentFactor) {}
>> +
>> +  /// Parse and store a sequence of CFI instructions from Data,
>> +  /// starting at *Offset and ending at EndOffset. *Offset is updated
>> +  /// to EndOffset upon successful parsing, or indicates the offset
>> +  /// where a problem occurred in case an error is returned.
>> +  Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset);
>> +
>> +  void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
>> +            unsigned IndentLevel = 1) const;
>> +
>> +private:
>> +  std::vector<Instruction> Instructions;
>> +  const uint64_t CodeAlignmentFactor;
>> +  const int64_t DataAlignmentFactor;
>> +
>> +  /// Convenience method to add a new instruction with the given opcode.
>> +  void addInstruction(uint8_t Opcode) {
>> +    Instructions.push_back(Instruction(Opcode));
>> +  }
>> +
>> +  /// Add a new single-operand instruction.
>> +  void addInstruction(uint8_t Opcode, uint64_t Operand1) {
>> +    Instructions.push_back(Instruction(Opcode));
>> +    Instructions.back().Ops.push_back(Operand1);
>> +  }
>> +
>> +  /// Add a new instruction that has two operands.
>> +  void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t
>> Operand2) {
>> +    Instructions.push_back(Instruction(Opcode));
>> +    Instructions.back().Ops.push_back(Operand1);
>> +    Instructions.back().Ops.push_back(Operand2);
>> +  }
>> +
>> +  /// Types of operands to CFI instructions
>> +  /// In DWARF, this type is implicitly tied to a CFI instruction opcode
>> and
>> +  /// thus this type doesn't need to be explictly written to the file
>> (this is
>> +  /// not a DWARF encoding). The relationship of instrs to operand types
>> can
>> +  /// be obtained from getOperandTypes() and is only used to simplify
>> +  /// instruction printing.
>> +  enum OperandType {
>> +    OT_Unset,
>> +    OT_None,
>> +    OT_Address,
>> +    OT_Offset,
>> +    OT_FactoredCodeOffset,
>> +    OT_SignedFactDataOffset,
>> +    OT_UnsignedFactDataOffset,
>> +    OT_Register,
>> +    OT_Expression
>> +  };
>> +
>> +  /// Retrieve the array describing the types of operands according to
>> the enum
>> +  /// above. This is indexed by opcode.
>> +  static ArrayRef<OperandType[2]> getOperandTypes();
>> +
>> +  /// Print \p Opcode's operand number \p OperandIdx which has value \p
>> Operand.
>> +  void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool
>> IsEH,
>> +                    const Instruction &Instr, unsigned OperandIdx,
>> +                    uint64_t Operand) const;
>> +};
>> +
>> +/// An entry in either debug_frame or eh_frame. This entry can be a CIE
>> or an
>> +/// FDE.
>> +class FrameEntry {
>> +public:
>> +  enum FrameKind { FK_CIE, FK_FDE };
>> +
>> +  FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t
>> CodeAlign,
>> +             int64_t DataAlign)
>> +      : Kind(K), Offset(Offset), Length(Length), CFIs(CodeAlign,
>> DataAlign) {}
>> +
>> +  virtual ~FrameEntry() {}
>> +
>> +  FrameKind getKind() const { return Kind; }
>> +  uint64_t getOffset() const { return Offset; }
>> +  uint64_t getLength() const { return Length; }
>> +  const CFIProgram &cfis() const { return CFIs; }
>> +  CFIProgram &cfis() { return CFIs; }
>> +
>> +  /// Dump the instructions in this CFI fragment
>> +  virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
>> +                    bool IsEH) const = 0;
>> +
>> +protected:
>> +  const FrameKind Kind;
>> +
>> +  /// Offset of this entry in the section.
>> +  const uint64_t Offset;
>> +
>> +  /// Entry length as specified in DWARF.
>> +  const uint64_t Length;
>> +
>> +  CFIProgram CFIs;
>> +};
>> +
>> +/// DWARF Common Information Entry (CIE)
>> +class CIE : public FrameEntry {
>> +public:
>> +  // CIEs (and FDEs) are simply container classes, so the only sensible
>> way to
>> +  // create them is by providing the full parsed contents in the
>> constructor.
>> +  CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
>> +      SmallString<8> Augmentation, uint8_t AddressSize,
>> +      uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
>> +      int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
>> +      SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
>> +      uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality,
>> +      Optional<uint32_t> PersonalityEnc)
>> +      : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor,
>> +                   DataAlignmentFactor),
>> +        Version(Version), Augmentation(std::move(Augmentation)),
>> +        AddressSize(AddressSize),
>> SegmentDescriptorSize(SegmentDescriptorSize),
>> +        CodeAlignmentFactor(CodeAlignmentFactor),
>> +        DataAlignmentFactor(DataAlignmentFactor),
>> +        ReturnAddressRegister(ReturnAddressRegister),
>> +        AugmentationData(std::move(AugmentationData)),
>> +        FDEPointerEncoding(FDEPointerEncoding),
>> +        LSDAPointerEncoding(LSDAPointerEncoding),
>> Personality(Personality),
>> +        PersonalityEnc(PersonalityEnc) {}
>> +
>> +  static bool classof(const FrameEntry *FE) { return FE->getKind() ==
>> FK_CIE; }
>> +
>> +  StringRef getAugmentationString() const { return Augmentation; }
>> +  uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
>> +  int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
>> +  uint8_t getVersion() const { return Version; }
>> +  uint64_t getReturnAddressRegister() const { return
>> ReturnAddressRegister; }
>> +  Optional<uint64_t> getPersonalityAddress() const { return Personality;
>> }
>> +  Optional<uint32_t> getPersonalityEncoding() const { return
>> PersonalityEnc; }
>> +
>> +  uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; }
>> +
>> +  uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; }
>> +
>> +  void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
>> +            bool IsEH) const override;
>> +
>> +private:
>> +  /// The following fields are defined in section 6.4.1 of the DWARF
>> standard v4
>> +  const uint8_t Version;
>> +  const SmallString<8> Augmentation;
>> +  const uint8_t AddressSize;
>> +  const uint8_t SegmentDescriptorSize;
>> +  const uint64_t CodeAlignmentFactor;
>> +  const int64_t DataAlignmentFactor;
>> +  const uint64_t ReturnAddressRegister;
>> +
>> +  // The following are used when the CIE represents an EH frame entry.
>> +  const SmallString<8> AugmentationData;
>> +  const uint32_t FDEPointerEncoding;
>> +  const uint32_t LSDAPointerEncoding;
>> +  const Optional<uint64_t> Personality;
>> +  const Optional<uint32_t> PersonalityEnc;
>> +};
>> +
>> +/// DWARF Frame Description Entry (FDE)
>> +class FDE : public FrameEntry {
>> +public:
>> +  // Each FDE has a CIE it's "linked to". Our FDE contains is
>> constructed with
>> +  // an offset to the CIE (provided by parsing the FDE header). The CIE
>> itself
>> +  // is obtained lazily once it's actually required.
>> +  FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
>> +      uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie,
>> +      Optional<uint64_t> LSDAAddress)
>> +      : FrameEntry(FK_FDE, Offset, Length,
>> +                   Cie ? Cie->getCodeAlignmentFactor() : 0,
>> +                   Cie ? Cie->getDataAlignmentFactor() : 0),
>> +        LinkedCIEOffset(LinkedCIEOffset),
>> InitialLocation(InitialLocation),
>> +        AddressRange(AddressRange), LinkedCIE(Cie),
>> LSDAAddress(LSDAAddress) {}
>> +
>> +  ~FDE() override = default;
>> +
>> +  const CIE *getLinkedCIE() const { return LinkedCIE; }
>> +  uint64_t getInitialLocation() const { return InitialLocation; }
>> +  uint64_t getAddressRange() const { return AddressRange; }
>> +  Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; }
>> +
>> +  void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
>> +            bool IsEH) const override;
>> +
>> +  static bool classof(const FrameEntry *FE) { return FE->getKind() ==
>> FK_FDE; }
>> +
>> +private:
>> +  /// The following fields are defined in section 6.4.1 of the DWARF
>> standard v3
>> +  const uint64_t LinkedCIEOffset;
>> +  const uint64_t InitialLocation;
>> +  const uint64_t AddressRange;
>> +  const CIE *LinkedCIE;
>> +  const Optional<uint64_t> LSDAAddress;
>> +};
>> +
>> +} // end namespace dwarf
>> +
>> +/// A parsed .debug_frame or .eh_frame section
>>  class DWARFDebugFrame {
>>    // True if this is parsing an eh_frame section.
>> -  bool IsEH;
>> +  const bool IsEH;
>> +  // Not zero for sane pointer values coming out of eh_frame
>> +  const uint64_t EHFrameAddress;
>> +
>> +  std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries;
>> +  using iterator = pointee_iterator<decltype(Entries)::const_iterator>;
>> +
>> +  /// Return the entry at the given offset or nullptr.
>> +  dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const;
>>
>>  public:
>> -  DWARFDebugFrame(bool IsEH);
>> +  // If IsEH is true, assume it is a .eh_frame section. Otherwise,
>> +  // it is a .debug_frame section. EHFrameAddress should be different
>> +  // than zero for correct parsing of .eh_frame addresses when they
>> +  // use a PC-relative encoding.
>> +  DWARFDebugFrame(bool IsEH = false, uint64_t EHFrameAddress = 0);
>>    ~DWARFDebugFrame();
>>
>>    /// Dump the section data into the given stream.
>> -  void dump(raw_ostream &OS, Optional<uint64_t> Offset) const;
>> +  void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
>> +            Optional<uint64_t> Offset) const;
>>
>> -  /// \brief Parse the section from raw data.
>> -  /// data is assumed to be pointing to the beginning of the section.
>> -  void parse(DataExtractor Data);
>> +  /// Parse the section from raw data. \p Data is assumed to contain the
>> whole
>> +  /// frame section contents to be parsed.
>> +  void parse(DWARFDataExtractor Data);
>>
>>    /// Return whether the section has any entries.
>>    bool empty() const { return Entries.empty(); }
>>
>> -  /// Return the entry at the given offset or nullptr.
>> -  FrameEntry *getEntryAtOffset(uint64_t Offset) const;
>> +  /// DWARF Frame entries accessors
>> +  iterator begin() const { return Entries.begin(); }
>> +  iterator end() const { return Entries.end(); }
>> +  iterator_range<iterator> entries() const {
>> +    return iterator_range<iterator>(Entries.begin(), Entries.end());
>> +  }
>>
>> -private:
>> -  std::vector<std::unique_ptr<FrameEntry>> Entries;
>> +  uint64_t getEHFrameAddress() const { return EHFrameAddress; }
>>  };
>>
>>  } // end namespace llvm
>>
>> Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFExpression.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFExpression.h?rev=326932&r1=326931&r2=326932&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFExpression.h (original)
>> +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFExpression.h Wed Mar  7
>> 11:19:51 2018
>> @@ -93,12 +93,13 @@ public:
>>
>>    /// An iterator to go through the expression operations.
>>    class iterator
>> -      : public iterator_facade_base<iterator, std::forward_iterator_tag,
>> Operation> {
>> +      : public iterator_facade_base<iterator, std::forward_iterator_tag,
>> +                                    Operation> {
>>      friend class DWARFExpression;
>> -    DWARFExpression *Expr;
>> +    const DWARFExpression *Expr;
>>      uint32_t Offset;
>>      Operation Op;
>> -    iterator(DWARFExpression *Expr, uint32_t Offset)
>> +    iterator(const DWARFExpression *Expr, uint32_t Offset)
>>          : Expr(Expr), Offset(Offset) {
>>        Op.Error =
>>            Offset >= Expr->Data.getData().size() ||
>> @@ -127,10 +128,11 @@ public:
>>      assert(AddressSize == 8 || AddressSize == 4);
>>    }
>>
>> -  iterator begin() { return iterator(this, 0); }
>> -  iterator end() { return iterator(this, Data.getData().size()); }
>> +  iterator begin() const { return iterator(this, 0); }
>> +  iterator end() const { return iterator(this, Data.getData().size()); }
>>
>> -  void print(raw_ostream &OS, const MCRegisterInfo *RegInfo);
>> +  void print(raw_ostream &OS, const MCRegisterInfo *RegInfo,
>> +             bool IsEH = false) const;
>>
>>  private:
>>    DataExtractor Data;
>>
>> Modified: llvm/trunk/include/llvm/Support/ScopedPrinter.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ScopedPrinter.h?rev=326932&r1=326931&r2=326932&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Support/ScopedPrinter.h (original)
>> +++ llvm/trunk/include/llvm/Support/ScopedPrinter.h Wed Mar  7 11:19:51
>> 2018
>> @@ -80,6 +80,8 @@ public:
>>
>>    void resetIndent() { IndentLevel = 0; }
>>
>> +  int getIndentLevel() { return IndentLevel; }
>> +
>>    void setPrefix(StringRef P) { Prefix = P; }
>>
>>    void printIndent() {
>>
>> Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp?rev=326932&r1=326931&r2=326932&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp (original)
>> +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp Wed Mar  7 11:19:51
>> 2018
>> @@ -349,11 +349,11 @@ void DWARFContext::dump(
>>
>>    if (shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
>>                   DObj->getDebugFrameSection()))
>> -    getDebugFrame()->dump(OS, DumpOffset);
>> +    getDebugFrame()->dump(OS, getRegisterInfo(), DumpOffset);
>>
>>    if (shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame,
>>                   DObj->getEHFrameSection()))
>> -    getEHFrame()->dump(OS, DumpOffset);
>> +    getEHFrame()->dump(OS, getRegisterInfo(), DumpOffset);
>>
>>    if (DumpType & DIDT_DebugMacro) {
>>      if (Explicit || !getDebugMacro()->empty()) {
>> @@ -712,8 +712,8 @@ const DWARFDebugFrame *DWARFContext::get
>>    // provides this information). This problem is fixed in DWARFv4
>>    // See this dwarf-discuss discussion for more details:
>>    //
>> http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
>> -  DataExtractor debugFrameData(DObj->getDebugFrameSection(),
>> isLittleEndian(),
>> -                               DObj->getAddressSize());
>> +  DWARFDataExtractor debugFrameData(DObj->getDebugFrameSection(),
>> +                                    isLittleEndian(),
>> DObj->getAddressSize());
>>    DebugFrame.reset(new DWARFDebugFrame(false /* IsEH */));
>>    DebugFrame->parse(debugFrameData);
>>    return DebugFrame.get();
>> @@ -723,8 +723,8 @@ const DWARFDebugFrame *DWARFContext::get
>>    if (EHFrame)
>>      return EHFrame.get();
>>
>> -  DataExtractor debugFrameData(DObj->getEHFrameSection(),
>> isLittleEndian(),
>> -                               DObj->getAddressSize());
>> +  DWARFDataExtractor debugFrameData(DObj->getEHFrameSection(),
>> isLittleEndian(),
>> +                                    DObj->getAddressSize());
>>    DebugFrame.reset(new DWARFDebugFrame(true /* IsEH */));
>>    DebugFrame->parse(debugFrameData);
>>    return DebugFrame.get();
>>
>> Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp?rev=326932&r1=326931&r2=326932&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp (original)
>> +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp Wed Mar  7
>> 11:19:51 2018
>> @@ -8,6 +8,7 @@
>>
>>  //===----------------------------------------------------------------------===//
>>
>>  #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
>> +#include "llvm/BinaryFormat/Dwarf.h"
>>  #include "llvm/DebugInfo/DWARF/DWARFContext.h"
>>
>>  using namespace llvm;
>> @@ -25,3 +26,71 @@ uint64_t DWARFDataExtractor::getRelocate
>>      *SecNdx = Rel->SectionIndex;
>>    return getUnsigned(Off, Size) + Rel->Value;
>>  }
>> +
>> +Optional<uint64_t>
>> +DWARFDataExtractor::getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
>> +                                      uint64_t PCRelOffset) const {
>> +  if (Encoding == dwarf::DW_EH_PE_omit)
>> +    return None;
>> +
>> +  uint64_t Result = 0;
>> +  uint32_t OldOffset = *Offset;
>> +  // First get value
>> +  switch (Encoding & 0x0F) {
>> +  case dwarf::DW_EH_PE_absptr:
>> +    switch (getAddressSize()) {
>> +    case 2:
>> +    case 4:
>> +    case 8:
>> +      Result = getUnsigned(Offset, getAddressSize());
>> +      break;
>> +    default:
>> +      return None;
>> +    }
>> +    break;
>> +  case dwarf::DW_EH_PE_uleb128:
>> +    Result = getULEB128(Offset);
>> +    break;
>> +  case dwarf::DW_EH_PE_sleb128:
>> +    Result = getSLEB128(Offset);
>> +    break;
>> +  case dwarf::DW_EH_PE_udata2:
>> +    Result = getUnsigned(Offset, 2);
>> +    break;
>> +  case dwarf::DW_EH_PE_udata4:
>> +    Result = getUnsigned(Offset, 4);
>> +    break;
>> +  case dwarf::DW_EH_PE_udata8:
>> +    Result = getUnsigned(Offset, 8);
>> +    break;
>> +  case dwarf::DW_EH_PE_sdata2:
>> +    Result = getSigned(Offset, 2);
>> +    break;
>> +  case dwarf::DW_EH_PE_sdata4:
>> +    Result = getSigned(Offset, 4);
>> +    break;
>> +  case dwarf::DW_EH_PE_sdata8:
>> +    Result = getSigned(Offset, 8);
>> +    break;
>> +  default:
>> +    return None;
>> +  }
>> +  // Then add relative offset, if required
>> +  switch (Encoding & 0x70) {
>> +  case dwarf::DW_EH_PE_absptr:
>> +    // do nothing
>> +    break;
>> +  case dwarf::DW_EH_PE_pcrel:
>> +    Result += PCRelOffset;
>> +    break;
>> +  case dwarf::DW_EH_PE_datarel:
>> +  case dwarf::DW_EH_PE_textrel:
>> +  case dwarf::DW_EH_PE_funcrel:
>> +  case dwarf::DW_EH_PE_aligned:
>> +  default:
>> +    *Offset = OldOffset;
>> +    return None;
>> +  }
>> +
>> +  return Result;
>> +}
>>
>> Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp?rev=326932&r1=326931&r2=326932&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp (original)
>> +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp Wed Mar  7
>> 11:19:51 2018
>> @@ -8,10 +8,8 @@
>>
>>  //===----------------------------------------------------------------------===//
>>
>>  #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
>> -#include "llvm/ADT/ArrayRef.h"
>>  #include "llvm/ADT/DenseMap.h"
>>  #include "llvm/ADT/Optional.h"
>> -#include "llvm/ADT/SmallString.h"
>>  #include "llvm/ADT/StringExtras.h"
>>  #include "llvm/ADT/StringRef.h"
>>  #include "llvm/BinaryFormat/Dwarf.h"
>> @@ -31,87 +29,13 @@
>>  using namespace llvm;
>>  using namespace dwarf;
>>
>> -/// \brief Abstract frame entry defining the common interface concrete
>> -/// entries implement.
>> -class llvm::FrameEntry {
>> -public:
>> -  enum FrameKind {FK_CIE, FK_FDE};
>> -
>> -  FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length)
>> -      : Kind(K), Offset(Offset), Length(Length) {}
>> -
>> -  virtual ~FrameEntry() = default;
>> -
>> -  FrameKind getKind() const { return Kind; }
>> -  virtual uint64_t getOffset() const { return Offset; }
>> -
>> -  /// Parse and store a sequence of CFI instructions from Data,
>> -  /// starting at *Offset and ending at EndOffset. If everything
>> -  /// goes well, *Offset should be equal to EndOffset when this method
>> -  /// returns. Otherwise, an error occurred.
>> -  virtual void parseInstructions(DataExtractor Data, uint32_t *Offset,
>> -                                 uint32_t EndOffset);
>> -
>> -  /// Dump the entry header to the given output stream.
>> -  virtual void dumpHeader(raw_ostream &OS) const = 0;
>> -
>> -  /// Dump the entry's instructions to the given output stream.
>> -  virtual void dumpInstructions(raw_ostream &OS) const;
>> -
>> -  /// Dump the entire entry to the given output stream.
>> -  void dump(raw_ostream &OS) const {
>> -    dumpHeader(OS);
>> -    dumpInstructions(OS);
>> -    OS << "\n";
>> -  }
>> -
>> -protected:
>> -  const FrameKind Kind;
>> -
>> -  /// \brief Offset of this entry in the section.
>> -  uint64_t Offset;
>> -
>> -  /// \brief Entry length as specified in DWARF.
>> -  uint64_t Length;
>> -
>> -  /// An entry may contain CFI instructions. An instruction consists of
>> an
>> -  /// opcode and an optional sequence of operands.
>> -  using Operands = std::vector<uint64_t>;
>> -  struct Instruction {
>> -    Instruction(uint8_t Opcode)
>> -      : Opcode(Opcode)
>> -    {}
>> -
>> -    uint8_t Opcode;
>> -    Operands Ops;
>> -  };
>> -
>> -  std::vector<Instruction> Instructions;
>> -
>> -  /// Convenience methods to add a new instruction with the given opcode
>> and
>> -  /// operands to the Instructions vector.
>> -  void addInstruction(uint8_t Opcode) {
>> -    Instructions.push_back(Instruction(Opcode));
>> -  }
>> -
>> -  void addInstruction(uint8_t Opcode, uint64_t Operand1) {
>> -    Instructions.push_back(Instruction(Opcode));
>> -    Instructions.back().Ops.push_back(Operand1);
>> -  }
>> -
>> -  void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t
>> Operand2) {
>> -    Instructions.push_back(Instruction(Opcode));
>> -    Instructions.back().Ops.push_back(Operand1);
>> -    Instructions.back().Ops.push_back(Operand2);
>> -  }
>> -};
>>
>>  // See DWARF standard v3, section 7.23
>>  const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
>>  const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
>>
>> -void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
>> -                                   uint32_t EndOffset) {
>> +Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset,
>> +                        uint32_t EndOffset) {
>>    while (*Offset < EndOffset) {
>>      uint8_t Opcode = Data.getU8(Offset);
>>      // Some instructions have a primary opcode encoded in the top bits.
>> @@ -122,67 +46,73 @@ void FrameEntry::parseInstructions(DataE
>>        // bits of the opcode itself.
>>        uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
>>        switch (Primary) {
>> -        default: llvm_unreachable("Impossible primary CFI opcode");
>> -        case DW_CFA_advance_loc:
>> -        case DW_CFA_restore:
>> -          addInstruction(Primary, Op1);
>> -          break;
>> -        case DW_CFA_offset:
>> -          addInstruction(Primary, Op1, Data.getULEB128(Offset));
>> -          break;
>> +      default:
>> +        return make_error<StringError>(
>> +            "Invalid primary CFI opcode",
>> +            std::make_error_code(std::errc::illegal_byte_sequence));
>> +      case DW_CFA_advance_loc:
>> +      case DW_CFA_restore:
>> +        addInstruction(Primary, Op1);
>> +        break;
>> +      case DW_CFA_offset:
>> +        addInstruction(Primary, Op1, Data.getULEB128(Offset));
>> +        break;
>>        }
>>      } else {
>>        // Extended opcode - its value is Opcode itself.
>>        switch (Opcode) {
>> -        default: llvm_unreachable("Invalid extended CFI opcode");
>> -        case DW_CFA_nop:
>> -        case DW_CFA_remember_state:
>> -        case DW_CFA_restore_state:
>> -        case DW_CFA_GNU_window_save:
>> -          // No operands
>> -          addInstruction(Opcode);
>> -          break;
>> -        case DW_CFA_set_loc:
>> -          // Operands: Address
>> -          addInstruction(Opcode, Data.getAddress(Offset));
>> -          break;
>> -        case DW_CFA_advance_loc1:
>> -          // Operands: 1-byte delta
>> -          addInstruction(Opcode, Data.getU8(Offset));
>> -          break;
>> -        case DW_CFA_advance_loc2:
>> -          // Operands: 2-byte delta
>> -          addInstruction(Opcode, Data.getU16(Offset));
>> -          break;
>> -        case DW_CFA_advance_loc4:
>> -          // Operands: 4-byte delta
>> -          addInstruction(Opcode, Data.getU32(Offset));
>> -          break;
>> -        case DW_CFA_restore_extended:
>> -        case DW_CFA_undefined:
>> -        case DW_CFA_same_value:
>> -        case DW_CFA_def_cfa_register:
>> -        case DW_CFA_def_cfa_offset:
>> -        case DW_CFA_GNU_args_size:
>> -          // Operands: ULEB128
>> -          addInstruction(Opcode, Data.getULEB128(Offset));
>> -          break;
>> -        case DW_CFA_def_cfa_offset_sf:
>> -          // Operands: SLEB128
>> -          addInstruction(Opcode, Data.getSLEB128(Offset));
>> -          break;
>> -        case DW_CFA_offset_extended:
>> -        case DW_CFA_register:
>> -        case DW_CFA_def_cfa:
>> -        case DW_CFA_val_offset: {
>> -          // Operands: ULEB128, ULEB128
>> -          // Note: We can not embed getULEB128 directly into function
>> -          // argument list. getULEB128 changes Offset and order of
>> evaluation
>> -          // for arguments is unspecified.
>> -          auto op1 = Data.getULEB128(Offset);
>> -          auto op2 = Data.getULEB128(Offset);
>> -          addInstruction(Opcode, op1, op2);
>> -          break;
>> +      default:
>> +        return make_error<StringError>(
>> +            "Invalid extended CFI opcode",
>> +            std::make_error_code(std::errc::illegal_byte_sequence));
>> +      case DW_CFA_nop:
>> +      case DW_CFA_remember_state:
>> +      case DW_CFA_restore_state:
>> +      case DW_CFA_GNU_window_save:
>> +        // No operands
>> +        addInstruction(Opcode);
>> +        break;
>> +      case DW_CFA_set_loc:
>> +        // Operands: Address
>> +        addInstruction(Opcode, Data.getAddress(Offset));
>> +        break;
>> +      case DW_CFA_advance_loc1:
>> +        // Operands: 1-byte delta
>> +        addInstruction(Opcode, Data.getU8(Offset));
>> +        break;
>> +      case DW_CFA_advance_loc2:
>> +        // Operands: 2-byte delta
>> +        addInstruction(Opcode, Data.getU16(Offset));
>> +        break;
>> +      case DW_CFA_advance_loc4:
>> +        // Operands: 4-byte delta
>> +        addInstruction(Opcode, Data.getU32(Offset));
>> +        break;
>> +      case DW_CFA_restore_extended:
>> +      case DW_CFA_undefined:
>> +      case DW_CFA_same_value:
>> +      case DW_CFA_def_cfa_register:
>> +      case DW_CFA_def_cfa_offset:
>> +      case DW_CFA_GNU_args_size:
>> +        // Operands: ULEB128
>> +        addInstruction(Opcode, Data.getULEB128(Offset));
>> +        break;
>> +      case DW_CFA_def_cfa_offset_sf:
>> +        // Operands: SLEB128
>> +        addInstruction(Opcode, Data.getSLEB128(Offset));
>> +        break;
>> +      case DW_CFA_offset_extended:
>> +      case DW_CFA_register:
>> +      case DW_CFA_def_cfa:
>> +      case DW_CFA_val_offset: {
>> +        // Operands: ULEB128, ULEB128
>> +        // Note: We can not embed getULEB128 directly into function
>> +        // argument list. getULEB128 changes Offset and order of
>> evaluation
>> +        // for arguments is unspecified.
>> +        auto op1 = Data.getULEB128(Offset);
>> +        auto op2 = Data.getULEB128(Offset);
>> +        addInstruction(Opcode, op1, op2);
>> +        break;
>>          }
>>          case DW_CFA_offset_extended_sf:
>>          case DW_CFA_def_cfa_sf:
>> @@ -194,162 +124,49 @@ void FrameEntry::parseInstructions(DataE
>>            addInstruction(Opcode, op1, op2);
>>            break;
>>          }
>> -        case DW_CFA_def_cfa_expression:
>> -          // FIXME: Parse the actual instruction.
>> -          *Offset += Data.getULEB128(Offset);
>> +        case DW_CFA_def_cfa_expression: {
>> +          uint32_t ExprLength = Data.getULEB128(Offset);
>> +          addInstruction(Opcode, 0);
>> +          DataExtractor Extractor(
>> +              Data.getData().slice(*Offset, *Offset + ExprLength),
>> +              Data.isLittleEndian(), Data.getAddressSize());
>> +          Instructions.back().Expression = DWARFExpression(
>> +              Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION);
>> +          *Offset += ExprLength;
>>            break;
>> +        }
>>          case DW_CFA_expression:
>>          case DW_CFA_val_expression: {
>> -          // FIXME: Parse the actual instruction.
>> -          Data.getULEB128(Offset);
>> -          *Offset += Data.getULEB128(Offset);
>> +          auto RegNum = Data.getULEB128(Offset);
>> +          auto BlockLength = Data.getULEB128(Offset);
>> +          addInstruction(Opcode, RegNum, 0);
>> +          DataExtractor Extractor(
>> +              Data.getData().slice(*Offset, *Offset + BlockLength),
>> +              Data.isLittleEndian(), Data.getAddressSize());
>> +          Instructions.back().Expression = DWARFExpression(
>> +              Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION);
>> +          *Offset += BlockLength;
>>            break;
>>          }
>>        }
>>      }
>>    }
>> +
>> +  return Error::success();
>>  }
>>
>>  namespace {
>>
>> -/// \brief DWARF Common Information Entry (CIE)
>> -class CIE : public FrameEntry {
>> -public:
>> -  // CIEs (and FDEs) are simply container classes, so the only sensible
>> way to
>> -  // create them is by providing the full parsed contents in the
>> constructor.
>> -  CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
>> -      SmallString<8> Augmentation, uint8_t AddressSize,
>> -      uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
>> -      int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
>> -      SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
>> -      uint32_t LSDAPointerEncoding)
>> -      : FrameEntry(FK_CIE, Offset, Length), Version(Version),
>> -        Augmentation(std::move(Augmentation)), AddressSize(AddressSize),
>> -        SegmentDescriptorSize(SegmentDescriptorSize),
>> -        CodeAlignmentFactor(CodeAlignmentFactor),
>> -        DataAlignmentFactor(DataAlignmentFactor),
>> -        ReturnAddressRegister(ReturnAddressRegister),
>> -        AugmentationData(std::move(AugmentationData)),
>> -        FDEPointerEncoding(FDEPointerEncoding),
>> -        LSDAPointerEncoding(LSDAPointerEncoding) {}
>> -
>> -  ~CIE() override = default;
>> -
>> -  StringRef getAugmentationString() const { return Augmentation; }
>> -  uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
>> -  int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
>> -
>> -  uint32_t getFDEPointerEncoding() const {
>> -    return FDEPointerEncoding;
>> -  }
>> -
>> -  uint32_t getLSDAPointerEncoding() const {
>> -    return LSDAPointerEncoding;
>> -  }
>> -
>> -  void dumpHeader(raw_ostream &OS) const override {
>> -    OS << format("%08x %08x %08x CIE",
>> -                 (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
>> -       << "\n";
>> -    OS << format("  Version:               %d\n", Version);
>> -    OS << "  Augmentation:          \"" << Augmentation << "\"\n";
>> -    if (Version >= 4) {
>> -      OS << format("  Address size:          %u\n",
>> -                   (uint32_t)AddressSize);
>> -      OS << format("  Segment desc size:     %u\n",
>> -                   (uint32_t)SegmentDescriptorSize);
>> -    }
>> -    OS << format("  Code alignment factor: %u\n",
>> -                 (uint32_t)CodeAlignmentFactor);
>> -    OS << format("  Data alignment factor: %d\n",
>> -                 (int32_t)DataAlignmentFactor);
>> -    OS << format("  Return address column: %d\n",
>> -                 (int32_t)ReturnAddressRegister);
>> -    if (!AugmentationData.empty()) {
>> -      OS << "  Augmentation data:    ";
>> -      for (uint8_t Byte : AugmentationData)
>> -        OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
>> -      OS << "\n";
>> -    }
>> -    OS << "\n";
>> -  }
>> -
>> -  static bool classof(const FrameEntry *FE) {
>> -    return FE->getKind() == FK_CIE;
>> -  }
>> -
>> -private:
>> -  /// The following fields are defined in section 6.4.1 of the DWARF
>> standard v4
>> -  uint8_t Version;
>> -  SmallString<8> Augmentation;
>> -  uint8_t AddressSize;
>> -  uint8_t SegmentDescriptorSize;
>> -  uint64_t CodeAlignmentFactor;
>> -  int64_t DataAlignmentFactor;
>> -  uint64_t ReturnAddressRegister;
>> -
>> -  // The following are used when the CIE represents an EH frame entry.
>> -  SmallString<8> AugmentationData;
>> -  uint32_t FDEPointerEncoding;
>> -  uint32_t LSDAPointerEncoding;
>> -};
>> -
>> -/// \brief DWARF Frame Description Entry (FDE)
>> -class FDE : public FrameEntry {
>> -public:
>> -  // Each FDE has a CIE it's "linked to". Our FDE contains is
>> constructed with
>> -  // an offset to the CIE (provided by parsing the FDE header). The CIE
>> itself
>> -  // is obtained lazily once it's actually required.
>> -  FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
>> -      uint64_t InitialLocation, uint64_t AddressRange,
>> -      CIE *Cie)
>> -      : FrameEntry(FK_FDE, Offset, Length),
>> LinkedCIEOffset(LinkedCIEOffset),
>> -        InitialLocation(InitialLocation), AddressRange(AddressRange),
>> -        LinkedCIE(Cie) {}
>> -
>> -  ~FDE() override = default;
>> -
>> -  CIE *getLinkedCIE() const { return LinkedCIE; }
>> -
>> -  void dumpHeader(raw_ostream &OS) const override {
>> -    OS << format("%08x %08x %08x FDE ",
>> -                 (uint32_t)Offset, (uint32_t)Length,
>> (int32_t)LinkedCIEOffset);
>> -    OS << format("cie=%08x pc=%08x...%08x\n",
>> -                 (int32_t)LinkedCIEOffset,
>> -                 (uint32_t)InitialLocation,
>> -                 (uint32_t)InitialLocation + (uint32_t)AddressRange);
>> -  }
>> -
>> -  static bool classof(const FrameEntry *FE) {
>> -    return FE->getKind() == FK_FDE;
>> -  }
>> -
>> -private:
>> -  /// The following fields are defined in section 6.4.1 of the DWARF
>> standard v3
>> -  uint64_t LinkedCIEOffset;
>> -  uint64_t InitialLocation;
>> -  uint64_t AddressRange;
>> -  CIE *LinkedCIE;
>> -};
>> -
>> -/// \brief Types of operands to CF instructions.
>> -enum OperandType {
>> -  OT_Unset,
>> -  OT_None,
>> -  OT_Address,
>> -  OT_Offset,
>> -  OT_FactoredCodeOffset,
>> -  OT_SignedFactDataOffset,
>> -  OT_UnsignedFactDataOffset,
>> -  OT_Register,
>> -  OT_Expression
>> -};
>>
>>  } // end anonymous namespace
>>
>> -/// \brief Initialize the array describing the types of operands.
>> -static ArrayRef<OperandType[2]> getOperandTypes() {
>> +ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() {
>>    static OperandType OpTypes[DW_CFA_restore+1][2];
>> +  static bool Initialized = false;
>> +  if (Initialized) {
>> +    return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
>> +  }
>> +  Initialized = true;
>>
>>  #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1)       \
>>    do {                                          \
>> @@ -396,15 +213,13 @@ static ArrayRef<OperandType[2]> getOpera
>>    return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
>>  }
>>
>> -static ArrayRef<OperandType[2]> OpTypes = getOperandTypes();
>> -
>> -/// \brief Print \p Opcode's operand number \p OperandIdx which has
>> -/// value \p Operand.
>> -static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned
>> OperandIdx,
>> -                         uint64_t Operand, uint64_t CodeAlignmentFactor,
>> -                         int64_t DataAlignmentFactor) {
>> +/// Print \p Opcode's operand number \p OperandIdx which has value \p
>> Operand.
>> +void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI,
>> +                              bool IsEH, const Instruction &Instr,
>> +                              unsigned OperandIdx, uint64_t Operand)
>> const {
>>    assert(OperandIdx < 2);
>> -  OperandType Type = OpTypes[Opcode][OperandIdx];
>> +  uint8_t Opcode = Instr.Opcode;
>> +  OperandType Type = getOperandTypes()[Opcode][OperandIdx];
>>
>>    switch (Type) {
>>    case OT_Unset: {
>> @@ -449,36 +264,68 @@ static void printOperand(raw_ostream &OS
>>      OS << format(" reg%" PRId64, Operand);
>>      break;
>>    case OT_Expression:
>> -    OS << " expression";
>> +    assert(Instr.Expression && "missing DWARFExpression object");
>> +    OS << " ";
>> +    Instr.Expression->print(OS, MRI, IsEH);
>>      break;
>>    }
>>  }
>>
>> -void FrameEntry::dumpInstructions(raw_ostream &OS) const {
>> -  uint64_t CodeAlignmentFactor = 0;
>> -  int64_t DataAlignmentFactor = 0;
>> -  const CIE *Cie = dyn_cast<CIE>(this);
>> -
>> -  if (!Cie)
>> -    Cie = cast<FDE>(this)->getLinkedCIE();
>> -  if (Cie) {
>> -    CodeAlignmentFactor = Cie->getCodeAlignmentFactor();
>> -    DataAlignmentFactor = Cie->getDataAlignmentFactor();
>> -  }
>> -
>> +void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool
>> IsEH,
>> +                      unsigned IndentLevel) const {
>>    for (const auto &Instr : Instructions) {
>>      uint8_t Opcode = Instr.Opcode;
>>      if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
>>        Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
>> -    OS << "  " << CallFrameString(Opcode) << ":";
>> +    OS.indent(2 * IndentLevel);
>> +    OS << CallFrameString(Opcode) << ":";
>>      for (unsigned i = 0; i < Instr.Ops.size(); ++i)
>> -      printOperand(OS, Opcode, i, Instr.Ops[i], CodeAlignmentFactor,
>> -                   DataAlignmentFactor);
>> +      printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]);
>>      OS << '\n';
>>    }
>>  }
>>
>> -DWARFDebugFrame::DWARFDebugFrame(bool IsEH) : IsEH(IsEH) {}
>> +void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH)
>> const {
>> +  OS << format("%08x %08x %08x CIE", (uint32_t)Offset, (uint32_t)Length,
>> +               DW_CIE_ID)
>> +     << "\n";
>> +  OS << format("  Version:               %d\n", Version);
>> +  OS << "  Augmentation:          \"" << Augmentation << "\"\n";
>> +  if (Version >= 4) {
>> +    OS << format("  Address size:          %u\n", (uint32_t)AddressSize);
>> +    OS << format("  Segment desc size:     %u\n",
>> +                 (uint32_t)SegmentDescriptorSize);
>> +  }
>> +  OS << format("  Code alignment factor: %u\n",
>> (uint32_t)CodeAlignmentFactor);
>> +  OS << format("  Data alignment factor: %d\n",
>> (int32_t)DataAlignmentFactor);
>> +  OS << format("  Return address column: %d\n",
>> (int32_t)ReturnAddressRegister);
>> +  if (Personality)
>> +    OS << format("  Personality Address: %08x\n", *Personality);
>> +  if (!AugmentationData.empty()) {
>> +    OS << "  Augmentation data:    ";
>> +    for (uint8_t Byte : AugmentationData)
>> +      OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
>> +    OS << "\n";
>> +  }
>> +  OS << "\n";
>> +  CFIs.dump(OS, MRI, IsEH);
>> +  OS << "\n";
>> +}
>> +
>> +void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH)
>> const {
>> +  OS << format("%08x %08x %08x FDE ", (uint32_t)Offset, (uint32_t)Length,
>> +               (int32_t)LinkedCIEOffset);
>> +  OS << format("cie=%08x pc=%08x...%08x\n", (int32_t)LinkedCIEOffset,
>> +               (uint32_t)InitialLocation,
>> +               (uint32_t)InitialLocation + (uint32_t)AddressRange);
>> +  if (LSDAAddress)
>> +    OS << format("  LSDA Address: %08x\n", *LSDAAddress);
>> +  CFIs.dump(OS, MRI, IsEH);
>> +  OS << "\n";
>> +}
>> +
>> +DWARFDebugFrame::DWARFDebugFrame(bool IsEH, uint64_t EHFrameAddress)
>> +    : IsEH(IsEH), EHFrameAddress(EHFrameAddress) {}
>>
>>  DWARFDebugFrame::~DWARFDebugFrame() = default;
>>
>> @@ -492,40 +339,6 @@ static void LLVM_ATTRIBUTE_UNUSED dumpDa
>>    errs() << "\n";
>>  }
>>
>> -static unsigned getSizeForEncoding(const DataExtractor &Data,
>> -                                   unsigned symbolEncoding) {
>> -  unsigned format = symbolEncoding & 0x0f;
>> -  switch (format) {
>> -    default: llvm_unreachable("Unknown Encoding");
>> -    case DW_EH_PE_absptr:
>> -    case DW_EH_PE_signed:
>> -      return Data.getAddressSize();
>> -    case DW_EH_PE_udata2:
>> -    case DW_EH_PE_sdata2:
>> -      return 2;
>> -    case DW_EH_PE_udata4:
>> -    case DW_EH_PE_sdata4:
>> -      return 4;
>> -    case DW_EH_PE_udata8:
>> -    case DW_EH_PE_sdata8:
>> -      return 8;
>> -  }
>> -}
>> -
>> -static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset,
>> -                            unsigned Encoding) {
>> -  switch (getSizeForEncoding(Data, Encoding)) {
>> -    case 2:
>> -      return Data.getU16(&Offset);
>> -    case 4:
>> -      return Data.getU32(&Offset);
>> -    case 8:
>> -      return Data.getU64(&Offset);
>> -    default:
>> -      llvm_unreachable("Illegal data size");
>> -  }
>> -}
>> -
>>  // This is a workaround for old compilers which do not allow
>>  // noreturn attribute usage in lambdas. Once the support for those
>>  // compilers are phased out, we can remove this and return back to
>> @@ -539,7 +352,7 @@ static void LLVM_ATTRIBUTE_NORETURN Repo
>>    report_fatal_error(Str);
>>  }
>>
>> -void DWARFDebugFrame::parse(DataExtractor Data) {
>> +void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
>>    uint32_t Offset = 0;
>>    DenseMap<uint32_t, CIE *> CIEs;
>>
>> @@ -569,9 +382,8 @@ void DWARFDebugFrame::parse(DataExtracto
>>
>>      // The Id field's size depends on the DWARF format
>>      Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4);
>> -    bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) ||
>> -                  Id == DW_CIE_ID ||
>> -                  (IsEH && !Id));
>> +    bool IsCIE =
>> +        ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID || (IsEH &&
>> !Id));
>>
>>      if (IsCIE) {
>>        uint8_t Version = Data.getU8(&Offset);
>> @@ -589,10 +401,9 @@ void DWARFDebugFrame::parse(DataExtracto
>>        StringRef AugmentationData("");
>>        uint32_t FDEPointerEncoding = DW_EH_PE_omit;
>>        uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
>> +      Optional<uint64_t> Personality;
>> +      Optional<uint32_t> PersonalityEncoding;
>>        if (IsEH) {
>> -        Optional<uint32_t> PersonalityEncoding;
>> -        Optional<uint64_t> Personality;
>> -
>>          Optional<uint64_t> AugmentationLength;
>>          uint32_t StartAugmentationOffset;
>>          uint32_t EndAugmentationOffset;
>> @@ -611,7 +422,9 @@ void DWARFDebugFrame::parse(DataExtracto
>>                  ReportError(StartOffset,
>>                              "Duplicate personality in entry at %lx");
>>                PersonalityEncoding = Data.getU8(&Offset);
>> -              Personality = readPointer(Data, Offset,
>> *PersonalityEncoding);
>> +              Personality = Data.getEncodedPointer(
>> +                  &Offset, *PersonalityEncoding,
>> +                  EHFrameAddress ? EHFrameAddress + Offset : 0);
>>                break;
>>              }
>>              case 'R':
>> @@ -639,14 +452,11 @@ void DWARFDebugFrame::parse(DataExtracto
>>          }
>>        }
>>
>> -      auto Cie = llvm::make_unique<CIE>(StartOffset, Length, Version,
>> -                                        AugmentationString, AddressSize,
>> -                                        SegmentDescriptorSize,
>> -                                        CodeAlignmentFactor,
>> -                                        DataAlignmentFactor,
>> -                                        ReturnAddressRegister,
>> -                                        AugmentationData,
>> FDEPointerEncoding,
>> -                                        LSDAPointerEncoding);
>> +      auto Cie = llvm::make_unique<CIE>(
>> +          StartOffset, Length, Version, AugmentationString, AddressSize,
>> +          SegmentDescriptorSize, CodeAlignmentFactor,
>> DataAlignmentFactor,
>> +          ReturnAddressRegister, AugmentationData, FDEPointerEncoding,
>> +          LSDAPointerEncoding, Personality, PersonalityEncoding);
>>        CIEs[StartOffset] = Cie.get();
>>        Entries.emplace_back(std::move(Cie));
>>      } else {
>> @@ -654,6 +464,7 @@ void DWARFDebugFrame::parse(DataExtracto
>>        uint64_t CIEPointer = Id;
>>        uint64_t InitialLocation = 0;
>>        uint64_t AddressRange = 0;
>> +      Optional<uint64_t> LSDAAddress;
>>        CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) :
>> CIEPointer];
>>
>>        if (IsEH) {
>> @@ -662,10 +473,15 @@ void DWARFDebugFrame::parse(DataExtracto
>>            ReportError(StartOffset,
>>                        "Parsing FDE data at %lx failed due to missing
>> CIE");
>>
>> -        InitialLocation = readPointer(Data, Offset,
>> -                                      Cie->getFDEPointerEncoding());
>> -        AddressRange = readPointer(Data, Offset,
>> -                                   Cie->getFDEPointerEncoding());
>> +        if (auto Val = Data.getEncodedPointer(
>> +                &Offset, Cie->getFDEPointerEncoding(),
>> +                EHFrameAddress ? EHFrameAddress + Offset : 0)) {
>> +          InitialLocation = *Val;
>> +        }
>> +        if (auto Val = Data.getEncodedPointer(
>> +                &Offset, Cie->getFDEPointerEncoding(), 0)) {
>> +          AddressRange = *Val;
>> +        }
>>
>>          StringRef AugmentationString = Cie->getAugmentationString();
>>          if (!AugmentationString.empty()) {
>> @@ -676,8 +492,11 @@ void DWARFDebugFrame::parse(DataExtracto
>>              Offset + static_cast<uint32_t>(AugmentationLength);
>>
>>            // Decode the LSDA if the CIE augmentation string said we
>> should.
>> -          if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit)
>> -            readPointer(Data, Offset, Cie->getLSDAPointerEncoding());
>> +          if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) {
>> +            LSDAAddress = Data.getEncodedPointer(
>> +                &Offset, Cie->getLSDAPointerEncoding(),
>> +                EHFrameAddress ? Offset + EHFrameAddress : 0);
>> +          }
>>
>>            if (Offset != EndAugmentationOffset)
>>              ReportError(StartOffset, "Parsing augmentation data at %lx
>> failed");
>> @@ -689,10 +508,13 @@ void DWARFDebugFrame::parse(DataExtracto
>>
>>        Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
>>                                     InitialLocation, AddressRange,
>> -                                   Cie));
>> +                                   Cie, LSDAAddress));
>>      }
>>
>> -    Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
>> +    if (Error E =
>> +            Entries.back()->cfis().parse(Data, &Offset,
>> EndStructureOffset)) {
>> +      report_fatal_error(toString(std::move(E)));
>> +    }
>>
>>      if (Offset != EndStructureOffset)
>>        ReportError(StartOffset, "Parsing entry instructions at %lx
>> failed");
>> @@ -709,14 +531,15 @@ FrameEntry *DWARFDebugFrame::getEntryAtO
>>    return nullptr;
>>  }
>>
>> -void DWARFDebugFrame::dump(raw_ostream &OS, Optional<uint64_t> Offset)
>> const {
>> +void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
>> +                           Optional<uint64_t> Offset) const {
>>    if (Offset) {
>>      if (auto *Entry = getEntryAtOffset(*Offset))
>> -      Entry->dump(OS);
>> +      Entry->dump(OS, MRI, IsEH);
>>      return;
>>    }
>>
>>    OS << "\n";
>>    for (const auto &Entry : Entries)
>> -    Entry->dump(OS);
>> +    Entry->dump(OS, MRI, IsEH);
>>  }
>>
>> Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp?rev=326932&r1=326931&r2=326932&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp (original)
>> +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFExpression.cpp Wed Mar  7
>> 11:19:51 2018
>> @@ -258,9 +258,10 @@ bool DWARFExpression::Operation::print(r
>>    return true;
>>  }
>>
>> -void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo
>> *RegInfo) {
>> +void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo
>> *RegInfo,
>> +                            bool IsEH) const {
>>    for (auto &Op : *this) {
>> -    if (!Op.print(OS, this, RegInfo, /* isEH */ false)) {
>> +    if (!Op.print(OS, this, RegInfo, IsEH)) {
>>        uint32_t FailOffset = Op.getEndOffset();
>>        while (FailOffset < Data.getData().size())
>>          OS << format(" %02x", Data.getU8(&FailOffset));
>>
>> Modified: llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/ELFYAML.cpp?rev=326932&r1=326931&r2=326932&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/ObjectYAML/ELFYAML.cpp (original)
>> +++ llvm/trunk/lib/ObjectYAML/ELFYAML.cpp Wed Mar  7 11:19:51 2018
>> @@ -50,6 +50,7 @@ void ScalarEnumerationTraits<ELFYAML::EL
>>    ECase(PT_SHLIB);
>>    ECase(PT_PHDR);
>>    ECase(PT_TLS);
>> +  ECase(PT_GNU_EH_FRAME);
>>  #undef ECase
>>    IO.enumFallback<Hex32>(Value);
>>  }
>>
>> Added:
>> llvm/trunk/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml?rev=326932&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml
>> (added)
>> +++ llvm/trunk/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml
>> Wed Mar  7 11:19:51 2018
>> @@ -0,0 +1,46 @@
>> +--- !ELF
>> +FileHeader:
>> +  Class:           ELFCLASS64
>> +  Data:            ELFDATA2LSB
>> +  Type:            ET_EXEC
>> +  Machine:         EM_X86_64
>> +  Entry:           0x0000000000400000
>> +Sections:
>> +  - Name:            .text
>> +    Type:            SHT_PROGBITS
>> +    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
>> +    Address:         0x0000000000400000
>> +    AddressAlign:    16
>> +    Content:         50C704240020400031C05AC3
>> +  - Name:            .eh_frame_hdr
>> +    Type:            SHT_PROGBITS
>> +    Flags:           [ SHF_ALLOC ]
>> +    Address:         0x00000000004013c0
>> +    AddressAlign:    4
>> +    Content:
>>  011B033B3C00000006000000E0F0FFFF8800000010F1FFFF58000000F6F1FFFFB000000010F2FFFFD000000090FEFFFF0001000000FFFFFF30010000
>> +  - Name:            .eh_frame
>> +    Type:            SHT_PROGBITS
>> +    Flags:           [ SHF_ALLOC ]
>> +    Address:         0x0000000000401400
>> +    AddressAlign:    8
>> +    Content:
>>  1400000000000000017A5200017810011B0C070890010710140000001C000000B0F0FFFF2A00000000000000000000001400000000000000017A5200017810011B0C070890010000240000001C00000050F0FFFF20000000000E10460E184A0F0B770880003F1A3B2A332422000000001C000000440000003EF1FFFF1000000000410E108602430D064B0C07080000002C0000006400000038F1FFFF7F0C000000450C0A00491006027600450F0376780603660C0C0A00450C070800000000002C0000009400000088FDFFFF6600000000410E108602430D06428F03458E04478D058C06488307024B0C07080000000014000000C4000000C8FDFFFF01000000000000000000000000000000
>> +Symbols:
>> +  Global:
>> +    - Name:            myfunc
>> +      Type:            STT_FUNC
>> +      Section:         .text
>> +      Value:           0x0000000000400000
>> +ProgramHeaders:
>> +  - Type: PT_LOAD
>> +    Flags: [ PF_X, PF_R ]
>> +    VAddr: 0x00400000
>> +    PAddr: 0x00400000
>> +    Sections:
>> +      - Section: .text
>> +  - Type: PT_GNU_EH_FRAME
>> +    Flags: [ PF_X, PF_R ]
>> +    VAddr: 0x004013C0
>> +    PAddr: 0x004013C0
>> +    Sections:
>> +      - Section: .eh_frame_hdr
>> +...
>>
>> Added: llvm/trunk/test/tools/llvm-readobj/unwind.test
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/unwind.test?rev=326932&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/tools/llvm-readobj/unwind.test (added)
>> +++ llvm/trunk/test/tools/llvm-readobj/unwind.test Wed Mar  7 11:19:51
>> 2018
>> @@ -0,0 +1,170 @@
>> +RUN: yaml2obj %p/Inputs/dwarf-exprs.exe-x86-64.yaml > %t.exe
>> +RUN: llvm-readobj -unwind %t.exe | FileCheck %s
>> +
>> +CHECK:      EH_FRAME Header [
>> +CHECK-NEXT:  Address: 0x4013c0
>> +CHECK-NEXT:  Offset: 0x27c
>> +CHECK-NEXT:  Size: 0x3c
>> +CHECK-NEXT:  Corresponding Section: .eh_frame_hdr
>> +CHECK-NEXT:  Header {
>> +CHECK-NEXT:    version: 1
>> +CHECK-NEXT:    eh_frame_ptr_enc: 0x1b
>> +CHECK-NEXT:    fde_count_enc: 0x3
>> +CHECK-NEXT:    table_enc: 0x3b
>> +CHECK-NEXT:    eh_frame_ptr: 0x401400
>> +CHECK-NEXT:    fde_count: 6
>> +CHECK-NEXT:    entry 0 {
>> +CHECK-NEXT:      initial_location: 0x4004a0
>> +CHECK-NEXT:      address: 0x401448
>> +CHECK-NEXT:    }
>> +CHECK-NEXT:    entry 1 {
>> +CHECK-NEXT:      initial_location: 0x4004d0
>> +CHECK-NEXT:      address: 0x401418
>> +CHECK-NEXT:    }
>> +CHECK-NEXT:    entry 2 {
>> +CHECK-NEXT:      initial_location: 0x4005b6
>> +CHECK-NEXT:      address: 0x401470
>> +CHECK-NEXT:    }
>> +CHECK-NEXT:    entry 3 {
>> +CHECK-NEXT:      initial_location: 0x4005d0
>> +CHECK-NEXT:      address: 0x401490
>> +CHECK-NEXT:    }
>> +CHECK-NEXT:    entry 4 {
>> +CHECK-NEXT:      initial_location: 0x401250
>> +CHECK-NEXT:      address: 0x4014c0
>> +CHECK-NEXT:    }
>> +CHECK-NEXT:    entry 5 {
>> +CHECK-NEXT:      initial_location: 0x4012c0
>> +CHECK-NEXT:      address: 0x4014f0
>> +CHECK-NEXT:    }
>> +CHECK-NEXT:  }
>> +CHECK-NEXT:]
>> +
>> +CHECK:      .eh_frame section at offset 0x2b8 address 0x401400:
>> +CHECK-NEXT:  [0x401400] CIE length=20
>> +CHECK-NEXT:    version: 1
>> +CHECK-NEXT:    augmentation: zR
>> +CHECK-NEXT:    code_alignment_factor: 1
>> +CHECK-NEXT:    data_alignment_factor: -8
>> +CHECK-NEXT:    return_address_register: 16
>> +
>> +CHECK:         Program:
>> +CHECK-NEXT:      DW_CFA_def_cfa: reg7 +8
>> +CHECK-NEXT:      DW_CFA_offset: reg16 -8
>> +CHECK-NEXT:      DW_CFA_undefined: reg16
>> +
>> +CHECK:       [0x401418] FDE length=20 cie=[0x401400]
>> +CHECK-NEXT:    initial_location: 0x4004d0
>> +CHECK-NEXT:    address_range: 0x2a (end : 0x4004fa)
>> +
>> +CHECK:         Program:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +
>> +CHECK:       [0x401430] CIE length=20
>> +CHECK-NEXT:    version: 1
>> +CHECK-NEXT:    augmentation: zR
>> +CHECK-NEXT:    code_alignment_factor: 1
>> +CHECK-NEXT:    data_alignment_factor: -8
>> +CHECK-NEXT:    return_address_register: 16
>> +
>> +CHECK:         Program:
>> +CHECK-NEXT:      DW_CFA_def_cfa: reg7 +8
>> +CHECK-NEXT:      DW_CFA_offset: reg16 -8
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +
>> +CHECK:       [0x401448] FDE length=36 cie=[0x401430]
>> +CHECK-NEXT:    initial_location: 0x4004a0
>> +CHECK-NEXT:    address_range: 0x20 (end : 0x4004c0)
>> +
>> +CHECK:         Program:
>> +CHECK-NEXT:      DW_CFA_def_cfa_offset: +16
>> +CHECK-NEXT:      DW_CFA_advance_loc: 6
>> +CHECK-NEXT:      DW_CFA_def_cfa_offset: +24
>> +CHECK-NEXT:      DW_CFA_advance_loc: 10
>> +CHECK-NEXT:      DW_CFA_def_cfa_expression: DW_OP_breg7 +8, DW_OP_breg16
>> +0, DW_OP_lit15, DW_OP_and, DW_OP_lit11, DW_OP_ge, DW_OP_lit3, DW_OP_shl,
>> DW_OP_plus
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +
>> +CHECK:       [0x401470] FDE length=28 cie=[0x401430]
>> +CHECK-NEXT:    initial_location: 0x4005b6
>> +CHECK-NEXT:    address_range: 0x10 (end : 0x4005c6)
>> +
>> +CHECK:         Program:
>> +CHECK-NEXT:      DW_CFA_advance_loc: 1
>> +CHECK-NEXT:      DW_CFA_def_cfa_offset: +16
>> +CHECK-NEXT:      DW_CFA_offset: reg6 -16
>> +CHECK-NEXT:      DW_CFA_advance_loc: 3
>> +CHECK-NEXT:      DW_CFA_def_cfa_register: reg6
>> +CHECK-NEXT:      DW_CFA_advance_loc: 11
>> +CHECK-NEXT:      DW_CFA_def_cfa: reg7 +8
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +
>> +CHECK:       [0x401490] FDE length=44 cie=[0x401430]
>> +CHECK-NEXT:    initial_location: 0x4005d0
>> +CHECK-NEXT:    address_range: 0xc7f (end : 0x40124f)
>> +
>> +CHECK:         Program:
>> +CHECK-NEXT:      DW_CFA_advance_loc: 5
>> +CHECK-NEXT:      DW_CFA_def_cfa: reg10 +0
>> +CHECK-NEXT:      DW_CFA_advance_loc: 9
>> +CHECK-NEXT:      DW_CFA_expression: reg6 DW_OP_breg6 +0
>> +CHECK-NEXT:      DW_CFA_advance_loc: 5
>> +CHECK-NEXT:      DW_CFA_def_cfa_expression: DW_OP_breg6 -8, DW_OP_deref
>> +CHECK-NEXT:      DW_CFA_advance_loc2: 3174
>> +CHECK-NEXT:      DW_CFA_def_cfa: reg10 +0
>> +CHECK-NEXT:      DW_CFA_advance_loc: 5
>> +CHECK-NEXT:      DW_CFA_def_cfa: reg7 +8
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +
>> +CHECK:       [0x4014c0] FDE length=44 cie=[0x401430]
>> +CHECK-NEXT:    initial_location: 0x401250
>> +CHECK-NEXT:    address_range: 0x66 (end : 0x4012b6)
>> +
>> +CHECK:         Program:
>> +CHECK-NEXT:      DW_CFA_advance_loc: 1
>> +CHECK-NEXT:      DW_CFA_def_cfa_offset: +16
>> +CHECK-NEXT:      DW_CFA_offset: reg6 -16
>> +CHECK-NEXT:      DW_CFA_advance_loc: 3
>> +CHECK-NEXT:      DW_CFA_def_cfa_register: reg6
>> +CHECK-NEXT:      DW_CFA_advance_loc: 2
>> +CHECK-NEXT:      DW_CFA_offset: reg15 -24
>> +CHECK-NEXT:      DW_CFA_advance_loc: 5
>> +CHECK-NEXT:      DW_CFA_offset: reg14 -32
>> +CHECK-NEXT:      DW_CFA_advance_loc: 7
>> +CHECK-NEXT:      DW_CFA_offset: reg13 -40
>> +CHECK-NEXT:      DW_CFA_offset: reg12 -48
>> +CHECK-NEXT:      DW_CFA_advance_loc: 8
>> +CHECK-NEXT:      DW_CFA_offset: reg3 -56
>> +CHECK-NEXT:      DW_CFA_advance_loc1: 75
>> +CHECK-NEXT:      DW_CFA_def_cfa: reg7 +8
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +
>> +CHECK:       [0x4014f0] FDE length=20 cie=[0x401430]
>> +CHECK-NEXT:    initial_location: 0x4012c0
>> +CHECK-NEXT:    address_range: 0x1 (end : 0x4012c1)
>> +
>> +CHECK:         Program:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>> +CHECK-NEXT:      DW_CFA_nop:
>>
>> Modified: llvm/trunk/tools/llvm-readobj/CMakeLists.txt
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/CMakeLists.txt?rev=326932&r1=326931&r2=326932&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/tools/llvm-readobj/CMakeLists.txt (original)
>> +++ llvm/trunk/tools/llvm-readobj/CMakeLists.txt Wed Mar  7 11:19:51 2018
>> @@ -1,5 +1,6 @@
>>  set(LLVM_LINK_COMPONENTS
>>    DebugInfoCodeView
>> +  DebugInfoDWARF
>>    Object
>>    BinaryFormat
>>    Support
>>
>> Added: llvm/trunk/tools/llvm-readobj/DwarfCFIEHPrinter.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/DwarfCFIEHPrinter.h?rev=326932&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/tools/llvm-readobj/DwarfCFIEHPrinter.h (added)
>> +++ llvm/trunk/tools/llvm-readobj/DwarfCFIEHPrinter.h Wed Mar  7 11:19:51
>> 2018
>> @@ -0,0 +1,244 @@
>> +//===--- DwarfCFIEHPrinter.h - DWARF-based Unwind Information Printer
>> -----===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H
>> +#define LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H
>> +
>> +#include "Error.h"
>> +#include "llvm/ADT/STLExtras.h"
>> +#include "llvm/BinaryFormat/Dwarf.h"
>> +#include "llvm/Object/ELF.h"
>> +#include "llvm/Object/ELFTypes.h"
>> +#include "llvm/Support/Casting.h"
>> +#include "llvm/Support/ScopedPrinter.h"
>> +#include "llvm/Support/Debug.h"
>> +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
>> +#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
>> +#include "llvm/Support/Endian.h"
>> +#include "llvm/Support/Format.h"
>> +#include "llvm/Support/type_traits.h"
>> +
>> +namespace llvm {
>> +namespace DwarfCFIEH {
>> +
>> +template <typename ELFT>
>> +class PrinterContext {
>> +  ScopedPrinter &W;
>> +  const object::ELFFile<ELFT> *Obj;
>> +
>> +  void printEHFrameHdr(uint64_t Offset, uint64_t Address, uint64_t Size)
>> const;
>> +
>> +  void printEHFrame(const typename ELFT::Shdr *EHFrameShdr) const;
>> +
>> +public:
>> +  PrinterContext(ScopedPrinter &W, const object::ELFFile<ELFT> *Obj)
>> +      : W(W), Obj(Obj) {}
>> +
>> +  void printUnwindInformation() const;
>> +};
>> +
>> +template <class ELFO>
>> +static const typename ELFO::Elf_Shdr *findSectionByAddress(const ELFO
>> *Obj,
>> +                                                           uint64_t
>> Addr) {
>> +  auto Sections = Obj->sections();
>> +  if (Error E = Sections.takeError())
>> +    reportError(toString(std::move(E)));
>> +
>> +  for (const auto &Shdr : *Sections)
>> +    if (Shdr.sh_addr == Addr)
>> +      return &Shdr;
>> +  return nullptr;
>> +}
>> +
>> +template <typename ELFT>
>> +void PrinterContext<ELFT>::printUnwindInformation() const {
>> +  const typename ELFT::Phdr *EHFramePhdr = nullptr;
>> +
>> +  auto PHs = Obj->program_headers();
>> +  if (Error E = PHs.takeError())
>> +    reportError(toString(std::move(E)));
>> +
>> +  for (const auto &Phdr : *PHs) {
>> +    if (Phdr.p_type == ELF::PT_GNU_EH_FRAME) {
>> +      EHFramePhdr = &Phdr;
>> +      if (Phdr.p_memsz != Phdr.p_filesz)
>> +        reportError("p_memsz does not match p_filesz for GNU_EH_FRAME");
>> +      break;
>> +    }
>> +  }
>> +
>> +  if (EHFramePhdr)
>> +    printEHFrameHdr(EHFramePhdr->p_offset, EHFramePhdr->p_vaddr,
>> +                    EHFramePhdr->p_memsz);
>> +
>> +  auto Sections = Obj->sections();
>> +  if (Error E = Sections.takeError())
>> +    reportError(toString(std::move(E)));
>> +
>> +  for (const auto &Shdr : *Sections) {
>> +    auto SectionName = Obj->getSectionName(&Shdr);
>> +    if (Error E = SectionName.takeError())
>> +      reportError(toString(std::move(E)));
>> +
>> +    if (*SectionName == ".eh_frame")
>> +      printEHFrame(&Shdr);
>> +  }
>> +}
>> +
>> +template <typename ELFT>
>> +void PrinterContext<ELFT>::printEHFrameHdr(uint64_t EHFrameHdrOffset,
>> +                                           uint64_t EHFrameHdrAddress,
>> +                                           uint64_t EHFrameHdrSize)
>> const {
>> +  ListScope L(W, "EH_FRAME Header");
>> +  W.startLine() << format("Address: 0x%" PRIx64 "\n", EHFrameHdrAddress);
>> +  W.startLine() << format("Offset: 0x%" PRIx64 "\n", EHFrameHdrOffset);
>> +  W.startLine() << format("Size: 0x%" PRIx64 "\n", EHFrameHdrSize);
>> +
>> +  const auto *EHFrameHdrShdr = findSectionByAddress(Obj,
>> EHFrameHdrAddress);
>> +  if (EHFrameHdrShdr) {
>> +    auto SectionName = Obj->getSectionName(EHFrameHdrShdr);
>> +    if (Error E = SectionName.takeError())
>> +      reportError(toString(std::move(E)));
>> +
>> +    W.printString("Corresponding Section", *SectionName);
>> +  }
>> +
>> +  DataExtractor DE(
>> +      StringRef(reinterpret_cast<const char *>(Obj->base()) +
>> EHFrameHdrOffset,
>> +                EHFrameHdrSize),
>> +      ELFT::TargetEndianness == support::endianness::little,
>> +      ELFT::Is64Bits ? 8 : 4);
>> +
>> +  DictScope D(W, "Header");
>> +  uint32_t Offset = 0;
>> +
>> +  auto Version = DE.getU8(&Offset);
>> +  W.printNumber("version", Version);
>> +  if (Version != 1)
>> +    reportError("only version 1 of .eh_frame_hdr is supported");
>> +
>> +  auto EHFramePtrEnc = DE.getU8(&Offset);
>> +  W.startLine() << format("eh_frame_ptr_enc: 0x%" PRIx64 "\n",
>> EHFramePtrEnc);
>> +  if (EHFramePtrEnc != (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4))
>> +    reportError("unexpected encoding eh_frame_ptr_enc");
>> +
>> +  auto FDECountEnc = DE.getU8(&Offset);
>> +  W.startLine() << format("fde_count_enc: 0x%" PRIx64 "\n", FDECountEnc);
>> +  if (FDECountEnc != dwarf::DW_EH_PE_udata4)
>> +    reportError("unexpected encoding fde_count_enc");
>> +
>> +  auto TableEnc = DE.getU8(&Offset);
>> +  W.startLine() << format("table_enc: 0x%" PRIx64 "\n", TableEnc);
>> +  if (TableEnc != (dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4))
>> +    reportError("unexpected encoding table_enc");
>> +
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180307/447f294f/attachment.html>


More information about the llvm-commits mailing list