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

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


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


More information about the llvm-commits mailing list