[BOLT rebase] Rebase fixes on top of LLVM Feb2018

Summary:
This commit includes all code necessary to make BOLT working again
after the rebase. This includes a redesign of the EHFrame work,
cherry-pick of the 3dnow disassembly work, compilation error fixes,
and port of the debug_info work. The macroop fusion feature is not
ported yet.

The rebased version has minor changes to the "executed instructions"
dynostats counter because REP prefixes are considered a part of the
instruction it applies to. Also, some X86 instructions had the "mayLoad"
tablegen property removed, which BOLT  uses to identify and account
for loads, thus reducing the total number of loads reported by
dynostats. This was observed in X86::MOVDQUmr. TRAP instructions are
not terminators anymore, changing our CFG. This commit adds compensation
to preserve this old behavior and minimize tests changes. debug_info
sections are now slightly larger. The discriminator field in the line
table is slightly different due to a change upstream. New profiles
generated with the other bolt are incompatible with this version
because of different hash values calculated for functions, so they will
be considered 100% stale. This commit changes the corresponding test
to XFAIL so it can be updated. The hash function changes because it
relies on raw opcode values, which change according to the opcodes
described in the X86 tablegen files. When processing HHVM, bolt was
observed to be using about 800MB more memory in the rebased version
and being about 5% slower.

(cherry picked from FBD7078072)
diff --git a/bolt/BinaryBasicBlock.h b/bolt/BinaryBasicBlock.h
index 90b4f11..431a8bd 100644
--- a/bolt/BinaryBasicBlock.h
+++ b/bolt/BinaryBasicBlock.h
@@ -804,6 +804,11 @@
     LayoutIndex = Index;
   }
 
+  /// FIXME
+  BinaryFunction *getParent() const {
+    return nullptr;
+  }
+
 private:
   void adjustNumPseudos(const MCInst &Inst, int Sign);
 
@@ -850,57 +855,57 @@
 
 // GraphTraits specializations for basic block graphs (CFGs)
 template <> struct GraphTraits<bolt::BinaryBasicBlock *> {
-  using NodeType = bolt::BinaryBasicBlock;
+  using NodeRef = bolt::BinaryBasicBlock *;
   using ChildIteratorType = bolt::BinaryBasicBlock::succ_iterator;
 
-  static NodeType *getEntryNode(bolt::BinaryBasicBlock *BB) { return BB; }
-  static inline ChildIteratorType child_begin(NodeType *N) {
+  static NodeRef getEntryNode(bolt::BinaryBasicBlock *BB) { return BB; }
+  static inline ChildIteratorType child_begin(NodeRef N) {
     return N->succ_begin();
   }
-  static inline ChildIteratorType child_end(NodeType *N) {
+  static inline ChildIteratorType child_end(NodeRef N) {
     return N->succ_end();
   }
 };
 
 template <> struct GraphTraits<const bolt::BinaryBasicBlock *> {
-  using NodeType = const bolt::BinaryBasicBlock;
+  using NodeRef = const bolt::BinaryBasicBlock *;
   using ChildIteratorType = bolt::BinaryBasicBlock::const_succ_iterator;
 
-  static NodeType *getEntryNode(const bolt::BinaryBasicBlock *BB) {
+  static NodeRef getEntryNode(const bolt::BinaryBasicBlock *BB) {
     return BB;
   }
-  static inline ChildIteratorType child_begin(NodeType *N) {
+  static inline ChildIteratorType child_begin(NodeRef N) {
     return N->succ_begin();
   }
-  static inline ChildIteratorType child_end(NodeType *N) {
+  static inline ChildIteratorType child_end(NodeRef N) {
     return N->succ_end();
   }
 };
 
 template <> struct GraphTraits<Inverse<bolt::BinaryBasicBlock *>> {
-  using NodeType = bolt::BinaryBasicBlock;
+  using NodeRef = bolt::BinaryBasicBlock *;
   using ChildIteratorType = bolt::BinaryBasicBlock::pred_iterator;
-  static NodeType *getEntryNode(Inverse<bolt::BinaryBasicBlock *> G) {
+  static NodeRef getEntryNode(Inverse<bolt::BinaryBasicBlock *> G) {
     return G.Graph;
   }
-  static inline ChildIteratorType child_begin(NodeType *N) {
+  static inline ChildIteratorType child_begin(NodeRef N) {
     return N->pred_begin();
   }
-  static inline ChildIteratorType child_end(NodeType *N) {
+  static inline ChildIteratorType child_end(NodeRef N) {
     return N->pred_end();
   }
 };
 
 template <> struct GraphTraits<Inverse<const bolt::BinaryBasicBlock *>> {
-  using NodeType = const bolt::BinaryBasicBlock;
+  using NodeRef = const bolt::BinaryBasicBlock *;
   using ChildIteratorType = bolt::BinaryBasicBlock::const_pred_iterator;
-  static NodeType *getEntryNode(Inverse<const bolt::BinaryBasicBlock *> G) {
+  static NodeRef getEntryNode(Inverse<const bolt::BinaryBasicBlock *> G) {
     return G.Graph;
   }
-  static inline ChildIteratorType child_begin(NodeType *N) {
+  static inline ChildIteratorType child_begin(NodeRef N) {
     return N->pred_begin();
   }
-  static inline ChildIteratorType child_end(NodeType *N) {
+  static inline ChildIteratorType child_end(NodeRef N) {
     return N->pred_end();
   }
 };
diff --git a/bolt/BinaryContext.cpp b/bolt/BinaryContext.cpp
index 337f439..363139c 100644
--- a/bolt/BinaryContext.cpp
+++ b/bolt/BinaryContext.cpp
@@ -15,6 +15,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 #include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/Support/CommandLine.h"
@@ -48,10 +49,11 @@
 
 BinaryContext::~BinaryContext() { }
 
-MCObjectWriter *BinaryContext::createObjectWriter(raw_pwrite_stream &OS) {
+std::unique_ptr<MCObjectWriter>
+BinaryContext::createObjectWriter(raw_pwrite_stream &OS) {
   if (!MAB) {
     MAB = std::unique_ptr<MCAsmBackend>(
-        TheTarget->createMCAsmBackend(*MRI, TripleName, ""));
+        TheTarget->createMCAsmBackend(*STI, *MRI, MCTargetOptions()));
   }
 
   return MAB->createObjectWriter(OS);
@@ -148,21 +150,20 @@
 /// Recursively finds DWARF DW_TAG_subprogram DIEs and match them with
 /// BinaryFunctions. Record DIEs for unknown subprograms (mostly functions that
 /// are never called and removed from the binary) in Unknown.
-void findSubprograms(DWARFCompileUnit *Unit,
-                     const DWARFDebugInfoEntryMinimal *DIE,
+void findSubprograms(const DWARFDie DIE,
                      std::map<uint64_t, BinaryFunction> &BinaryFunctions) {
-  if (DIE->isSubprogramDIE()) {
+  if (DIE.isSubprogramDIE()) {
     // TODO: handle DW_AT_ranges.
-    uint64_t LowPC, HighPC;
-    if (DIE->getLowAndHighPC(Unit, LowPC, HighPC)) {
+    uint64_t LowPC, HighPC, SectionIndex;
+    if (DIE.getLowAndHighPC(LowPC, HighPC, SectionIndex)) {
       auto It = BinaryFunctions.find(LowPC);
       if (It != BinaryFunctions.end()) {
-        It->second.addSubprogramDIE(Unit, DIE);
+        It->second.addSubprogramDIE(DIE);
       } else {
         // The function must have been optimized away by GC.
       }
     } else {
-      const auto RangesVector = DIE->getAddressRanges(Unit);
+      const auto RangesVector = DIE.getAddressRanges();
       if (!RangesVector.empty()) {
         errs() << "BOLT-ERROR: split function detected in .debug_info. "
                   "Split functions are not supported.\n";
@@ -171,10 +172,9 @@
     }
   }
 
-  for (auto ChildDIE = DIE->getFirstChild();
-       ChildDIE != nullptr && !ChildDIE->isNULL();
-       ChildDIE = ChildDIE->getSibling()) {
-    findSubprograms(Unit, ChildDIE, BinaryFunctions);
+  for (auto ChildDIE = DIE.getFirstChild(); ChildDIE && !ChildDIE.isNULL();
+       ChildDIE = ChildDIE.getSibling()) {
+    findSubprograms(ChildDIE, BinaryFunctions);
   }
 }
 
@@ -190,10 +190,13 @@
   // means empty dir.
   assert(FileIndex > 0 && FileIndex <= FileNames.size() &&
          "FileIndex out of range for the compilation unit.");
-  const char *Dir = FileNames[FileIndex - 1].DirIdx ?
-    LineTable->Prologue.IncludeDirectories[FileNames[FileIndex - 1].DirIdx - 1] :
-    "";
-  return Ctx->getDwarfFile(Dir, FileNames[FileIndex - 1].Name, 0, DestCUID);
+  StringRef Dir =
+      FileNames[FileIndex - 1].DirIdx
+          ? LineTable->Prologue
+                .IncludeDirectories[FileNames[FileIndex - 1].DirIdx - 1]
+          : "";
+  return Ctx->getDwarfFile(Dir, FileNames[FileIndex - 1].Name, 0, nullptr,
+                           DestCUID);
 }
 
 std::vector<BinaryFunction *> BinaryContext::getSortedFunctions(
@@ -221,22 +224,23 @@
   // Populate MCContext with DWARF files.
   for (const auto &CU : DwCtx->compile_units()) {
     const auto CUID = CU->getOffset();
-    auto LineTable = DwCtx->getLineTableForUnit(CU.get());
+    auto *LineTable = DwCtx->getLineTableForUnit(CU.get());
     const auto &FileNames = LineTable->Prologue.FileNames;
     for (size_t I = 0, Size = FileNames.size(); I != Size; ++I) {
       // Dir indexes start at 1, as DWARF file numbers, and a dir index 0
       // means empty dir.
-      const char *Dir = FileNames[I].DirIdx ?
-          LineTable->Prologue.IncludeDirectories[FileNames[I].DirIdx - 1] :
-          "";
-      Ctx->getDwarfFile(Dir, FileNames[I].Name, 0, CUID);
+      StringRef Dir =
+          FileNames[I].DirIdx
+              ? LineTable->Prologue.IncludeDirectories[FileNames[I].DirIdx - 1]
+              : "";
+      Ctx->getDwarfFile(Dir, FileNames[I].Name, 0, nullptr, CUID);
     }
   }
 
   // For each CU, iterate over its children DIEs and match subprogram DIEs to
   // BinaryFunctions.
   for (auto &CU : DwCtx->compile_units()) {
-    findSubprograms(CU.get(), CU->getUnitDIE(false), BinaryFunctions);
+    findSubprograms(CU->getUnitDIE(false), BinaryFunctions);
   }
 
   // Some functions may not have a corresponding subprogram DIE
@@ -250,8 +254,8 @@
     if (auto DebugAranges = DwCtx->getDebugAranges()) {
       auto CUOffset = DebugAranges->findAddress(FunctionAddress);
       if (CUOffset != -1U) {
-        Function.addSubprogramDIE(DwCtx->getCompileUnitForOffset(CUOffset),
-                                  nullptr);
+        Function.addSubprogramDIE(
+            DWARFDie(DwCtx->getCompileUnitForOffset(CUOffset), nullptr));
         continue;
       }
     }
@@ -266,7 +270,7 @@
       for (const auto &Range : CUDie->getAddressRanges(CU.get())) {
         if (FunctionAddress >= Range.first &&
             FunctionAddress < Range.second) {
-          Function.addSubprogramDIE(CU.get(), nullptr);
+          Function.addSubprogramDIE(DWARFDie(CU.get(), nullptr));
           break;
         }
       }
@@ -495,7 +499,7 @@
   StringRef SectionContents = Section->getContents();
   DataExtractor DE(SectionContents,
                    AsmInfo->isLittleEndian(),
-                   AsmInfo->getPointerSize());
+                   AsmInfo->getCodePointerSize());
   uint32_t SectionOffset = Address - Section->getAddress();
   return DE.getAddress(&SectionOffset);
 }
diff --git a/bolt/BinaryContext.h b/bolt/BinaryContext.h
index ad8150c..c906716 100644
--- a/bolt/BinaryContext.h
+++ b/bolt/BinaryContext.h
@@ -23,7 +23,7 @@
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCCodeEmitter.h"
 #include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCDisassembler/MCDisassembler.h"
 #include "llvm/MC/MCInstPrinter.h"
 #include "llvm/MC/MCInstrAnalysis.h"
 #include "llvm/MC/MCInstrInfo.h"
@@ -189,7 +189,7 @@
 
   ~BinaryContext();
 
-  MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS);
+  std::unique_ptr<MCObjectWriter> createObjectWriter(raw_pwrite_stream &OS);
 
   /// Return a global symbol registered at a given \p Address. If no symbol
   /// exists, create one with unique name using \p Prefix.
diff --git a/bolt/BinaryFunction.cpp b/bolt/BinaryFunction.cpp
index 1e20509..3e9c7fe 100644
--- a/bolt/BinaryFunction.cpp
+++ b/bolt/BinaryFunction.cpp
@@ -90,8 +90,7 @@
                  "function execution frequency"),
       clEnumValN(JTS_AGGRESSIVE, "aggressive",
                  "aggressively split jump tables section based on usage "
-                 "of the tables"),
-      clEnumValEnd),
+                 "of the tables")),
   cl::ZeroOrMore,
   cl::cat(BoltOptCategory));
 
@@ -163,7 +162,8 @@
 
 constexpr const char *DynoStats::Desc[];
 constexpr unsigned BinaryFunction::MinAlign;
-const char BinaryFunction::TimerGroupName[] = "Build binary functions";
+const char BinaryFunction::TimerGroupName[] = "buildfuncs";
+const char BinaryFunction::TimerGroupDesc[] = "Build Binary Functions";
 
 namespace {
 
@@ -485,7 +485,7 @@
       OS << '\n';
     }
 
-    Offset = RoundUpToAlignment(Offset, BB->getAlignment());
+    Offset = alignTo(Offset, BB->getAlignment());
 
     // Note: offsets are imprecise since this is happening prior to relaxation.
     Offset = BC.printInstructions(OS, BB->begin(), BB->end(), Offset, this);
@@ -605,7 +605,7 @@
 IndirectBranchType BinaryFunction::processIndirectBranch(MCInst &Instruction,
                                                          unsigned Size,
                                                          uint64_t Offset) {
-  const auto PtrSize = BC.AsmInfo->getPointerSize();
+  const auto PtrSize = BC.AsmInfo->getCodePointerSize();
 
   // An instruction referencing memory used by jump instruction (directly or
   // via register). This location could be an array of function pointers
@@ -869,7 +869,8 @@
 }
 
 void BinaryFunction::disassemble(ArrayRef<uint8_t> FunctionData) {
-  NamedRegionTimer T("disassemble", TimerGroupName, opts::TimeBuild);
+  NamedRegionTimer T("disassemble", "Disassemble function", TimerGroupName,
+                     TimerGroupDesc, opts::TimeBuild);
 
   assert(FunctionData.size() == getSize() &&
          "function size does not match raw data size");
@@ -1435,7 +1436,8 @@
 }
 
 bool BinaryFunction::buildCFG() {
-  NamedRegionTimer T("build cfg", TimerGroupName, opts::TimeBuild);
+  NamedRegionTimer T("buildcfg", "Build CFG", TimerGroupName, TimerGroupDesc,
+                     opts::TimeBuild);
   auto &MIA = BC.MIA;
 
   if (!isSimple()) {
@@ -2073,8 +2075,6 @@
       Streamer.EmitCodeAlignment(BB->getAlignment());
     Streamer.EmitLabel(BB->getLabel());
 
-    // Remember if last instruction emitted was a prefix
-    bool LastIsPrefix = false;
     SMLoc LastLocSeen;
     for (auto I = BB->begin(), E = BB->end(); I != E; ++I) {
       auto &Instr = *I;
@@ -2105,7 +2105,6 @@
       }
 
       Streamer.EmitInstruction(Instr, *BC.STI);
-      LastIsPrefix = BC.MIA->isPrefix(Instr);
     }
   }
 
@@ -3129,10 +3128,9 @@
                                   uint64_t SymbolSize) const {
   // For aarch64, the ABI defines mapping symbols so we identify data in the
   // code section (see IHI0056B). $d identifies a symbol starting data contents.
-  if (BC.TheTriple->getArch() == llvm::Triple::aarch64 &&
-      Symbol.getType() == SymbolRef::ST_Unknown &&
-      SymbolSize == 0 &&
-      (!Symbol.getName().getError() && *Symbol.getName() == "$d"))
+  if (BC.TheTriple->getArch() == llvm::Triple::aarch64 && Symbol.getType() &&
+      cantFail(Symbol.getType()) == SymbolRef::ST_Unknown && SymbolSize == 0 &&
+      Symbol.getName() && cantFail(Symbol.getName()) == "$d")
     return true;
   return false;
 }
@@ -3142,10 +3140,9 @@
   // For aarch64, the ABI defines mapping symbols so we identify data in the
   // code section (see IHI0056B). $x identifies a symbol starting code or the
   // end of a data chunk inside code.
-  if (BC.TheTriple->getArch() == llvm::Triple::aarch64 &&
-      Symbol.getType() == SymbolRef::ST_Unknown &&
-      SymbolSize == 0 &&
-      (!Symbol.getName().getError() && *Symbol.getName() == "$x"))
+  if (BC.TheTriple->getArch() == llvm::Triple::aarch64 && Symbol.getType() &&
+      cantFail(Symbol.getType()) == SymbolRef::ST_Unknown && SymbolSize == 0 &&
+      Symbol.getName() && cantFail(Symbol.getName()) == "$x")
     return true;
   return false;
 }
@@ -3159,10 +3156,10 @@
 
   // It's okay to have a zero-sized symbol in the middle of non-zero-sized
   // function.
-  if (SymbolSize == 0 && containsAddress(*Symbol.getAddress()))
+  if (SymbolSize == 0 && containsAddress(cantFail(Symbol.getAddress())))
     return true;
 
-  if (Symbol.getType() != SymbolRef::ST_Unknown)
+  if (cantFail(Symbol.getType()) != SymbolRef::ST_Unknown)
     return false;
 
   if (Symbol.getFlags() & SymbolRef::SF_Global)
@@ -3413,8 +3410,8 @@
 
 void BinaryFunction::calculateLoopInfo() {
   // Discover loops.
-  BinaryDominatorTree DomTree(false);
-  DomTree.recalculate<BinaryFunction>(*this);
+  BinaryDominatorTree DomTree;
+  DomTree.recalculate(*this);
   BLI.reset(new BinaryLoopInfo());
   BLI->analyze(DomTree);
 
@@ -3531,15 +3528,15 @@
   uint64_t PrevEndAddress = 0;
   DWARFAddressRangesVector OutputRanges;
   for (const auto &Range : InputRanges) {
-    if (!containsAddress(Range.first)) {
+    if (!containsAddress(Range.LowPC)) {
       DEBUG(dbgs() << "BOLT-DEBUG: invalid debug address range detected for "
-                   << *this << " : [0x" << Twine::utohexstr(Range.first)
-                   << ", 0x" << Twine::utohexstr(Range.second) << "]\n");
+                   << *this << " : [0x" << Twine::utohexstr(Range.LowPC)
+                   << ", 0x" << Twine::utohexstr(Range.HighPC) << "]\n");
       PrevEndAddress = 0;
       continue;
     }
-    auto InputOffset = Range.first - getAddress();
-    const auto InputEndOffset = std::min(Range.second - getAddress(), getSize());
+    auto InputOffset = Range.LowPC - getAddress();
+    const auto InputEndOffset = std::min(Range.HighPC - getAddress(), getSize());
 
     auto BBI = std::upper_bound(BasicBlockOffsets.begin(),
                                 BasicBlockOffsets.end(),
@@ -3550,8 +3547,8 @@
       const auto *BB = BBI->second;
       if (InputOffset < BB->getOffset() || InputOffset >= BB->getEndOffset()) {
         DEBUG(dbgs() << "BOLT-DEBUG: invalid debug address range detected for "
-                     << *this << " : [0x" << Twine::utohexstr(Range.first)
-                     << ", 0x" << Twine::utohexstr(Range.second) << "]\n");
+                     << *this << " : [0x" << Twine::utohexstr(Range.LowPC)
+                     << ", 0x" << Twine::utohexstr(Range.HighPC) << "]\n");
         PrevEndAddress = 0;
         break;
       }
@@ -3564,13 +3561,13 @@
           EndAddress = StartAddress + InputEndOffset - InputOffset;
 
         if (StartAddress == PrevEndAddress) {
-          OutputRanges.back().second = std::max(OutputRanges.back().second,
+          OutputRanges.back().HighPC = std::max(OutputRanges.back().HighPC,
                                                 EndAddress);
         } else {
           OutputRanges.emplace_back(StartAddress,
                                     std::max(StartAddress, EndAddress));
         }
-        PrevEndAddress = OutputRanges.back().second;
+        PrevEndAddress = OutputRanges.back().HighPC;
       }
 
       InputOffset = BB->getEndOffset();
@@ -3583,13 +3580,13 @@
   DWARFAddressRangesVector MergedRanges;
   PrevEndAddress = 0;
   for(const auto &Range : OutputRanges) {
-    if (Range.first <= PrevEndAddress) {
-      MergedRanges.back().second = std::max(MergedRanges.back().second,
-                                            Range.second);
+    if (Range.LowPC <= PrevEndAddress) {
+      MergedRanges.back().HighPC = std::max(MergedRanges.back().HighPC,
+                                            Range.HighPC);
     } else {
-      MergedRanges.emplace_back(Range.first, Range.second);
+      MergedRanges.emplace_back(Range.LowPC, Range.HighPC);
     }
-    PrevEndAddress = MergedRanges.back().second;
+    PrevEndAddress = MergedRanges.back().HighPC;
   }
 
   return MergedRanges;
@@ -3619,27 +3616,28 @@
 
 DWARFDebugLoc::LocationList BinaryFunction::translateInputToOutputLocationList(
       const DWARFDebugLoc::LocationList &InputLL,
-      uint64_t BaseAddress) const {
+      BaseAddress BaseAddr) const {
+  uint64_t BAddr = BaseAddr.Address;
   // If the function wasn't changed - there's nothing to update.
   if (!isEmitted() && !BC.HasRelocations) {
-    if (!BaseAddress) {
+    if (!BAddr) {
       return InputLL;
     } else {
       auto OutputLL = std::move(InputLL);
       for (auto &Entry : OutputLL.Entries) {
-        Entry.Begin += BaseAddress;
-        Entry.End += BaseAddress;
+        Entry.Begin += BAddr;
+        Entry.End += BAddr;
       }
       return OutputLL;
     }
   }
 
   uint64_t PrevEndAddress = 0;
-  SmallVectorImpl<unsigned char> *PrevLoc = nullptr;
+  SmallVectorImpl<char> *PrevLoc = nullptr;
   DWARFDebugLoc::LocationList OutputLL;
   for (auto &Entry : InputLL.Entries) {
-    const auto Start = Entry.Begin + BaseAddress;
-    const auto End = Entry.End + BaseAddress;
+    const auto Start = Entry.Begin + BAddr;
+    const auto End = Entry.End + BAddr;
     if (!containsAddress(Start)) {
       DEBUG(dbgs() << "BOLT-DEBUG: invalid debug address range detected for "
                    << *this << " : [0x" << Twine::utohexstr(Start)
diff --git a/bolt/BinaryFunction.h b/bolt/BinaryFunction.h
index 88546fe..43985de 100644
--- a/bolt/BinaryFunction.h
+++ b/bolt/BinaryFunction.h
@@ -24,9 +24,10 @@
 #include "DebugData.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/ilist.h"
+#include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/MC/MCCodeEmitter.h"
 #include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCDisassembler/MCDisassembler.h"
 #include "llvm/MC/MCDwarf.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstrAnalysis.h"
@@ -34,7 +35,6 @@
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/Debug.h"
-#include "llvm/Support/Dwarf.h"
 #include "llvm/Support/raw_ostream.h"
 #include <limits>
 #include <unordered_map>
@@ -45,14 +45,14 @@
 
 namespace llvm {
 
-class DWARFCompileUnit;
+class DWARFUnit;
 class DWARFDebugInfoEntryMinimal;
 
 namespace bolt {
 
 struct SectionInfo;
 
-using DWARFUnitLineTable = std::pair<DWARFCompileUnit *,
+using DWARFUnitLineTable = std::pair<DWARFUnit *,
                                      const DWARFDebugLine::LineTable *>;
 
 /// Class encapsulating runtime statistics about an execution unit.
@@ -233,6 +233,7 @@
   static constexpr unsigned MinAlign = 2;
 
   static const char TimerGroupName[];
+  static const char TimerGroupDesc[];
 
   using BasicBlockOrderType = std::vector<BinaryBasicBlock *>;
 
@@ -345,8 +346,7 @@
 
   /// Associated DIEs in the .debug_info section with their respective CUs.
   /// There can be multiple because of identical code folding.
-  std::vector<std::pair<const DWARFDebugInfoEntryMinimal *,
-                        DWARFCompileUnit *>> SubprogramDIEs;
+  std::vector<DWARFDie> SubprogramDIEs;
 
   /// Line table for the function with containing compilation unit.
   /// Because of identical code folding the function could have multiple
@@ -1235,11 +1235,11 @@
     case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
     case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
     case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
-    case ELF::R_AARCH64_TLSDESC_LD64_LO12_NC:
+    case ELF::R_AARCH64_TLSDESC_LD64_LO12:
     case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
     case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
     case ELF::R_AARCH64_LD64_GOT_LO12_NC:
-    case ELF::R_AARCH64_TLSDESC_ADD_LO12_NC:
+    case ELF::R_AARCH64_TLSDESC_ADD_LO12:
     case ELF::R_AARCH64_ADD_ABS_LO12_NC:
     case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
     case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
@@ -2163,12 +2163,12 @@
   std::size_t hash(bool Recompute = true, bool UseDFS = false) const;
 
   /// Sets the associated .debug_info entry.
-  void addSubprogramDIE(DWARFCompileUnit *Unit,
-                        const DWARFDebugInfoEntryMinimal *DIE) {
-    SubprogramDIEs.emplace_back(DIE, Unit);
+  void addSubprogramDIE(const DWARFDie DIE) {
+    SubprogramDIEs.emplace_back(DIE);
     if (!UnitLineTable.first) {
-      if (const auto *LineTable = BC.DwCtx->getLineTableForUnit(Unit)) {
-        UnitLineTable = std::make_pair(Unit, LineTable);
+      if (const auto *LineTable =
+              BC.DwCtx->getLineTableForUnit(DIE.getDwarfUnit())) {
+        UnitLineTable = std::make_pair(DIE.getDwarfUnit(), LineTable);
       }
     }
   }
@@ -2285,7 +2285,7 @@
   /// \p BaseAddress is applied to all addresses in \pInputLL.
   DWARFDebugLoc::LocationList translateInputToOutputLocationList(
       const DWARFDebugLoc::LocationList &InputLL,
-      uint64_t BaseAddress) const;
+      BaseAddress BaseAddr) const;
 
   virtual ~BinaryFunction();
 
@@ -2388,18 +2388,20 @@
 // GraphTraits specializations for function basic block graphs (CFGs)
 template <> struct GraphTraits<bolt::BinaryFunction *> :
   public GraphTraits<bolt::BinaryBasicBlock *> {
-  static NodeType *getEntryNode(bolt::BinaryFunction *F) {
+  static NodeRef getEntryNode(bolt::BinaryFunction *F) {
     return *F->layout_begin();
   }
 
-  typedef bolt::BinaryBasicBlock * nodes_iterator;
+  using nodes_iterator = pointer_iterator<bolt::BinaryFunction::iterator>;
+
+//  typedef bolt::BinaryBasicBlock * nodes_iterator;
   static nodes_iterator nodes_begin(bolt::BinaryFunction *F) {
     llvm_unreachable("Not implemented");
-    return &(*F->begin());
+    return nodes_iterator(F->begin());
   }
   static nodes_iterator nodes_end(bolt::BinaryFunction *F) {
     llvm_unreachable("Not implemented");
-    return &(*F->end());
+    return nodes_iterator(F->end());
   }
   static size_t size(bolt::BinaryFunction *F) {
     return F->size();
@@ -2408,18 +2410,19 @@
 
 template <> struct GraphTraits<const bolt::BinaryFunction *> :
   public GraphTraits<const bolt::BinaryBasicBlock *> {
-  static NodeType *getEntryNode(const bolt::BinaryFunction *F) {
+  static NodeRef getEntryNode(const bolt::BinaryFunction *F) {
     return *F->layout_begin();
   }
 
-  typedef const bolt::BinaryBasicBlock * nodes_iterator;
+  using nodes_iterator = pointer_iterator<bolt::BinaryFunction::const_iterator>;
+
   static nodes_iterator nodes_begin(const bolt::BinaryFunction *F) {
     llvm_unreachable("Not implemented");
-    return &(*F->begin());
+    return nodes_iterator(F->begin());
   }
   static nodes_iterator nodes_end(const bolt::BinaryFunction *F) {
     llvm_unreachable("Not implemented");
-    return &(*F->end());
+    return nodes_iterator(F->end());
   }
   static size_t size(const bolt::BinaryFunction *F) {
     return F->size();
@@ -2428,14 +2431,14 @@
 
 template <> struct GraphTraits<Inverse<bolt::BinaryFunction *>> :
   public GraphTraits<Inverse<bolt::BinaryBasicBlock *>> {
-  static NodeType *getEntryNode(Inverse<bolt::BinaryFunction *> G) {
+  static NodeRef getEntryNode(Inverse<bolt::BinaryFunction *> G) {
     return *G.Graph->layout_begin();
   }
 };
 
 template <> struct GraphTraits<Inverse<const bolt::BinaryFunction *>> :
   public GraphTraits<Inverse<const bolt::BinaryBasicBlock *>> {
-  static NodeType *getEntryNode(Inverse<const bolt::BinaryFunction *> G) {
+  static NodeRef getEntryNode(Inverse<const bolt::BinaryFunction *> G) {
     return *G.Graph->layout_begin();
   }
 };
diff --git a/bolt/BinaryFunctionProfile.cpp b/bolt/BinaryFunctionProfile.cpp
index c341faa..6b84ec5 100644
--- a/bolt/BinaryFunctionProfile.cpp
+++ b/bolt/BinaryFunctionProfile.cpp
@@ -56,8 +56,7 @@
     clEnumValN(MCF_LOG, "log",
                "cost function is inversely proportional to log of edge count"),
     clEnumValN(MCF_BLAMEFTS, "blamefts",
-               "tune cost to blame fall-through edges for surplus flow"),
-    clEnumValEnd),
+               "tune cost to blame fall-through edges for surplus flow")),
   cl::ZeroOrMore,
   cl::Hidden,
   cl::cat(BoltOptCategory));
diff --git a/bolt/BinaryLoop.h b/bolt/BinaryLoop.h
index dc396d5..4406f07 100644
--- a/bolt/BinaryLoop.h
+++ b/bolt/BinaryLoop.h
@@ -25,8 +25,8 @@
 
 class BinaryBasicBlock;
 
-typedef DomTreeNodeBase<BinaryBasicBlock> BinaryDomTreeNode;
-typedef DominatorTreeBase<BinaryBasicBlock> BinaryDominatorTree;
+using BinaryDomTreeNode = DomTreeNodeBase<BinaryBasicBlock>;
+using BinaryDominatorTree =  DomTreeBase<BinaryBasicBlock>;
 
 class BinaryLoop : public LoopBase<BinaryBasicBlock, BinaryLoop> {
 public:
@@ -76,7 +76,7 @@
 
 template <> struct GraphTraits<bolt::BinaryDominatorTree *>
   : public GraphTraits<bolt::BinaryDomTreeNode *> {
-  static NodeType *getEntryNode(bolt::BinaryDominatorTree *DT) {
+  static NodeRef getEntryNode(bolt::BinaryDominatorTree *DT) {
     return DT->getRootNode();
   }
 
diff --git a/bolt/BinaryPassManager.cpp b/bolt/BinaryPassManager.cpp
index 48d3d63..bbdba97 100644
--- a/bolt/BinaryPassManager.cpp
+++ b/bolt/BinaryPassManager.cpp
@@ -272,6 +272,8 @@
 using namespace opts;
 
 const char BinaryFunctionPassManager::TimerGroupName[] =
+    "passman";
+const char BinaryFunctionPassManager::TimerGroupDesc[] =
     "Binary Function Pass Manager";
 
 void BinaryFunctionPassManager::runPasses() {
@@ -285,7 +287,8 @@
       outs() << "BOLT-INFO: Starting pass: " << Pass->getName() << "\n";
     }
 
-    NamedRegionTimer T(Pass->getName(), TimerGroupName, TimeOpts);
+    NamedRegionTimer T(Pass->getName(), Pass->getName(), TimerGroupName,
+                       TimerGroupDesc, TimeOpts);
 
     callWithDynoStats(
       [this,&Pass] {
diff --git a/bolt/BinaryPassManager.h b/bolt/BinaryPassManager.h
index ceacc33..08fa9c1 100644
--- a/bolt/BinaryPassManager.h
+++ b/bolt/BinaryPassManager.h
@@ -34,6 +34,7 @@
 
  public:
   static const char TimerGroupName[];
+  static const char TimerGroupDesc[];
 
   BinaryFunctionPassManager(BinaryContext &BC,
                             std::map<uint64_t, BinaryFunction> &BFs,
diff --git a/bolt/BinarySection.cpp b/bolt/BinarySection.cpp
index 92417bc..80c038e 100644
--- a/bolt/BinarySection.cpp
+++ b/bolt/BinarySection.cpp
@@ -50,8 +50,8 @@
   case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
   case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
   case ELF::R_AARCH64_LD64_GOT_LO12_NC:
-  case ELF::R_AARCH64_TLSDESC_LD64_LO12_NC:
-  case ELF::R_AARCH64_TLSDESC_ADD_LO12_NC:
+  case ELF::R_AARCH64_TLSDESC_LD64_LO12:
+  case ELF::R_AARCH64_TLSDESC_ADD_LO12:
   case ELF::R_AARCH64_TLSDESC_CALL:
   case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
   case ELF::R_AARCH64_JUMP26:
@@ -93,8 +93,8 @@
   case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
   case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
   case ELF::R_AARCH64_LD64_GOT_LO12_NC:
-  case ELF::R_AARCH64_TLSDESC_LD64_LO12_NC:
-  case ELF::R_AARCH64_TLSDESC_ADD_LO12_NC:
+  case ELF::R_AARCH64_TLSDESC_LD64_LO12:
+  case ELF::R_AARCH64_TLSDESC_ADD_LO12:
   case ELF::R_AARCH64_TLSDESC_CALL:
   case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
   case ELF::R_AARCH64_JUMP26:
@@ -137,7 +137,7 @@
     return Contents;
   }
   case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
-  case ELF::R_AARCH64_TLSDESC_LD64_LO12_NC:
+  case ELF::R_AARCH64_TLSDESC_LD64_LO12:
   case ELF::R_AARCH64_LD64_GOT_LO12_NC:
   case ELF::R_AARCH64_LDST64_ABS_LO12_NC: {
     // Immediate goes in bits 21:10 of LD/ST instruction, taken
@@ -147,7 +147,7 @@
   }
   case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
   case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
-  case ELF::R_AARCH64_TLSDESC_ADD_LO12_NC:
+  case ELF::R_AARCH64_TLSDESC_ADD_LO12:
   case ELF::R_AARCH64_ADD_ABS_LO12_NC: {
     // Immediate goes in bits 21:10 of ADD instruction
     Contents &= ~0xffffffffffc003ffU;
@@ -203,8 +203,8 @@
   case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
   case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
   case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
-  case ELF::R_AARCH64_TLSDESC_LD64_LO12_NC:
-  case ELF::R_AARCH64_TLSDESC_ADD_LO12_NC:
+  case ELF::R_AARCH64_TLSDESC_LD64_LO12:
+  case ELF::R_AARCH64_TLSDESC_ADD_LO12:
   case ELF::R_AARCH64_TLSDESC_CALL:
     return true;
   }
@@ -221,8 +221,8 @@
   case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
   case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
   case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
-  case ELF::R_AARCH64_TLSDESC_LD64_LO12_NC:
-  case ELF::R_AARCH64_TLSDESC_ADD_LO12_NC:
+  case ELF::R_AARCH64_TLSDESC_LD64_LO12:
+  case ELF::R_AARCH64_TLSDESC_ADD_LO12:
   case ELF::R_AARCH64_TLSDESC_CALL:
   case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
     return true;
@@ -251,8 +251,8 @@
   case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12:
   case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
   case ELF::R_AARCH64_LD64_GOT_LO12_NC:
-  case ELF::R_AARCH64_TLSDESC_LD64_LO12_NC:
-  case ELF::R_AARCH64_TLSDESC_ADD_LO12_NC:
+  case ELF::R_AARCH64_TLSDESC_LD64_LO12:
+  case ELF::R_AARCH64_TLSDESC_ADD_LO12:
     return false;
 
   case ELF::R_X86_64_PC8:
@@ -305,10 +305,10 @@
 
 void Relocation::print(raw_ostream &OS) const {
   static const char *X86RelocNames[] = {
-#include "llvm/Support/ELFRelocs/x86_64.def"
+#include "llvm/BinaryFormat/ELFRelocs/x86_64.def"
   };
   static const char *AArch64RelocNames[] = {
-#include "llvm/Support/ELFRelocs/AArch64.def"
+#include "llvm/BinaryFormat/ELFRelocs/AArch64.def"
   };
   if (Arch == Triple::aarch64)
     OS << AArch64RelocNames[Type];
diff --git a/bolt/BinarySection.h b/bolt/BinarySection.h
index 4f0eb80..80a3072 100644
--- a/bolt/BinarySection.h
+++ b/bolt/BinarySection.h
@@ -13,10 +13,10 @@
 #define LLVM_TOOLS_LLVM_BOLT_BINARY_SECTION_H
 
 #include "llvm/ADT/Triple.h"
+#include "llvm/BinaryFormat/ELF.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/ELF.h"
 #include "llvm/Support/ErrorOr.h"
 #include "llvm/Support/raw_ostream.h"
 #include <set>
diff --git a/bolt/CMakeLists.txt b/bolt/CMakeLists.txt
index bdcdb05..7424053 100644
--- a/bolt/CMakeLists.txt
+++ b/bolt/CMakeLists.txt
@@ -75,6 +75,9 @@
   ProfileReader.cpp
   ProfileWriter.cpp
   RewriteInstance.cpp
+
+  DEPENDS
+  intrinsics_gen
   )
 
 add_llvm_tool_symlink(perf2bolt llvm-bolt)
diff --git a/bolt/DWARFRewriter.cpp b/bolt/DWARFRewriter.cpp
index 5e89156..67f31d6 100644
--- a/bolt/DWARFRewriter.cpp
+++ b/bolt/DWARFRewriter.cpp
@@ -15,12 +15,14 @@
 #include "BinaryFunction.h"
 #include "RewriteInstance.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCSection.h"
 #include "llvm/MC/MCSectionELF.h"
 #include "llvm/MC/MCStreamer.h"
@@ -29,11 +31,9 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
-#include "llvm/Support/Dwarf.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/TimeValue.h"
 #include "llvm/Support/Timer.h"
 #include <algorithm>
 
@@ -67,8 +67,7 @@
   LocationListWriter = llvm::make_unique<DebugLocWriter>(BC.get());
 
   for (auto &CU : BC->DwCtx->compile_units()) {
-    updateUnitDebugInfo(CU.get(),
-                        CU->getUnitDIE(false),
+    updateUnitDebugInfo(CU->getUnitDIE(false),
                         std::vector<const BinaryFunction *>{});
   }
 
@@ -78,28 +77,27 @@
 }
 
 void RewriteInstance::updateUnitDebugInfo(
-    DWARFCompileUnit *Unit,
-    const DWARFDebugInfoEntryMinimal *DIE,
+    const DWARFDie DIE,
     std::vector<const BinaryFunction *> FunctionStack) {
 
   bool IsFunctionDef = false;
-  switch (DIE->getTag()) {
+  switch (DIE.getTag()) {
   case dwarf::DW_TAG_compile_unit:
     {
-      const auto ModuleRanges = DIE->getAddressRanges(Unit);
+      const auto ModuleRanges = DIE.getAddressRanges();
       auto OutputRanges = translateModuleAddressRanges(ModuleRanges);
       const auto RangesSectionOffset =
-        RangesSectionsWriter->addCURanges(Unit->getOffset(),
+        RangesSectionsWriter->addCURanges(DIE.getDwarfUnit()->getOffset(),
                                           std::move(OutputRanges));
-      updateDWARFObjectAddressRanges(Unit, DIE, RangesSectionOffset);
+      updateDWARFObjectAddressRanges(DIE, RangesSectionOffset);
     }
     break;
 
   case dwarf::DW_TAG_subprogram:
     {
       // The function cannot have multiple ranges on the input.
-      uint64_t LowPC, HighPC;
-      if (DIE->getLowAndHighPC(Unit, LowPC, HighPC)) {
+      uint64_t SectionIndex, LowPC, HighPC;
+      if (DIE.getLowAndHighPC(LowPC, HighPC, SectionIndex)) {
         IsFunctionDef = true;
         const auto *Function = getBinaryFunctionAtAddress(LowPC);
         if (Function && Function->isFolded()) {
@@ -114,7 +112,7 @@
             RangesSectionsWriter->addRanges(Function,
                                             std::move(FunctionRanges));
         }
-        updateDWARFObjectAddressRanges(Unit, DIE, RangesSectionOffset);
+        updateDWARFObjectAddressRanges(DIE, RangesSectionOffset);
       }
     }
     break;
@@ -129,19 +127,19 @@
       const BinaryFunction *Function =
         FunctionStack.empty() ? nullptr : FunctionStack.back();
       if (Function) {
-        const auto Ranges = DIE->getAddressRanges(Unit);
+        const auto Ranges = DIE.getAddressRanges();
         auto OutputRanges = Function->translateInputToOutputRanges(Ranges);
         DEBUG(
           if (OutputRanges.empty() != Ranges.empty()) {
             dbgs() << "BOLT-DEBUG: problem with DIE at 0x"
-                   << Twine::utohexstr(DIE->getOffset()) << " in CU at 0x"
-                   << Twine::utohexstr(Unit->getOffset()) << '\n';
+                   << Twine::utohexstr(DIE.getOffset()) << " in CU at 0x"
+                   << Twine::utohexstr(DIE.getDwarfUnit()->getOffset()) << '\n';
           }
         );
         RangesSectionOffset =
           RangesSectionsWriter->addRanges(Function, std::move(OutputRanges));
       }
-      updateDWARFObjectAddressRanges(Unit, DIE, RangesSectionOffset);
+      updateDWARFObjectAddressRanges(DIE, RangesSectionOffset);
     }
     break;
 
@@ -152,8 +150,8 @@
       uint32_t AttrOffset;
       const BinaryFunction *Function =
         FunctionStack.empty() ? nullptr : FunctionStack.back();
-      if (DIE->getAttributeValue(Unit, dwarf::DW_AT_location, Value,
-                                 &AttrOffset)) {
+      if (auto V = DIE.find(dwarf::DW_AT_location, &AttrOffset)) {
+        Value = *V;
         if (Value.isFormClass(DWARFFormValue::FC_Constant) ||
             Value.isFormClass(DWARFFormValue::FC_SectionOffset)) {
           auto LocListSectionOffset = LocationListWriter->getEmptyListOffset();
@@ -164,20 +162,25 @@
               Value.getAsUnsignedConstant().getValue() :
               Value.getAsSectionOffset().getValue();
 
-            Unit->getContext().getOneDebugLocList(LL);
-            if (LL.Entries.empty()) {
+            uint32_t LLOff = LL.Offset;
+            auto OptLL =
+                DIE.getDwarfUnit()->getContext().getOneDebugLocList(&LLOff);
+            if (!OptLL || OptLL->Entries.empty()) {
               errs() << "BOLT-WARNING: empty location list detected at 0x"
-                     << Twine::utohexstr(LL.Offset) << " for DIE at 0x"
-                     << Twine::utohexstr(DIE->getOffset()) << " in CU at 0x"
-                     << Twine::utohexstr(Unit->getOffset()) << '\n';
+                     << Twine::utohexstr(LLOff) << " for DIE at 0x"
+                     << Twine::utohexstr(DIE.getOffset()) << " in CU at 0x"
+                     << Twine::utohexstr(DIE.getDwarfUnit()->getOffset())
+                     << '\n';
             } else {
-              const auto OutputLL = Function->
-                translateInputToOutputLocationList(LL, Unit->getBaseAddress());
+              const auto OutputLL =
+                  Function->translateInputToOutputLocationList(
+                      *OptLL, *DIE.getDwarfUnit()->getBaseAddress());
               DEBUG(if (OutputLL.Entries.empty()) {
                 dbgs() << "BOLT-DEBUG: location list translated to an empty "
                           "one at 0x"
-                       << Twine::utohexstr(DIE->getOffset()) << " in CU at 0x"
-                       << Twine::utohexstr(Unit->getOffset()) << '\n';
+                       << Twine::utohexstr(DIE.getOffset()) << " in CU at 0x"
+                       << Twine::utohexstr(DIE.getDwarfUnit()->getOffset())
+                       << '\n';
               });
               LocListSectionOffset = LocationListWriter->addList(OutputLL);
             }
@@ -192,9 +195,9 @@
                   Value.isFormClass(DWARFFormValue::FC_Block)) &&
                  "unexpected DW_AT_location form");
         }
-      } else if (DIE->getAttributeValue(Unit, dwarf::DW_AT_low_pc, Value,
-                                        &AttrOffset)) {
-        const auto Result = Value.getAsAddress(Unit);
+      } else if (auto V = DIE.find(dwarf::DW_AT_low_pc, &AttrOffset)) {
+        Value = *V;
+        const auto Result = Value.getAsAddress();
         if (Result.hasValue()) {
           uint64_t NewAddress = 0;
           if (Function) {
@@ -202,7 +205,7 @@
             NewAddress = Function->translateInputToOutputAddress(Address);
             DEBUG(dbgs() << "BOLT-DEBUG: Fixing low_pc 0x"
                          << Twine::utohexstr(Address)
-                         << " for DIE with tag " << DIE->getTag()
+                         << " for DIE with tag " << DIE.getTag()
                          << " to 0x" << Twine::utohexstr(NewAddress) << '\n');
           }
           auto DebugInfoPatcher =
@@ -218,19 +221,16 @@
   }
 
   // Recursively update each child.
-  for (auto Child = DIE->getFirstChild(); Child; Child = Child->getSibling()) {
-    updateUnitDebugInfo(Unit, Child, FunctionStack);
+  for (auto Child = DIE.getFirstChild(); Child; Child = Child.getSibling()) {
+    updateUnitDebugInfo(Child, FunctionStack);
   }
 
   if (IsFunctionDef)
     FunctionStack.pop_back();
 }
 
-
 void RewriteInstance::updateDWARFObjectAddressRanges(
-    const DWARFUnit *Unit,
-    const DWARFDebugInfoEntryMinimal *DIE,
-    uint64_t DebugRangesOffset) {
+    const DWARFDie DIE, uint64_t DebugRangesOffset) {
 
   // Some objects don't have an associated DIE and cannot be updated (such as
   // compiler-generated functions).
@@ -240,7 +240,7 @@
 
   if (opts::Verbosity >= 2 && DebugRangesOffset == -1U) {
     errs() << "BOLT-WARNING: using invalid DW_AT_range for DIE at offset 0x"
-           << Twine::utohexstr(DIE->getOffset()) << '\n';
+           << Twine::utohexstr(DIE.getOffset()) << '\n';
   }
 
   auto DebugInfoPatcher =
@@ -250,24 +250,24 @@
 
   assert(DebugInfoPatcher && AbbrevPatcher && "Patchers not initialized.");
 
-  const auto *AbbreviationDecl = DIE->getAbbreviationDeclarationPtr();
+  const auto *AbbreviationDecl = DIE.getAbbreviationDeclarationPtr();
   if (!AbbreviationDecl) {
     if (opts::Verbosity >= 1) {
       errs() << "BOLT-WARNING: object's DIE doesn't have an abbreviation: "
              << "skipping update. DIE at offset 0x"
-             << Twine::utohexstr(DIE->getOffset()) << '\n';
+             << Twine::utohexstr(DIE.getOffset()) << '\n';
     }
     return;
   }
 
   auto AbbrevCode = AbbreviationDecl->getCode();
 
-  if (AbbreviationDecl->findAttributeIndex(dwarf::DW_AT_ranges) != -1U) {
+  if (AbbreviationDecl->findAttributeIndex(dwarf::DW_AT_ranges)) {
     // Case 1: The object was already non-contiguous and had DW_AT_ranges.
     // In this case we simply need to update the value of DW_AT_ranges.
-    DWARFFormValue FormValue;
     uint32_t AttrOffset = -1U;
-    DIE->getAttributeValue(Unit, dwarf::DW_AT_ranges, FormValue, &AttrOffset);
+    DIE.find(dwarf::DW_AT_ranges, &AttrOffset);
+    assert(AttrOffset != -1U &&  "failed to locate DWARF attribute");
     DebugInfoPatcher->addLE32Patch(AttrOffset, DebugRangesOffset);
   } else {
     // Case 2: The object has both DW_AT_low_pc and DW_AT_high_pc emitted back
@@ -282,38 +282,37 @@
     // To fill in the gap we use a variable length DW_FORM_udata encoding for
     // DW_AT_low_pc. We exploit the fact that the encoding can take an arbitrary
     // large size.
-    if (AbbreviationDecl->findAttributeIndex(dwarf::DW_AT_low_pc) != -1U &&
-        AbbreviationDecl->findAttributeIndex(dwarf::DW_AT_high_pc) != -1U) {
+    if (AbbreviationDecl->findAttributeIndex(dwarf::DW_AT_low_pc) &&
+        AbbreviationDecl->findAttributeIndex(dwarf::DW_AT_high_pc)) {
       uint32_t LowPCOffset = -1U;
       uint32_t HighPCOffset = -1U;
-      DWARFFormValue LowPCFormValue;
-      DWARFFormValue HighPCFormValue;
-      DIE->getAttributeValue(Unit, dwarf::DW_AT_low_pc, LowPCFormValue,
-                             &LowPCOffset);
-      DIE->getAttributeValue(Unit, dwarf::DW_AT_high_pc, HighPCFormValue,
-                             &HighPCOffset);
+      DWARFFormValue LowPCFormValue =
+          *DIE.find(dwarf::DW_AT_low_pc, &LowPCOffset);
+      DWARFFormValue HighPCFormValue =
+          *DIE.find(dwarf::DW_AT_high_pc, &HighPCOffset);
+
       if (LowPCFormValue.getForm() != dwarf::DW_FORM_addr ||
           (HighPCFormValue.getForm() != dwarf::DW_FORM_addr &&
            HighPCFormValue.getForm() != dwarf::DW_FORM_data8 &&
            HighPCFormValue.getForm() != dwarf::DW_FORM_data4)) {
         errs() << "BOLT-WARNING: unexpected form value. Cannot update DIE "
-                 << "at offset 0x" << Twine::utohexstr(DIE->getOffset())
+                 << "at offset 0x" << Twine::utohexstr(DIE.getOffset())
                  << "\n";
         return;
       }
       if (LowPCOffset == -1U || (LowPCOffset + 8 != HighPCOffset)) {
         errs() << "BOLT-WARNING: high_pc expected immediately after low_pc. "
                << "Cannot update DIE at offset 0x"
-               << Twine::utohexstr(DIE->getOffset()) << '\n';
+               << Twine::utohexstr(DIE.getOffset()) << '\n';
         return;
       }
 
-      AbbrevPatcher->addAttributePatch(Unit,
+      AbbrevPatcher->addAttributePatch(DIE.getDwarfUnit(),
                                        AbbrevCode,
                                        dwarf::DW_AT_low_pc,
                                        dwarf::DW_AT_ranges,
                                        dwarf::DW_FORM_sec_offset);
-      AbbrevPatcher->addAttributePatch(Unit,
+      AbbrevPatcher->addAttributePatch(DIE.getDwarfUnit(),
                                        AbbrevCode,
                                        dwarf::DW_AT_high_pc,
                                        dwarf::DW_AT_low_pc,
@@ -332,7 +331,7 @@
     } else {
       if (opts::Verbosity >= 1) {
         errs() << "BOLT-WARNING: Cannot update ranges for DIE at offset 0x"
-               << Twine::utohexstr(DIE->getOffset()) << '\n';
+               << Twine::utohexstr(DIE.getOffset()) << '\n';
       }
     }
   }
@@ -378,7 +377,7 @@
             Row.Address);
         auto Loc = BC->Ctx->getCurrentDwarfLoc();
         BC->Ctx->clearDwarfLocSeen();
-        OutputLineTable.addLineEntry(MCLineEntry{nullptr, Loc},
+        OutputLineTable.addLineEntry(MCDwarfLineEntry{nullptr, Loc},
                                      FunctionSection);
       }
       // Add an empty entry past the end of the function
@@ -387,7 +386,7 @@
                                   Address + Function.getMaxSize());
       auto Loc = BC->Ctx->getCurrentDwarfLoc();
       BC->Ctx->clearDwarfLocSeen();
-      OutputLineTable.addLineEntry(MCLineEntry{nullptr, Loc},
+      OutputLineTable.addLineEntry(MCDwarfLineEntry{nullptr, Loc},
                                    FunctionSection);
     } else {
       DEBUG(dbgs() << "BOLT-DEBUG: Function " << Function
@@ -397,7 +396,7 @@
 }
 
 void RewriteInstance::updateLineTableOffsets() {
-  const auto LineSection =
+  const auto *LineSection =
     BC->Ctx->getObjectFileInfo()->getDwarfLineSection();
   auto CurrentFragment = LineSection->begin();
   uint32_t CurrentOffset = 0;
@@ -460,8 +459,8 @@
     SmallVector<char, 16> ARangesBuffer;
     raw_svector_ostream OS(ARangesBuffer);
 
-    auto MAB = std::unique_ptr<MCAsmBackend>(
-        BC->TheTarget->createMCAsmBackend(*BC->MRI, BC->TripleName, ""));
+    auto MAB = std::unique_ptr<MCAsmBackend>(BC->TheTarget->createMCAsmBackend(
+        *BC->STI, *BC->MRI, MCTargetOptions()));
     auto Writer = std::unique_ptr<MCObjectWriter>(MAB->createObjectWriter(OS));
 
     RangesSectionsWriter->writeArangesSection(Writer.get());
@@ -591,8 +590,8 @@
     const auto CUIndex = OffsetToIndexMap[CURangesPair.first];
     const auto &Ranges = CURangesPair.second;
     for (const auto &Range : Ranges) {
-      write64le(Buffer, Range.first);
-      write64le(Buffer + 8, Range.second);
+      write64le(Buffer, Range.LowPC);
+      write64le(Buffer + 8, Range.HighPC);
       write32le(Buffer + 16, CUIndex);
       Buffer += 20;
     }
diff --git a/bolt/DataAggregator.cpp b/bolt/DataAggregator.cpp
index 1b039c4..32145fd 100644
--- a/bolt/DataAggregator.cpp
+++ b/bolt/DataAggregator.cpp
@@ -46,7 +46,8 @@
 
 namespace {
 
-const char TimerGroupName[] = "Aggregator";
+const char TimerGroupName[] = "aggregator";
+const char TimerGroupDesc[] = "Aggregator";
 
 }
 
@@ -83,8 +84,6 @@
 
 bool DataAggregator::launchPerfBranchEventsNoWait() {
   SmallVector<const char*, 4> Argv;
-  SmallVector<StringRef, 3> Redirects;
-  SmallVector<const StringRef*, 3> RedirectPtrs;
 
   outs() << "PERF2BOLT: Spawning perf-script job to read branch events\n";
   Argv.push_back(PerfPath.data());
@@ -108,28 +107,23 @@
            << PerfBranchEventsErrPath << " with error " << Errc.message() << "\n";
     exit(1);
   }
-
-  Redirects.push_back("");                                           // Stdin
-  Redirects.push_back(StringRef(PerfBranchEventsOutputPath.data())); // Stdout
-  Redirects.push_back(StringRef(PerfBranchEventsErrPath.data()));    // Stderr
-  RedirectPtrs.push_back(&Redirects[0]);
-  RedirectPtrs.push_back(&Redirects[1]);
-  RedirectPtrs.push_back(&Redirects[2]);
+  Optional<StringRef> Redirects[] = {
+      llvm::None,                                   // Stdin
+      StringRef(PerfBranchEventsOutputPath.data()), // Stdout
+      StringRef(PerfBranchEventsErrPath.data())};   // Stderr
 
   DEBUG(dbgs() << "Launching perf: " << PerfPath.data() << " 1> "
                << PerfBranchEventsOutputPath.data() << " 2> "
                << PerfBranchEventsErrPath.data() << "\n");
 
   BranchEventsPI = sys::ExecuteNoWait(PerfPath.data(), Argv.data(),
-                                      /*envp*/ nullptr, &RedirectPtrs[0]);
+                                      /*envp*/ nullptr, Redirects);
 
   return true;
 }
 
 bool DataAggregator::launchPerfMemEventsNoWait() {
   SmallVector<const char*, 4> Argv;
-  SmallVector<StringRef, 3> Redirects;
-  SmallVector<const StringRef*, 3> RedirectPtrs;
 
   outs() << "PERF2BOLT: Spawning perf-script job to read mem events\n";
   Argv.push_back(PerfPath.data());
@@ -154,27 +148,23 @@
     exit(1);
   }
 
-  Redirects.push_back("");                                        // Stdin
-  Redirects.push_back(StringRef(PerfMemEventsOutputPath.data())); // Stdout
-  Redirects.push_back(StringRef(PerfMemEventsErrPath.data()));    // Stderr
-  RedirectPtrs.push_back(&Redirects[0]);
-  RedirectPtrs.push_back(&Redirects[1]);
-  RedirectPtrs.push_back(&Redirects[2]);
+  Optional<StringRef> Redirects[] = {
+      llvm::None,                                // Stdin
+      StringRef(PerfMemEventsOutputPath.data()), // Stdout
+      StringRef(PerfMemEventsErrPath.data())};   // Stderr
 
   DEBUG(dbgs() << "Launching perf: " << PerfPath.data() << " 1> "
                << PerfMemEventsOutputPath.data() << " 2> "
                << PerfMemEventsErrPath.data() << "\n");
 
   MemEventsPI = sys::ExecuteNoWait(PerfPath.data(), Argv.data(),
-                                   /*envp*/ nullptr, &RedirectPtrs[0]);
+                                   /*envp*/ nullptr, Redirects);
 
   return true;
 }
 
 bool DataAggregator::launchPerfTasksNoWait() {
   SmallVector<const char*, 4> Argv;
-  SmallVector<StringRef, 3> Redirects;
-  SmallVector<const StringRef*, 3> RedirectPtrs;
 
   outs() << "PERF2BOLT: Spawning perf-script job to read tasks\n";
   Argv.push_back(PerfPath.data());
@@ -198,27 +188,23 @@
     exit(1);
   }
 
-  Redirects.push_back("");                                    // Stdin
-  Redirects.push_back(StringRef(PerfTasksOutputPath.data())); // Stdout
-  Redirects.push_back(StringRef(PerfTasksErrPath.data()));    // Stderr
-  RedirectPtrs.push_back(&Redirects[0]);
-  RedirectPtrs.push_back(&Redirects[1]);
-  RedirectPtrs.push_back(&Redirects[2]);
+  Optional<StringRef> Redirects[] = {
+      llvm::None,                            // Stdin
+      StringRef(PerfTasksOutputPath.data()), // Stdout
+      StringRef(PerfTasksErrPath.data())};   // Stderr
 
   DEBUG(dbgs() << "Launching perf: " << PerfPath.data() << " 1> "
                << PerfTasksOutputPath.data() << " 2> "
                << PerfTasksErrPath.data() << "\n");
 
   TasksPI = sys::ExecuteNoWait(PerfPath.data(), Argv.data(),
-                               /*envp*/ nullptr, &RedirectPtrs[0]);
+                               /*envp*/ nullptr, Redirects);
 
   return true;
 }
 
 Optional<std::string> DataAggregator::getPerfBuildID() {
   SmallVector<const char *, 4> Argv;
-  SmallVector<StringRef, 3> Redirects;
-  SmallVector<const StringRef*, 3> RedirectPtrs;
   SmallVector<char, 256> OutputPath;
   SmallVector<char, 256> ErrPath;
 
@@ -242,19 +228,17 @@
     exit(1);
   }
 
-  Redirects.push_back("");                           // Stdin
-  Redirects.push_back(StringRef(OutputPath.data())); // Stdout
-  Redirects.push_back(StringRef(ErrPath.data()));    // Stderr
-  RedirectPtrs.push_back(&Redirects[0]);
-  RedirectPtrs.push_back(&Redirects[1]);
-  RedirectPtrs.push_back(&Redirects[2]);
+  Optional<StringRef> Redirects[] = {
+      llvm::None,                   // Stdin
+      StringRef(OutputPath.data()), // Stdout
+      StringRef(ErrPath.data())};   // Stderr
 
   DEBUG(dbgs() << "Launching perf: " << PerfPath.data() << " 1> "
                << OutputPath.data() << " 2> "
                << ErrPath.data() << "\n");
 
   auto RetCode = sys::ExecuteAndWait(PerfPath.data(), Argv.data(),
-                                     /*envp*/ nullptr, &RedirectPtrs[0]);
+                                     /*envp*/ nullptr, Redirects);
 
   if (RetCode != 0) {
     ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
@@ -729,8 +713,8 @@
 
 std::error_code DataAggregator::parseBranchEvents() {
   outs() << "PERF2BOLT: Aggregating branch events...\n";
-  NamedRegionTimer T("Branch samples parsing", TimerGroupName,
-                      opts::TimeAggregator);
+  NamedRegionTimer T("parseBranch", "Branch samples parsing", TimerGroupName,
+                     TimerGroupDesc, opts::TimeAggregator);
   uint64_t NumEntries{0};
   uint64_t NumSamples{0};
   uint64_t NumTraces{0};
@@ -800,7 +784,8 @@
 
 std::error_code DataAggregator::parseMemEvents() {
   outs() << "PERF2BOLT: Aggregating memory events...\n";
-  NamedRegionTimer T("Mem samples parsing", TimerGroupName, opts::TimeAggregator);
+  NamedRegionTimer T("memevents", "Mem samples parsing", TimerGroupName,
+                     TimerGroupDesc, opts::TimeAggregator);
 
   while (hasData()) {
     auto SampleRes = parseMemSample();
@@ -889,7 +874,8 @@
 
 std::error_code DataAggregator::parseTasks() {
   outs() << "PERF2BOLT: Parsing perf-script tasks output\n";
-  NamedRegionTimer T("Tasks parsing", TimerGroupName, opts::TimeAggregator);
+  NamedRegionTimer T("parseTasks", "Tasks parsing", TimerGroupName,
+                     TimerGroupDesc, opts::TimeAggregator);
 
   while (hasData()) {
     auto PIDRes = parseTaskPID();
diff --git a/bolt/DebugData.cpp b/bolt/DebugData.cpp
index 9b96006..3bc981d 100644
--- a/bolt/DebugData.cpp
+++ b/bolt/DebugData.cpp
@@ -43,9 +43,9 @@
     const DWARFAddressRangesVector &AddressRanges,
     const bool WriteRelativeRanges = false) {
   for (auto &Range : AddressRanges) {
-    Writer->writeLE64(Range.first);
-    Writer->writeLE64(WriteRelativeRanges ? Range.second - Range.first
-                                          : Range.second);
+    Writer->writeLE64(Range.LowPC);
+    Writer->writeLE64(WriteRelativeRanges ? Range.HighPC - Range.LowPC
+                                          : Range.HighPC);
   }
   // Finish with 0 entries.
   Writer->writeLE64(0);
@@ -202,13 +202,9 @@
 }
 
 void SimpleBinaryPatcher::addUDataPatch(uint32_t Offset, uint64_t Value, uint64_t Size) {
-  const auto EncodedSize = getULEB128Size(Value);
-  assert(EncodedSize <= Size && "value did not fit");
-
-  const auto Padding = Size - EncodedSize;
   std::string Buff;
   raw_string_ostream OS(Buff);
-  encodeULEB128(Value, OS, Padding);
+  encodeULEB128(Value, OS, Size);
 
   Patches.emplace_back(Offset, OS.str());
 }
@@ -235,7 +231,7 @@
 
 void DebugAbbrevPatcher::addAttributePatch(const DWARFUnit *Unit,
                                            uint32_t AbbrevCode,
-                                           uint16_t AttrTag,
+                                           dwarf::Attribute AttrTag,
                                            uint8_t NewAttrTag,
                                            uint8_t NewAttrForm) {
   assert(Unit && "No compile unit specified.");
@@ -256,8 +252,8 @@
       const auto *AbbreviationDeclaration =
         UnitAbbreviations->getAbbreviationDeclaration(AttrPatch.Code);
       assert(AbbreviationDeclaration && "No abbreviation with given code.");
-      const auto *Attribute = AbbreviationDeclaration->findAttribute(
-          AttrPatch.Attr);
+      const auto Attribute =
+          AbbreviationDeclaration->findAttribute(AttrPatch.Attr);
 
       assert(Attribute && "Specified attribute doesn't occur in abbreviation.");
       // Because we're only handling standard values (i.e. no DW_FORM_GNU_* or
diff --git a/bolt/DebugData.h b/bolt/DebugData.h
index 6b46ef0..9b8c18c 100644
--- a/bolt/DebugData.h
+++ b/bolt/DebugData.h
@@ -220,7 +220,7 @@
   /// Patch of changing one attribute to another.
   struct AbbrevAttrPatch {
     uint32_t Code;    // Code of abbreviation to be modified.
-    uint16_t Attr;    // ID of attribute to be replaced.
+    dwarf::Attribute Attr;    // ID of attribute to be replaced.
     uint8_t NewAttr;  // ID of the new attribute.
     uint8_t NewForm;  // Form of the new attribute.
   };
@@ -238,7 +238,7 @@
   /// We only handle standard forms, that are encoded in a single byte.
   void addAttributePatch(const DWARFUnit *Unit,
                          uint32_t AbbrevCode,
-                         uint16_t AttrTag,
+                         dwarf::Attribute AttrTag,
                          uint8_t NewAttrTag,
                          uint8_t NewAttrForm);
 
diff --git a/bolt/Exceptions.cpp b/bolt/Exceptions.cpp
index 34568e1..358641b 100644
--- a/bolt/Exceptions.cpp
+++ b/bolt/Exceptions.cpp
@@ -19,12 +19,12 @@
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/Twine.h"
-#include "llvm/DebugInfo/DWARF/DWARFFrame.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
-#include "llvm/Support/Dwarf.h"
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
@@ -61,7 +61,7 @@
   default: llvm_unreachable("unknown encoding");
   case dwarf::DW_EH_PE_absptr:
   case dwarf::DW_EH_PE_signed:
-    return BC.AsmInfo->getPointerSize();
+    return BC.AsmInfo->getCodePointerSize();
   case dwarf::DW_EH_PE_udata2:
   case dwarf::DW_EH_PE_sdata2:
     return 2;
@@ -133,30 +133,24 @@
   if (!getLSDAAddress())
     return;
 
-  assert(getLSDAAddress() < LSDASectionAddress + LSDASectionData.size() &&
-         "wrong LSDA address");
+  DWARFDataExtractor Data(
+      StringRef(reinterpret_cast<const char *>(LSDASectionData.data()),
+                LSDASectionData.size()),
+      BC.DwCtx->getDWARFObj().isLittleEndian(), 8);
+  uint32_t Offset = getLSDAAddress() - LSDASectionAddress;
+  assert(Data.isValidOffset(Offset) && "wrong LSDA address");
 
-  // Given an address in memory corresponding to some entity in mapped
-  // LSDA section return address of this entity in a binary file.
-  auto getFileAddress = [&](const uint8_t *InMemAddress) {
-    return InMemAddress - LSDASectionData.data() + LSDASectionAddress;
-  };
-  const uint8_t *Ptr =
-      LSDASectionData.data() + getLSDAAddress() - LSDASectionAddress;
-
-  uint8_t LPStartEncoding = *Ptr++;
-  uintptr_t LPStart = 0;
-  if (LPStartEncoding != DW_EH_PE_omit) {
-    LPStart = readEncodedPointer(Ptr, LPStartEncoding, getFileAddress(Ptr));
-  }
+  uint8_t LPStartEncoding = Data.getU8(&Offset);
+  uint64_t LPStart = Data.getEncodedPointer(&Offset, LPStartEncoding,
+                                            Offset + LSDASectionAddress);
 
   assert(LPStart == 0 && "support for split functions not implemented");
 
-  const auto TTypeEncoding = *Ptr++;
+  const auto TTypeEncoding = Data.getU8(&Offset);
   size_t TTypeEncodingSize = 0;
   uintptr_t TTypeEnd = 0;
   if (TTypeEncoding != DW_EH_PE_omit) {
-    TTypeEnd = readULEB128(Ptr);
+    TTypeEnd = Data.getULEB128(&Offset);
     TTypeEncodingSize = getEncodingSize(TTypeEncoding, BC);
   }
 
@@ -171,24 +165,24 @@
   }
 
   // Table to store list of indices in type table. Entries are uleb128 values.
-  auto TypeIndexTableStart = Ptr + TTypeEnd;
+  const uint32_t TypeIndexTableStart = Offset + TTypeEnd;
 
   // Offset past the last decoded index.
-  intptr_t MaxTypeIndexTableOffset = 0;
+  uint32_t MaxTypeIndexTableOffset = 0;
 
   // Max positive index used in type table.
   unsigned MaxTypeIndex = 0;
 
   // The actual type info table starts at the same location, but grows in
   // opposite direction. TTypeEncoding is used to encode stored values.
-  const auto TypeTableStart = Ptr + TTypeEnd;
+  const auto TypeTableStart = Offset + TTypeEnd;
 
-  uint8_t       CallSiteEncoding = *Ptr++;
-  uint32_t      CallSiteTableLength = readULEB128(Ptr);
-  const uint8_t *CallSiteTableStart = Ptr;
-  const uint8_t *CallSiteTableEnd = CallSiteTableStart + CallSiteTableLength;
-  const uint8_t *CallSitePtr = CallSiteTableStart;
-  const uint8_t *ActionTableStart = CallSiteTableEnd;
+  uint8_t CallSiteEncoding = Data.getU8(&Offset);
+  uint32_t CallSiteTableLength = Data.getULEB128(&Offset);
+  auto CallSiteTableStart = Offset;
+  auto CallSiteTableEnd = CallSiteTableStart + CallSiteTableLength;
+  auto CallSitePtr = CallSiteTableStart;
+  auto ActionTableStart = CallSiteTableEnd;
 
   if (opts::PrintExceptions) {
     outs() << "CallSite Encoding = " << (unsigned)CallSiteEncoding << '\n';
@@ -199,13 +193,13 @@
   HasEHRanges = CallSitePtr < CallSiteTableEnd;
   uint64_t RangeBase = getAddress();
   while (CallSitePtr < CallSiteTableEnd) {
-    uintptr_t Start = readEncodedPointer(CallSitePtr, CallSiteEncoding,
-                                         getFileAddress(CallSitePtr));
-    uintptr_t Length = readEncodedPointer(CallSitePtr, CallSiteEncoding,
-                                          getFileAddress(CallSitePtr));
-    uintptr_t LandingPad = readEncodedPointer(CallSitePtr, CallSiteEncoding,
-                                              getFileAddress(CallSitePtr));
-    uintptr_t ActionEntry = readULEB128(CallSitePtr);
+    uintptr_t Start = Data.getEncodedPointer(&CallSitePtr, CallSiteEncoding,
+                                             CallSitePtr + LSDASectionAddress);
+    uintptr_t Length = Data.getEncodedPointer(&CallSitePtr, CallSiteEncoding,
+                                              CallSitePtr + LSDASectionAddress);
+    uintptr_t LandingPad = Data.getEncodedPointer(
+        &CallSitePtr, CallSiteEncoding, CallSitePtr + LSDASectionAddress);
+    uintptr_t ActionEntry = Data.getULEB128(&CallSitePtr);
 
     if (opts::PrintExceptions) {
       outs() << "Call Site: [0x" << Twine::utohexstr(RangeBase + Start)
@@ -258,11 +252,10 @@
     if (ActionEntry != 0) {
       auto printType = [&] (int Index, raw_ostream &OS) {
         assert(Index > 0 && "only positive indices are valid");
-        const uint8_t *TTEntry = TypeTableStart - Index * TTypeEncodingSize;
-        const auto TTEntryAddress = getFileAddress(TTEntry);
-        auto TypeAddress = readEncodedPointer(TTEntry,
-                                              TTypeEncoding,
-                                              TTEntryAddress);
+        uint32_t TTEntry = TypeTableStart - Index * TTypeEncodingSize;
+        const auto TTEntryAddress = TTEntry + LSDASectionAddress;
+        auto TypeAddress =
+            Data.getEncodedPointer(&TTEntry, TTypeEncoding, TTEntryAddress);
         if ((TTypeEncoding & DW_EH_PE_pcrel) &&
             (TypeAddress == TTEntryAddress)) {
           TypeAddress = 0;
@@ -285,14 +278,14 @@
       };
       if (opts::PrintExceptions)
         outs() << "    actions: ";
-      const uint8_t *ActionPtr = ActionTableStart + ActionEntry - 1;
+      uint32_t ActionPtr = ActionTableStart + ActionEntry - 1;
       long long ActionType;
       long long ActionNext;
       auto Sep = "";
       do {
-        ActionType = readSLEB128(ActionPtr);
+        ActionType = Data.getSLEB128(&ActionPtr);
         auto Self = ActionPtr;
-        ActionNext = readSLEB128(ActionPtr);
+        ActionNext = Data.getSLEB128(&ActionPtr);
         if (opts::PrintExceptions)
           outs() << Sep << "(" << ActionType << ", " << ActionNext << ") ";
         if (ActionType == 0) {
@@ -314,8 +307,8 @@
           // of indices with base 1.
           // E.g. -1 means offset 0, -2 is offset 1, etc. The indices are
           // encoded using uleb128 thus we cannot directly dereference them.
-          auto TypeIndexTablePtr = TypeIndexTableStart - ActionType - 1;
-          while (auto Index = readULEB128(TypeIndexTablePtr)) {
+          uint32_t TypeIndexTablePtr = TypeIndexTableStart - ActionType - 1;
+          while (auto Index = Data.getULEB128(&TypeIndexTablePtr)) {
             MaxTypeIndex = std::max(MaxTypeIndex, static_cast<unsigned>(Index));
             if (opts::PrintExceptions) {
               outs() << TSep;
@@ -340,22 +333,20 @@
     outs() << '\n';
 
   assert(TypeIndexTableStart + MaxTypeIndexTableOffset <=
-         LSDASectionData.data() + LSDASectionData.size() &&
+             Data.getData().size() &&
          "LSDA entry has crossed section boundary");
 
   if (TTypeEnd) {
-    // TypeIndexTableStart is a <uint8_t *> alias for TypeTableStart.
-    LSDAActionTable =
-      ArrayRef<uint8_t>(ActionTableStart, TypeIndexTableStart -
-                        MaxTypeIndex * TTypeEncodingSize - ActionTableStart);
+    LSDAActionTable = LSDASectionData.slice(
+        ActionTableStart, TypeIndexTableStart -
+                              MaxTypeIndex * TTypeEncodingSize -
+                              ActionTableStart);
     for (unsigned Index = 1; Index <= MaxTypeIndex; ++Index) {
-      const uint8_t *TTEntry = TypeTableStart - Index * TTypeEncodingSize;
-      const auto TTEntryAddress = getFileAddress(TTEntry);
-      auto TypeAddress = readEncodedPointer(TTEntry,
-                                            TTypeEncoding,
-                                            TTEntryAddress);
-      if ((TTypeEncoding & DW_EH_PE_pcrel) &&
-          (TypeAddress == TTEntryAddress)) {
+      uint32_t TTEntry = TypeTableStart - Index * TTypeEncodingSize;
+      const auto TTEntryAddress = TTEntry + LSDASectionAddress;
+      auto TypeAddress =
+          Data.getEncodedPointer(&TTEntry, TTypeEncoding, TTEntryAddress);
+      if ((TTypeEncoding & DW_EH_PE_pcrel) && (TypeAddress == TTEntryAddress)) {
         TypeAddress = 0;
       }
       if (TypeAddress &&
@@ -367,7 +358,7 @@
       LSDATypeTable.emplace_back(TypeAddress);
     }
     LSDATypeIndexTable =
-      ArrayRef<uint8_t>(TypeIndexTableStart, MaxTypeIndexTableOffset);
+        LSDASectionData.slice(TypeIndexTableStart, MaxTypeIndexTableOffset);
   }
 }
 
@@ -595,7 +586,7 @@
 
   // Account for any extra padding that will be added to the call site table
   // length.
-  Streamer->EmitULEB128IntValue(TTypeBaseOffset, SizeAlign);
+  Streamer->EmitPaddedULEB128IntValue(TTypeBaseOffset, SizeAlign);
 
   // Emit the landing pad call site table. We use signed data4 since we can emit
   // a landing pad in a different part of the split function that could appear
@@ -684,21 +675,22 @@
     return false;
   }
 
-  Function.setLSDAAddress(CurFDE.getLSDAAddress());
+  auto LSDA = CurFDE.getLSDAAddress();
+  Function.setLSDAAddress(LSDA ? *LSDA : 0);
 
   uint64_t Offset = 0;
   uint64_t CodeAlignment = CurFDE.getLinkedCIE()->getCodeAlignmentFactor();
   uint64_t DataAlignment = CurFDE.getLinkedCIE()->getDataAlignmentFactor();
-  if (CurFDE.getLinkedCIE()->getPersonalityAddress() != 0) {
+  if (CurFDE.getLinkedCIE()->getPersonalityAddress()) {
     Function.setPersonalityFunction(
-        CurFDE.getLinkedCIE()->getPersonalityAddress());
+        *CurFDE.getLinkedCIE()->getPersonalityAddress());
     Function.setPersonalityEncoding(
-        CurFDE.getLinkedCIE()->getPersonalityEncoding());
+        *CurFDE.getLinkedCIE()->getPersonalityEncoding());
   }
 
   auto decodeFrameInstruction =
       [&Function, &Offset, Address, CodeAlignment, DataAlignment](
-          const FrameEntry::Instruction &Instr) {
+          const CFIProgram::Instruction &Instr) {
         uint8_t Opcode = Instr.Opcode;
         if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
           Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
@@ -854,12 +846,12 @@
         return true;
       };
 
-  for (const FrameEntry::Instruction &Instr : *(CurFDE.getLinkedCIE())) {
+  for (const CFIProgram::Instruction &Instr : CurFDE.getLinkedCIE()->cfis()) {
     if (!decodeFrameInstruction(Instr))
       return false;
   }
 
-  for (const FrameEntry::Instruction &Instr : CurFDE) {
+  for (const CFIProgram::Instruction &Instr : CurFDE.cfis()) {
     if (!decodeFrameInstruction(Instr))
       return false;
   }
@@ -868,8 +860,8 @@
 }
 
 std::vector<char> CFIReaderWriter::generateEHFrameHeader(
-    const DWARFFrame &OldEHFrame,
-    const DWARFFrame &NewEHFrame,
+    const DWARFDebugFrame &OldEHFrame,
+    const DWARFDebugFrame &NewEHFrame,
     uint64_t EHFrameHeaderAddress,
     std::vector<uint64_t> &FailedAddresses) const {
   // Common PC -> FDE map to be written into .eh_frame_hdr.
@@ -881,7 +873,7 @@
   // Initialize PCToFDE using NewEHFrame.
   NewEHFrame.for_each_FDE([&](const dwarf::FDE *FDE) {
     const auto FuncAddress = FDE->getInitialLocation();
-    const auto FDEAddress = NewEHFrame.EHFrameAddress + FDE->getOffset();
+    const auto FDEAddress = NewEHFrame.getEHFrameAddress() + FDE->getOffset();
 
     // Ignore unused FDEs.
     if (FuncAddress == 0)
@@ -898,13 +890,15 @@
   });
 
   DEBUG(dbgs() << "BOLT-DEBUG: new .eh_frame contains "
-               << NewEHFrame.Entries.size() << " entries\n");
+               << std::distance(NewEHFrame.entries().begin(),
+                                NewEHFrame.entries().end())
+               << " entries\n");
 
   // Add entries from the original .eh_frame corresponding to the functions
   // that we did not update.
   OldEHFrame.for_each_FDE([&](const dwarf::FDE *FDE) {
     const auto FuncAddress = FDE->getInitialLocation();
-    const auto FDEAddress = OldEHFrame.EHFrameAddress + FDE->getOffset();
+    const auto FDEAddress = OldEHFrame.getEHFrameAddress() + FDE->getOffset();
 
     // Add the address if we failed to write it.
     if (PCToFDE.count(FuncAddress) == 0) {
@@ -916,7 +910,9 @@
   });
 
   DEBUG(dbgs() << "BOLT-DEBUG: old .eh_frame contains "
-               << OldEHFrame.Entries.size() << " entries\n");
+               << std::distance(OldEHFrame.entries().begin(),
+                                OldEHFrame.entries().end())
+               << " entries\n");
 
   // Generate a new .eh_frame_hdr based on the new map.
 
@@ -934,7 +930,7 @@
 
   // Address of eh_frame. Use the new one.
   support::ulittle32_t::ref(EHFrameHeader.data() + 4) =
-    NewEHFrame.EHFrameAddress - (EHFrameHeaderAddress + 4);
+    NewEHFrame.getEHFrameAddress() - (EHFrameHeaderAddress + 4);
 
   // Number of entries in the table (FDE count).
   support::ulittle32_t::ref(EHFrameHeader.data() + 8) = PCToFDE.size();
diff --git a/bolt/Exceptions.h b/bolt/Exceptions.h
index b38cb5c..fe0862f 100644
--- a/bolt/Exceptions.h
+++ b/bolt/Exceptions.h
@@ -14,7 +14,7 @@
 
 #include "BinaryContext.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/DebugInfo/DWARF/DWARFFrame.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
 #include "llvm/Support/Casting.h"
 #include <map>
 
@@ -28,10 +28,10 @@
 /// BinaryFunction, as well as rewriting CFI sections.
 class CFIReaderWriter {
 public:
-  explicit CFIReaderWriter(const DWARFFrame &EHFrame) {
+  explicit CFIReaderWriter(const DWARFDebugFrame &EHFrame) {
     // Prepare FDEs for fast lookup
-    for (const auto &Entry : EHFrame.Entries) {
-      const auto *CurFDE = dyn_cast<dwarf::FDE>(Entry.get());
+    for (const auto &Entry : EHFrame.entries()) {
+      const auto *CurFDE = dyn_cast<dwarf::FDE>(&Entry);
       // Skip CIEs.
       if (!CurFDE)
         continue;
@@ -69,8 +69,8 @@
   /// \p EHFrameHeaderAddress specifies location of .eh_frame_hdr,
   /// and is required for relative addressing used in the section.
   std::vector<char> generateEHFrameHeader(
-      const DWARFFrame &OldEHFrame,
-      const DWARFFrame &NewEHFrame,
+      const DWARFDebugFrame &OldEHFrame,
+      const DWARFDebugFrame &NewEHFrame,
       uint64_t EHFrameHeaderAddress,
       std::vector<uint64_t> &FailedAddresses) const;
 
diff --git a/bolt/Passes/BinaryFunctionCallGraph.cpp b/bolt/Passes/BinaryFunctionCallGraph.cpp
index 2b49f32..706caf9 100644
--- a/bolt/Passes/BinaryFunctionCallGraph.cpp
+++ b/bolt/Passes/BinaryFunctionCallGraph.cpp
@@ -37,8 +37,8 @@
 }
 
 std::deque<BinaryFunction *> BinaryFunctionCallGraph::buildTraversalOrder() {
-  NamedRegionTimer T1("Build cg traversal order", "CG breakdown",
-                      opts::TimeOpts);
+  NamedRegionTimer T1("buildcgorder", "Build cg traversal order",
+                      "CG breakdown", "CG breakdown", opts::TimeOpts);
   std::deque<BinaryFunction *> TopologicalOrder;
   enum NodeStatus { NEW, VISITING, VISITED };
   std::vector<NodeStatus> NodeStatus(Funcs.size());
@@ -85,7 +85,8 @@
                                        bool UseSplitHotSize,
                                        bool UseEdgeCounts,
                                        bool IgnoreRecursiveCalls) {
-  NamedRegionTimer T1("Callgraph construction", "CG breakdown", opts::TimeOpts);
+  NamedRegionTimer T1("buildcg", "Callgraph construction", "CG breakdown",
+                      "CG breakdown", opts::TimeOpts);
   BinaryFunctionCallGraph Cg;
   static constexpr auto COUNT_NO_PROFILE = BinaryBasicBlock::COUNT_NO_PROFILE;
 
@@ -161,7 +162,7 @@
           });
         return true;
       }
-      
+
       return false;
     };
 
diff --git a/bolt/Passes/BinaryPasses.cpp b/bolt/Passes/BinaryPasses.cpp
index f276251..d2c5402 100644
--- a/bolt/Passes/BinaryPasses.cpp
+++ b/bolt/Passes/BinaryPasses.cpp
@@ -111,8 +111,7 @@
     clEnumValN(PEEP_TAILCALL_TRAPS, "tailcall-traps", "insert tail call traps"),
     clEnumValN(PEEP_USELESS_BRANCHES, "useless-branches",
                "remove useless conditional branches"),
-    clEnumValN(PEEP_ALL, "all", "enable all peephole optimizations"),
-    clEnumValEnd),
+    clEnumValN(PEEP_ALL, "all", "enable all peephole optimizations")),
   cl::ZeroOrMore,
   cl::cat(BoltOptCategory));
 
@@ -135,7 +134,8 @@
                dynoStatsOptDesc(bolt::DynoStats::name)),
     DYNO_STATS
 #undef D
-    clEnumValEnd),
+    clEnumValN(0xffff, ".", ".")
+    ),
   cl::ZeroOrMore,
   cl::cat(BoltOptCategory));
 
@@ -166,8 +166,7 @@
       "perform layout optimizing I-cache behavior"),
     clEnumValN(bolt::ReorderBasicBlocks::LT_OPTIMIZE_SHUFFLE,
       "cluster-shuffle",
-      "perform random layout of clusters"),
-    clEnumValEnd),
+      "perform random layout of clusters")),
   cl::ZeroOrMore,
   cl::cat(BoltOptCategory));
 
@@ -196,8 +195,7 @@
       "preserved"),
     clEnumValN(SctcHeuristic,
       "heuristic",
-      "use branch prediction data to control sctc"),
-    clEnumValEnd),
+      "use branch prediction data to control sctc")),
   cl::ZeroOrMore,
   cl::cat(BoltOptCategory));
 
@@ -1539,16 +1537,10 @@
     for (auto &BB : BFI.second) {
       auto LastInstRIter = BB.getLastNonPseudo();
       if (LastInstRIter == BB.rend() ||
-          !BC.MIA->isReturn(*LastInstRIter))
+          !BC.MIA->isReturn(*LastInstRIter) ||
+          !BC.MIA->deleteREPPrefix(*LastInstRIter))
         continue;
 
-      auto NextToLastInstRIter = std::next(LastInstRIter);
-      if (NextToLastInstRIter == BB.rend() ||
-          !BC.MIA->isPrefix(*NextToLastInstRIter))
-        continue;
-
-      BB.eraseInstruction(std::next(NextToLastInstRIter).base());
-
       NumPrefixesRemoved += BB.getKnownExecutionCount();
       ++NumBytesSaved;
     }
diff --git a/bolt/Passes/CMakeLists.txt b/bolt/Passes/CMakeLists.txt
index 0255e7b..1473956 100644
--- a/bolt/Passes/CMakeLists.txt
+++ b/bolt/Passes/CMakeLists.txt
@@ -30,6 +30,9 @@
   StackPointerTracking.cpp
   StackReachingUses.cpp
   StokeInfo.cpp
+
+  DEPENDS
+  intrinsics_gen
   )
 
 include_directories( ${LLVM_MAIN_SRC_DIR}/tools/llvm-bolt )
diff --git a/bolt/Passes/CallGraphWalker.cpp b/bolt/Passes/CallGraphWalker.cpp
index 720dc6c..d3ebd6b 100644
--- a/bolt/Passes/CallGraphWalker.cpp
+++ b/bolt/Passes/CallGraphWalker.cpp
@@ -10,7 +10,8 @@
 namespace bolt {
 
 void CallGraphWalker::traverseCG() {
-  NamedRegionTimer T1("CG Traversal", "CG breakdown", opts::TimeOpts);
+  NamedRegionTimer T1("CG Traversal", "CG Traversal", "CG breakdown",
+                      "CG breakdown", opts::TimeOpts);
   std::queue<BinaryFunction *> Queue;
   std::set<BinaryFunction *> InQueue;
 
diff --git a/bolt/Passes/DominatorAnalysis.h b/bolt/Passes/DominatorAnalysis.h
index 5586dac..f807c57 100644
--- a/bolt/Passes/DominatorAnalysis.h
+++ b/bolt/Passes/DominatorAnalysis.h
@@ -104,7 +104,8 @@
   }
 
   void run() {
-    NamedRegionTimer T1("DA", "Dataflow", opts::TimeOpts);
+    NamedRegionTimer T1("DA", "Dominator Analysis", "Dataflow", "Dataflow",
+                        opts::TimeOpts);
     InstrsDataflowAnalysis<DominatorAnalysis<Backward>, Backward>::run();
   }
 
diff --git a/bolt/Passes/FrameAnalysis.cpp b/bolt/Passes/FrameAnalysis.cpp
index a4e1571..21223b3 100644
--- a/bolt/Passes/FrameAnalysis.cpp
+++ b/bolt/Passes/FrameAnalysis.cpp
@@ -152,7 +152,8 @@
   FrameAccessAnalysis(const BinaryContext &BC, BinaryFunction &BF)
       : SPT(BC, BF), BC(BC), BF(BF) {
     {
-      NamedRegionTimer T1("SPT", "Dataflow", opts::TimeOpts);
+      NamedRegionTimer T1("SPT", "Stack Pointer Tracking", "Dataflow",
+                          "Dataflow", opts::TimeOpts);
       SPT.run();
     }
   }
@@ -519,8 +520,8 @@
     }
 
     {
-      NamedRegionTimer T1("restore frame index", "FOP breakdown",
-                          opts::TimeOpts);
+      NamedRegionTimer T1("restorefi", "restore frame index", "FOP",
+                          "FOP breakdown", opts::TimeOpts);
       if (!restoreFrameIndex(I.second)) {
         ++NumFunctionsFailedRestoreFI;
         auto Count = I.second.getExecutionCount();
diff --git a/bolt/Passes/FrameOptimizer.cpp b/bolt/Passes/FrameOptimizer.cpp
index 30b3c84..7f0e521 100644
--- a/bolt/Passes/FrameOptimizer.cpp
+++ b/bolt/Passes/FrameOptimizer.cpp
@@ -35,8 +35,7 @@
   cl::values(
     clEnumValN(FOP_NONE, "none", "do not perform frame optimization"),
     clEnumValN(FOP_HOT, "hot", "perform FOP on hot functions"),
-    clEnumValN(FOP_ALL, "all", "perform FOP on all functions"),
-    clEnumValEnd),
+    clEnumValN(FOP_ALL, "all", "perform FOP on all functions")),
   cl::ZeroOrMore,
   cl::cat(BoltOptCategory));
 
@@ -249,18 +248,21 @@
                    << BC.getHotThreshold() << " )\n");
     }
     {
-      NamedRegionTimer T1("remove loads", "FOP breakdown", opts::TimeOpts);
+      NamedRegionTimer T1("removeloads", "remove loads", "FOP", "FOP breakdown",
+                          opts::TimeOpts);
       removeUnnecessaryLoads(RA, FA, BC, I.second);
     }
     if (opts::RemoveStores) {
-      NamedRegionTimer T1("remove stores", "FOP breakdown", opts::TimeOpts);
+      NamedRegionTimer T1("removestores", "remove stores", "FOP",
+                          "FOP breakdown", opts::TimeOpts);
       removeUnusedStores(FA, BC, I.second);
     }
     // Don't even start shrink wrapping if no profiling info is available
     if (I.second.getKnownExecutionCount() == 0)
       continue;
     {
-      NamedRegionTimer T1("move spills", "FOP breakdown", opts::TimeOpts);
+      NamedRegionTimer T1("movespills", "move spills", "FOP", "FOP breakdown",
+                          opts::TimeOpts);
       DataflowInfoManager Info(BC, I.second, &RA, &FA);
       ShrinkWrapping SW(FA, BC, I.second, Info);
       SW.perform();
diff --git a/bolt/Passes/IndirectCallPromotion.cpp b/bolt/Passes/IndirectCallPromotion.cpp
index 5bb0044..47a8cd6 100644
--- a/bolt/Passes/IndirectCallPromotion.cpp
+++ b/bolt/Passes/IndirectCallPromotion.cpp
@@ -35,8 +35,7 @@
     clEnumValN(ICP_NONE, "none", "do not perform indirect call promotion"),
     clEnumValN(ICP_CALLS, "calls", "perform ICP on indirect calls"),
     clEnumValN(ICP_JUMP_TABLES, "jump-tables", "perform ICP on jump tables"),
-    clEnumValN(ICP_ALL, "all", "perform ICP on calls and jump tables"),
-    clEnumValEnd),
+    clEnumValN(ICP_ALL, "all", "perform ICP on calls and jump tables")),
   cl::ZeroOrMore,
   cl::cat(BoltOptCategory));
 
@@ -174,7 +173,7 @@
     const auto *JI = JT->Counts.empty() ? &DefaultJI : &JT->Counts[Range.first];
     const size_t JIAdj = JT->Counts.empty() ? 0 : 1;
     assert(JT->Type == BinaryFunction::JumpTable::JTT_PIC ||
-           JT->EntrySize == BC.AsmInfo->getPointerSize());
+           JT->EntrySize == BC.AsmInfo->getCodePointerSize());
     for (size_t I = Range.first; I < Range.second; ++I, JI += JIAdj) {
       auto *Entry = JT->Entries[I];
       assert(BF.getBasicBlockForLabel(Entry) ||
@@ -307,16 +306,9 @@
   int64_t DispValue;
   const MCExpr *DispExpr;
   MutableArrayRef<MCInst> Insts(&BB->front(), &CallInst);
-  const auto Type = BC.MIA->analyzeIndirectBranch(CallInst,
-                                                  Insts.begin(),
-                                                  Insts.end(),
-                                                  BC.AsmInfo->getPointerSize(),
-                                                  MemLocInstr,
-                                                  BaseReg,
-                                                  IndexReg,
-                                                  DispValue,
-                                                  DispExpr,
-                                                  PCRelBaseOut);
+  const auto Type = BC.MIA->analyzeIndirectBranch(
+      CallInst, Insts.begin(), Insts.end(), BC.AsmInfo->getCodePointerSize(),
+      MemLocInstr, BaseReg, IndexReg, DispValue, DispExpr, PCRelBaseOut);
 
   assert(MemLocInstr && "There should always be a load for jump tables");
   if (!MemLocInstr)
@@ -665,7 +657,7 @@
 
   return MethodInfoType(VtableAddrs, MethodFetchInsns);
 }
-  
+
 std::vector<std::unique_ptr<BinaryBasicBlock>>
 IndirectCallPromotion::rewriteCall(
    BinaryContext &BC,
@@ -1201,7 +1193,7 @@
             for (const auto &BInfo : getCallTargets(Function, Inst)) {
               NumCalls += BInfo.Branches;
             }
-            
+
             IndirectCalls.push_back(std::make_pair(NumCalls, &Inst));
             TotalIndirectCalls += NumCalls;
           }
diff --git a/bolt/Passes/LivenessAnalysis.h b/bolt/Passes/LivenessAnalysis.h
index 1b22d0a..fa8347e 100644
--- a/bolt/Passes/LivenessAnalysis.h
+++ b/bolt/Passes/LivenessAnalysis.h
@@ -50,7 +50,8 @@
   }
 
   void run() {
-    NamedRegionTimer T1("LA", "Dataflow", opts::TimeOpts);
+    NamedRegionTimer T1("LA", "Liveness Analysis", "Dataflow", "Dataflow",
+                        opts::TimeOpts);
     Parent::run();
   }
 
diff --git a/bolt/Passes/LongJmp.cpp b/bolt/Passes/LongJmp.cpp
index 7a2beae..5b2e81f 100644
--- a/bolt/Passes/LongJmp.cpp
+++ b/bolt/Passes/LongJmp.cpp
@@ -130,7 +130,7 @@
   }
   BC.MIA->replaceBranchTarget(Inst, StubSymbol, BC.Ctx.get());
   ++StubRefCount[StubBB];
-  StubBits[StubBB] = BC.AsmInfo->getPointerSize() * 8;
+  StubBits[StubBB] = BC.AsmInfo->getCodePointerSize() * 8;
 
   if (NewBB) {
     if (BB.isCold())
@@ -216,7 +216,7 @@
   for (auto Func : SortedFunctions) {
     if (!Func->isSplit())
       continue;
-    DotAddress = RoundUpToAlignment(DotAddress, BinaryFunction::MinAlign);
+    DotAddress = alignTo(DotAddress, BinaryFunction::MinAlign);
     auto Pad = OffsetToAlignment(DotAddress, opts::AlignFunctions);
     if (Pad <= opts::AlignFunctionsMaxBytes)
       DotAddress += Pad;
@@ -253,7 +253,7 @@
       ColdLayoutDone = true;
     }
 
-    DotAddress = RoundUpToAlignment(DotAddress, BinaryFunction::MinAlign);
+    DotAddress = alignTo(DotAddress, BinaryFunction::MinAlign);
     auto Pad = OffsetToAlignment(DotAddress, opts::AlignFunctions);
     if (Pad <= opts::AlignFunctionsMaxBytes)
       DotAddress += Pad;
@@ -282,7 +282,7 @@
   if (!BC.HasRelocations) {
     for (auto Func : SortedFunctions) {
       HotAddresses[Func] = Func->getAddress();
-      DotAddress = RoundUpToAlignment(DotAddress, ColdFragAlign);
+      DotAddress = alignTo(DotAddress, ColdFragAlign);
       ColdAddresses[Func] = DotAddress;
       if (Func->isSplit())
         DotAddress += Func->estimateColdSize();
@@ -303,7 +303,7 @@
       DotAddress += Pad;
     }
   } else {
-    DotAddress = RoundUpToAlignment(BC.LayoutStartAddress, PageAlign);
+    DotAddress = alignTo(BC.LayoutStartAddress, PageAlign);
   }
 
   tentativeLayoutRelocMode(BC, SortedFunctions, DotAddress);
diff --git a/bolt/Passes/PLTCall.cpp b/bolt/Passes/PLTCall.cpp
index 78eba87..219ecc1 100644
--- a/bolt/Passes/PLTCall.cpp
+++ b/bolt/Passes/PLTCall.cpp
@@ -34,8 +34,7 @@
       "optimize executed (hot) PLT calls"),
     clEnumValN(bolt::PLTCall::OT_ALL,
       "all",
-      "optimize all PLT calls"),
-    clEnumValEnd),
+      "optimize all PLT calls")),
   cl::ZeroOrMore,
   cl::cat(BoltOptCategory));
 
diff --git a/bolt/Passes/ReachingDefOrUse.h b/bolt/Passes/ReachingDefOrUse.h
index 2113eb4..01ed496 100644
--- a/bolt/Passes/ReachingDefOrUse.h
+++ b/bolt/Passes/ReachingDefOrUse.h
@@ -58,7 +58,8 @@
   }
 
   void run() {
-    NamedRegionTimer T1("RD", "Dataflow", opts::TimeOpts);
+    NamedRegionTimer T1("RD", "Reaching Defs", "Dataflow", "Dataflow",
+                        opts::TimeOpts);
     InstrsDataflowAnalysis<ReachingDefOrUse<Def>, !Def>::run();
   }
 
diff --git a/bolt/Passes/ReachingInsns.h b/bolt/Passes/ReachingInsns.h
index 047c6e3..3706380 100644
--- a/bolt/Passes/ReachingInsns.h
+++ b/bolt/Passes/ReachingInsns.h
@@ -46,7 +46,8 @@
   }
 
   void run() {
-    NamedRegionTimer T1("RI", "Dataflow", opts::TimeOpts);
+    NamedRegionTimer T1("RI", "Reaching Insns", "Dataflow", "Dataflow",
+                        opts::TimeOpts);
     InstrsDataflowAnalysis<ReachingInsns<Backward>, Backward>::run();
   }
 
diff --git a/bolt/Passes/ReorderFunctions.cpp b/bolt/Passes/ReorderFunctions.cpp
index 3535588..fe4b144 100644
--- a/bolt/Passes/ReorderFunctions.cpp
+++ b/bolt/Passes/ReorderFunctions.cpp
@@ -51,8 +51,7 @@
       "reorder functions randomly"),
     clEnumValN(bolt::ReorderFunctions::RT_USER,
       "user",
-      "use function order specified by -function-order"),
-    clEnumValEnd),
+      "use function order specified by -function-order")),
   cl::cat(BoltOptCategory));
 
 static cl::opt<bool>
diff --git a/bolt/Passes/ShrinkWrapping.cpp b/bolt/Passes/ShrinkWrapping.cpp
index 56c57b5..a3bed48 100644
--- a/bolt/Passes/ShrinkWrapping.cpp
+++ b/bolt/Passes/ShrinkWrapping.cpp
@@ -1366,7 +1366,8 @@
         TodoMap(TodoMap), Info(Info) {}
 
   void run() {
-    NamedRegionTimer T1("PSPT", "Dataflow", opts::TimeOpts);
+    NamedRegionTimer T1("PSPT", "Predictive Stack Pointer Tracking", "Dataflow",
+                        "Dataflow", opts::TimeOpts);
     StackPointerTrackingBase<PredictiveStackPointerTracking>::run();
   }
 };
diff --git a/bolt/Passes/StackAllocationAnalysis.h b/bolt/Passes/StackAllocationAnalysis.h
index 2229144..19df811 100644
--- a/bolt/Passes/StackAllocationAnalysis.h
+++ b/bolt/Passes/StackAllocationAnalysis.h
@@ -41,7 +41,8 @@
   virtual ~StackAllocationAnalysis() {}
 
   void run() {
-    NamedRegionTimer T1("SAA", "Dataflow", opts::TimeOpts);
+    NamedRegionTimer T1("SAA", "Stack Allocation Analysis", "Dataflow",
+                        "Dataflow", opts::TimeOpts);
     InstrsDataflowAnalysis<StackAllocationAnalysis, false>::run();
   }
 
diff --git a/bolt/Passes/StackAvailableExpressions.h b/bolt/Passes/StackAvailableExpressions.h
index 8291ce5..c5b19d34 100644
--- a/bolt/Passes/StackAvailableExpressions.h
+++ b/bolt/Passes/StackAvailableExpressions.h
@@ -36,7 +36,8 @@
   virtual ~StackAvailableExpressions() {}
 
   void run() {
-    NamedRegionTimer T1("SAE", "Dataflow", opts::TimeOpts);
+    NamedRegionTimer T1("SAE", "Stack Available Expressions", "Dataflow",
+                        "Dataflow", opts::TimeOpts);
     InstrsDataflowAnalysis<StackAvailableExpressions>::run();
   }
 
diff --git a/bolt/Passes/StackPointerTracking.h b/bolt/Passes/StackPointerTracking.h
index cec3244..3438a07 100644
--- a/bolt/Passes/StackPointerTracking.h
+++ b/bolt/Passes/StackPointerTracking.h
@@ -204,7 +204,8 @@
   virtual ~StackPointerTracking() {}
 
   void run() {
-    NamedRegionTimer T1("SPT", "Dataflow", opts::TimeOpts);
+    NamedRegionTimer T1("SPT", "Stack Pointer Tracking", "Dataflow", "Dataflow",
+                        opts::TimeOpts);
     StackPointerTrackingBase<StackPointerTracking>::run();
   }
 };
diff --git a/bolt/Passes/StackReachingUses.h b/bolt/Passes/StackReachingUses.h
index bc34db3..3d8fa9d 100644
--- a/bolt/Passes/StackReachingUses.h
+++ b/bolt/Passes/StackReachingUses.h
@@ -51,7 +51,8 @@
                    bool IncludeLocalAccesses = true) const;
 
   void run() {
-    NamedRegionTimer T1("SRU", "Dataflow", opts::TimeOpts);
+    NamedRegionTimer T1("SRU", "Stack Reaching Uses", "Dataflow", "Dataflow",
+                        opts::TimeOpts);
     InstrsDataflowAnalysis<StackReachingUses, true>::run();
   }
 
diff --git a/bolt/RewriteInstance.cpp b/bolt/RewriteInstance.cpp
index 40871da..be8fcbc 100644
--- a/bolt/RewriteInstance.cpp
+++ b/bolt/RewriteInstance.cpp
@@ -23,22 +23,24 @@
 #include "RewriteInstance.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
-#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCAsmLayout.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCDisassembler/MCDisassembler.h"
 #include "llvm/MC/MCDwarf.h"
 #include "llvm/MC/MCInstPrinter.h"
 #include "llvm/MC/MCInstrAnalysis.h"
 #include "llvm/MC/MCInstrInfo.h"
 #include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCSection.h"
 #include "llvm/MC/MCSectionELF.h"
@@ -49,7 +51,6 @@
 #include "llvm/Object/SymbolicFile.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Dwarf.h"
 #include "llvm/Support/DataExtractor.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/ManagedStatic.h"
@@ -262,8 +263,7 @@
              clEnumValN(BinaryFunction::ST_LARGE, "2",
                         "also split if function too large to fit"),
              clEnumValN(BinaryFunction::ST_ALL, "3",
-                        "split all functions"),
-             clEnumValEnd),
+                        "split all functions")),
   cl::ZeroOrMore,
   cl::cat(BoltOptCategory));
 
@@ -420,7 +420,8 @@
 
 const std::string RewriteInstance::BOLTSecPrefix = ".bolt";
 
-const char RewriteInstance::TimerGroupName[] = "Rewrite passes";
+const char RewriteInstance::TimerGroupName[] = "rewrite";
+const char RewriteInstance::TimerGroupDesc[] = "Rewrite passes";
 
 namespace llvm {
 namespace bolt {
@@ -432,6 +433,13 @@
   exit(1);
 }
 
+void report_error(StringRef Message, Error E) {
+  assert(E);
+  errs() << "BOLT-ERROR: '" << Message << "': " << toString(std::move(E))
+         << ".\n";
+  exit(1);
+}
+
 void check_error(std::error_code EC, StringRef Message) {
   if (!EC)
     return;
@@ -447,6 +455,28 @@
                                                       StringRef SectionName,
                                                       bool IsCode,
                                                       bool IsReadOnly) {
+  // Register as note section (non-allocatable) if we recognize it as so
+  for (auto &OverwriteName : RewriteInstance::SectionsToOverwrite) {
+    if (SectionName == OverwriteName) {
+      uint8_t *DataCopy = new uint8_t[Size];
+      DEBUG(dbgs() << "BOLT: note section " << SectionName << " with size "
+                   << Size << ", alignment " << Alignment << " at 0x"
+                   << Twine::utohexstr(reinterpret_cast<uint64_t>(DataCopy))
+                   << '\n');
+      NoteSectionInfo[SectionName] =
+        SectionInfo(reinterpret_cast<uint64_t>(DataCopy),
+                    Size,
+                    Alignment,
+                    /*IsCode=*/false,
+                    /*IsReadOnly=*/true,
+                    /*IsLocal=*/false,
+                    0,
+                    0,
+                    SectionID);
+      return DataCopy;
+    }
+  }
+
   uint8_t *ret;
   if (IsCode) {
     ret = SectionMemoryManager::allocateCodeSection(Size, Alignment,
@@ -590,8 +620,7 @@
     llvm::make_unique<MCObjectFileInfo>();
   std::unique_ptr<MCContext> Ctx =
     llvm::make_unique<MCContext>(AsmInfo.get(), MRI.get(), MOFI.get());
-  MOFI->InitMCObjectFileInfo(*TheTriple, Reloc::Default,
-                             CodeModel::Small, *Ctx);
+  MOFI->InitMCObjectFileInfo(*TheTriple, /*PIC=*/false, *Ctx);
 
   std::unique_ptr<MCDisassembler> DisAsm(
     TheTarget->createMCDisassembler(*STI, *Ctx));
@@ -653,11 +682,12 @@
 RewriteInstance::RewriteInstance(ELFObjectFileBase *File, DataReader &DR,
                                  DataAggregator &DA, const int Argc,
                                  const char *const *Argv)
-  : InputFile(File), Argc(Argc), Argv(Argv), DA(DA),
-    BC(createBinaryContext(
-        File, DR,
-        std::unique_ptr<DWARFContext>(
-            new DWARFContextInMemory(*InputFile, nullptr, true)))) {}
+    : InputFile(File), Argc(Argc), Argv(Argv), DA(DA),
+      BC(createBinaryContext(
+          File, DR,
+          DWARFContext::create(*File, nullptr,
+                               DWARFContext::defaultErrorHandler, "", false))),
+      SHStrTab(StringTableBuilder::ELF) {}
 
 RewriteInstance::~RewriteInstance() {}
 
@@ -667,10 +697,11 @@
   auto &DR = BC->DR;
   BC = createBinaryContext(
       InputFile, DR,
-      std::unique_ptr<DWARFContext>(
-          new DWARFContextInMemory(*InputFile, nullptr, true)));
+      DWARFContext::create(*InputFile, nullptr,
+                           DWARFContext::defaultErrorHandler, "", false));
   CFIRdWrt.reset(nullptr);
-  EFMM.reset(nullptr);
+  OLT.reset(nullptr);
+  EFMM.reset();
   Out.reset(nullptr);
   EHFrame = nullptr;
   FailedAddresses.clear();
@@ -679,7 +710,8 @@
 }
 
 void RewriteInstance::discoverStorage() {
-  NamedRegionTimer T("discover storage", TimerGroupName, opts::TimeRewrite);
+  NamedRegionTimer T("discoverStorage", "discover storage", TimerGroupName,
+                     TimerGroupDesc, opts::TimeRewrite);
 
   // Stubs are harmful because RuntimeDyld may try to increase the size of
   // sections accounting for stubs when we need those sections to match the
@@ -702,7 +734,8 @@
 
   NextAvailableAddress = 0;
   uint64_t NextAvailableOffset = 0;
-  for (const auto &Phdr : Obj->program_headers()) {
+  auto PHs = cantFail(Obj->program_headers(), "program_headers() failed");
+  for (const auto &Phdr : PHs) {
     if (Phdr.p_type == ELF::PT_LOAD) {
       FirstAllocAddress = std::min(FirstAllocAddress,
                                    static_cast<uint64_t>(Phdr.p_vaddr));
@@ -746,8 +779,8 @@
 
   FirstNonAllocatableOffset = NextAvailableOffset;
 
-  NextAvailableAddress = RoundUpToAlignment(NextAvailableAddress, PageAlign);
-  NextAvailableOffset = RoundUpToAlignment(NextAvailableOffset, PageAlign);
+  NextAvailableAddress = alignTo(NextAvailableAddress, PageAlign);
+  NextAvailableOffset = alignTo(NextAvailableOffset, PageAlign);
 
   if (!opts::UseGnuStack) {
     // This is where the black magic happens. Creating PHDR table in a segment
@@ -784,8 +817,8 @@
   }
 
   // Align at cache line.
-  NextAvailableAddress = RoundUpToAlignment(NextAvailableAddress, 64);
-  NextAvailableOffset = RoundUpToAlignment(NextAvailableOffset, 64);
+  NextAvailableAddress = alignTo(NextAvailableAddress, 64);
+  NextAvailableOffset = alignTo(NextAvailableOffset, 64);
 
   NewTextSegmentAddress = NextAvailableAddress;
   NewTextSegmentOffset = NextAvailableOffset;
@@ -826,7 +859,7 @@
       return NoneType();
 
     StringRef Name = SectionContents.slice(Offset, Offset + NameSz);
-    Offset = RoundUpToAlignment(Offset + NameSz, 4);
+    Offset = alignTo(Offset + NameSz, 4);
     StringRef BinaryBuildID = SectionContents.slice(Offset, Offset + DescSz);
     if (Name.substr(0, 3) != "GNU")
       return NoneType();
@@ -949,8 +982,8 @@
 
   // Copy allocatable part of the input.
   std::error_code EC;
-  Out = llvm::make_unique<tool_output_file>(opts::OutputFilename, EC,
-                                            sys::fs::F_None, 0777);
+  Out = llvm::make_unique<ToolOutputFile>(opts::OutputFilename, EC,
+                                          sys::fs::F_None, 0777);
   check_error(EC, "cannot create output executable file");
   Out->os() << InputFile->getData().substr(0, FirstNonAllocatableOffset);
 
@@ -959,8 +992,8 @@
 }
 
 void RewriteInstance::discoverFileObjects() {
-  NamedRegionTimer T("discover file objects", TimerGroupName,
-                      opts::TimeRewrite);
+  NamedRegionTimer T("discoverFileObjects", "discover file objects",
+                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
 
   FileSymRefs.clear();
   BinaryFunctions.clear();
@@ -977,7 +1010,7 @@
   };
   std::unordered_map<SymbolRef, StringRef, SymbolRefHash> SymbolToFileName;
   for (const auto &Symbol : InputFile->symbols()) {
-    ErrorOr<StringRef> NameOrError = Symbol.getName();
+    auto NameOrError = Symbol.getName();
     if (NameOrError && NameOrError->startswith("__asan_init")) {
       errs() << "BOLT-ERROR: input file was compiled or linked with sanitizer "
                 "support. Cannot optimize.\n";
@@ -992,13 +1025,14 @@
     if (Symbol.getFlags() & SymbolRef::SF_Undefined)
       continue;
 
-    if (Symbol.getType() == SymbolRef::ST_File) {
-      check_error(NameOrError.getError(), "cannot get symbol name for file");
+    if (cantFail(Symbol.getType()) == SymbolRef::ST_File) {
+      auto Name =
+          cantFail(std::move(NameOrError), "cannot get symbol name for file");
       // Ignore Clang LTO artificial FILE symbol as it is not always generated,
       // and this uncertainty is causing havoc in function name matching.
-      if (*NameOrError == "ld-temp.o")
+      if (Name == "ld-temp.o")
         continue;
-      FileSymbolName = *NameOrError;
+      FileSymbolName = Name;
       SeenFileName = true;
       continue;
     }
@@ -1014,11 +1048,13 @@
   std::stable_sort(SortedFileSymbols.begin(), SortedFileSymbols.end(),
                    [](const SymbolRef &A, const SymbolRef &B) {
                      // FUNC symbols have higher precedence.
-                     if (*(A.getAddress()) == *(B.getAddress())) {
-                       return A.getType() == SymbolRef::ST_Function &&
-                              B.getType() != SymbolRef::ST_Function;
+                     auto AddressA = cantFail(A.getAddress());
+                     auto AddressB = cantFail(B.getAddress());
+                     if (AddressA == AddressB) {
+                       return cantFail(A.getType()) == SymbolRef::ST_Function &&
+                              cantFail(B.getType()) != SymbolRef::ST_Function;
                      }
-                     return *(A.getAddress()) < *(B.getAddress());
+                     return AddressA < AddressB;
                    });
 
   // For aarch64, the ABI defines mapping symbols so we identify data in the
@@ -1028,9 +1064,9 @@
     MarkersBegin = std::stable_partition(
         SortedFileSymbols.begin(), SortedFileSymbols.end(),
         [](const SymbolRef &Symbol) {
-          ErrorOr<StringRef> NameOrError = Symbol.getName();
-          return !(Symbol.getType() == SymbolRef::ST_Unknown &&
-                   (*NameOrError == "$d" || *NameOrError == "$x"));
+          StringRef Name = cantFail(Symbol.getName());
+          return !(cantFail(Symbol.getType()) == SymbolRef::ST_Unknown &&
+                   (Name == "$d" || Name == "$x"));
         });
   }
 
@@ -1041,17 +1077,15 @@
     if (Symbol.getFlags() & SymbolRef::SF_Undefined)
       continue;
 
-    if (Symbol.getType() == SymbolRef::ST_File)
+    if (cantFail(Symbol.getType()) == SymbolRef::ST_File)
       continue;
 
-    ErrorOr<StringRef> NameOrError = Symbol.getName();
-    check_error(NameOrError.getError(), "cannot get symbol name");
-
-    ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
-    check_error(AddressOrErr.getError(), "cannot get symbol address");
-    uint64_t Address = *AddressOrErr;
+    StringRef SymName = cantFail(Symbol.getName(), "cannot get symbol name");
+    uint64_t Address =
+        cantFail(Symbol.getAddress(), "cannot get symbol address");
     if (Address == 0) {
-      if (opts::Verbosity >= 1 && Symbol.getType() == SymbolRef::ST_Function)
+      if (opts::Verbosity >= 1 &&
+          cantFail(Symbol.getType()) == SymbolRef::ST_Function)
         errs() << "BOLT-WARNING: function with 0 address seen\n";
       continue;
     }
@@ -1060,16 +1094,15 @@
 
     // There's nothing horribly wrong with anonymous symbols, but let's
     // ignore them for now.
-    if (NameOrError->empty())
+    if (SymName.empty())
       continue;
 
     /// It is possible we are seeing a globalized local. LLVM might treat it as
     /// a local if it has a "private global" prefix, e.g. ".L". Thus we have to
     /// change the prefix to enforce global scope of the symbol.
-    std::string Name =
-      NameOrError->startswith(BC->AsmInfo->getPrivateGlobalPrefix())
-        ? "PG" + std::string(*NameOrError)
-        : std::string(*NameOrError);
+    std::string Name = SymName.startswith(BC->AsmInfo->getPrivateGlobalPrefix())
+                           ? "PG" + std::string(SymName)
+                           : std::string(SymName);
 
     // Disambiguate all local symbols before adding to symbol table.
     // Since we don't know if we will see a global with the same name,
@@ -1119,9 +1152,8 @@
     if (!AlternativeName.empty())
       BC->registerNameAtAddress(AlternativeName, Address);
 
-    ErrorOr<section_iterator> SectionOrErr = Symbol.getSection();
-    check_error(SectionOrErr.getError(), "cannot get symbol section");
-    section_iterator Section = *SectionOrErr;
+    section_iterator Section =
+        cantFail(Symbol.getSection(), "cannot get symbol section");
     if (Section == InputFile->section_end()) {
       // Could be an absolute symbol. Could record for pretty printing.
       continue;
@@ -1131,7 +1163,7 @@
                  << " for function\n");
 
     if (!Section->isText()) {
-      assert(Symbol.getType() != SymbolRef::ST_Function &&
+      assert(cantFail(Symbol.getType()) != SymbolRef::ST_Function &&
              "unexpected function inside non-code section");
       DEBUG(dbgs() << "BOLT-DEBUG: rejecting as symbol is not in code\n");
       continue;
@@ -1146,7 +1178,7 @@
     // Sometimes assembly functions are not marked as functions and neither are
     // their local labels. The only way to tell them apart is to look at
     // symbol scope - global vs local.
-    if (Symbol.getType() != SymbolRef::ST_Function) {
+    if (cantFail(Symbol.getType()) != SymbolRef::ST_Function) {
       if (PreviousFunction) {
         if (PreviousFunction->getSize() == 0) {
           if (PreviousFunction->isSymbolValidInScope(Symbol, SymbolSize)) {
@@ -1308,10 +1340,9 @@
   // Annotate functions with code/data markers in AArch64
   for (auto ISym = MarkersBegin; ISym != SortedFileSymbols.end(); ++ISym) {
     const auto &Symbol = *ISym;
-    ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
-    check_error(AddressOrErr.getError(), "cannot get symbol address");
+    uint64_t Address =
+        cantFail(Symbol.getAddress(), "cannot get symbol address");
     auto SymbolSize = ELFSymbolRef(Symbol).getSize();
-    uint64_t Address = *AddressOrErr;
     auto *BF = getBinaryFunctionContainingAddress(Address, true, true);
     if (!BF) {
       // Stray marker
@@ -1390,7 +1421,7 @@
         const auto SymbolIter = Rel.getSymbol();
         assert(SymbolIter != InputFile->symbol_end() &&
                "non-null symbol expected");
-        const auto SymbolName = *(*SymbolIter).getName();
+        const auto SymbolName = cantFail((*SymbolIter).getName());
         std::string Name = SymbolName.str() + "@PLT";
         auto *BF = createBinaryFunction(Name,
                                         *PLTSection,
@@ -1451,9 +1482,6 @@
 
       ++NextSymRefI;
     }
-    auto NextSymRefSectionI = (NextSymRefI == FileSymRefs.end())
-      ? InputFile->section_end()
-      : NextSymRefI->second.getSection();
 
     // Function runs at most till the end of the containing section.
     uint64_t NextObjectAddress = Function.getSection().getEndAddress();
@@ -1492,11 +1520,10 @@
 void RewriteInstance::relocateEHFrameSection() {
   assert(EHFrameSection && "non-empty .eh_frame section expected");
 
-  DWARFFrame EHFrame(EHFrameSection->getAddress());
+  DWARFDebugFrame EHFrame(true, EHFrameSection->getAddress());
   StringRef EHFrameSectionContents = EHFrameSection->getContents();
-  DataExtractor DE(EHFrameSectionContents,
-                   BC->AsmInfo->isLittleEndian(),
-                   BC->AsmInfo->getPointerSize());
+  DWARFDataExtractor DE(EHFrameSectionContents, BC->AsmInfo->isLittleEndian(),
+                        BC->AsmInfo->getCodePointerSize());
   auto createReloc = [&](uint64_t Value, uint64_t Offset, uint64_t DwarfType) {
     if (DwarfType == dwarf::DW_EH_PE_omit)
       return;
@@ -1518,10 +1545,12 @@
     case dwarf::DW_EH_PE_sdata4:
     case dwarf::DW_EH_PE_udata4:
       RelType = ELF::R_X86_64_PC32;
+      Offset -= 4;
       break;
     case dwarf::DW_EH_PE_sdata8:
     case dwarf::DW_EH_PE_udata8:
       RelType = ELF::R_X86_64_PC64;
+      Offset -= 8;
       break;
     }
 
@@ -1539,12 +1568,6 @@
   };
 
   EHFrame.parse(DE, createReloc);
-
-  if (!EHFrame.ParseError.empty()) {
-    errs() << "BOLT-ERROR: EHFrame reader failed with message \""
-           << EHFrame.ParseError << '\n';
-    exit(1);
-  }
 }
 
 BinaryFunction *RewriteInstance::createBinaryFunction(
@@ -1560,8 +1583,8 @@
 }
 
 void RewriteInstance::readSpecialSections() {
-  NamedRegionTimer T("read special sections", TimerGroupName,
-                      opts::TimeRewrite);
+  NamedRegionTimer T("readSpecialSections", "read special sections",
+                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
 
   bool HasTextRelocations = false;
 
@@ -1570,11 +1593,14 @@
     StringRef SectionName;
     check_error(Section.getName(SectionName), "cannot get section name");
     StringRef SectionContents;
-    check_error(Section.getContents(SectionContents),
-                "cannot get section contents");
-    ArrayRef<uint8_t> SectionData(
-        reinterpret_cast<const uint8_t *>(SectionContents.data()),
-        Section.getSize());
+    ArrayRef<uint8_t> SectionData;
+    if (!(ELFSectionRef(Section).getType() & ELF::SHT_NOBITS)) {
+      check_error(Section.getContents(SectionContents),
+                  "cannot get section contents");
+      SectionData = ArrayRef<uint8_t>(
+          reinterpret_cast<const uint8_t *>(SectionContents.data()),
+          Section.getSize());
+    }
 
     if (SectionName == ".gcc_except_table") {
       LSDAData = SectionData;
@@ -1612,14 +1638,9 @@
   EHFrame = BC->DwCtx->getEHFrame();
   if (opts::DumpEHFrame) {
     outs() << "BOLT-INFO: Dumping original binary .eh_frame\n";
-    EHFrame->dump(outs());
+    EHFrame->dump(outs(), NoneType());
   }
   CFIRdWrt.reset(new CFIReaderWriter(*EHFrame));
-  if (!EHFrame->ParseError.empty()) {
-    errs() << "BOLT-ERROR: EHFrame reader failed with message \""
-           << EHFrame->ParseError << '\n';
-    exit(1);
-  }
 }
 
 namespace {
@@ -1629,7 +1650,7 @@
   int64_t Addend = 0;
   const ELFFile<ELFT> &EF = *Obj->getELFFile();
   DataRefImpl Rel = RelRef.getRawDataRefImpl();
-  const auto *RelocationSection = *(EF.getSection(Rel.d.a));
+  const auto *RelocationSection = cantFail(EF.getSection(Rel.d.a));
   switch (RelocationSection->sh_type) {
   default: llvm_unreachable("unexpected relocation section type");
   case ELF::SHT_REL:
@@ -1668,21 +1689,21 @@
 
   const bool IsAArch64 = BC->TheTriple->getArch() == llvm::Triple::aarch64;
   const bool IsFromCode = RelocatedSection.isText();
-  
+
   // For value extraction.
   StringRef RelocatedSectionContents;
   RelocatedSection.getContents(RelocatedSectionContents);
   DataExtractor DE(RelocatedSectionContents,
                    BC->AsmInfo->isLittleEndian(),
-                   BC->AsmInfo->getPointerSize());
+                   BC->AsmInfo->getCodePointerSize());
 
   const bool IsPCRelative = Relocation::isPCRelative(Rel.getType());
   auto SymbolIter = Rel.getSymbol();
   assert(SymbolIter != InputFile->symbol_end() &&
          "relocation symbol must exist");
   auto Symbol = *SymbolIter;
-  SymbolName = *(Symbol.getName());
-  SymbolAddress = *(Symbol.getAddress());
+  SymbolName = cantFail(Symbol.getName());
+  SymbolAddress = cantFail(Symbol.getAddress());
   Addend = getRelocationAddend(InputFile, Rel);
 
   uint32_t RelocationOffset =
@@ -1698,9 +1719,9 @@
   }
 
   // Weird stuff - section symbols are marked as ST_Debug.
-  const bool SymbolIsSection = (Symbol.getType() == SymbolRef::ST_Debug);
-  const auto PCRelOffset =
-    IsPCRelative && !IsAArch64 ? Rel.getOffset() : 0;
+  const bool SymbolIsSection =
+      (cantFail(Symbol.getType()) == SymbolRef::ST_Debug);
+  const auto PCRelOffset = IsPCRelative && !IsAArch64 ? Rel.getOffset() : 0;
 
   // If no symbol has been found or if it is a relocation requiring the
   // creation of a GOT entry, do not link against the symbol but against
@@ -1781,10 +1802,10 @@
              << "; type name = " << TypeName
              << "; value = 0x" << Twine::utohexstr(ExtractedValue)
              << "; symbol = " << SymbolName
-             << "; symbol type = " << Symbol.getType()
+             << "; symbol type = " << cantFail(Symbol.getType())
              << "; symbol address = 0x" << Twine::utohexstr(SymbolAddress)
              << "; orig symbol address = 0x"
-             << Twine::utohexstr(*(Symbol.getAddress()))
+             << Twine::utohexstr(cantFail(Symbol.getAddress()))
              << "; symbol section = " << getSectionName(**Section)
              << "; addend = 0x" << Twine::utohexstr(Addend)
              << "; original addend = 0x"
@@ -1981,7 +2002,8 @@
 }
 
 void RewriteInstance::readDebugInfo() {
-  NamedRegionTimer T("read debug info", TimerGroupName, opts::TimeRewrite);
+  NamedRegionTimer T("readDebugInfo", "read debug info", TimerGroupName,
+                     TimerGroupDesc, opts::TimeRewrite);
   if (!opts::UpdateDebugSections)
     return;
 
@@ -1990,7 +2012,8 @@
 
 void RewriteInstance::processProfileData() {
   if (DA.started()) {
-    NamedRegionTimer T("aggregate data", TimerGroupName, opts::TimeRewrite);
+    NamedRegionTimer T("aggregate", "aggregate data", TimerGroupName,
+                       TimerGroupDesc, opts::TimeRewrite);
     DA.aggregate(*BC.get(), BinaryFunctions);
 
     for (auto &BFI : BinaryFunctions) {
@@ -2004,7 +2027,8 @@
       }
     }
   } else {
-    NamedRegionTimer T("read profile data", TimerGroupName, opts::TimeRewrite);
+    NamedRegionTimer T("readprofile", "read profile data", TimerGroupName,
+                       TimerGroupDesc, opts::TimeRewrite);
 
     if (!opts::BoltProfile.empty()) {
       ProfileReader PR;
@@ -2042,8 +2066,8 @@
 }
 
 void RewriteInstance::disassembleFunctions() {
-  NamedRegionTimer T("disassemble functions", TimerGroupName,
-                      opts::TimeRewrite);
+  NamedRegionTimer T("disassembleFunctions", "disassemble functions",
+                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
   for (auto &BFI : BinaryFunctions) {
     BinaryFunction &Function = BFI.second;
 
@@ -2190,8 +2214,8 @@
 }
 
 void RewriteInstance::runOptimizationPasses() {
-  NamedRegionTimer T("run optimization passes", TimerGroupName,
-                     opts::TimeRewrite);
+  NamedRegionTimer T("runOptimizationPasses", "run optimization passes",
+                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
   BinaryFunctionPassManager::runAllPasses(*BC, BinaryFunctions, LargeFunctions);
 }
 
@@ -2232,7 +2256,6 @@
       Streamer.EmitCodeAlignment(Function.getAlignment(), MaxAlignBytes);
   } else {
     Streamer.EmitCodeAlignment(Function.getAlignment());
-    Streamer.setCodeSkew(EmitColdPart ? 0 : Function.getAddress());
   }
 
   MCContext &Context = Streamer.getContext();
@@ -2293,7 +2316,7 @@
   if (auto Padding = opts::padFunction(Function)) {
     DEBUG(dbgs() << "BOLT-DEBUG: padding function " << Function << " with "
                  << Padding << " bytes\n");
-    Streamer.EmitFill(Padding, MAI->getTextAlignFillValue());
+    Streamer.emitFill(Padding, MAI->getTextAlignFillValue());
   }
 
   if (opts::MarkFuncs) {
@@ -2328,14 +2351,15 @@
 } // anonymous namespace
 
 void RewriteInstance::emitFunctions() {
-  NamedRegionTimer T("emit functions", TimerGroupName, opts::TimeRewrite);
+  NamedRegionTimer T("emitFunctions", "emit functions", TimerGroupName,
+                     TimerGroupDesc, opts::TimeRewrite);
   std::error_code EC;
 
   // This is an object file, which we keep for debugging purposes.
   // Once we decide it's useless, we should create it in memory.
-  std::unique_ptr<tool_output_file> TempOut =
-    llvm::make_unique<tool_output_file>(opts::OutputFilename + ".bolt.o",
-                                        EC, sys::fs::F_None);
+  std::unique_ptr<ToolOutputFile> TempOut =
+    llvm::make_unique<ToolOutputFile>(opts::OutputFilename + ".bolt.o",
+                                      EC, sys::fs::F_None);
   check_error(EC, "cannot create output object file");
 
   std::unique_ptr<buffer_ostream> BOS =
@@ -2346,16 +2370,14 @@
   // and MCCodeEmitter (MCE). ~MCObjectStreamer() will delete these
   // two instances.
   auto MCE = BC->TheTarget->createMCCodeEmitter(*BC->MII, *BC->MRI, *BC->Ctx);
-  auto MAB = BC->TheTarget->createMCAsmBackend(*BC->MRI, BC->TripleName, "");
-  std::unique_ptr<MCStreamer> Streamer(
-    BC->TheTarget->createMCObjectStreamer(*BC->TheTriple,
-                                          *BC->Ctx,
-                                          *MAB,
-                                          *OS,
-                                          MCE,
-                                          *BC->STI,
-                                          /* RelaxAll */ false,
-                                          /* DWARFMustBeAtTheEnd */ false));
+  auto MAB =
+      BC->TheTarget->createMCAsmBackend(*BC->STI, *BC->MRI, MCTargetOptions());
+  std::unique_ptr<MCStreamer> Streamer(BC->TheTarget->createMCObjectStreamer(
+      *BC->TheTriple, *BC->Ctx, std::unique_ptr<MCAsmBackend>(MAB), *OS,
+      std::unique_ptr<MCCodeEmitter>(MCE), *BC->STI,
+      /* RelaxAll */ false,
+      /* IncrementalLinkerCompatible */ false,
+      /* DWARFMustBeAtTheEnd */ false));
 
   Streamer->InitSections(false);
 
@@ -2465,18 +2487,17 @@
   // Get output object as ObjectFile.
   std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
       MemoryBuffer::getMemBuffer(BOS->str(), "in-memory object file", false);
-  ErrorOr<std::unique_ptr<object::ObjectFile>> ObjOrErr =
-    object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef());
-  check_error(ObjOrErr.getError(), "error creating in-memory object");
+  std::unique_ptr<object::ObjectFile> Obj = cantFail(
+      object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
+      "error creating in-memory object");
 
   auto Resolver = orc::createLambdaResolver(
-          [&](const std::string &Name) {
+          [&](const std::string &Name) -> JITSymbol {
             DEBUG(dbgs() << "BOLT: looking for " << Name << "\n");
             auto I = BC->GlobalSymbols.find(Name);
             if (I == BC->GlobalSymbols.end())
-              return RuntimeDyld::SymbolInfo(nullptr);
-            return RuntimeDyld::SymbolInfo(I->second,
-                                           JITSymbolFlags::None);
+              return JITSymbol(nullptr);
+            return JITSymbol(I->second, JITSymbolFlags());
           },
           [](const std::string &S) {
             DEBUG(dbgs() << "BOLT: resolving " << S << "\n");
@@ -2485,21 +2506,35 @@
       );
   Resolver->setAllowsZeroSymbols(true);
 
-  auto ObjectsHandle = OLT.addObjectSet(
-        singletonSet(std::move(ObjOrErr.get())),
-        EFMM.get(),
-        std::move(Resolver),
-        /* ProcessAllSections = */true);
-
-  // Assign addresses to all sections.
-  mapFileSections(ObjectsHandle);
-
-  // Update output addresses based on the new section map and layout.
   MCAsmLayout FinalLayout(
         static_cast<MCObjectStreamer *>(Streamer.get())->getAssembler());
-  updateOutputValues(FinalLayout);
 
-  OLT.emitAndFinalize(ObjectsHandle);
+  OLT.reset(new decltype(OLT)::element_type(
+      [this]() {
+        // Get memory manager
+        return EFMM;
+      },
+      [&](orc::RTDyldObjectLinkingLayerBase::ObjHandleT Handle,
+          const orc::RTDyldObjectLinkingLayer::ObjectPtr &Obj,
+          const RuntimeDyld::LoadedObjectInfo &) {
+        // On NotifyLoaded...
+        // Assign addresses to all sections.
+        mapFileSections(Handle);
+
+        // Update output addresses based on the new section map and
+        // layout.
+        updateOutputValues(FinalLayout);
+      }));
+
+  OLT->setProcessAllSections(true);
+  auto ObjectsHandle = cantFail(
+      OLT->addObject(std::unique_ptr<OwningBinary<object::ObjectFile>>(
+                        new OwningBinary<object::ObjectFile>(
+                            std::move(Obj), std::move(ObjectMemBuffer))),
+                     std::move(Resolver)),
+      "failed in addObject()");
+
+  cantFail(OLT->emitAndFinalize(ObjectsHandle));
 
   if (opts::PrintCacheMetrics) {
     outs() << "BOLT-INFO: cache metrics after emitting functions:\n";
@@ -2511,7 +2546,7 @@
 }
 
 void RewriteInstance::mapFileSections(
-    orc::ObjectLinkingLayer<>::ObjSetHandleT &ObjectsHandle) {
+    orc::RTDyldObjectLinkingLayer::ObjHandleT &ObjectsHandle) {
   NewTextSectionStartAddress = NextAvailableAddress;
   if (BC->HasRelocations) {
     auto SMII = EFMM->SectionMapInfo.find(".text");
@@ -2550,9 +2585,9 @@
                  << Twine::utohexstr(SMII->second.AllocAddress)
                  << " to 0x" << Twine::utohexstr(NewTextSectionStartAddress)
                  << '\n');
-    OLT.mapSectionAddress(ObjectsHandle,
-                          SI.SectionID,
-                          NewTextSectionStartAddress);
+    OLT->mapSectionAddress(ObjectsHandle,
+                           SI.SectionID,
+                           NewTextSectionStartAddress);
   } else {
     for (auto &BFI : BinaryFunctions) {
       auto &Function = BFI.second;
@@ -2567,9 +2602,9 @@
                    << Twine::utohexstr(SMII->second.AllocAddress)
                    << " to 0x" << Twine::utohexstr(Function.getAddress())
                    << '\n');
-      OLT.mapSectionAddress(ObjectsHandle,
-                            SMII->second.SectionID,
-                            Function.getAddress());
+      OLT->mapSectionAddress(ObjectsHandle,
+                             SMII->second.SectionID,
+                             Function.getAddress());
       Function.setImageAddress(SMII->second.AllocAddress);
       Function.setImageSize(SMII->second.Size);
       if (Function.getImageSize() > Function.getMaxSize()) {
@@ -2588,9 +2623,9 @@
           JT.SecInfo->FileAddress = JT.Address;
           DEBUG(dbgs() << "BOLT-DEBUG: mapping " << JT.SectionName << " to 0x"
                        << Twine::utohexstr(JT.Address) << '\n');
-          OLT.mapSectionAddress(ObjectsHandle,
-                                JT.SecInfo->SectionID,
-                                JT.Address);
+          OLT->mapSectionAddress(ObjectsHandle,
+                                 JT.SecInfo->SectionID,
+                                 JT.Address);
         }
       }
 
@@ -2601,7 +2636,7 @@
       assert(SMII != EFMM->SectionMapInfo.end() &&
              "cannot find section for cold part");
       // Cold fragments are aligned at 16 bytes.
-      NextAvailableAddress = RoundUpToAlignment(NextAvailableAddress, 16);
+      NextAvailableAddress = alignTo(NextAvailableAddress, 16);
       auto &ColdPart = Function.cold();
       if (TooLarge) {
         // The corresponding FDE will refer to address 0.
@@ -2622,9 +2657,9 @@
                    << Twine::utohexstr(ColdPart.getAddress())
                    << " with size "
                    << Twine::utohexstr(ColdPart.getImageSize()) << '\n');
-      OLT.mapSectionAddress(ObjectsHandle,
-                            SMII->second.SectionID,
-                            ColdPart.getAddress());
+      OLT->mapSectionAddress(ObjectsHandle,
+                             SMII->second.SectionID,
+                             ColdPart.getAddress());
 
       NextAvailableAddress += ColdPart.getImageSize();
     }
@@ -2657,16 +2692,15 @@
     if (SMII == EFMM->SectionMapInfo.end())
       continue;
     SectionInfo &SI = SMII->second;
-    NextAvailableAddress = RoundUpToAlignment(NextAvailableAddress,
-                                              SI.Alignment);
+    NextAvailableAddress = alignTo(NextAvailableAddress, SI.Alignment);
     DEBUG(dbgs() << "BOLT: mapping section " << SectionName << " (0x"
                  << Twine::utohexstr(SI.AllocAddress)
                  << ") to 0x" << Twine::utohexstr(NextAvailableAddress)
                  << '\n');
 
-    OLT.mapSectionAddress(ObjectsHandle,
-                          SI.SectionID,
-                          NextAvailableAddress);
+    OLT->mapSectionAddress(ObjectsHandle,
+                           SI.SectionID,
+                           NextAvailableAddress);
     SI.FileAddress = NextAvailableAddress;
     SI.FileOffset = getFileOffsetForAddress(NextAvailableAddress);
 
@@ -2696,9 +2730,9 @@
                  << ") to 0x" << Twine::utohexstr(Section.getAddress())
                  << '\n');
 
-    OLT.mapSectionAddress(ObjectsHandle,
-                          SI.SectionID,
-                          Section.getAddress());
+    OLT->mapSectionAddress(ObjectsHandle,
+                           SI.SectionID,
+                           Section.getAddress());
     SI.FileAddress = Section.getAddress();
 
     StringRef SectionContents = Section.getContents();
@@ -2730,10 +2764,10 @@
       Function.setOutputSize(EndOffset - StartOffset);
       if (Function.isSplit()) {
         const auto *ColdStartSymbol = Function.getColdSymbol();
-        assert(ColdStartSymbol && ColdStartSymbol->isDefined(false) &&
+        assert(ColdStartSymbol && ColdStartSymbol->isDefined() &&
                "split function should have defined cold symbol");
         const auto *ColdEndSymbol = Function.getFunctionColdEndLabel();
-        assert(ColdEndSymbol && ColdEndSymbol->isDefined(false) &&
+        assert(ColdEndSymbol && ColdEndSymbol->isDefined() &&
                "split function should have defined cold end symbol");
         const auto ColdStartOffset = Layout.getSymbolOffset(*ColdStartSymbol);
         const auto ColdEndOffset = Layout.getSymbolOffset(*ColdEndSymbol);
@@ -2763,7 +2797,7 @@
     for (auto BBI = Function.layout_begin(), BBE = Function.layout_end();
          BBI != BBE; ++BBI) {
       auto *BB = *BBI;
-      assert(BB->getLabel()->isDefined(false) && "symbol should be defined");
+      assert(BB->getLabel()->isDefined() && "symbol should be defined");
       uint64_t BaseAddress;
       if (BC->HasRelocations) {
         BaseAddress = NewTextSectionStartAddress;
@@ -2900,7 +2934,7 @@
   (void)AddedSegment;
 
   // Copy existing program headers with modifications.
-  for (auto &Phdr : Obj->program_headers()) {
+  for (auto &Phdr : cantFail(Obj->program_headers())) {
     auto NewPhdr = Phdr;
     if (PHDRTableAddress && Phdr.p_type == ELF::PT_PHDR) {
       NewPhdr.p_offset = PHDRTableOffset;
@@ -2986,7 +3020,7 @@
   OS.seek(NextAvailableOffset);
 
   // Copy over non-allocatable section contents and update file offsets.
-  for (auto &Section : Obj->sections()) {
+  for (auto &Section : cantFail(Obj->sections())) {
     if (Section.sh_type == ELF::SHT_NULL)
       continue;
     if (Section.sh_flags & ELF::SHF_ALLOC)
@@ -2999,17 +3033,17 @@
     NextAvailableOffset =
       appendPadding(OS, NextAvailableOffset, Section.sh_addralign);
 
-    ErrorOr<StringRef> SectionName = Obj->getSectionName(&Section);
-    check_error(SectionName.getError(), "cannot get section name");
+    StringRef SectionName =
+        cantFail(Obj->getSectionName(&Section), "cannot get section name");
 
     // New section size.
     uint64_t Size = 0;
 
     // Copy over section contents unless it's one of the sections we overwrite.
-    if (!willOverwriteSection(*SectionName)) {
+    if (!willOverwriteSection(SectionName)) {
       Size = Section.sh_size;
       std::string Data = InputFile->getData().substr(Section.sh_offset, Size);
-      auto SectionPatchersIt = SectionPatchers.find(*SectionName);
+      auto SectionPatchersIt = SectionPatchers.find(SectionName);
       if (SectionPatchersIt != SectionPatchers.end()) {
         (*SectionPatchersIt->second).patchBinary(Data);
       }
@@ -3023,8 +3057,7 @@
     uint64_t Address{0};
 
     // Perform section post-processing.
-
-    auto SII = EFMM->NoteSectionInfo.find(*SectionName);
+    auto SII = EFMM->NoteSectionInfo.find(SectionName);
     if (SII != EFMM->NoteSectionInfo.end()) {
       auto &SI = SII->second;
       assert(SI.Alignment <= Section.sh_addralign &&
@@ -3035,14 +3068,14 @@
       if (Address) {
         DEBUG(dbgs() << "BOLT-DEBUG: " << (Size ? "appending" : "writing")
                      << " contents to section "
-                     << *SectionName << '\n');
+                     << SectionName << '\n');
         OS.write(reinterpret_cast<const char *>(Address), SI.Size);
         Size += SI.Size;
       }
 
       if (!SI.PendingRelocs.empty()) {
         DEBUG(dbgs() << "BOLT-DEBUG: processing relocs for section "
-                     << *SectionName << '\n');
+                     << SectionName << '\n');
         for (auto &Reloc : SI.PendingRelocs) {
           DEBUG(dbgs() << "BOLT-DEBUG: writing value "
                        << Twine::utohexstr(Reloc.Value)
@@ -3059,7 +3092,7 @@
     }
 
     // Set/modify section info.
-    EFMM->NoteSectionInfo[*SectionName] =
+    EFMM->NoteSectionInfo[SectionName] =
       SectionInfo(Address,
                   Size,
                   Section.sh_addralign,
@@ -3097,12 +3130,15 @@
   auto *Obj = File->getELFFile();
 
   // Pre-populate section header string table.
-  for (auto &Section : Obj->sections()) {
-    ErrorOr<StringRef> SectionName = Obj->getSectionName(&Section);
-    check_error(SectionName.getError(), "cannot get section name");
-    SHStrTab.add(*SectionName);
-    if (willOverwriteSection(*SectionName))
-      SHStrTab.add(OrgSecPrefix + SectionName->str());
+  for (auto &Section : cantFail(Obj->sections())) {
+    StringRef SectionName =
+        cantFail(Obj->getSectionName(&Section), "cannot get section name");
+    SHStrTab.add(SectionName);
+    if (willOverwriteSection(SectionName)) {
+      AllSHStrTabStrings.emplace_back(
+          SHStrTabPool.intern(OrgSecPrefix + SectionName.str()));
+      SHStrTab.add(*AllSHStrTabStrings.back());
+    }
   }
   for (auto &SMII : EFMM->SectionMapInfo) {
     SHStrTab.add(SMII.first);
@@ -3110,11 +3146,12 @@
   for (auto &SMII : EFMM->NoteSectionInfo) {
     SHStrTab.add(SMII.first);
   }
-  SHStrTab.finalize(StringTableBuilder::ELF);
+  SHStrTab.finalize();
 
-  const auto SHStrTabSize = SHStrTab.data().size();
+  const auto SHStrTabSize = SHStrTab.getSize();
   uint8_t *DataCopy = new uint8_t[SHStrTabSize];
-  memcpy(DataCopy, SHStrTab.data().data(), SHStrTabSize);
+  memset(DataCopy, 0, SHStrTabSize);
+  SHStrTab.write(DataCopy);
   EFMM->NoteSectionInfo[".shstrtab"] =
     SectionInfo(reinterpret_cast<uint64_t>(DataCopy),
                 SHStrTabSize,
@@ -3147,12 +3184,12 @@
     OS.write(reinterpret_cast<const char*>(&(Type)), 4);
     OS << NameStr;
     for (uint64_t I = NameStr.size();
-         I < RoundUpToAlignment(NameStr.size(), 4); ++I) {
+         I < alignTo(NameStr.size(), 4); ++I) {
       OS << '\0';
     }
     OS << DescStr;
     for (uint64_t I = DescStr.size();
-         I < RoundUpToAlignment(DescStr.size(), 4); ++I) {
+         I < alignTo(DescStr.size(), 4); ++I) {
       OS << '\0';
     }
 
@@ -3181,14 +3218,16 @@
 RewriteInstance::getOutputSections(ELFObjectFile<ELFT> *File,
                                    std::vector<ELFShdrTy> *OutputSections) {
   auto *Obj = File->getELFFile();
+  auto Sections = cantFail(Obj->sections());
 
-  std::vector<uint32_t> NewSectionIndex(Obj->getNumSections(), 0);
+  std::vector<uint32_t> NewSectionIndex(
+      std::distance(Sections.begin(), Sections.end()), 0);
   NewTextSectionIndex = 0;
   uint32_t CurIndex{0};
 
   // Copy over entries for original allocatable sections with minor
   // modifications (e.g. name).
-  for (auto &Section : Obj->sections()) {
+  for (auto &Section : Sections) {
     // Always ignore this section.
     if (Section.sh_type == ELF::SHT_NULL) {
       NewSectionIndex[0] = CurIndex++;
@@ -3209,27 +3248,27 @@
     if (!(Section.sh_flags & ELF::SHF_ALLOC))
       continue;
 
-    NewSectionIndex[std::distance(Obj->section_begin(), &Section)] =
+    NewSectionIndex[std::distance(Sections.begin(), &Section)] =
       CurIndex++;
 
     // If only computing the map, we're done with this iteration
     if (!OutputSections)
       continue;
 
-    ErrorOr<StringRef> SectionName = Obj->getSectionName(&Section);
-    check_error(SectionName.getError(), "cannot get section name");
+    StringRef SectionName =
+        cantFail(Obj->getSectionName(&Section), "cannot get section name");
 
     auto NewSection = Section;
-    if (*SectionName == ".bss") {
+    if (SectionName == ".bss") {
       // .bss section offset matches that of the next section.
       NewSection.sh_offset = NewTextSegmentOffset;
     }
 
-    if (willOverwriteSection(*SectionName)) {
+    if (willOverwriteSection(SectionName)) {
       NewSection.sh_name = SHStrTab.getOffset(OrgSecPrefix +
-                                              SectionName->str());
+                                              SectionName.str());
     } else {
-      NewSection.sh_name = SHStrTab.getOffset(*SectionName);
+      NewSection.sh_name = SHStrTab.getOffset(SectionName);
     }
 
     OutputSections->emplace_back(NewSection);
@@ -3278,7 +3317,7 @@
 
   // Copy over entries for non-allocatable sections performing necessary
   // adjustments.
-  for (auto &Section : Obj->sections()) {
+  for (auto &Section : Sections) {
     if (Section.sh_type == ELF::SHT_NULL)
       continue;
     if (Section.sh_flags & ELF::SHF_ALLOC)
@@ -3287,17 +3326,17 @@
     if (Section.sh_type == ELF::SHT_RELA)
       continue;
 
-    NewSectionIndex[std::distance(Obj->section_begin(), &Section)] =
+    NewSectionIndex[std::distance(Sections.begin(), &Section)] =
       CurIndex++;
 
     // If only computing the map, we're done with this iteration
     if (!OutputSections)
       continue;
 
-    ErrorOr<StringRef> SectionName = Obj->getSectionName(&Section);
-    check_error(SectionName.getError(), "cannot get section name");
+    StringRef SectionName =
+        cantFail(Obj->getSectionName(&Section), "cannot get section name");
 
-    auto SII = EFMM->NoteSectionInfo.find(*SectionName);
+    auto SII = EFMM->NoteSectionInfo.find(SectionName);
     assert(SII != EFMM->NoteSectionInfo.end() &&
            "missing section info for non-allocatable section");
 
@@ -3305,7 +3344,7 @@
     auto NewSection = Section;
     NewSection.sh_offset = SI.FileOffset;
     NewSection.sh_size = SI.Size;
-    NewSection.sh_name = SHStrTab.getOffset(*SectionName);
+    NewSection.sh_name = SHStrTab.getOffset(SectionName);
 
     OutputSections->emplace_back(NewSection);
 
@@ -3436,10 +3475,10 @@
                                std::function<void(size_t, const char *, size_t)>
                                Write,
                                std::function<size_t(StringRef)> AddToStrTab) {
-    auto StringSection = *Obj->getStringTableForSymtab(*Section);
+    auto StringSection = cantFail(Obj->getStringTableForSymtab(*Section));
     unsigned IsHotTextUpdated = 0;
 
-    for (const Elf_Sym &Symbol : Obj->symbols(Section)) {
+    for (const Elf_Sym &Symbol : cantFail(Obj->symbols(Section))) {
       auto NewSymbol = Symbol;
       const auto *Function = getBinaryFunctionAtAddress(Symbol.st_value);
       // Some section symbols may be mistakenly associated with the first
@@ -3456,9 +3495,10 @@
         if (!PatchExisting && Function->isSplit()) {
           auto NewColdSym = NewSymbol;
           SmallVector<char, 256> Buf;
-          NewColdSym.st_name = AddToStrTab(Twine(*Symbol.getName(StringSection))
-                                               .concat(".cold.0")
-                                               .toStringRef(Buf));
+          NewColdSym.st_name =
+              AddToStrTab(Twine(cantFail(Symbol.getName(StringSection)))
+                              .concat(".cold.0")
+                              .toStringRef(Buf));
           NewColdSym.st_value = Function->cold().getAddress();
           NewColdSym.st_size = Function->cold().getImageSize();
           Write(0, reinterpret_cast<const char *>(&NewColdSym),
@@ -3511,9 +3551,9 @@
         if (NewSymbol.getType() == ELF::STT_NOTYPE &&
             NewSymbol.getBinding() == ELF::STB_LOCAL &&
             NewSymbol.st_size == 0) {
-          if (auto SecOrErr =
-                  File->getELFFile()->getSection(NewSymbol.st_shndx)) {
-            auto Section = *SecOrErr;
+          auto ExpectedSec = File->getELFFile()->getSection(NewSymbol.st_shndx);
+          if (ExpectedSec) {
+            auto Section = *ExpectedSec;
             if (Section->sh_type == ELF::SHT_PROGBITS &&
                 Section->sh_flags & ELF::SHF_ALLOC &&
                 Section->sh_flags & ELF::SHF_EXECINSTR) {
@@ -3524,6 +3564,8 @@
               // If patching an existing symtab, patch this value to zero.
               NewSymbol.st_value = 0;
             }
+          } else {
+            consumeError(ExpectedSec.takeError());
           }
         }
       }
@@ -3538,13 +3580,14 @@
           return true;
         };
 
-        auto SymbolName = Symbol.getName(StringSection);
-        assert(SymbolName && "cannot get symbol name");
-        if (*SymbolName == "__hot_start" || *SymbolName == "__hot_end")
-          updateSymbolValue(*SymbolName);
+        auto SymbolName =
+            cantFail(Symbol.getName(StringSection), "cannot get symbol name");
+        if (SymbolName == "__hot_start" || SymbolName == "__hot_end")
+          updateSymbolValue(SymbolName);
       }
 
-      Write((&Symbol - Obj->symbol_begin(Section)) * sizeof(Elf_Sym),
+      Write((&Symbol - cantFail(Obj->symbols(Section)).begin()) *
+                sizeof(Elf_Sym),
             reinterpret_cast<const char *>(&NewSymbol), sizeof(NewSymbol));
     }
 
@@ -3572,7 +3615,7 @@
 
   // Update dynamic symbol table.
   const Elf_Shdr *DynSymSection = nullptr;
-  for (const Elf_Shdr &Section : Obj->sections()) {
+  for (const Elf_Shdr &Section : cantFail(Obj->sections())) {
     if (Section.sh_type == ELF::SHT_DYNSYM) {
       DynSymSection = &Section;
       break;
@@ -3588,7 +3631,7 @@
 
   // (re)create regular symbol table.
   const Elf_Shdr *SymTabSection = nullptr;
-  for (const auto &Section : Obj->sections()) {
+  for (const auto &Section : cantFail(Obj->sections())) {
     if (Section.sh_type == ELF::SHT_SYMTAB) {
       SymTabSection = &Section;
       break;
@@ -3599,12 +3642,13 @@
     return;
   }
 
-  const Elf_Shdr *StrTabSection = *Obj->getSection(SymTabSection->sh_link);
+  const Elf_Shdr *StrTabSection =
+      cantFail(Obj->getSection(SymTabSection->sh_link));
   std::string NewContents;
   std::string NewStrTab =
       File->getData().substr(StrTabSection->sh_offset, StrTabSection->sh_size);
-  auto SecName = *Obj->getSectionName(SymTabSection);
-  auto StrSecName = *Obj->getSectionName(StrTabSection);
+  auto SecName = cantFail(Obj->getSectionName(SymTabSection));
+  auto StrSecName = cantFail(Obj->getSectionName(StrTabSection));
 
   updateSymbolTable(/*patch existing table?*/false, SymTabSection,
                     [&](size_t Offset, const char *Buf, size_t Size) {
@@ -3707,7 +3751,7 @@
   // Locate DYNAMIC by looking through program headers.
   uint64_t DynamicOffset = 0;
   const Elf_Phdr *DynamicPhdr = 0;
-  for (auto &Phdr : Obj->program_headers()) {
+  for (auto &Phdr : cantFail(Obj->program_headers())) {
     if (Phdr.p_type == ELF::PT_DYNAMIC) {
       DynamicOffset = Phdr.p_offset;
       DynamicPhdr = &Phdr;
@@ -3721,10 +3765,11 @@
 
   // Go through all dynamic entries and patch functions addresses with
   // new ones.
-  ErrorOr<const Elf_Dyn *> DTB = Obj->dynamic_table_begin(DynamicPhdr);
-  ErrorOr<const Elf_Dyn *> DTE = Obj->dynamic_table_end(DynamicPhdr);
-  assert(DTB && DTE && "error accessing dynamic table");
-  for (auto *DE = *DTB; DE != *DTE; ++DE) {
+  const Elf_Dyn *DTB = cantFail(Obj->dynamic_table_begin(DynamicPhdr),
+                                "error accessing dynamic table");
+  const Elf_Dyn *DTE = cantFail(Obj->dynamic_table_end(DynamicPhdr),
+                                "error accessing dynamic table");
+  for (auto *DE = DTB; DE != DTE; ++DE) {
     auto NewDE = *DE;
     bool ShouldPatch = true;
     switch (DE->getTag()) {
@@ -3756,7 +3801,7 @@
     }
     if (ShouldPatch) {
       OS.pwrite(reinterpret_cast<const char *>(&NewDE), sizeof(NewDE),
-                DynamicOffset + (DE - *DTB) * sizeof(*DE));
+                DynamicOffset + (DE - DTB) * sizeof(*DE));
     }
   }
 
@@ -3781,16 +3826,14 @@
   // We obtain an asm-specific writer so that we can emit nops in an
   // architecture-specific way at the end of the function.
   auto MCE = BC->TheTarget->createMCCodeEmitter(*BC->MII, *BC->MRI, *BC->Ctx);
-  auto MAB = BC->TheTarget->createMCAsmBackend(*BC->MRI, BC->TripleName, "");
-  std::unique_ptr<MCStreamer> Streamer(
-    BC->TheTarget->createMCObjectStreamer(*BC->TheTriple,
-                                          *BC->Ctx,
-                                          *MAB,
-                                          OS,
-                                          MCE,
-                                          *BC->STI,
-                                          /* RelaxAll */ false,
-                                          /* DWARFMustBeAtTheEnd */ false));
+  auto MAB =
+      BC->TheTarget->createMCAsmBackend(*BC->STI, *BC->MRI, MCTargetOptions());
+  std::unique_ptr<MCStreamer> Streamer(BC->TheTarget->createMCObjectStreamer(
+      *BC->TheTriple, *BC->Ctx, std::unique_ptr<MCAsmBackend>(MAB), OS,
+      std::unique_ptr<MCCodeEmitter>(MCE), *BC->STI,
+      /* RelaxAll */ false,
+      /*IncrementalLinkerCompatible */ false,
+      /* DWARFMustBeAtTheEnd */ false));
 
   auto &Writer = static_cast<MCObjectStreamer *>(Streamer.get())
                      ->getAssembler()
@@ -3929,6 +3972,8 @@
     OS.pwrite(reinterpret_cast<const char *>(SI.AllocAddress),
                      SI.Size,
                      SI.FileOffset);
+    assert(SI.AllocAddress &&
+           "writing section that was not assigned an address");
   }
 
   // If .eh_frame is present create .eh_frame_hdr.
@@ -3965,51 +4010,37 @@
 
   // If requested, open again the binary we just wrote to dump its EH Frame
   if (opts::DumpEHFrame) {
-    ErrorOr<OwningBinary<Binary>> BinaryOrErr =
+    Expected<OwningBinary<Binary>> BinaryOrErr =
         createBinary(opts::OutputFilename);
-    if (std::error_code EC = BinaryOrErr.getError())
-      report_error(opts::OutputFilename, EC);
+    if (auto E = BinaryOrErr.takeError())
+      report_error(opts::OutputFilename, std::move(E));
     Binary &Binary = *BinaryOrErr.get().getBinary();
 
     if (auto *E = dyn_cast<ELFObjectFileBase>(&Binary)) {
-      DWARFContextInMemory DwCtx(*E, nullptr, true);
-      const auto &EHFrame = DwCtx.getEHFrame();
+      auto DwCtx = DWARFContext::create(*E);
+      const auto &EHFrame = DwCtx->getEHFrame();
       outs() << "BOLT-INFO: Dumping rewritten .eh_frame\n";
-      EHFrame->dump(outs());
+      EHFrame->dump(outs(), NoneType());
     }
   }
 }
 
 void RewriteInstance::writeEHFrameHeader(SectionInfo &EHFrameSecInfo) {
-  DWARFFrame NewEHFrame(EHFrameSecInfo.FileAddress);
-  NewEHFrame.parse(
-    DataExtractor(StringRef(reinterpret_cast<const char *>(
-                                                 EHFrameSecInfo.AllocAddress),
-                            EHFrameSecInfo.Size),
-                  BC->AsmInfo->isLittleEndian(),
-                  BC->AsmInfo->getPointerSize()));
-  if (!NewEHFrame.ParseError.empty()) {
-    errs() << "BOLT-ERROR: EHFrame reader failed with message \""
-           << NewEHFrame.ParseError << '\n';
-    exit(1);
-  }
+  DWARFDebugFrame NewEHFrame(true, EHFrameSecInfo.FileAddress);
+  NewEHFrame.parse(DWARFDataExtractor(
+      StringRef(reinterpret_cast<const char *>(EHFrameSecInfo.AllocAddress),
+                EHFrameSecInfo.Size),
+      BC->AsmInfo->isLittleEndian(), BC->AsmInfo->getCodePointerSize()));
 
   auto OldSMII = EFMM->SectionMapInfo.find(".eh_frame_old");
   assert(OldSMII != EFMM->SectionMapInfo.end() &&
          "expected .eh_frame_old to be present");
   auto &OldEHFrameSecInfo = OldSMII->second;
-  DWARFFrame OldEHFrame(OldEHFrameSecInfo.FileAddress);
-  OldEHFrame.parse(
-    DataExtractor(StringRef(reinterpret_cast<const char *>(
-                                              OldEHFrameSecInfo.AllocAddress),
-                            OldEHFrameSecInfo.Size),
-                  BC->AsmInfo->isLittleEndian(),
-                  BC->AsmInfo->getPointerSize()));
-  if (!OldEHFrame.ParseError.empty()) {
-    errs() << "BOLT-ERROR: EHFrame reader failed with message \""
-           << OldEHFrame.ParseError << '\n';
-    exit(1);
-  }
+  DWARFDebugFrame OldEHFrame(true, OldEHFrameSecInfo.FileAddress);
+  OldEHFrame.parse(DWARFDataExtractor(
+      StringRef(reinterpret_cast<const char *>(OldEHFrameSecInfo.AllocAddress),
+                OldEHFrameSecInfo.Size),
+      BC->AsmInfo->isLittleEndian(), BC->AsmInfo->getCodePointerSize()));
 
   DEBUG(dbgs() << "BOLT: writing a new .eh_frame_hdr\n");
 
@@ -4107,10 +4138,10 @@
   DWARFAddressRangesVector OutputRanges;
 
   for (const auto Range : InputRanges) {
-    auto BFI = BinaryFunctions.lower_bound(Range.first);
+    auto BFI = BinaryFunctions.lower_bound(Range.LowPC);
     while (BFI != BinaryFunctions.end()) {
       const auto &Function = BFI->second;
-      if (Function.getAddress() >= Range.second)
+      if (Function.getAddress() >= Range.HighPC)
         break;
       const auto FunctionRanges = Function.getOutputAddressRanges();
       std::move(std::begin(FunctionRanges),
diff --git a/bolt/RewriteInstance.h b/bolt/RewriteInstance.h
index fbe4af2..80107f2 100644
--- a/bolt/RewriteInstance.h
+++ b/bolt/RewriteInstance.h
@@ -17,11 +17,12 @@
 #include "BinaryFunction.h"
 #include "DebugData.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
 #include "llvm/MC/StringTableBuilder.h"
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/StringPool.h"
 #include <map>
 #include <set>
 
@@ -29,7 +30,7 @@
 
 class DWARFContext;
 class DWARFFrame;
-class tool_output_file;
+class ToolOutputFile;
 
 namespace bolt {
 
@@ -67,6 +68,7 @@
               bool IsReadOnly, bool IsLocal, uint64_t FileAddress = 0,
               uint64_t FileOffset = 0, unsigned SectionID = 0,
               bool IsELFNote = false)
+
       : AllocAddress(Address), Size(Size), Alignment(Alignment), IsCode(IsCode),
         IsReadOnly(IsReadOnly), IsLocal(IsLocal), FileAddress(FileAddress),
         FileOffset(FileOffset), SectionID(SectionID), IsELFNote(IsELFNote) {}
@@ -211,12 +213,12 @@
   /// Recursively update debug info for all DIEs in \p Unit.
   /// If \p Function is not empty, it points to a function corresponding
   /// to a parent DW_TAG_subprogram node of the current \p DIE.
-  void updateUnitDebugInfo(DWARFCompileUnit *Unit,
-                           const DWARFDebugInfoEntryMinimal *DIE,
+  void updateUnitDebugInfo(const DWARFDie DIE,
                            std::vector<const BinaryFunction *> FunctionStack);
 
   /// Map all sections to their final addresses.
-  void mapFileSections(orc::ObjectLinkingLayer<>::ObjSetHandleT &ObjectsHandle);
+  void
+  mapFileSections(orc::RTDyldObjectLinkingLayer::ObjHandleT &ObjectsHandle);
 
   /// Update output object's values based on the final \p Layout.
   void updateOutputValues(const MCAsmLayout &Layout);
@@ -245,7 +247,8 @@
 
   /// Return value for the symbol \p Name in the output.
   uint64_t getNewValueForSymbol(const StringRef Name) {
-    return OLT.findSymbol(Name, false).getAddress();
+    return cantFail(OLT->findSymbol(Name, false).getAddress(),
+                    "findSymbol failed");
   }
 
   /// Return BinaryFunction containing a given \p Address or nullptr if
@@ -311,9 +314,6 @@
   /// Write .eh_frame_hdr.
   void writeEHFrameHeader(SectionInfo &EHFrameSecInfo);
 
-  // Run ObjectLinkingLayer() with custom memory manager and symbol resolver.
-  orc::ObjectLinkingLayer<> OLT;
-
   /// Disassemble and create function entries for PLT.
   void disassemblePLT();
 
@@ -385,8 +385,7 @@
   /// new address ranges in the output binary.
   /// \p Unit Compile uniit the object belongs to.
   /// \p DIE is the object's DIE in the input binary.
-  void updateDWARFObjectAddressRanges(const DWARFUnit *Unit,
-                                      const DWARFDebugInfoEntryMinimal *DIE,
+  void updateDWARFObjectAddressRanges(const DWARFDie DIE,
                                       uint64_t DebugRangesOffset);
 
   /// Return file offset corresponding to a given virtual address.
@@ -411,8 +410,8 @@
                                        uint64_t Address,
                                        uint64_t Size,
                                        bool IsSimple);
-private:
 
+public:
   /// When updating debug info, these are the sections we overwrite.
   static constexpr const char *SectionsToOverwrite[] = {
     ".shstrtab",
@@ -425,8 +424,12 @@
     ".gdb_index",
   };
 
+private:
+
   static const char TimerGroupName[];
 
+  static const char TimerGroupDesc[];
+
   /// Huge page size used for alignment.
   static constexpr unsigned PageAlign = 0x200000;
 
@@ -448,11 +451,14 @@
 
   /// Memory manager for sections and segments. Used to communicate with ORC
   /// among other things.
-  std::unique_ptr<ExecutableFileMemoryManager> EFMM;
+  std::shared_ptr<ExecutableFileMemoryManager> EFMM;
+
+  // Run ObjectLinkingLayer() with custom memory manager and symbol resolver.
+  std::unique_ptr<orc::RTDyldObjectLinkingLayer> OLT;
 
   /// Output file where we mix original code from the input binary and
   /// optimized code for selected functions.
-  std::unique_ptr<tool_output_file> Out;
+  std::unique_ptr<ToolOutputFile> Out;
 
   /// Offset in the input file where non-allocatable sections start.
   uint64_t FirstNonAllocatableOffset{0};
@@ -496,7 +502,7 @@
   /// Exception handling and stack unwinding information in this binary.
   ArrayRef<uint8_t> LSDAData;
   uint64_t LSDAAddress{0};
-  const llvm::DWARFFrame *EHFrame{nullptr};
+  const llvm::DWARFDebugFrame *EHFrame{nullptr};
   ErrorOr<BinarySection &> EHFrameSection{std::errc::bad_address};
 
   /// .plt section.
@@ -536,6 +542,8 @@
 
   /// Section header string table.
   StringTableBuilder SHStrTab;
+  StringPool SHStrTabPool;
+  std::vector<PooledStringPtr> AllSHStrTabStrings;
 
   /// A rewrite of strtab
   std::string NewStrTab;
diff --git a/bolt/llvm-bolt.cpp b/bolt/llvm-bolt.cpp
index b283e37..42040ee 100644
--- a/bolt/llvm-bolt.cpp
+++ b/bolt/llvm-bolt.cpp
@@ -91,6 +91,13 @@
   exit(1);
 }
 
+static void report_error(StringRef Message, Error E) {
+  assert(E);
+  errs() << ToolName << ": '" << Message << "': " << toString(std::move(E))
+         << ".\n";
+  exit(1);
+}
+
 namespace llvm {
 namespace bolt {
 const char *BoltRevision =
@@ -99,8 +106,8 @@
 }
 }
 
-static void printBoltRevision() {
-  errs() << "BOLT revision " << BoltRevision << "\n";
+static void printBoltRevision(llvm::raw_ostream &OS) {
+  OS << "BOLT revision " << BoltRevision << "\n";
 }
 
 void perf2boltMode(int argc, char **argv) {
@@ -139,7 +146,7 @@
 
 int main(int argc, char **argv) {
   // Print a stack trace if we signal out.
-  sys::PrintStackTraceOnErrorSignal();
+  sys::PrintStackTraceOnErrorSignal(argv[0]);
   PrettyStackTraceProgram X(argc, argv);
 
   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
@@ -198,9 +205,10 @@
   }
 
   // Attempt to open the binary.
-  ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(opts::InputFilename);
-  if (std::error_code EC = BinaryOrErr.getError())
-    report_error(opts::InputFilename, EC);
+  Expected<OwningBinary<Binary>> BinaryOrErr =
+      createBinary(opts::InputFilename);
+  if (auto E = BinaryOrErr.takeError())
+    report_error(opts::InputFilename, std::move(E));
   Binary &Binary = *BinaryOrErr.get().getBinary();
 
   if (auto *e = dyn_cast<ELFObjectFileBase>(&Binary)) {
diff --git a/bolt/merge-fdata/merge-fdata.cpp b/bolt/merge-fdata/merge-fdata.cpp
index 7aca645..9c6d2a7 100644
--- a/bolt/merge-fdata/merge-fdata.cpp
+++ b/bolt/merge-fdata/merge-fdata.cpp
@@ -15,6 +15,7 @@
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Object/Binary.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Signals.h"
@@ -56,8 +57,7 @@
       "print functions sorted by execution count"),
     clEnumValN(ST_TOTAL_BRANCHES,
       "branches",
-      "print functions sorted by total branch count"),
-    clEnumValEnd),
+      "print functions sorted by total branch count")),
   cl::cat(MergeFdataCategory));
 
 static cl::opt<bool>
@@ -79,7 +79,7 @@
 
 int main(int argc, char **argv) {
   // Print a stack trace if we signal out.
-  sys::PrintStackTraceOnErrorSignal();
+  sys::PrintStackTraceOnErrorSignal(argv[0]);
   PrettyStackTraceProgram X(argc, argv);
 
   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.