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

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


I reverted this change in r326953. Feel free to re-submit with a fix for
the broken test.


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

> 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/34772eba/attachment-0001.html>


More information about the llvm-commits mailing list