[PATCH] D43313: [DebugInfo] Support parsing DWARF expressions

Rafael Avila de Espindola via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 1 18:20:42 PST 2018


The handling of object files seems fine.

I will let someone familiar with lib/DebugInfo give the final LGTM.

Cheers,
Rafael

Rafael Auler via Phabricator via llvm-commits
<llvm-commits at lists.llvm.org> writes:

> rafauler updated this revision to Diff 136634.
> rafauler added a comment.
>
> Address rafael's comments
>
>
> Repository:
>   rL LLVM
>
> https://reviews.llvm.org/D43313
>
> Files:
>   include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
>   include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
>   include/llvm/DebugInfo/DWARF/DWARFExpression.h
>   include/llvm/Support/ScopedPrinter.h
>   lib/DebugInfo/DWARF/DWARFContext.cpp
>   lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
>   lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
>   lib/DebugInfo/DWARF/DWARFExpression.cpp
>   test/tools/llvm-readobj/Inputs/trivial.exe.elf-x86-64
>   test/tools/llvm-readobj/unwind.test
>   tools/llvm-readobj/CMakeLists.txt
>   tools/llvm-readobj/DwarfCFIEHPrinter.h
>   tools/llvm-readobj/ELFDumper.cpp
>
> Index: tools/llvm-readobj/ELFDumper.cpp
> ===================================================================
> --- tools/llvm-readobj/ELFDumper.cpp
> +++ tools/llvm-readobj/ELFDumper.cpp
> @@ -13,6 +13,7 @@
>  //===----------------------------------------------------------------------===//
>  
>  #include "ARMEHABIPrinter.h"
> +#include "DwarfCFIEHPrinter.h"
>  #include "Error.h"
>  #include "ObjDumper.h"
>  #include "StackMapPrinter.h"
> @@ -1808,6 +1809,11 @@
>  
>  template<class ELFT>
>  void ELFDumper<ELFT>::printUnwindInfo() {
> +  const unsigned Machine = Obj->getHeader()->e_machine;
> +  if (Machine == EM_386 || Machine == EM_X86_64) {
> +    DwarfCFIEH::PrinterContext<ELFT> Ctx(W, Obj);
> +    return Ctx.printUnwindInformation();
> +  }
>    W.startLine() << "UnwindInfo not implemented.\n";
>  }
>  
> Index: tools/llvm-readobj/DwarfCFIEHPrinter.h
> ===================================================================
> --- /dev/null
> +++ tools/llvm-readobj/DwarfCFIEHPrinter.h
> @@ -0,0 +1,246 @@
> +//===--- 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);
> +  }
> +
> +  StringRef EHFrameHdrContents(
> +      reinterpret_cast<const char *>(Obj->base()) + EHFrameHdrOffset,
> +      EHFrameHdrSize);
> +  constexpr bool IsLittleEndian =
> +      (ELFT::TargetEndianness == support::endianness::little);
> +  constexpr uint8_t AddressSize = ELFT::Is64Bits ? 8 : 4;
> +  DataExtractor DE(EHFrameHdrContents, IsLittleEndian, AddressSize);
> +
> +  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");
> +
> +  auto EHFramePtr = DE.getSigned(&Offset, 4) + EHFrameHdrAddress + 4;
> +  W.startLine() << format("eh_frame_ptr: 0x%" PRIx64 "\n", EHFramePtr);
> +
> +  auto FDECount = DE.getUnsigned(&Offset, 4);
> +  W.printNumber("fde_count", FDECount);
> +
> +  unsigned NumEntries = 0;
> +  uint64_t PrevPC = 0;
> +  while (Offset + 8 <= EHFrameHdrSize && NumEntries < FDECount) {
> +    DictScope D(W, std::string("entry ")  + std::to_string(NumEntries));
> +
> +    auto InitialPC = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;
> +    W.startLine() << format("initial_location: 0x%" PRIx64 "\n", InitialPC);
> +    auto Address = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;
> +    W.startLine() << format("address: 0x%" PRIx64 "\n", Address);
> +
> +    if (InitialPC < PrevPC)
> +      reportError("initial_location is out of order");
> +
> +    PrevPC = InitialPC;
> +    ++NumEntries;
> +  }
> +}
> +
> +template <typename ELFT>
> +void PrinterContext<ELFT>::printEHFrame(
> +    const typename ELFT::Shdr *EHFrameShdr) const {
> +  uint64_t Address = EHFrameShdr->sh_addr;
> +  uint64_t ShOffset = EHFrameShdr->sh_offset;
> +  W.startLine() << format(".eh_frame section at offset 0x%" PRIx64
> +                          " address 0x%" PRIx64 ":\n",
> +                          ShOffset, Address);
> +  W.indent();
> +
> +  auto Result = Obj->getSectionContents(EHFrameShdr);
> +  if (Error E = Result.takeError())
> +    reportError(toString(std::move(E)));
> +
> +  auto Contents = Result.get();
> +  DWARFDataExtractor DE(
> +      StringRef(reinterpret_cast<const char *>(Contents.data()),
> +                Contents.size()),
> +      ELFT::TargetEndianness == support::endianness::little,
> +      ELFT::Is64Bits ? 8 : 4);
> +  DWARFDebugFrame EHFrame(/*IsEH=*/true, /*EHFrameAddress=*/Address);
> +  EHFrame.parse(DE);
> +
> +  for (const auto &Entry : EHFrame) {
> +    if (const auto *CIE = dyn_cast<dwarf::CIE>(&Entry)) {
> +      W.startLine() << format("[0x%" PRIx64 "] CIE length=%" PRIu64 "\n",
> +                              Address + CIE->getOffset(),
> +                              CIE->getLength());
> +      W.indent();
> +
> +      W.printNumber("version", CIE->getVersion());
> +      W.printString("augmentation", CIE->getAugmentationString());
> +      W.printNumber("code_alignment_factor", CIE->getCodeAlignmentFactor());
> +      W.printNumber("data_alignment_factor", CIE->getDataAlignmentFactor());
> +      W.printNumber("return_address_register", CIE->getReturnAddressRegister());
> +
> +      W.getOStream() << "\n";
> +      W.startLine() << "Program:\n";
> +      W.indent();
> +      CIE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel());
> +      W.unindent();
> +
> +      W.unindent();
> +      W.getOStream() << "\n";
> +
> +    } else if (const auto *FDE = dyn_cast<dwarf::FDE>(&Entry)) {
> +      W.startLine() << format("[0x%" PRIx64 "] FDE length=%" PRIu64
> +                              " cie=[0x%" PRIx64 "]\n",
> +                              Address + FDE->getOffset(),
> +                              FDE->getLength(),
> +                              Address + FDE->getLinkedCIE()->getOffset());
> +      W.indent();
> +
> +      W.startLine() << format("initial_location: 0x%" PRIx64 "\n",
> +                              FDE->getInitialLocation());
> +      W.startLine()
> +        << format("address_range: 0x%" PRIx64 " (end : 0x%" PRIx64 ")\n",
> +                  FDE->getAddressRange(),
> +                  FDE->getInitialLocation() + FDE->getAddressRange());
> +
> +      W.getOStream() << "\n";
> +      W.startLine() << "Program:\n";
> +      W.indent();
> +      FDE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel());
> +      W.unindent();
> +
> +      W.unindent();
> +      W.getOStream() << "\n";
> +    } else {
> +      llvm_unreachable("unexpected DWARF frame kind");
> +    }
> +  }
> +
> +  W.unindent();
> +}
> +
> +}
> +}
> +
> +#endif
> Index: tools/llvm-readobj/CMakeLists.txt
> ===================================================================
> --- tools/llvm-readobj/CMakeLists.txt
> +++ tools/llvm-readobj/CMakeLists.txt
> @@ -1,5 +1,6 @@
>  set(LLVM_LINK_COMPONENTS
>    DebugInfoCodeView
> +  DebugInfoDWARF
>    Object
>    BinaryFormat
>    Support
> Index: test/tools/llvm-readobj/unwind.test
> ===================================================================
> --- /dev/null
> +++ test/tools/llvm-readobj/unwind.test
> @@ -0,0 +1,169 @@
> +RUN: llvm-readobj -unwind %p/Inputs/trivial.exe.elf-x86-64 | FileCheck %s
> +
> +CHECK:      EH_FRAME Header [
> +CHECK-NEXT:  Address: 0x4013c0
> +CHECK-NEXT:  Offset: 0x13c0
> +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 0x1400 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:
> Index: lib/DebugInfo/DWARF/DWARFExpression.cpp
> ===================================================================
> --- lib/DebugInfo/DWARF/DWARFExpression.cpp
> +++ lib/DebugInfo/DWARF/DWARFExpression.cpp
> @@ -258,9 +258,10 @@
>    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));
> Index: lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
> ===================================================================
> --- lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
> +++ lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
> @@ -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 @@
>        // 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>(
> +            "Impossible 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 @@
>            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 @@
>    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 @@
>      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 @@
>    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 @@
>    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 @@
>  
>      // 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 @@
>        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 @@
>                  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,33 +452,36 @@
>          }
>        }
>  
> -      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 {
>        // FDE
>        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) {
>          // The address size is encoded in the CIE we reference.
>          if (!Cie)
>            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 @@
>              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 @@
>  
>        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 @@
>    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);
>  }
> Index: lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
> ===================================================================
> --- lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
> +++ lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
> @@ -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 @@
>      *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;
> +}
> Index: lib/DebugInfo/DWARF/DWARFContext.cpp
> ===================================================================
> --- lib/DebugInfo/DWARF/DWARFContext.cpp
> +++ lib/DebugInfo/DWARF/DWARFContext.cpp
> @@ -349,11 +349,11 @@
>  
>    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 @@
>    // 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 @@
>    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();
> Index: include/llvm/Support/ScopedPrinter.h
> ===================================================================
> --- include/llvm/Support/ScopedPrinter.h
> +++ include/llvm/Support/ScopedPrinter.h
> @@ -80,6 +80,8 @@
>  
>    void resetIndent() { IndentLevel = 0; }
>  
> +  int getIndentLevel() { return IndentLevel; }
> +
>    void setPrefix(StringRef P) { Prefix = P; }
>  
>    void printIndent() {
> Index: include/llvm/DebugInfo/DWARF/DWARFExpression.h
> ===================================================================
> --- include/llvm/DebugInfo/DWARF/DWARFExpression.h
> +++ include/llvm/DebugInfo/DWARF/DWARFExpression.h
> @@ -93,12 +93,13 @@
>  
>    /// 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 @@
>      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;
> Index: include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
> ===================================================================
> --- include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
> +++ include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
> @@ -10,40 +10,280 @@
>  #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 instructions that, when read in order,
> +/// construct a table mapping PC to frame state.
> +class CFIProgram {
> +public:
> +  /// Types of operands to CFI instructions.
> +  enum OperandType {
> +    OT_Unset,
> +    OT_None,
> +    OT_Address,
> +    OT_Offset,
> +    OT_FactoredCodeOffset,
> +    OT_SignedFactDataOffset,
> +    OT_UnsignedFactDataOffset,
> +    OT_Register,
> +    OT_Expression
> +  };
> +
> +  typedef std::vector<uint64_t> 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);
> +  }
> +
> +  /// Retrieve the array describing the types of operands.
> +  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
> Index: include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
> ===================================================================
> --- include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
> +++ include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
> @@ -44,6 +44,13 @@
>    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
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list