Importing rustc-1.56.0

Change-Id: I98941481270706fa55f8fb2cb91686ae3bd30f38
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
index 13baa5f..48cbad0 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
@@ -45,5 +45,4 @@
 
   LINK_COMPONENTS
   Support
-  DebugInfoMSF
   )
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
index 69390c7..d12f6c7 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
@@ -9,6 +9,7 @@
 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h"
+#include <string>
 
 using namespace llvm;
 using namespace llvm::codeview;
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
index c272985..1af59ff 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
@@ -188,14 +188,17 @@
 
 Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value, const Twine &Comment) {
   if (isStreaming()) {
+    // FIXME: We also need to handle big values here, but it's
+    //        not clear how we can excercise this code path yet.
     if (Value.isSigned())
       emitEncodedSignedInteger(Value.getSExtValue(), Comment);
     else
       emitEncodedUnsignedInteger(Value.getZExtValue(), Comment);
   } else if (isWriting()) {
     if (Value.isSigned())
-      return writeEncodedSignedInteger(Value.getSExtValue());
-    return writeEncodedUnsignedInteger(Value.getZExtValue());
+      return writeEncodedSignedInteger(
+          Value.isSingleWord() ? Value.getSExtValue() : INT64_MIN);
+    return writeEncodedUnsignedInteger(Value.getLimitedValue());
   } else
     return consume(*Reader, Value);
   return Error::success();
@@ -273,6 +276,9 @@
 
 void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value,
                                                 const Twine &Comment) {
+  // FIXME: There are no test cases covering this function.
+  // This may be because we always consider enumerators to be unsigned.
+  // See FIXME at CodeViewDebug.cpp : CodeViewDebug::lowerTypeEnum.
   if (Value >= std::numeric_limits<int8_t>::min()) {
     Streamer->emitIntValue(LF_CHAR, 2);
     emitComment(Comment);
@@ -291,8 +297,8 @@
   } else {
     Streamer->emitIntValue(LF_QUADWORD, 2);
     emitComment(Comment);
-    Streamer->emitIntValue(Value, 4);
-    incrStreamedLen(6);
+    Streamer->emitIntValue(Value, 4); // FIXME: Why not 8 (size of quadword)?
+    incrStreamedLen(6);               // FIXME: Why not 10 (8 + 2)?
   }
 }
 
@@ -313,10 +319,11 @@
     Streamer->emitIntValue(Value, 4);
     incrStreamedLen(6);
   } else {
+    // FIXME: There are no test cases covering this block.
     Streamer->emitIntValue(LF_UQUADWORD, 2);
     emitComment(Comment);
     Streamer->emitIntValue(Value, 8);
-    incrStreamedLen(6);
+    incrStreamedLen(6); // FIXME: Why not 10 (8 + 2)?
   }
 }
 
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/EnumTables.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
index 949707b..b4a2a00 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
@@ -189,7 +189,6 @@
     CV_ENUM_CLASS_ENT(CPUType, ARM_XMAC),
     CV_ENUM_CLASS_ENT(CPUType, ARM_WMMX),
     CV_ENUM_CLASS_ENT(CPUType, ARM7),
-    CV_ENUM_CLASS_ENT(CPUType, ARM64),
     CV_ENUM_CLASS_ENT(CPUType, Omni),
     CV_ENUM_CLASS_ENT(CPUType, Ia64),
     CV_ENUM_CLASS_ENT(CPUType, Ia64_2),
@@ -201,6 +200,10 @@
     CV_ENUM_CLASS_ENT(CPUType, EBC),
     CV_ENUM_CLASS_ENT(CPUType, Thumb),
     CV_ENUM_CLASS_ENT(CPUType, ARMNT),
+    CV_ENUM_CLASS_ENT(CPUType, ARM64),
+    CV_ENUM_CLASS_ENT(CPUType, HybridX86ARM64),
+    CV_ENUM_CLASS_ENT(CPUType, ARM64EC),
+    CV_ENUM_CLASS_ENT(CPUType, ARM64X),
     CV_ENUM_CLASS_ENT(CPUType, D3D11_Shader),
 };
 
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/Formatters.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/Formatters.cpp
index a7a8c7f..f1f51bc 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/CodeView/Formatters.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/Formatters.cpp
@@ -23,21 +23,33 @@
 GuidAdapter::GuidAdapter(ArrayRef<uint8_t> Guid)
     : FormatAdapter(std::move(Guid)) {}
 
+// From https://docs.microsoft.com/en-us/windows/win32/msi/guid documentation:
+// The GUID data type is a text string representing a Class identifier (ID).
+// All GUIDs must be authored in uppercase.
+// The valid format for a GUID is {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} where
+// X is a hex digit (0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F).
+//
+// The individual string components must be padded to comply with the specific
+// lengths of {8-4-4-4-12} characters.
+// The llvm-yaml2obj tool checks that a GUID follow that format:
+// - the total length to be 38 (including the curly braces.
+// - there is a dash at the positions: 8, 13, 18 and 23.
 void GuidAdapter::format(raw_ostream &Stream, StringRef Style) {
-  static const char *Lookup = "0123456789ABCDEF";
-
   assert(Item.size() == 16 && "Expected 16-byte GUID");
-  Stream << "{";
-  for (int i = 0; i < 16;) {
-    uint8_t Byte = Item[i];
-    uint8_t HighNibble = (Byte >> 4) & 0xF;
-    uint8_t LowNibble = Byte & 0xF;
-    Stream << Lookup[HighNibble] << Lookup[LowNibble];
-    ++i;
-    if (i >= 4 && i <= 10 && i % 2 == 0)
-      Stream << "-";
-  }
-  Stream << "}";
+  struct MSGuid {
+    support::ulittle32_t Data1;
+    support::ulittle16_t Data2;
+    support::ulittle16_t Data3;
+    support::ubig64_t Data4;
+  };
+  const MSGuid *G = reinterpret_cast<const MSGuid *>(Item.data());
+  Stream
+      << '{' << format_hex_no_prefix(G->Data1, 8, /*Upper=*/true)
+      << '-' << format_hex_no_prefix(G->Data2, 4, /*Upper=*/true)
+      << '-' << format_hex_no_prefix(G->Data3, 4, /*Upper=*/true)
+      << '-' << format_hex_no_prefix(G->Data4 >> 48, 4, /*Upper=*/true) << '-'
+      << format_hex_no_prefix(G->Data4 & ((1ULL << 48) - 1), 12, /*Upper=*/true)
+      << '}';
 }
 
 raw_ostream &llvm::codeview::operator<<(raw_ostream &OS, const GUID &Guid) {
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
index 7ac3761..d272999 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
@@ -8,7 +8,9 @@
 
 #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
 #include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/Support/MD5.h"
 
 using namespace llvm;
 using namespace llvm::codeview;
@@ -144,28 +146,51 @@
 };
 } // namespace
 
+// Computes a string representation of a hash of the specified name, suitable
+// for use when emitting CodeView type names.
+static void computeHashString(StringRef Name,
+                              SmallString<32> &StringifiedHash) {
+  llvm::MD5 Hash;
+  llvm::MD5::MD5Result Result;
+  Hash.update(Name);
+  Hash.final(Result);
+  Hash.stringifyResult(Result, StringifiedHash);
+}
+
 static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name,
                                   StringRef &UniqueName, bool HasUniqueName) {
   if (IO.isWriting()) {
     // Try to be smart about what we write here.  We can't write anything too
-    // large, so if we're going to go over the limit, truncate both the name
-    // and unique name by the same amount.
+    // large, so if we're going to go over the limit, replace lengthy names with
+    // a stringified hash value.
     size_t BytesLeft = IO.maxFieldLength();
     if (HasUniqueName) {
       size_t BytesNeeded = Name.size() + UniqueName.size() + 2;
-      StringRef N = Name;
-      StringRef U = UniqueName;
       if (BytesNeeded > BytesLeft) {
-        size_t BytesToDrop = (BytesNeeded - BytesLeft);
-        size_t DropN = std::min(N.size(), BytesToDrop / 2);
-        size_t DropU = std::min(U.size(), BytesToDrop - DropN);
+        // The minimum space required for emitting hashes of both names.
+        assert(BytesLeft >= 70);
 
-        N = N.drop_back(DropN);
-        U = U.drop_back(DropU);
+        // Replace the entire unique name with a hash of the unique name.
+        SmallString<32> Hash;
+        computeHashString(UniqueName, Hash);
+        std::string UniqueB = Twine("??@" + Hash + "@").str();
+        assert(UniqueB.size() == 36);
+
+        // Truncate the name if necessary and append a hash of the name.
+        // The name length, hash included, is limited to 4096 bytes.
+        const size_t MaxTakeN = 4096;
+        size_t TakeN = std::min(MaxTakeN, BytesLeft - UniqueB.size() - 2) - 32;
+        computeHashString(Name, Hash);
+        std::string NameB = (Name.take_front(TakeN) + Hash).str();
+
+        StringRef N = NameB;
+        StringRef U = UniqueB;
+        error(IO.mapStringZ(N));
+        error(IO.mapStringZ(U));
+      } else {
+        error(IO.mapStringZ(Name));
+        error(IO.mapStringZ(UniqueName));
       }
-
-      error(IO.mapStringZ(N));
-      error(IO.mapStringZ(U));
     } else {
       // Cap the length of the string at however many bytes we have available,
       // plus one for the required null terminator.
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
index 2b08120..6e30309 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
@@ -26,7 +26,8 @@
   if (!getAbbreviations())
     OS << " (invalid)";
   OS << ", addr_size = " << format("0x%02x", getAddressByteSize());
-  if (getVersion() >= 5 && getUnitType() != dwarf::DW_UT_compile)
+  if (getVersion() >= 5 && (getUnitType() == dwarf::DW_UT_skeleton ||
+                            getUnitType() == dwarf::DW_UT_split_compile))
     OS << ", DWO_id = " << format("0x%016" PRIx64, *getDWOId());
   OS << " (next unit at " << format("0x%08" PRIx64, getNextUnitOffset())
      << ")\n";
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index 749d738..4e1cafe 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -823,6 +823,8 @@
   if (DebugFrame)
     return DebugFrame.get();
 
+  const DWARFSection &DS = DObj->getFrameSection();
+
   // There's a "bug" in the DWARFv3 standard with respect to the target address
   // size within debug frame sections. While DWARF is supposed to be independent
   // of its container, FDEs have fields with size being "target address size",
@@ -832,10 +834,11 @@
   // provides this information). This problem is fixed in DWARFv4
   // See this dwarf-discuss discussion for more details:
   // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
-  DWARFDataExtractor debugFrameData(*DObj, DObj->getFrameSection(),
-                                    isLittleEndian(), DObj->getAddressSize());
-  auto DF = std::make_unique<DWARFDebugFrame>(getArch(), /*IsEH=*/false);
-  if (Error E = DF->parse(debugFrameData))
+  DWARFDataExtractor DebugFrameData(*DObj, DS, isLittleEndian(),
+                                    DObj->getAddressSize());
+  auto DF =
+      std::make_unique<DWARFDebugFrame>(getArch(), /*IsEH=*/false, DS.Address);
+  if (Error E = DF->parse(DebugFrameData))
     return std::move(E);
 
   DebugFrame.swap(DF);
@@ -846,11 +849,13 @@
   if (EHFrame)
     return EHFrame.get();
 
-  DWARFDataExtractor debugFrameData(*DObj, DObj->getEHFrameSection(),
-                                    isLittleEndian(), DObj->getAddressSize());
+  const DWARFSection &DS = DObj->getEHFrameSection();
+  DWARFDataExtractor DebugFrameData(*DObj, DS, isLittleEndian(),
+                                    DObj->getAddressSize());
 
-  auto DF = std::make_unique<DWARFDebugFrame>(getArch(), /*IsEH=*/true);
-  if (Error E = DF->parse(debugFrameData))
+  auto DF =
+      std::make_unique<DWARFDebugFrame>(getArch(), /*IsEH=*/true, DS.Address);
+  if (Error E = DF->parse(DebugFrameData))
     return std::move(E);
   DebugFrame.swap(DF);
   return DebugFrame.get();
@@ -1022,8 +1027,7 @@
       break;
     }
 
-    for (auto Child : DIE)
-      Worklist.push_back(Child);
+    append_range(Worklist, DIE);
   }
 
   return Result;
@@ -1031,13 +1035,11 @@
 
 /// TODO: change input parameter from "uint64_t Address"
 ///       into "SectionedAddress Address"
-static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU,
-                                                  uint64_t Address,
-                                                  FunctionNameKind Kind,
-                                                  DILineInfoSpecifier::FileLineInfoKind FileNameKind,
-                                                  std::string &FunctionName,
-                                                  std::string &StartFile,
-                                                  uint32_t &StartLine) {
+static bool getFunctionNameAndStartLineForAddress(
+    DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind,
+    DILineInfoSpecifier::FileLineInfoKind FileNameKind,
+    std::string &FunctionName, std::string &StartFile, uint32_t &StartLine,
+    Optional<uint64_t> &StartAddress) {
   // The address may correspond to instruction in some inlined function,
   // so we have to build the chain of inlined functions and take the
   // name of the topmost function in it.
@@ -1062,7 +1064,8 @@
     StartLine = DeclLineResult;
     FoundResult = true;
   }
-
+  if (auto LowPcAddr = toSectionedAddress(DIE.find(DW_AT_low_pc)))
+    StartAddress = LowPcAddr->Address;
   return FoundResult;
 }
 
@@ -1229,9 +1232,9 @@
   if (!CU)
     return Result;
 
-  getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, Spec.FLIKind,
-                                        Result.FunctionName,
-                                        Result.StartFileName, Result.StartLine);
+  getFunctionNameAndStartLineForAddress(
+      CU, Address.Address, Spec.FNKind, Spec.FLIKind, Result.FunctionName,
+      Result.StartFileName, Result.StartLine, Result.StartAddress);
   if (Spec.FLIKind != FileLineInfoKind::None) {
     if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) {
       LineTable->getFileLineInfoForAddress(
@@ -1244,7 +1247,7 @@
 
 DILineInfoTable DWARFContext::getLineInfoForAddressRange(
     object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) {
-  DILineInfoTable  Lines;
+  DILineInfoTable Lines;
   DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
   if (!CU)
     return Lines;
@@ -1252,8 +1255,10 @@
   uint32_t StartLine = 0;
   std::string StartFileName;
   std::string FunctionName(DILineInfo::BadString);
-  getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, Spec.FLIKind,
-                                        FunctionName, StartFileName, StartLine);
+  Optional<uint64_t> StartAddress;
+  getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind,
+                                        Spec.FLIKind, FunctionName,
+                                        StartFileName, StartLine, StartAddress);
 
   // If the Specifier says we don't need FileLineInfo, just
   // return the top-most function at the starting address.
@@ -1262,6 +1267,7 @@
     Result.FunctionName = FunctionName;
     Result.StartFileName = StartFileName;
     Result.StartLine = StartLine;
+    Result.StartAddress = StartAddress;
     Lines.push_back(std::make_pair(Address.Address, Result));
     return Lines;
   }
@@ -1286,6 +1292,7 @@
     Result.Column = Row.Column;
     Result.StartFileName = StartFileName;
     Result.StartLine = StartLine;
+    Result.StartAddress = StartAddress;
     Lines.push_back(std::make_pair(Row.Address.Address, Result));
   }
 
@@ -1328,6 +1335,8 @@
     if (auto DeclLineResult = FunctionDIE.getDeclLine())
       Frame.StartLine = DeclLineResult;
     Frame.StartFileName = FunctionDIE.getDeclFile(Spec.FLIKind);
+    if (auto LowPcAddr = toSectionedAddress(FunctionDIE.find(DW_AT_low_pc)))
+      Frame.StartAddress = LowPcAddr->Address;
     if (Spec.FLIKind != FileLineInfoKind::None) {
       if (i == 0) {
         // For the topmost frame, initialize the line table of this
@@ -1678,7 +1687,8 @@
       // Try to obtain an already relocated version of this section.
       // Else use the unrelocated section from the object file. We'll have to
       // apply relocations ourselves later.
-      section_iterator RelocatedSection = *SecOrErr;
+      section_iterator RelocatedSection =
+          Obj.isRelocatableObject() ? *SecOrErr : Obj.section_end();
       if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) {
         Expected<StringRef> E = Section.getContents();
         if (E)
@@ -1708,6 +1718,9 @@
         if (Name == "debug_ranges") {
           // FIXME: Use the other dwo range section when we emit it.
           RangesDWOSection.Data = Data;
+        } else if (Name == "debug_frame" || Name == "eh_frame") {
+          if (DWARFSection *S = mapNameToDWARFSection(Name))
+            S->Address = Section.getAddress();
         }
       } else if (InfoSectionMap *Sections =
                      StringSwitch<InfoSectionMap *>(Name)
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp
index 4afac2f..d91a630 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp
@@ -67,6 +67,35 @@
   return &Decls[AbbrCode - FirstAbbrCode];
 }
 
+std::string DWARFAbbreviationDeclarationSet::getCodeRange() const {
+  // Create a sorted list of all abbrev codes.
+  std::vector<uint32_t> Codes;
+  Codes.reserve(Decls.size());
+  for (const auto &Decl : Decls)
+    Codes.push_back(Decl.getCode());
+
+  std::string Buffer = "";
+  raw_string_ostream Stream(Buffer);
+  // Each iteration through this loop represents a single contiguous range in
+  // the set of codes.
+  for (auto Current = Codes.begin(), End = Codes.end(); Current != End;) {
+    uint32_t RangeStart = *Current;
+    // Add the current range start.
+    Stream << *Current;
+    uint32_t RangeEnd = RangeStart;
+    // Find the end of the current range.
+    while (++Current != End && *Current == RangeEnd + 1)
+      ++RangeEnd;
+    // If there is more than one value in the range, add the range end too.
+    if (RangeStart != RangeEnd)
+      Stream << "-" << RangeEnd;
+    // If there is at least one more range, add a separator.
+    if (Current != End)
+      Stream << ", ";
+  }
+  return Buffer;
+}
+
 DWARFDebugAbbrev::DWARFDebugAbbrev() { clear(); }
 
 void DWARFDebugAbbrev::clear() {
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp
index e0db469..1a1b8ea 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp
@@ -15,7 +15,6 @@
 #include <cassert>
 #include <cstdint>
 #include <set>
-#include <vector>
 
 using namespace llvm;
 
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
index b74ecac..92a461d 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -24,8 +24,6 @@
 #include <cassert>
 #include <cinttypes>
 #include <cstdint>
-#include <string>
-#include <vector>
 
 using namespace llvm;
 using namespace dwarf;
@@ -43,6 +41,211 @@
   OS << "reg" << RegNum;
 }
 
+UnwindLocation UnwindLocation::createUnspecified() { return {Unspecified}; }
+
+UnwindLocation UnwindLocation::createUndefined() { return {Undefined}; }
+
+UnwindLocation UnwindLocation::createSame() { return {Same}; }
+
+UnwindLocation UnwindLocation::createIsConstant(int32_t Value) {
+  return {Constant, InvalidRegisterNumber, Value, None, false};
+}
+
+UnwindLocation UnwindLocation::createIsCFAPlusOffset(int32_t Offset) {
+  return {CFAPlusOffset, InvalidRegisterNumber, Offset, None, false};
+}
+
+UnwindLocation UnwindLocation::createAtCFAPlusOffset(int32_t Offset) {
+  return {CFAPlusOffset, InvalidRegisterNumber, Offset, None, true};
+}
+
+UnwindLocation
+UnwindLocation::createIsRegisterPlusOffset(uint32_t RegNum, int32_t Offset,
+                                           Optional<uint32_t> AddrSpace) {
+  return {RegPlusOffset, RegNum, Offset, AddrSpace, false};
+}
+
+UnwindLocation
+UnwindLocation::createAtRegisterPlusOffset(uint32_t RegNum, int32_t Offset,
+                                           Optional<uint32_t> AddrSpace) {
+  return {RegPlusOffset, RegNum, Offset, AddrSpace, true};
+}
+
+UnwindLocation UnwindLocation::createIsDWARFExpression(DWARFExpression Expr) {
+  return {Expr, false};
+}
+
+UnwindLocation UnwindLocation::createAtDWARFExpression(DWARFExpression Expr) {
+  return {Expr, true};
+}
+
+void UnwindLocation::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+                          bool IsEH) const {
+  if (Dereference)
+    OS << '[';
+  switch (Kind) {
+  case Unspecified:
+    OS << "unspecified";
+    break;
+  case Undefined:
+    OS << "undefined";
+    break;
+  case Same:
+    OS << "same";
+    break;
+  case CFAPlusOffset:
+    OS << "CFA";
+    if (Offset == 0)
+      break;
+    if (Offset > 0)
+      OS << "+";
+    OS << Offset;
+    break;
+  case RegPlusOffset:
+    printRegister(OS, MRI, IsEH, RegNum);
+    if (Offset == 0 && !AddrSpace)
+      break;
+    if (Offset >= 0)
+      OS << "+";
+    OS << Offset;
+    if (AddrSpace)
+      OS << " in addrspace" << *AddrSpace;
+    break;
+  case DWARFExpr:
+    Expr->print(OS, DIDumpOptions(), MRI, nullptr, IsEH);
+    break;
+  case Constant:
+    OS << Offset;
+    break;
+  }
+  if (Dereference)
+    OS << ']';
+}
+
+raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,
+                                     const UnwindLocation &UL) {
+  UL.dump(OS, nullptr, false);
+  return OS;
+}
+
+bool UnwindLocation::operator==(const UnwindLocation &RHS) const {
+  if (Kind != RHS.Kind)
+    return false;
+  switch (Kind) {
+  case Unspecified:
+  case Undefined:
+  case Same:
+    return true;
+  case CFAPlusOffset:
+    return Offset == RHS.Offset && Dereference == RHS.Dereference;
+  case RegPlusOffset:
+    return RegNum == RHS.RegNum && Offset == RHS.Offset &&
+           Dereference == RHS.Dereference;
+  case DWARFExpr:
+    return *Expr == *RHS.Expr && Dereference == RHS.Dereference;
+  case Constant:
+    return Offset == RHS.Offset;
+  }
+  return false;
+}
+
+void RegisterLocations::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+                             bool IsEH) const {
+  bool First = true;
+  for (const auto &RegLocPair : Locations) {
+    if (First)
+      First = false;
+    else
+      OS << ", ";
+    printRegister(OS, MRI, IsEH, RegLocPair.first);
+    OS << '=';
+    RegLocPair.second.dump(OS, MRI, IsEH);
+  }
+}
+
+raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,
+                                     const RegisterLocations &RL) {
+  RL.dump(OS, nullptr, false);
+  return OS;
+}
+
+void UnwindRow::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
+                     unsigned IndentLevel) const {
+  OS.indent(2 * IndentLevel);
+  if (hasAddress())
+    OS << format("0x%" PRIx64 ": ", *Address);
+  OS << "CFA=";
+  CFAValue.dump(OS, MRI, IsEH);
+  if (RegLocs.hasLocations()) {
+    OS << ": ";
+    RegLocs.dump(OS, MRI, IsEH);
+  }
+  OS << "\n";
+}
+
+raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindRow &Row) {
+  Row.dump(OS, nullptr, false, 0);
+  return OS;
+}
+
+void UnwindTable::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
+                       unsigned IndentLevel) const {
+  for (const UnwindRow &Row : Rows)
+    Row.dump(OS, MRI, IsEH, IndentLevel);
+}
+
+raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) {
+  Rows.dump(OS, nullptr, false, 0);
+  return OS;
+}
+
+Expected<UnwindTable> UnwindTable::create(const FDE *Fde) {
+  const CIE *Cie = Fde->getLinkedCIE();
+  if (Cie == nullptr)
+    return createStringError(errc::invalid_argument,
+                             "unable to get CIE for FDE at offset 0x%" PRIx64,
+                             Fde->getOffset());
+
+  // Rows will be empty if there are no CFI instructions.
+  if (Cie->cfis().empty() && Fde->cfis().empty())
+    return UnwindTable();
+
+  UnwindTable UT;
+  UnwindRow Row;
+  Row.setAddress(Fde->getInitialLocation());
+  UT.EndAddress = Fde->getInitialLocation() + Fde->getAddressRange();
+  if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
+    return std::move(CieError);
+  // We need to save the initial locations of registers from the CIE parsing
+  // in case we run into DW_CFA_restore or DW_CFA_restore_extended opcodes.
+  const RegisterLocations InitialLocs = Row.getRegisterLocations();
+  if (Error FdeError = UT.parseRows(Fde->cfis(), Row, &InitialLocs))
+    return std::move(FdeError);
+  // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
+  // Do not add that to the unwind table.
+  if (Row.getRegisterLocations().hasLocations() ||
+      Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)
+    UT.Rows.push_back(Row);
+  return UT;
+}
+
+Expected<UnwindTable> UnwindTable::create(const CIE *Cie) {
+  // Rows will be empty if there are no CFI instructions.
+  if (Cie->cfis().empty())
+    return UnwindTable();
+
+  UnwindTable UT;
+  UnwindRow Row;
+  if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
+    return std::move(CieError);
+  // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
+  // Do not add that to the unwind table.
+  if (Row.getRegisterLocations().hasLocations() ||
+      Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)
+    UT.Rows.push_back(Row);
+  return UT;
+}
+
 // See DWARF standard v3, section 7.23
 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
@@ -115,6 +318,16 @@
       // Operands: SLEB128
       addInstruction(Opcode, Data.getSLEB128(C));
       break;
+    case DW_CFA_LLVM_def_aspace_cfa:
+    case DW_CFA_LLVM_def_aspace_cfa_sf: {
+      auto RegNum = Data.getULEB128(C);
+      auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa
+                           ? Data.getULEB128(C)
+                           : Data.getSLEB128(C);
+      auto AddressSpace = Data.getULEB128(C);
+      addInstruction(Opcode, RegNum, CfaOffset, AddressSpace);
+      break;
+    }
     case DW_CFA_offset_extended:
     case DW_CFA_register:
     case DW_CFA_def_cfa:
@@ -175,24 +388,424 @@
   return C.takeError();
 }
 
-namespace {
+StringRef CFIProgram::callFrameString(unsigned Opcode) const {
+  return dwarf::CallFrameString(Opcode, Arch);
+}
 
+const char *CFIProgram::operandTypeString(CFIProgram::OperandType OT) {
+#define ENUM_TO_CSTR(e)                                                        \
+  case e:                                                                      \
+    return #e;
+  switch (OT) {
+    ENUM_TO_CSTR(OT_Unset);
+    ENUM_TO_CSTR(OT_None);
+    ENUM_TO_CSTR(OT_Address);
+    ENUM_TO_CSTR(OT_Offset);
+    ENUM_TO_CSTR(OT_FactoredCodeOffset);
+    ENUM_TO_CSTR(OT_SignedFactDataOffset);
+    ENUM_TO_CSTR(OT_UnsignedFactDataOffset);
+    ENUM_TO_CSTR(OT_Register);
+    ENUM_TO_CSTR(OT_AddressSpace);
+    ENUM_TO_CSTR(OT_Expression);
+  }
+  return "<unknown CFIProgram::OperandType>";
+}
 
-} // end anonymous namespace
+llvm::Expected<uint64_t>
+CFIProgram::Instruction::getOperandAsUnsigned(const CFIProgram &CFIP,
+                                              uint32_t OperandIdx) const {
+  if (OperandIdx >= MaxOperands)
+    return createStringError(errc::invalid_argument,
+                             "operand index %" PRIu32 " is not valid",
+                             OperandIdx);
+  OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx];
+  uint64_t Operand = Ops[OperandIdx];
+  switch (Type) {
+  case OT_Unset:
+  case OT_None:
+  case OT_Expression:
+    return createStringError(errc::invalid_argument,
+                             "op[%" PRIu32 "] has type %s which has no value",
+                             OperandIdx, CFIProgram::operandTypeString(Type));
 
-ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() {
-  static OperandType OpTypes[DW_CFA_restore+1][2];
+  case OT_Offset:
+  case OT_SignedFactDataOffset:
+  case OT_UnsignedFactDataOffset:
+    return createStringError(
+        errc::invalid_argument,
+        "op[%" PRIu32 "] has OperandType OT_Offset which produces a signed "
+        "result, call getOperandAsSigned instead",
+        OperandIdx);
+
+  case OT_Address:
+  case OT_Register:
+  case OT_AddressSpace:
+    return Operand;
+
+  case OT_FactoredCodeOffset: {
+    const uint64_t CodeAlignmentFactor = CFIP.codeAlign();
+    if (CodeAlignmentFactor == 0)
+      return createStringError(
+          errc::invalid_argument,
+          "op[%" PRIu32 "] has type OT_FactoredCodeOffset but code alignment "
+          "is zero",
+          OperandIdx);
+    return Operand * CodeAlignmentFactor;
+  }
+  }
+  llvm_unreachable("invalid operand type");
+}
+
+llvm::Expected<int64_t>
+CFIProgram::Instruction::getOperandAsSigned(const CFIProgram &CFIP,
+                                            uint32_t OperandIdx) const {
+  if (OperandIdx >= MaxOperands)
+    return createStringError(errc::invalid_argument,
+                             "operand index %" PRIu32 " is not valid",
+                             OperandIdx);
+  OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx];
+  uint64_t Operand = Ops[OperandIdx];
+  switch (Type) {
+  case OT_Unset:
+  case OT_None:
+  case OT_Expression:
+    return createStringError(errc::invalid_argument,
+                             "op[%" PRIu32 "] has type %s which has no value",
+                             OperandIdx, CFIProgram::operandTypeString(Type));
+
+  case OT_Address:
+  case OT_Register:
+  case OT_AddressSpace:
+    return createStringError(
+        errc::invalid_argument,
+        "op[%" PRIu32 "] has OperandType %s which produces an unsigned result, "
+        "call getOperandAsUnsigned instead",
+        OperandIdx, CFIProgram::operandTypeString(Type));
+
+  case OT_Offset:
+    return (int64_t)Operand;
+
+  case OT_FactoredCodeOffset:
+  case OT_SignedFactDataOffset: {
+    const int64_t DataAlignmentFactor = CFIP.dataAlign();
+    if (DataAlignmentFactor == 0)
+      return createStringError(errc::invalid_argument,
+                               "op[%" PRIu32 "] has type %s but data "
+                               "alignment is zero",
+                               OperandIdx, CFIProgram::operandTypeString(Type));
+    return int64_t(Operand) * DataAlignmentFactor;
+  }
+
+  case OT_UnsignedFactDataOffset: {
+    const int64_t DataAlignmentFactor = CFIP.dataAlign();
+    if (DataAlignmentFactor == 0)
+      return createStringError(errc::invalid_argument,
+                               "op[%" PRIu32
+                               "] has type OT_UnsignedFactDataOffset but data "
+                               "alignment is zero",
+                               OperandIdx);
+    return Operand * DataAlignmentFactor;
+  }
+  }
+  llvm_unreachable("invalid operand type");
+}
+
+Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row,
+                             const RegisterLocations *InitialLocs) {
+  std::vector<RegisterLocations> RegisterStates;
+  for (const CFIProgram::Instruction &Inst : CFIP) {
+    switch (Inst.Opcode) {
+    case dwarf::DW_CFA_set_loc: {
+      // The DW_CFA_set_loc instruction takes a single operand that
+      // represents a target address. The required action is to create a new
+      // table row using the specified address as the location. All other
+      // values in the new row are initially identical to the current row.
+      // The new location value is always greater than the current one. If
+      // the segment_size field of this FDE's CIE is non- zero, the initial
+      // location is preceded by a segment selector of the given length
+      llvm::Expected<uint64_t> NewAddress = Inst.getOperandAsUnsigned(CFIP, 0);
+      if (!NewAddress)
+        return NewAddress.takeError();
+      if (*NewAddress <= Row.getAddress())
+        return createStringError(
+            errc::invalid_argument,
+            "%s with adrress 0x%" PRIx64 " which must be greater than the "
+            "current row address 0x%" PRIx64,
+            CFIP.callFrameString(Inst.Opcode).str().c_str(), *NewAddress,
+            Row.getAddress());
+      Rows.push_back(Row);
+      Row.setAddress(*NewAddress);
+      break;
+    }
+
+    case dwarf::DW_CFA_advance_loc:
+    case dwarf::DW_CFA_advance_loc1:
+    case dwarf::DW_CFA_advance_loc2:
+    case dwarf::DW_CFA_advance_loc4: {
+      // The DW_CFA_advance instruction takes a single operand that
+      // represents a constant delta. The required action is to create a new
+      // table row with a location value that is computed by taking the
+      // current entry’s location value and adding the value of delta *
+      // code_alignment_factor. All other values in the new row are initially
+      // identical to the current row.
+      Rows.push_back(Row);
+      llvm::Expected<uint64_t> Offset = Inst.getOperandAsUnsigned(CFIP, 0);
+      if (!Offset)
+        return Offset.takeError();
+      Row.slideAddress(*Offset);
+      break;
+    }
+
+    case dwarf::DW_CFA_restore:
+    case dwarf::DW_CFA_restore_extended: {
+      // The DW_CFA_restore instruction takes a single operand (encoded with
+      // the opcode) that represents a register number. The required action
+      // is to change the rule for the indicated register to the rule
+      // assigned it by the initial_instructions in the CIE.
+      if (InitialLocs == nullptr)
+        return createStringError(
+            errc::invalid_argument, "%s encountered while parsing a CIE",
+            CFIP.callFrameString(Inst.Opcode).str().c_str());
+      llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
+      if (!RegNum)
+        return RegNum.takeError();
+      if (Optional<UnwindLocation> O =
+              InitialLocs->getRegisterLocation(*RegNum))
+        Row.getRegisterLocations().setRegisterLocation(*RegNum, *O);
+      else
+        Row.getRegisterLocations().removeRegisterLocation(*RegNum);
+      break;
+    }
+
+    case dwarf::DW_CFA_offset:
+    case dwarf::DW_CFA_offset_extended:
+    case dwarf::DW_CFA_offset_extended_sf: {
+      llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
+      if (!RegNum)
+        return RegNum.takeError();
+      llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
+      if (!Offset)
+        return Offset.takeError();
+      Row.getRegisterLocations().setRegisterLocation(
+          *RegNum, UnwindLocation::createAtCFAPlusOffset(*Offset));
+      break;
+    }
+
+    case dwarf::DW_CFA_nop:
+      break;
+
+    case dwarf::DW_CFA_remember_state:
+      RegisterStates.push_back(Row.getRegisterLocations());
+      break;
+
+    case dwarf::DW_CFA_restore_state:
+      if (RegisterStates.empty())
+        return createStringError(errc::invalid_argument,
+                                 "DW_CFA_restore_state without a matching "
+                                 "previous DW_CFA_remember_state");
+      Row.getRegisterLocations() = RegisterStates.back();
+      RegisterStates.pop_back();
+      break;
+
+    case dwarf::DW_CFA_GNU_window_save:
+      switch (CFIP.triple()) {
+      case Triple::aarch64:
+      case Triple::aarch64_be:
+      case Triple::aarch64_32: {
+        // DW_CFA_GNU_window_save is used for different things on different
+        // architectures. For aarch64 it is known as
+        // DW_CFA_AARCH64_negate_ra_state. The action is to toggle the
+        // value of the return address state between 1 and 0. If there is
+        // no rule for the AARCH64_DWARF_PAUTH_RA_STATE register, then it
+        // should be initially set to 1.
+        constexpr uint32_t AArch64DWARFPAuthRaState = 34;
+        auto LRLoc = Row.getRegisterLocations().getRegisterLocation(
+            AArch64DWARFPAuthRaState);
+        if (LRLoc) {
+          if (LRLoc->getLocation() == UnwindLocation::Constant) {
+            // Toggle the constant value from 0 to 1 or 1 to 0.
+            LRLoc->setConstant(LRLoc->getConstant() ^ 1);
+          } else {
+            return createStringError(
+                errc::invalid_argument,
+                "%s encountered when existing rule for this register is not "
+                "a constant",
+                CFIP.callFrameString(Inst.Opcode).str().c_str());
+          }
+        } else {
+          Row.getRegisterLocations().setRegisterLocation(
+              AArch64DWARFPAuthRaState, UnwindLocation::createIsConstant(1));
+        }
+        break;
+      }
+
+      case Triple::sparc:
+      case Triple::sparcv9:
+      case Triple::sparcel:
+        for (uint32_t RegNum = 16; RegNum < 32; ++RegNum) {
+          Row.getRegisterLocations().setRegisterLocation(
+              RegNum, UnwindLocation::createAtCFAPlusOffset((RegNum - 16) * 8));
+        }
+        break;
+
+      default: {
+        return createStringError(
+            errc::not_supported,
+            "DW_CFA opcode %#x is not supported for architecture %s",
+            Inst.Opcode, Triple::getArchTypeName(CFIP.triple()).str().c_str());
+
+        break;
+      }
+      }
+      break;
+
+    case dwarf::DW_CFA_undefined: {
+      llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
+      if (!RegNum)
+        return RegNum.takeError();
+      Row.getRegisterLocations().setRegisterLocation(
+          *RegNum, UnwindLocation::createUndefined());
+      break;
+    }
+
+    case dwarf::DW_CFA_same_value: {
+      llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
+      if (!RegNum)
+        return RegNum.takeError();
+      Row.getRegisterLocations().setRegisterLocation(
+          *RegNum, UnwindLocation::createSame());
+      break;
+    }
+
+    case dwarf::DW_CFA_GNU_args_size:
+      break;
+
+    case dwarf::DW_CFA_register: {
+      llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
+      if (!RegNum)
+        return RegNum.takeError();
+      llvm::Expected<uint64_t> NewRegNum = Inst.getOperandAsUnsigned(CFIP, 1);
+      if (!NewRegNum)
+        return NewRegNum.takeError();
+      Row.getRegisterLocations().setRegisterLocation(
+          *RegNum, UnwindLocation::createIsRegisterPlusOffset(*NewRegNum, 0));
+      break;
+    }
+
+    case dwarf::DW_CFA_val_offset:
+    case dwarf::DW_CFA_val_offset_sf: {
+      llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
+      if (!RegNum)
+        return RegNum.takeError();
+      llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
+      if (!Offset)
+        return Offset.takeError();
+      Row.getRegisterLocations().setRegisterLocation(
+          *RegNum, UnwindLocation::createIsCFAPlusOffset(*Offset));
+      break;
+    }
+
+    case dwarf::DW_CFA_expression: {
+      llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
+      if (!RegNum)
+        return RegNum.takeError();
+      Row.getRegisterLocations().setRegisterLocation(
+          *RegNum, UnwindLocation::createAtDWARFExpression(*Inst.Expression));
+      break;
+    }
+
+    case dwarf::DW_CFA_val_expression: {
+      llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
+      if (!RegNum)
+        return RegNum.takeError();
+      Row.getRegisterLocations().setRegisterLocation(
+          *RegNum, UnwindLocation::createIsDWARFExpression(*Inst.Expression));
+      break;
+    }
+
+    case dwarf::DW_CFA_def_cfa_register: {
+      llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
+      if (!RegNum)
+        return RegNum.takeError();
+      if (Row.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset)
+        Row.getCFAValue() =
+            UnwindLocation::createIsRegisterPlusOffset(*RegNum, 0);
+      else
+        Row.getCFAValue().setRegister(*RegNum);
+      break;
+    }
+
+    case dwarf::DW_CFA_def_cfa_offset:
+    case dwarf::DW_CFA_def_cfa_offset_sf: {
+      llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 0);
+      if (!Offset)
+        return Offset.takeError();
+      if (Row.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset) {
+        return createStringError(
+            errc::invalid_argument,
+            "%s found when CFA rule was not RegPlusOffset",
+            CFIP.callFrameString(Inst.Opcode).str().c_str());
+      }
+      Row.getCFAValue().setOffset(*Offset);
+      break;
+    }
+
+    case dwarf::DW_CFA_def_cfa:
+    case dwarf::DW_CFA_def_cfa_sf: {
+      llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
+      if (!RegNum)
+        return RegNum.takeError();
+      llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
+      if (!Offset)
+        return Offset.takeError();
+      Row.getCFAValue() =
+          UnwindLocation::createIsRegisterPlusOffset(*RegNum, *Offset);
+      break;
+    }
+
+    case dwarf::DW_CFA_LLVM_def_aspace_cfa:
+    case dwarf::DW_CFA_LLVM_def_aspace_cfa_sf: {
+      llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
+      if (!RegNum)
+        return RegNum.takeError();
+      llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
+      if (!Offset)
+        return Offset.takeError();
+      llvm::Expected<uint32_t> CFAAddrSpace =
+          Inst.getOperandAsUnsigned(CFIP, 2);
+      if (!CFAAddrSpace)
+        return CFAAddrSpace.takeError();
+      Row.getCFAValue() = UnwindLocation::createIsRegisterPlusOffset(
+          *RegNum, *Offset, *CFAAddrSpace);
+      break;
+    }
+
+    case dwarf::DW_CFA_def_cfa_expression:
+      Row.getCFAValue() =
+          UnwindLocation::createIsDWARFExpression(*Inst.Expression);
+      break;
+    }
+  }
+  return Error::success();
+}
+
+ArrayRef<CFIProgram::OperandType[CFIProgram::MaxOperands]>
+CFIProgram::getOperandTypes() {
+  static OperandType OpTypes[DW_CFA_restore + 1][MaxOperands];
   static bool Initialized = false;
   if (Initialized) {
-    return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
+    return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1);
   }
   Initialized = true;
 
-#define DECLARE_OP2(OP, OPTYPE0, OPTYPE1)       \
-  do {                                          \
-    OpTypes[OP][0] = OPTYPE0;                   \
-    OpTypes[OP][1] = OPTYPE1;                   \
+#define DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OPTYPE2)                             \
+  do {                                                                         \
+    OpTypes[OP][0] = OPTYPE0;                                                  \
+    OpTypes[OP][1] = OPTYPE1;                                                  \
+    OpTypes[OP][2] = OPTYPE2;                                                  \
   } while (false)
+#define DECLARE_OP2(OP, OPTYPE0, OPTYPE1)                                      \
+  DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OT_None)
 #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
 #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
 
@@ -205,6 +818,10 @@
   DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
   DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
   DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
+  DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa, OT_Register, OT_Offset,
+              OT_AddressSpace);
+  DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa_sf, OT_Register,
+              OT_SignedFactDataOffset, OT_AddressSpace);
   DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
   DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
   DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
@@ -230,7 +847,7 @@
 #undef DECLARE_OP1
 #undef DECLARE_OP2
 
-  return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
+  return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1);
 }
 
 /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
@@ -238,14 +855,14 @@
                               const MCRegisterInfo *MRI, bool IsEH,
                               const Instruction &Instr, unsigned OperandIdx,
                               uint64_t Operand) const {
-  assert(OperandIdx < 2);
+  assert(OperandIdx < MaxOperands);
   uint8_t Opcode = Instr.Opcode;
   OperandType Type = getOperandTypes()[Opcode][OperandIdx];
 
   switch (Type) {
   case OT_Unset: {
     OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
-    auto OpcodeName = CallFrameString(Opcode, Arch);
+    auto OpcodeName = callFrameString(Opcode);
     if (!OpcodeName.empty())
       OS << " " << OpcodeName;
     else
@@ -285,6 +902,9 @@
     OS << ' ';
     printRegister(OS, MRI, IsEH, Operand);
     break;
+  case OT_AddressSpace:
+    OS << format(" in addrspace%" PRId64, Operand);
+    break;
   case OT_Expression:
     assert(Instr.Expression && "missing DWARFExpression object");
     OS << " ";
@@ -298,10 +918,8 @@
                       unsigned IndentLevel) const {
   for (const auto &Instr : Instructions) {
     uint8_t Opcode = Instr.Opcode;
-    if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
-      Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
     OS.indent(2 * IndentLevel);
-    OS << CallFrameString(Opcode, Arch) << ":";
+    OS << callFrameString(Opcode) << ":";
     for (unsigned i = 0; i < Instr.Ops.size(); ++i)
       printOperand(OS, DumpOpts, MRI, IsEH, Instr, i, Instr.Ops[i]);
     OS << '\n';
@@ -333,8 +951,10 @@
      << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8,
                getCIEId(IsDWARF64, IsEH))
      << " CIE\n"
-     << "  Format:                " << FormatString(IsDWARF64) << "\n"
-     << format("  Version:               %d\n", Version)
+     << "  Format:                " << FormatString(IsDWARF64) << "\n";
+  if (IsEH && Version != 1)
+    OS << "WARNING: unsupported CIE version\n";
+  OS << format("  Version:               %d\n", Version)
      << "  Augmentation:          \"" << Augmentation << "\"\n";
   if (Version >= 4) {
     OS << format("  Address size:          %u\n", (uint32_t)AddressSize);
@@ -355,6 +975,16 @@
   OS << "\n";
   CFIs.dump(OS, DumpOpts, MRI, IsEH);
   OS << "\n";
+
+  if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
+    RowsOrErr->dump(OS, MRI, IsEH, 1);
+  else {
+    DumpOpts.RecoverableErrorHandler(joinErrors(
+        createStringError(errc::invalid_argument,
+                          "decoding the CIE opcodes into rows failed"),
+        RowsOrErr.takeError()));
+  }
+  OS << "\n";
 }
 
 void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
@@ -374,6 +1004,16 @@
     OS << format("  LSDA Address: %016" PRIx64 "\n", *LSDAAddress);
   CFIs.dump(OS, DumpOpts, MRI, IsEH);
   OS << "\n";
+
+  if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
+    RowsOrErr->dump(OS, MRI, IsEH, 1);
+  else {
+    DumpOpts.RecoverableErrorHandler(joinErrors(
+        createStringError(errc::invalid_argument,
+                          "decoding the FDE opcodes into rows failed"),
+        RowsOrErr.takeError()));
+  }
+  OS << "\n";
 }
 
 DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch,
@@ -434,11 +1074,6 @@
       uint8_t Version = Data.getU8(&Offset);
       const char *Augmentation = Data.getCStr(&Offset);
       StringRef AugmentationString(Augmentation ? Augmentation : "");
-      // TODO: we should provide a way to report a warning and continue dumping.
-      if (IsEH && Version != 1)
-        return createStringError(errc::not_supported,
-                                 "unsupported CIE version: %" PRIu8, Version);
-
       uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :
                                           Data.getU8(&Offset);
       Data.setAddressSize(AddressSize);
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp
index 2b7d0c3..7ebb009 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp
@@ -8,6 +8,7 @@
 
 #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
@@ -30,17 +31,42 @@
                                       uint64_t UEndOffset, uint32_t D) {
   Offset = *OffsetPtr;
   Depth = D;
-  if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset))
+  if (Offset >= UEndOffset) {
+    U.getContext().getWarningHandler()(
+        createStringError(errc::invalid_argument,
+                          "DWARF unit from offset 0x%8.8" PRIx64 " incl. "
+                          "to offset 0x%8.8" PRIx64 " excl. "
+                          "tries to read DIEs at offset 0x%8.8" PRIx64,
+                          U.getOffset(), U.getNextUnitOffset(), *OffsetPtr));
     return false;
+  }
+  assert(DebugInfoData.isValidOffset(UEndOffset - 1));
   uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr);
   if (0 == AbbrCode) {
     // NULL debug tag entry.
     AbbrevDecl = nullptr;
     return true;
   }
-  if (const auto *AbbrevSet = U.getAbbreviations())
-    AbbrevDecl = AbbrevSet->getAbbreviationDeclaration(AbbrCode);
-  if (nullptr == AbbrevDecl) {
+  const auto *AbbrevSet = U.getAbbreviations();
+  if (!AbbrevSet) {
+    U.getContext().getWarningHandler()(
+        createStringError(errc::invalid_argument,
+                          "DWARF unit at offset 0x%8.8" PRIx64 " "
+                          "contains invalid abbreviation set offset 0x%" PRIx64,
+                          U.getOffset(), U.getAbbreviationsOffset()));
+    // Restore the original offset.
+    *OffsetPtr = Offset;
+    return false;
+  }
+  AbbrevDecl = AbbrevSet->getAbbreviationDeclaration(AbbrCode);
+  if (!AbbrevDecl) {
+    U.getContext().getWarningHandler()(
+        createStringError(errc::invalid_argument,
+                          "DWARF unit at offset 0x%8.8" PRIx64 " "
+                          "contains invalid abbreviation %" PRIu64 " at "
+                          "offset 0x%8.8" PRIx64 ", valid abbreviations are %s",
+                          U.getOffset(), AbbrCode, *OffsetPtr,
+                          AbbrevSet->getCodeRange().c_str()));
     // Restore the original offset.
     *OffsetPtr = Offset;
     return false;
@@ -62,6 +88,11 @@
                                           OffsetPtr, U.getFormParams())) {
       // We failed to skip this attribute's value, restore the original offset
       // and return the failure status.
+      U.getContext().getWarningHandler()(createStringError(
+          errc::invalid_argument,
+          "DWARF unit at offset 0x%8.8" PRIx64 " "
+          "contains invalid FORM_* 0x%" PRIx16 " at offset 0x%8.8" PRIx64,
+          U.getOffset(), AttrSpec.Form, *OffsetPtr));
       *OffsetPtr = Offset;
       return false;
     }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index 5a55f3a..0501e3e 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -69,39 +69,43 @@
   }
 }
 
-static void dumpLocation(raw_ostream &OS, const DWARFFormValue &FormValue,
-                         DWARFUnit *U, unsigned Indent,
-                         DIDumpOptions DumpOpts) {
+static void dumpLocationList(raw_ostream &OS, const DWARFFormValue &FormValue,
+                             DWARFUnit *U, unsigned Indent,
+                             DIDumpOptions DumpOpts) {
+  assert(FormValue.isFormClass(DWARFFormValue::FC_SectionOffset) &&
+         "bad FORM for location list");
   DWARFContext &Ctx = U->getContext();
   const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
-  if (FormValue.isFormClass(DWARFFormValue::FC_Block) ||
-      FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) {
-    ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();
-    DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
-                       Ctx.isLittleEndian(), 0);
-    DWARFExpression(Data, U->getAddressByteSize(), U->getFormParams().Format)
-        .print(OS, DumpOpts, MRI, U);
-    return;
+  uint64_t Offset = *FormValue.getAsSectionOffset();
+
+  if (FormValue.getForm() == DW_FORM_loclistx) {
+    FormValue.dump(OS, DumpOpts);
+
+    if (auto LoclistOffset = U->getLoclistOffset(Offset))
+      Offset = *LoclistOffset;
+    else
+      return;
   }
+  U->getLocationTable().dumpLocationList(&Offset, OS, U->getBaseAddress(), MRI,
+                                         Ctx.getDWARFObj(), U, DumpOpts,
+                                         Indent);
+  return;
+}
 
-  if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {
-    uint64_t Offset = *FormValue.getAsSectionOffset();
-
-    if (FormValue.getForm() == DW_FORM_loclistx) {
-      FormValue.dump(OS, DumpOpts);
-
-      if (auto LoclistOffset = U->getLoclistOffset(Offset))
-        Offset = *LoclistOffset;
-      else
-        return;
-    }
-    U->getLocationTable().dumpLocationList(&Offset, OS, U->getBaseAddress(),
-                                           MRI, Ctx.getDWARFObj(), U, DumpOpts,
-                                           Indent);
-    return;
-  }
-
-  FormValue.dump(OS, DumpOpts);
+static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue,
+                             DWARFUnit *U, unsigned Indent,
+                             DIDumpOptions DumpOpts) {
+  assert((FormValue.isFormClass(DWARFFormValue::FC_Block) ||
+          FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) &&
+         "bad FORM for location expression");
+  DWARFContext &Ctx = U->getContext();
+  const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
+  ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();
+  DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
+                     Ctx.isLittleEndian(), 0);
+  DWARFExpression(Data, U->getAddressByteSize(), U->getFormParams().Format)
+      .print(OS, DumpOpts, MRI, U);
+  return;
 }
 
 /// Dump the name encoded in the type tag.
@@ -289,9 +293,15 @@
       else
         FormValue.dump(OS, DumpOpts);
     }
-  } else if (Form == dwarf::Form::DW_FORM_exprloc ||
-             DWARFAttribute::mayHaveLocationDescription(Attr))
-    dumpLocation(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts);
+  } else if (DWARFAttribute::mayHaveLocationList(Attr) &&
+             FormValue.isFormClass(DWARFFormValue::FC_SectionOffset))
+    dumpLocationList(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4,
+                     DumpOpts);
+  else if (FormValue.isFormClass(DWARFFormValue::FC_Exprloc) ||
+           (DWARFAttribute::mayHaveLocationExpr(Attr) &&
+            FormValue.isFormClass(DWARFFormValue::FC_Block)))
+    dumpLocationExpr(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4,
+                     DumpOpts);
   else
     FormValue.dump(OS, DumpOpts);
 
@@ -571,11 +581,16 @@
 
 std::string
 DWARFDie::getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const {
+  auto D = getAttributeValueAsReferencedDie(DW_AT_abstract_origin);
+  if (!D)
+    D = *this;
   std::string FileName;
-  if (auto DeclFile = toUnsigned(findRecursively(DW_AT_decl_file))) {
-    if (const auto *LT = U->getContext().getLineTableForUnit(U)) {
-      LT->getFileNameByIndex(*DeclFile, U->getCompilationDir(), Kind, FileName);
-    }
+  if (auto DeclFile = toUnsigned(D.find(DW_AT_decl_file))) {
+    if (const auto *LineTable =
+            getDwarfUnit()->getContext().getLineTableForUnit(
+                D.getDwarfUnit()->getLinkedUnit()))
+      LineTable->getFileNameByIndex(
+          *DeclFile, D.getDwarfUnit()->getCompilationDir(), Kind, FileName);
   }
   return FileName;
 }
@@ -635,14 +650,14 @@
         for (const DWARFAttribute &AttrValue : attributes())
           dumpAttribute(OS, *this, AttrValue, Indent, DumpOpts);
 
-        DWARFDie child = getFirstChild();
-        if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0 && child) {
+        if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0) {
+          DWARFDie Child = getFirstChild();
           DumpOpts.ChildRecurseDepth--;
           DIDumpOptions ChildDumpOpts = DumpOpts;
           ChildDumpOpts.ShowParents = false;
-          while (child) {
-            child.dump(OS, Indent + 2, ChildDumpOpts);
-            child = child.getSibling();
+          while (Child) {
+            Child.dump(OS, Indent + 2, ChildDumpOpts);
+            Child = Child.getSibling();
           }
         }
       } else {
@@ -739,11 +754,29 @@
   return *this;
 }
 
-bool DWARFAttribute::mayHaveLocationDescription(dwarf::Attribute Attr) {
+bool DWARFAttribute::mayHaveLocationList(dwarf::Attribute Attr) {
+  switch(Attr) {
+  case DW_AT_location:
+  case DW_AT_string_length:
+  case DW_AT_return_addr:
+  case DW_AT_data_member_location:
+  case DW_AT_frame_base:
+  case DW_AT_static_link:
+  case DW_AT_segment:
+  case DW_AT_use_location:
+  case DW_AT_vtable_elem_location:
+    return true;
+  default:
+    return false;
+  }
+}
+
+bool DWARFAttribute::mayHaveLocationExpr(dwarf::Attribute Attr) {
   switch (Attr) {
   // From the DWARF v5 specification.
   case DW_AT_location:
   case DW_AT_byte_size:
+  case DW_AT_bit_offset:
   case DW_AT_bit_size:
   case DW_AT_string_length:
   case DW_AT_lower_bound:
@@ -759,6 +792,7 @@
   case DW_AT_vtable_elem_location:
   case DW_AT_allocated:
   case DW_AT_associated:
+  case DW_AT_data_location:
   case DW_AT_byte_stride:
   case DW_AT_rank:
   case DW_AT_call_value:
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
index 8117161..4b9be85 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
@@ -174,7 +174,10 @@
     case Operation::WasmLocationArg:
       assert(Operand == 1);
       switch (Operands[0]) {
-      case 0: case 1: case 2:
+      case 0:
+      case 1:
+      case 2:
+      case 4:
         Operands[Operand] = Data.getULEB128(&Offset);
         break;
       case 3: // global as uint32
@@ -294,8 +297,11 @@
     } else if (Size == Operation::WasmLocationArg) {
       assert(Operand == 1);
       switch (Operands[0]) {
-      case 0: case 1: case 2:
+      case 0:
+      case 1:
+      case 2:
       case 3: // global as uint32
+      case 4:
         OS << format(" 0x%" PRIx64, Operands[Operand]);
         break;
       default: assert(false);
@@ -319,6 +325,10 @@
                             const MCRegisterInfo *RegInfo, DWARFUnit *U,
                             bool IsEH) const {
   uint32_t EntryValExprSize = 0;
+  uint64_t EntryValStartOffset = 0;
+  if (Data.getData().empty())
+    OS << "<empty>";
+
   for (auto &Op : *this) {
     if (!Op.print(OS, DumpOpts, this, RegInfo, U, IsEH)) {
       uint64_t FailOffset = Op.getEndOffset();
@@ -331,11 +341,12 @@
         Op.getCode() == DW_OP_GNU_entry_value) {
       OS << "(";
       EntryValExprSize = Op.getRawOperand(0);
+      EntryValStartOffset = Op.getEndOffset();
       continue;
     }
 
     if (EntryValExprSize) {
-      EntryValExprSize--;
+      EntryValExprSize -= Op.getEndOffset() - EntryValStartOffset;
       if (EntryValExprSize == 0)
         OS << ")";
     }
@@ -501,4 +512,10 @@
   return printCompactDWARFExpr(OS, begin(), end(), MRI);
 }
 
+bool DWARFExpression::operator==(const DWARFExpression &RHS) const {
+  if (AddressSize != RHS.AddressSize || Format != RHS.Format)
+    return false;
+  return Data.getData() == RHS.Data.getData();
+}
+
 } // namespace llvm
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
index 2559765..2244a69 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
@@ -74,7 +74,7 @@
     DWARFFormValue::FC_Address,       // 0x2a DW_FORM_addrx2
     DWARFFormValue::FC_Address,       // 0x2b DW_FORM_addrx3
     DWARFFormValue::FC_Address,       // 0x2c DW_FORM_addrx4
-
+    DWARFFormValue::FC_Address,       // 0x2001 DW_FORM_addrx_offset
 };
 
 DWARFFormValue DWARFFormValue::createFromSValue(dwarf::Form F, int64_t V) {
@@ -192,6 +192,11 @@
       DebugInfoData.getULEB128(OffsetPtr);
       return true;
 
+    case DW_FORM_LLVM_addrx_offset:
+      DebugInfoData.getULEB128(OffsetPtr);
+      *OffsetPtr += 4;
+      return true;
+
     case DW_FORM_indirect:
       Indirect = true;
       Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr));
@@ -218,6 +223,8 @@
   case DW_FORM_GNU_str_index:
   case DW_FORM_GNU_strp_alt:
     return (FC == FC_String);
+  case DW_FORM_LLVM_addrx_offset:
+    return (FC == FC_Address);
   default:
     break;
   }
@@ -323,6 +330,10 @@
     case DW_FORM_strx:
       Value.uval = Data.getULEB128(OffsetPtr, &Err);
       break;
+    case DW_FORM_LLVM_addrx_offset:
+      Value.uval = Data.getULEB128(OffsetPtr, &Err) << 32;
+      Value.uval = Data.getU32(OffsetPtr, &Err);
+      break;
     case DW_FORM_string:
       Value.cstr = Data.getCStr(OffsetPtr, &Err);
       break;
@@ -421,6 +432,23 @@
       OS << "<unresolved>";
     break;
   }
+  case DW_FORM_LLVM_addrx_offset: {
+    if (U == nullptr) {
+      OS << "<invalid dwarf unit>";
+      break;
+    }
+    uint32_t Index = UValue >> 32;
+    uint32_t Offset = UValue & 0xffffffff;
+    Optional<object::SectionedAddress> A = U->getAddrOffsetSectionItem(Index);
+    if (!A || DumpOpts.Verbose)
+      AddrOS << format("indexed (%8.8x) + 0x%x address = ", Index, Offset);
+    if (A) {
+      A->Address += Offset;
+      dumpSectionedAddress(AddrOS, DumpOpts, *A);
+    } else
+      OS << "<unresolved>";
+    break;
+  }
   case DW_FORM_flag_present:
     OS << "true";
     break;
@@ -641,13 +669,17 @@
 DWARFFormValue::getAsSectionedAddress() const {
   if (!isFormClass(FC_Address))
     return None;
-  if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx) {
-    uint32_t Index = Value.uval;
+  bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset;
+  if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx || AddrOffset) {
+
+    uint32_t Index = AddrOffset ? (Value.uval >> 32) : Value.uval;
     if (!U)
       return None;
     Optional<object::SectionedAddress> SA = U->getAddrOffsetSectionItem(Index);
     if (!SA)
       return None;
+    if (AddrOffset)
+      SA->Address += (Value.uval & 0xffffffff);
     return SA;
   }
   return {{Value.uval, Value.SectionIndex}};
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index 8493950..f17dacf 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -192,17 +192,18 @@
 
 Optional<object::SectionedAddress>
 DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const {
-  if (IsDWO) {
+  if (!AddrOffsetSectionBase) {
     auto R = Context.info_section_units();
     // Surprising if a DWO file has more than one skeleton unit in it - this
     // probably shouldn't be valid, but if a use case is found, here's where to
     // support it (probably have to linearly search for the matching skeleton CU
     // here)
-    if (hasSingleElement(R))
+    if (IsDWO && hasSingleElement(R))
       return (*R.begin())->getAddrOffsetSectionItem(Index);
-  }
-  if (!AddrOffsetSectionBase)
+
     return None;
+  }
+
   uint64_t Offset = *AddrOffsetSectionBase + Index * getAddressByteSize();
   if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize())
     return None;
@@ -258,26 +259,73 @@
   } else if (UnitType == DW_UT_split_compile || UnitType == DW_UT_skeleton)
     DWOId = debug_info.getU64(offset_ptr, &Err);
 
-  if (errorToBool(std::move(Err)))
+  if (Err) {
+    Context.getWarningHandler()(joinErrors(
+        createStringError(
+            errc::invalid_argument,
+            "DWARF unit at 0x%8.8" PRIx64 " cannot be parsed:", Offset),
+        std::move(Err)));
     return false;
+  }
 
   // Header fields all parsed, capture the size of this unit header.
   assert(*offset_ptr - Offset <= 255 && "unexpected header size");
   Size = uint8_t(*offset_ptr - Offset);
+  uint64_t NextCUOffset = Offset + getUnitLengthFieldByteSize() + getLength();
+
+  if (!debug_info.isValidOffset(getNextUnitOffset() - 1)) {
+    Context.getWarningHandler()(
+        createStringError(errc::invalid_argument,
+                          "DWARF unit from offset 0x%8.8" PRIx64 " incl. "
+                          "to offset  0x%8.8" PRIx64 " excl. "
+                          "extends past section size 0x%8.8zx",
+                          Offset, NextCUOffset, debug_info.size()));
+    return false;
+  }
+
+  if (!DWARFContext::isSupportedVersion(getVersion())) {
+    Context.getWarningHandler()(createStringError(
+        errc::invalid_argument,
+        "DWARF unit at offset 0x%8.8" PRIx64 " "
+        "has unsupported version %" PRIu16 ", supported are 2-%u",
+        Offset, getVersion(), DWARFContext::getMaxSupportedVersion()));
+    return false;
+  }
 
   // Type offset is unit-relative; should be after the header and before
   // the end of the current unit.
-  bool TypeOffsetOK =
-      !isTypeUnit()
-          ? true
-          : TypeOffset >= Size &&
-                TypeOffset < getLength() + getUnitLengthFieldByteSize();
-  bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
-  bool VersionOK = DWARFContext::isSupportedVersion(getVersion());
-  bool AddrSizeOK = DWARFContext::isAddressSizeSupported(getAddressByteSize());
-
-  if (!LengthOK || !VersionOK || !AddrSizeOK || !TypeOffsetOK)
+  if (isTypeUnit() && TypeOffset < Size) {
+    Context.getWarningHandler()(
+        createStringError(errc::invalid_argument,
+                          "DWARF type unit at offset "
+                          "0x%8.8" PRIx64 " "
+                          "has its relocated type_offset 0x%8.8" PRIx64 " "
+                          "pointing inside the header",
+                          Offset, Offset + TypeOffset));
     return false;
+  }
+  if (isTypeUnit() &&
+      TypeOffset >= getUnitLengthFieldByteSize() + getLength()) {
+    Context.getWarningHandler()(createStringError(
+        errc::invalid_argument,
+        "DWARF type unit from offset 0x%8.8" PRIx64 " incl. "
+        "to offset 0x%8.8" PRIx64 " excl. has its "
+        "relocated type_offset 0x%8.8" PRIx64 " pointing past the unit end",
+        Offset, NextCUOffset, Offset + TypeOffset));
+    return false;
+  }
+
+  if (!DWARFContext::isAddressSizeSupported(getAddressByteSize())) {
+    SmallVector<std::string, 3> Sizes;
+    for (auto Size : DWARFContext::getSupportedAddressSizes())
+      Sizes.push_back(std::to_string(Size));
+    Context.getWarningHandler()(createStringError(
+        errc::invalid_argument,
+        "DWARF unit at offset 0x%8.8" PRIx64 " "
+        "has unsupported address size %" PRIu8 ", supported are %s",
+        Offset, getAddressByteSize(), llvm::join(Sizes, ", ").c_str()));
+    return false;
+  }
 
   // Keep track of the highest DWARF version we encounter across all units.
   Context.setMaxVersionIfGreater(getVersion());
@@ -340,6 +388,7 @@
   RangeSectionBase = 0;
   LocSectionBase = 0;
   AddrOffsetSectionBase = None;
+  SU = nullptr;
   clearDIEs(false);
   DWO.reset();
 }
@@ -360,6 +409,8 @@
   uint64_t NextCUOffset = getNextUnitOffset();
   DWARFDebugInfoEntry DIE;
   DWARFDataExtractor DebugInfoData = getDebugInfoExtractor();
+  // The end offset has been already checked by DWARFUnitHeader::extract.
+  assert(DebugInfoData.isValidOffset(NextCUOffset - 1));
   uint32_t Depth = 0;
   bool IsCUDie = true;
 
@@ -384,6 +435,8 @@
       // Normal DIE
       if (AbbrDecl->hasChildren())
         ++Depth;
+      else if (Depth == 0)
+        break; // This unit has a single DIE with no children.
     } else {
       // NULL DIE.
       if (Depth > 0)
@@ -392,17 +445,6 @@
         break;  // We are done with this compile unit!
     }
   }
-
-  // Give a little bit of info if we encounter corrupt DWARF (our offset
-  // should always terminate at or before the start of the next compilation
-  // unit header).
-  if (DIEOffset > NextCUOffset)
-    Context.getWarningHandler()(
-        createStringError(errc::invalid_argument,
-                          "DWARF compile unit extends beyond its "
-                          "bounds cu 0x%8.8" PRIx64 " "
-                          "at 0x%8.8" PRIx64 "\n",
-                          getOffset(), DIEOffset));
 }
 
 void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
@@ -545,13 +587,11 @@
   if (!DWOCU)
     return false;
   DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU);
+  DWO->setSkeletonUnit(this);
   // Share .debug_addr and .debug_ranges section with compile unit in .dwo
   if (AddrOffsetSectionBase)
     DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase);
-  if (getVersion() >= 5) {
-    DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(),
-                          DWARFListTableHeader::getHeaderSize(getFormat()));
-  } else {
+  if (getVersion() == 4) {
     auto DWORangesBase = UnitDie.getRangesBaseAttribute();
     DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0);
   }
@@ -688,15 +728,15 @@
   DWARFDie SubroutineDIE =
       (DWO ? *DWO : *this).getSubroutineForAddress(Address);
 
-  if (!SubroutineDIE)
-    return;
-
-  while (!SubroutineDIE.isSubprogramDIE()) {
+  while (SubroutineDIE) {
+    if (SubroutineDIE.isSubprogramDIE()) {
+      InlinedChain.push_back(SubroutineDIE);
+      return;
+    }
     if (SubroutineDIE.getTag() == DW_TAG_inlined_subroutine)
       InlinedChain.push_back(SubroutineDIE);
     SubroutineDIE  = SubroutineDIE.getParent();
   }
-  InlinedChain.push_back(SubroutineDIE);
 }
 
 const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context,
@@ -793,7 +833,7 @@
 
 const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const {
   if (!Abbrevs)
-    Abbrevs = Abbrev->getAbbreviationDeclarationSet(Header.getAbbrOffset());
+    Abbrevs = Abbrev->getAbbreviationDeclarationSet(getAbbreviationsOffset());
   return Abbrevs;
 }
 
diff --git a/src/llvm-project/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp b/src/llvm-project/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp
index 1e527ab..cdea0e3 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp
@@ -310,8 +310,10 @@
       // so break out after printing a warning.
       auto FirstLE = FI.OptLineTable->first();
       if (FirstLE && *FirstLE == LE) {
-        Log << "warning: duplicate line table detected for DIE:\n";
-        Die.dump(Log, 0, DIDumpOptions::getForSingleDIE());
+        if (!Gsym.isQuiet()) {
+          Log << "warning: duplicate line table detected for DIE:\n";
+          Die.dump(Log, 0, DIDumpOptions::getForSingleDIE());
+        }
       } else {
         // Print out (ignore if os == nulls as this is expensive)
         Log << "error: line table has addresses that do not "
@@ -390,11 +392,14 @@
         // and the debug info wasn't able to be stripped from the DWARF. If
         // the LowPC isn't zero or -1, then we should emit an error.
         if (Range.LowPC != 0) {
-          // Unexpected invalid address, emit an error
-          Log << "warning: DIE has an address range whose start address is "
-              "not in any executable sections (" <<
-              *Gsym.GetValidTextRanges() << ") and will not be processed:\n";
-          Die.dump(Log, 0, DIDumpOptions::getForSingleDIE());
+          if (!Gsym.isQuiet()) {
+            // Unexpected invalid address, emit a warning
+            Log << "warning: DIE has an address range whose start address is "
+                   "not in any executable sections ("
+                << *Gsym.GetValidTextRanges()
+                << ") and will not be processed:\n";
+            Die.dump(Log, 0, DIDumpOptions::getForSingleDIE());
+          }
         }
         break;
       }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp b/src/llvm-project/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp
index 2001478..1c20a59 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp
@@ -20,13 +20,12 @@
 using namespace llvm;
 using namespace gsym;
 
-
-GsymCreator::GsymCreator() : StrTab(StringTableBuilder::ELF) {
+GsymCreator::GsymCreator(bool Quiet)
+    : StrTab(StringTableBuilder::ELF), Quiet(Quiet) {
   insertFile(StringRef());
 }
 
-uint32_t GsymCreator::insertFile(StringRef Path,
-                                 llvm::sys::path::Style Style) {
+uint32_t GsymCreator::insertFile(StringRef Path, llvm::sys::path::Style Style) {
   llvm::StringRef directory = llvm::sys::path::parent_path(Path, Style);
   llvm::StringRef filename = llvm::sys::path::filename(Path, Style);
   // We must insert the strings first, then call the FileEntry constructor.
@@ -37,7 +36,7 @@
   const uint32_t Base = insertString(filename);
   FileEntry FE(Dir, Base);
 
-  std::lock_guard<std::recursive_mutex> Guard(Mutex);
+  std::lock_guard<std::mutex> Guard(Mutex);
   const auto NextIndex = Files.size();
   // Find FE in hash map and insert if not present.
   auto R = FileEntryToIndex.insert(std::make_pair(FE, NextIndex));
@@ -57,7 +56,7 @@
 }
 
 llvm::Error GsymCreator::encode(FileWriter &O) const {
-  std::lock_guard<std::recursive_mutex> Guard(Mutex);
+  std::lock_guard<std::mutex> Guard(Mutex);
   if (Funcs.empty())
     return createStringError(std::errc::invalid_argument,
                              "no functions to encode");
@@ -69,7 +68,8 @@
     return createStringError(std::errc::invalid_argument,
                              "too many FunctionInfos");
 
-  const uint64_t MinAddr = BaseAddress ? *BaseAddress : Funcs.front().startAddress();
+  const uint64_t MinAddr =
+      BaseAddress ? *BaseAddress : Funcs.front().startAddress();
   const uint64_t MaxAddr = Funcs.back().startAddress();
   const uint64_t AddrDelta = MaxAddr - MinAddr;
   Header Hdr;
@@ -80,7 +80,7 @@
   Hdr.BaseAddress = MinAddr;
   Hdr.NumAddresses = static_cast<uint32_t>(Funcs.size());
   Hdr.StrtabOffset = 0; // We will fix this up later.
-  Hdr.StrtabSize = 0; // We will fix this up later.
+  Hdr.StrtabSize = 0;   // We will fix this up later.
   memset(Hdr.UUID, 0, sizeof(Hdr.UUID));
   if (UUID.size() > sizeof(Hdr.UUID))
     return createStringError(std::errc::invalid_argument,
@@ -106,11 +106,19 @@
   O.alignTo(Hdr.AddrOffSize);
   for (const auto &FuncInfo : Funcs) {
     uint64_t AddrOffset = FuncInfo.startAddress() - Hdr.BaseAddress;
-    switch(Hdr.AddrOffSize) {
-      case 1: O.writeU8(static_cast<uint8_t>(AddrOffset)); break;
-      case 2: O.writeU16(static_cast<uint16_t>(AddrOffset)); break;
-      case 4: O.writeU32(static_cast<uint32_t>(AddrOffset)); break;
-      case 8: O.writeU64(AddrOffset); break;
+    switch (Hdr.AddrOffSize) {
+    case 1:
+      O.writeU8(static_cast<uint8_t>(AddrOffset));
+      break;
+    case 2:
+      O.writeU16(static_cast<uint16_t>(AddrOffset));
+      break;
+    case 4:
+      O.writeU32(static_cast<uint32_t>(AddrOffset));
+      break;
+    case 8:
+      O.writeU64(AddrOffset);
+      break;
     }
   }
 
@@ -127,12 +135,11 @@
   assert(Files[0].Base == 0);
   size_t NumFiles = Files.size();
   if (NumFiles > UINT32_MAX)
-    return createStringError(std::errc::invalid_argument,
-                             "too many files");
+    return createStringError(std::errc::invalid_argument, "too many files");
   O.writeU32(static_cast<uint32_t>(NumFiles));
-  for (auto File: Files) {
-      O.writeU32(File.Dir);
-      O.writeU32(File.Base);
+  for (auto File : Files) {
+    O.writeU32(File.Dir);
+    O.writeU32(File.Base);
   }
 
   // Write out the sting table.
@@ -144,9 +151,9 @@
   // Write out the address infos for each function info.
   for (const auto &FuncInfo : Funcs) {
     if (Expected<uint64_t> OffsetOrErr = FuncInfo.encode(O))
-        AddrInfoOffsets.push_back(OffsetOrErr.get());
+      AddrInfoOffsets.push_back(OffsetOrErr.get());
     else
-        return OffsetOrErr.takeError();
+      return OffsetOrErr.takeError();
   }
   // Fixup the string table offset and size in the header
   O.fixup32((uint32_t)StrtabOffset, offsetof(Header, StrtabOffset));
@@ -154,18 +161,37 @@
 
   // Fixup all address info offsets
   uint64_t Offset = 0;
-  for (auto AddrInfoOffset: AddrInfoOffsets) {
+  for (auto AddrInfoOffset : AddrInfoOffsets) {
     O.fixup32(AddrInfoOffset, AddrInfoOffsetsOffset + Offset);
     Offset += 4;
   }
   return ErrorSuccess();
 }
 
+// Similar to std::remove_if, but the predicate is binary and it is passed both
+// the previous and the current element.
+template <class ForwardIt, class BinaryPredicate>
+static ForwardIt removeIfBinary(ForwardIt FirstIt, ForwardIt LastIt,
+                                BinaryPredicate Pred) {
+  if (FirstIt != LastIt) {
+    auto PrevIt = FirstIt++;
+    FirstIt = std::find_if(FirstIt, LastIt, [&](const auto &Curr) {
+      return Pred(*PrevIt++, Curr);
+    });
+    if (FirstIt != LastIt)
+      for (ForwardIt CurrIt = FirstIt; ++CurrIt != LastIt;)
+        if (!Pred(*PrevIt, *CurrIt)) {
+          PrevIt = FirstIt;
+          *FirstIt++ = std::move(*CurrIt);
+        }
+  }
+  return FirstIt;
+}
+
 llvm::Error GsymCreator::finalize(llvm::raw_ostream &OS) {
-  std::lock_guard<std::recursive_mutex> Guard(Mutex);
+  std::lock_guard<std::mutex> Guard(Mutex);
   if (Finalized)
-    return createStringError(std::errc::invalid_argument,
-                             "already finalized");
+    return createStringError(std::errc::invalid_argument, "already finalized");
   Finalized = true;
 
   // Sort function infos so we can emit sorted functions.
@@ -195,55 +221,68 @@
   // we wouldn't find any function for range (end of Y, end of X)
   // with binary search
   auto NumBefore = Funcs.size();
-  auto Curr = Funcs.begin();
-  auto Prev = Funcs.end();
-  while (Curr != Funcs.end()) {
-    // Can't check for overlaps or same address ranges if we don't have a
-    // previous entry
-    if (Prev != Funcs.end()) {
-      if (Prev->Range.intersects(Curr->Range)) {
-        // Overlapping address ranges.
-        if (Prev->Range == Curr->Range) {
-          // Same address range. Check if one is from debug info and the other
-          // is from a symbol table. If so, then keep the one with debug info.
-          // Our sorting guarantees that entries with matching address ranges
-          // that have debug info are last in the sort.
-          if (*Prev == *Curr) {
-            // FunctionInfo entries match exactly (range, lines, inlines)
-            OS << "warning: duplicate function info entries for range: "
-               << Curr->Range << '\n';
-            Curr = Funcs.erase(Prev);
-          } else {
-            if (!Prev->hasRichInfo() && Curr->hasRichInfo()) {
-              // Same address range, one with no debug info (symbol) and the
-              // next with debug info. Keep the latter.
-              Curr = Funcs.erase(Prev);
-            } else {
-              OS << "warning: same address range contains different debug "
-                 << "info. Removing:\n"
-                 << *Prev << "\nIn favor of this one:\n"
-                 << *Curr << "\n";
-              Curr = Funcs.erase(Prev);
-            }
-          }
-        } else {
-          // print warnings about overlaps
-          OS << "warning: function ranges overlap:\n"
-             << *Prev << "\n"
-             << *Curr << "\n";
-        }
-      } else if (Prev->Range.size() == 0 &&
-                 Curr->Range.contains(Prev->Range.Start)) {
-        OS << "warning: removing symbol:\n"
-           << *Prev << "\nKeeping:\n"
-           << *Curr << "\n";
-        Curr = Funcs.erase(Prev);
-      }
-    }
-    if (Curr == Funcs.end())
-      break;
-    Prev = Curr++;
-  }
+  Funcs.erase(
+      removeIfBinary(Funcs.begin(), Funcs.end(),
+                     [&](const auto &Prev, const auto &Curr) {
+                       // Empty ranges won't intersect, but we still need to
+                       // catch the case where we have multiple symbols at the
+                       // same address and coalesce them.
+                       const bool ranges_equal = Prev.Range == Curr.Range;
+                       if (ranges_equal || Prev.Range.intersects(Curr.Range)) {
+                         // Overlapping ranges or empty identical ranges.
+                         if (ranges_equal) {
+                           // Same address range. Check if one is from debug
+                           // info and the other is from a symbol table. If
+                           // so, then keep the one with debug info. Our
+                           // sorting guarantees that entries with matching
+                           // address ranges that have debug info are last in
+                           // the sort.
+                           if (Prev == Curr) {
+                             // FunctionInfo entries match exactly (range,
+                             // lines, inlines)
+
+                             // We used to output a warning here, but this was
+                             // so frequent on some binaries, in particular
+                             // when those were built with GCC, that it slowed
+                             // down processing extremely.
+                             return true;
+                           } else {
+                             if (!Prev.hasRichInfo() && Curr.hasRichInfo()) {
+                               // Same address range, one with no debug info
+                               // (symbol) and the next with debug info. Keep
+                               // the latter.
+                               return true;
+                             } else {
+                               if (!Quiet) {
+                                 OS << "warning: same address range contains "
+                                       "different debug "
+                                    << "info. Removing:\n"
+                                    << Prev << "\nIn favor of this one:\n"
+                                    << Curr << "\n";
+                               }
+                               return true;
+                             }
+                           }
+                         } else {
+                           if (!Quiet) { // print warnings about overlaps
+                             OS << "warning: function ranges overlap:\n"
+                                << Prev << "\n"
+                                << Curr << "\n";
+                           }
+                         }
+                       } else if (Prev.Range.size() == 0 &&
+                                  Curr.Range.contains(Prev.Range.Start)) {
+                         if (!Quiet) {
+                           OS << "warning: removing symbol:\n"
+                              << Prev << "\nKeeping:\n"
+                              << Curr << "\n";
+                         }
+                         return true;
+                       }
+
+                       return false;
+                     }),
+      Funcs.end());
 
   // If our last function info entry doesn't have a size and if we have valid
   // text ranges, we should set the size of the last entry since any search for
@@ -251,8 +290,8 @@
   // help ensure we don't cause lookups to always return the last symbol that
   // has no size when doing lookups.
   if (!Funcs.empty() && Funcs.back().Range.size() == 0 && ValidTextRanges) {
-    if (auto Range = ValidTextRanges->getRangeThatContains(
-          Funcs.back().Range.Start)) {
+    if (auto Range =
+            ValidTextRanges->getRangeThatContains(Funcs.back().Range.Start)) {
       Funcs.back().Range.End = Range->End;
     }
   }
@@ -264,7 +303,10 @@
 uint32_t GsymCreator::insertString(StringRef S, bool Copy) {
   if (S.empty())
     return 0;
-  std::lock_guard<std::recursive_mutex> Guard(Mutex);
+
+  // The hash can be calculated outside the lock.
+  CachedHashStringRef CHStr(S);
+  std::lock_guard<std::mutex> Guard(Mutex);
   if (Copy) {
     // We need to provide backing storage for the string if requested
     // since StringTableBuilder stores references to strings. Any string
@@ -272,22 +314,22 @@
     // copied, but any string created by code will need to be copied.
     // This allows GsymCreator to be really fast when parsing DWARF and
     // other object files as most strings don't need to be copied.
-    CachedHashStringRef CHStr(S);
     if (!StrTab.contains(CHStr))
-      S = StringStorage.insert(S).first->getKey();
+      CHStr = CachedHashStringRef{StringStorage.insert(S).first->getKey(),
+                                  CHStr.hash()};
   }
-  return StrTab.add(S);
+  return StrTab.add(CHStr);
 }
 
 void GsymCreator::addFunctionInfo(FunctionInfo &&FI) {
-  std::lock_guard<std::recursive_mutex> Guard(Mutex);
+  std::lock_guard<std::mutex> Guard(Mutex);
   Ranges.insert(FI.Range);
-  Funcs.emplace_back(FI);
+  Funcs.emplace_back(std::move(FI));
 }
 
 void GsymCreator::forEachFunctionInfo(
     std::function<bool(FunctionInfo &)> const &Callback) {
-  std::lock_guard<std::recursive_mutex> Guard(Mutex);
+  std::lock_guard<std::mutex> Guard(Mutex);
   for (auto &FI : Funcs) {
     if (!Callback(FI))
       break;
@@ -296,15 +338,15 @@
 
 void GsymCreator::forEachFunctionInfo(
     std::function<bool(const FunctionInfo &)> const &Callback) const {
-  std::lock_guard<std::recursive_mutex> Guard(Mutex);
+  std::lock_guard<std::mutex> Guard(Mutex);
   for (const auto &FI : Funcs) {
     if (!Callback(FI))
       break;
   }
 }
 
-size_t GsymCreator::getNumFunctionInfos() const{
-  std::lock_guard<std::recursive_mutex> Guard(Mutex);
+size_t GsymCreator::getNumFunctionInfos() const {
+  std::lock_guard<std::mutex> Guard(Mutex);
   return Funcs.size();
 }
 
@@ -315,6 +357,6 @@
 }
 
 bool GsymCreator::hasFunctionInfoForAddress(uint64_t Addr) const {
-  std::lock_guard<std::recursive_mutex> Guard(Mutex);
+  std::lock_guard<std::mutex> Guard(Mutex);
   return Ranges.contains(Addr);
 }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
index f946dd4..1a92e2c 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
@@ -15,6 +15,7 @@
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/FormatVariadic.h"
 #include <algorithm>
 #include <cassert>
 #include <cstdint>
@@ -341,7 +342,18 @@
 
   Layout = std::move(*L);
 
-  uint64_t FileSize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
+  uint64_t FileSize = uint64_t(Layout.SB->BlockSize) * Layout.SB->NumBlocks;
+  if (FileSize > UINT32_MAX) {
+    // FIXME: Changing the BinaryStream classes to use 64-bit numbers lets
+    // us create PDBs larger than 4 GiB successfully. The file format is
+    // block-based and as long as each stream is small enough, PDBs larger than
+    // 4 GiB might work. Check if tools can handle these large PDBs, and if so
+    // add support for writing them.
+    return make_error<MSFError>(
+        msf_error_code::size_overflow,
+        formatv("File size would have been {0,1:N}", FileSize));
+  }
+
   auto OutFileOrError = FileOutputBuffer::create(Path, FileSize);
   if (auto EC = OutFileOrError.takeError())
     return std::move(EC);
diff --git a/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFError.cpp b/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFError.cpp
index b368b80..e42157e 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFError.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFError.cpp
@@ -9,6 +9,7 @@
 #include "llvm/DebugInfo/MSF/MSFError.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h"
+#include <string>
 
 using namespace llvm;
 using namespace llvm::msf;
@@ -27,6 +28,8 @@
     case msf_error_code::insufficient_buffer:
       return "The buffer is not large enough to read the requested number of "
              "bytes.";
+    case msf_error_code::size_overflow:
+      return "Output data is larger than 4 GiB.";
     case msf_error_code::not_writable:
       return "The specified stream is not writable.";
     case msf_error_code::no_stream:
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
index 52df26b..9084e68 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
@@ -156,14 +156,14 @@
   size_t RS = S2.size();
   // Shorter strings always compare less than longer strings.
   if (LS != RS)
-    return LS - RS;
+    return (LS > RS) - (LS < RS);
 
   // If either string contains non ascii characters, memcmp them.
   if (LLVM_UNLIKELY(!isAsciiString(S1) || !isAsciiString(S2)))
     return memcmp(S1.data(), S2.data(), LS);
 
   // Both strings are ascii, perform a case-insensitive comparison.
-  return S1.compare_lower(S2.data());
+  return S1.compare_insensitive(S2.data());
 }
 
 void GSIStreamBuilder::finalizePublicBuckets() {
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
index 5d7946c..7212a0e 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
@@ -83,7 +83,7 @@
 static Expected<std::unique_ptr<PDBFile>>
 loadPdbFile(StringRef PdbPath, std::unique_ptr<BumpPtrAllocator> &Allocator) {
   ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
-      MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1,
+      MemoryBuffer::getFile(PdbPath, /*IsText=*/false,
                             /*RequiresNullTerminator=*/false);
   if (!ErrorOrBuffer)
     return make_error<RawError>(ErrorOrBuffer.getError());
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
index deb0f20..a508f16 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
-#include "llvm/ADT/BitVector.h"
 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
 #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
diff --git a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp
index 01dc31d..555d29f 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp
@@ -30,127 +30,368 @@
 namespace llvm {
 namespace symbolize {
 
-// Prints source code around in the FileName the Line.
-void DIPrinter::printContext(const std::string &FileName, int64_t Line) {
-  if (PrintSourceContext <= 0)
-    return;
+class SourceCode {
+  std::unique_ptr<MemoryBuffer> MemBuf;
 
-  ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
-      MemoryBuffer::getFile(FileName);
-  if (!BufOrErr)
-    return;
+  const Optional<StringRef> load(StringRef FileName,
+                                 const Optional<StringRef> &EmbeddedSource) {
+    if (Lines <= 0)
+      return None;
 
-  std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
-  int64_t FirstLine =
-      std::max(static_cast<int64_t>(1), Line - PrintSourceContext / 2);
-  int64_t LastLine = FirstLine + PrintSourceContext;
-  size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
+    if (EmbeddedSource)
+      return EmbeddedSource;
+    else {
+      ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
+          MemoryBuffer::getFile(FileName);
+      if (!BufOrErr)
+        return None;
+      MemBuf = std::move(*BufOrErr);
+      return MemBuf->getBuffer();
+    }
+  }
 
-  for (line_iterator I = line_iterator(*Buf, false);
-       !I.is_at_eof() && I.line_number() <= LastLine; ++I) {
-    int64_t L = I.line_number();
-    if (L >= FirstLine && L <= LastLine) {
+  const Optional<StringRef> pruneSource(const Optional<StringRef> &Source) {
+    if (!Source)
+      return None;
+    size_t FirstLinePos = StringRef::npos, Pos = 0;
+    for (int64_t L = 1; L <= LastLine; ++L, ++Pos) {
+      if (L == FirstLine)
+        FirstLinePos = Pos;
+      Pos = Source->find('\n', Pos);
+      if (Pos == StringRef::npos)
+        break;
+    }
+    if (FirstLinePos == StringRef::npos)
+      return None;
+    return Source->substr(FirstLinePos, (Pos == StringRef::npos)
+                                            ? StringRef::npos
+                                            : Pos - FirstLinePos);
+  }
+
+public:
+  const int64_t Line;
+  const int Lines;
+  const int64_t FirstLine;
+  const int64_t LastLine;
+  const Optional<StringRef> PrunedSource;
+
+  SourceCode(
+      StringRef FileName, int64_t Line, int Lines,
+      const Optional<StringRef> &EmbeddedSource = Optional<StringRef>(None))
+      : Line(Line), Lines(Lines),
+        FirstLine(std::max(static_cast<int64_t>(1), Line - Lines / 2)),
+        LastLine(FirstLine + Lines - 1),
+        PrunedSource(pruneSource(load(FileName, EmbeddedSource))) {}
+
+  void format(raw_ostream &OS) {
+    if (!PrunedSource)
+      return;
+    size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
+    int64_t L = FirstLine;
+    for (size_t Pos = 0; Pos < PrunedSource->size(); ++L) {
+      size_t PosEnd = PrunedSource->find('\n', Pos);
+      StringRef String = PrunedSource->substr(
+          Pos, (PosEnd == StringRef::npos) ? StringRef::npos : (PosEnd - Pos));
+      if (String.endswith("\r"))
+        String = String.drop_back(1);
       OS << format_decimal(L, MaxLineNumberWidth);
       if (L == Line)
         OS << " >: ";
       else
         OS << "  : ";
-      OS << *I << "\n";
+      OS << String << '\n';
+      if (PosEnd == StringRef::npos)
+        break;
+      Pos = PosEnd + 1;
     }
   }
+};
+
+void PlainPrinterBase::printHeader(uint64_t Address) {
+  if (Config.PrintAddress) {
+    OS << "0x";
+    OS.write_hex(Address);
+    StringRef Delimiter = Config.Pretty ? ": " : "\n";
+    OS << Delimiter;
+  }
 }
 
-void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
-  if (PrintFunctionNames) {
-    std::string FunctionName = Info.FunctionName;
+// Prints source code around in the FileName the Line.
+void PlainPrinterBase::printContext(SourceCode SourceCode) {
+  SourceCode.format(OS);
+}
+
+void PlainPrinterBase::printFunctionName(StringRef FunctionName, bool Inlined) {
+  if (Config.PrintFunctions) {
     if (FunctionName == DILineInfo::BadString)
       FunctionName = DILineInfo::Addr2LineBadString;
-
-    StringRef Delimiter = PrintPretty ? " at " : "\n";
-    StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : "";
+    StringRef Delimiter = Config.Pretty ? " at " : "\n";
+    StringRef Prefix = (Config.Pretty && Inlined) ? " (inlined by) " : "";
     OS << Prefix << FunctionName << Delimiter;
   }
-  std::string Filename = Info.FileName;
+}
+
+void LLVMPrinter::printSimpleLocation(StringRef Filename,
+                                      const DILineInfo &Info) {
+  OS << Filename << ':' << Info.Line << ':' << Info.Column << '\n';
+  printContext(
+      SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source));
+}
+
+void GNUPrinter::printSimpleLocation(StringRef Filename,
+                                     const DILineInfo &Info) {
+  OS << Filename << ':' << Info.Line;
+  if (Info.Discriminator)
+    OS << " (discriminator " << Info.Discriminator << ')';
+  OS << '\n';
+  printContext(
+      SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source));
+}
+
+void PlainPrinterBase::printVerbose(StringRef Filename,
+                                    const DILineInfo &Info) {
+  OS << "  Filename: " << Filename << '\n';
+  if (Info.StartLine) {
+    OS << "  Function start filename: " << Info.StartFileName << '\n';
+    OS << "  Function start line: " << Info.StartLine << '\n';
+  }
+  printStartAddress(Info);
+  OS << "  Line: " << Info.Line << '\n';
+  OS << "  Column: " << Info.Column << '\n';
+  if (Info.Discriminator)
+    OS << "  Discriminator: " << Info.Discriminator << '\n';
+}
+
+void LLVMPrinter::printStartAddress(const DILineInfo &Info) {
+  if (Info.StartAddress) {
+    OS << "  Function start address: 0x";
+    OS.write_hex(*Info.StartAddress);
+    OS << '\n';
+  }
+}
+
+void LLVMPrinter::printFooter() { OS << '\n'; }
+
+void PlainPrinterBase::print(const DILineInfo &Info, bool Inlined) {
+  printFunctionName(Info.FunctionName, Inlined);
+  StringRef Filename = Info.FileName;
   if (Filename == DILineInfo::BadString)
     Filename = DILineInfo::Addr2LineBadString;
-  if (!Verbose) {
-    OS << Filename << ":" << Info.Line;
-    if (Style == OutputStyle::LLVM)
-      OS << ":" << Info.Column;
-    else if (Style == OutputStyle::GNU && Info.Discriminator != 0)
-      OS << " (discriminator " << Info.Discriminator << ")";
-    OS << "\n";
-    printContext(Filename, Info.Line);
-    return;
-  }
-  OS << "  Filename: " << Filename << "\n";
-  if (Info.StartLine) {
-    OS << "  Function start filename: " << Info.StartFileName << "\n";
-    OS << "  Function start line: " << Info.StartLine << "\n";
-  }
-  OS << "  Line: " << Info.Line << "\n";
-  OS << "  Column: " << Info.Column << "\n";
-  if (Info.Discriminator)
-    OS << "  Discriminator: " << Info.Discriminator << "\n";
+  if (Config.Verbose)
+    printVerbose(Filename, Info);
+  else
+    printSimpleLocation(Filename, Info);
 }
 
-DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
+void PlainPrinterBase::print(const Request &Request, const DILineInfo &Info) {
+  printHeader(*Request.Address);
   print(Info, false);
-  return *this;
+  printFooter();
 }
 
-DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
+void PlainPrinterBase::print(const Request &Request,
+                             const DIInliningInfo &Info) {
+  printHeader(*Request.Address);
   uint32_t FramesNum = Info.getNumberOfFrames();
-  if (FramesNum == 0) {
+  if (FramesNum == 0)
     print(DILineInfo(), false);
-    return *this;
-  }
-  for (uint32_t i = 0; i < FramesNum; i++)
-    print(Info.getFrame(i), i > 0);
-  return *this;
+  else
+    for (uint32_t I = 0; I < FramesNum; ++I)
+      print(Info.getFrame(I), I > 0);
+  printFooter();
 }
 
-DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
-  std::string Name = Global.Name;
+void PlainPrinterBase::print(const Request &Request, const DIGlobal &Global) {
+  printHeader(*Request.Address);
+  StringRef Name = Global.Name;
   if (Name == DILineInfo::BadString)
     Name = DILineInfo::Addr2LineBadString;
   OS << Name << "\n";
   OS << Global.Start << " " << Global.Size << "\n";
-  return *this;
+  printFooter();
 }
 
-DIPrinter &DIPrinter::operator<<(const DILocal &Local) {
-  if (Local.FunctionName.empty())
-    OS << "??\n";
+void PlainPrinterBase::print(const Request &Request,
+                             const std::vector<DILocal> &Locals) {
+  printHeader(*Request.Address);
+  if (Locals.empty())
+    OS << DILineInfo::Addr2LineBadString << '\n';
   else
-    OS << Local.FunctionName << '\n';
+    for (const DILocal &L : Locals) {
+      if (L.FunctionName.empty())
+        OS << DILineInfo::Addr2LineBadString;
+      else
+        OS << L.FunctionName;
+      OS << '\n';
 
-  if (Local.Name.empty())
-    OS << "??\n";
-  else
-    OS << Local.Name << '\n';
+      if (L.Name.empty())
+        OS << DILineInfo::Addr2LineBadString;
+      else
+        OS << L.Name;
+      OS << '\n';
 
-  if (Local.DeclFile.empty())
-    OS << "??";
-  else
-    OS << Local.DeclFile;
-  OS << ':' << Local.DeclLine << '\n';
+      if (L.DeclFile.empty())
+        OS << DILineInfo::Addr2LineBadString;
+      else
+        OS << L.DeclFile;
 
-  if (Local.FrameOffset)
-    OS << *Local.FrameOffset << ' ';
-  else
-    OS << "?? ";
+      OS << ':' << L.DeclLine << '\n';
 
-  if (Local.Size)
-    OS << *Local.Size << ' ';
-  else
-    OS << "?? ";
+      if (L.FrameOffset)
+        OS << *L.FrameOffset;
+      else
+        OS << DILineInfo::Addr2LineBadString;
+      OS << ' ';
 
-  if (Local.TagOffset)
-    OS << *Local.TagOffset << '\n';
+      if (L.Size)
+        OS << *L.Size;
+      else
+        OS << DILineInfo::Addr2LineBadString;
+      OS << ' ';
+
+      if (L.TagOffset)
+        OS << *L.TagOffset;
+      else
+        OS << DILineInfo::Addr2LineBadString;
+      OS << '\n';
+    }
+  printFooter();
+}
+
+void PlainPrinterBase::printInvalidCommand(const Request &Request,
+                                           StringRef Command) {
+  OS << Command << '\n';
+}
+
+bool PlainPrinterBase::printError(const Request &Request,
+                                  const ErrorInfoBase &ErrorInfo,
+                                  StringRef ErrorBanner) {
+  ES << ErrorBanner;
+  ErrorInfo.log(ES);
+  ES << '\n';
+  // Print an empty struct too.
+  return true;
+}
+
+static std::string toHex(uint64_t V) {
+  return ("0x" + Twine::utohexstr(V)).str();
+}
+
+static json::Object toJSON(const Request &Request, StringRef ErrorMsg = "") {
+  json::Object Json({{"ModuleName", Request.ModuleName.str()}});
+  if (Request.Address)
+    Json["Address"] = toHex(*Request.Address);
+  if (!ErrorMsg.empty())
+    Json["Error"] = json::Object({{"Message", ErrorMsg.str()}});
+  return Json;
+}
+
+void JSONPrinter::print(const Request &Request, const DILineInfo &Info) {
+  DIInliningInfo InliningInfo;
+  InliningInfo.addFrame(Info);
+  print(Request, InliningInfo);
+}
+
+void JSONPrinter::print(const Request &Request, const DIInliningInfo &Info) {
+  json::Array Array;
+  for (uint32_t I = 0, N = Info.getNumberOfFrames(); I < N; ++I) {
+    const DILineInfo &LineInfo = Info.getFrame(I);
+    json::Object Object(
+        {{"FunctionName", LineInfo.FunctionName != DILineInfo::BadString
+                              ? LineInfo.FunctionName
+                              : ""},
+         {"StartFileName", LineInfo.StartFileName != DILineInfo::BadString
+                               ? LineInfo.StartFileName
+                               : ""},
+         {"StartLine", LineInfo.StartLine},
+         {"StartAddress",
+          LineInfo.StartAddress ? toHex(*LineInfo.StartAddress) : ""},
+         {"FileName",
+          LineInfo.FileName != DILineInfo::BadString ? LineInfo.FileName : ""},
+         {"Line", LineInfo.Line},
+         {"Column", LineInfo.Column},
+         {"Discriminator", LineInfo.Discriminator}});
+    SourceCode SourceCode(LineInfo.FileName, LineInfo.Line,
+                          Config.SourceContextLines, LineInfo.Source);
+    std::string FormattedSource;
+    raw_string_ostream Stream(FormattedSource);
+    SourceCode.format(Stream);
+    if (!FormattedSource.empty())
+      Object["Source"] = std::move(FormattedSource);
+    Array.push_back(std::move(Object));
+  }
+  json::Object Json = toJSON(Request);
+  Json["Symbol"] = std::move(Array);
+  if (ObjectList)
+    ObjectList->push_back(std::move(Json));
   else
-    OS << "??\n";
-  return *this;
+    printJSON(std::move(Json));
+}
+
+void JSONPrinter::print(const Request &Request, const DIGlobal &Global) {
+  json::Object Data(
+      {{"Name", Global.Name != DILineInfo::BadString ? Global.Name : ""},
+       {"Start", toHex(Global.Start)},
+       {"Size", toHex(Global.Size)}});
+  json::Object Json = toJSON(Request);
+  Json["Data"] = std::move(Data);
+  if (ObjectList)
+    ObjectList->push_back(std::move(Json));
+  else
+    printJSON(std::move(Json));
+}
+
+void JSONPrinter::print(const Request &Request,
+                        const std::vector<DILocal> &Locals) {
+  json::Array Frame;
+  for (const DILocal &Local : Locals) {
+    json::Object FrameObject(
+        {{"FunctionName", Local.FunctionName},
+         {"Name", Local.Name},
+         {"DeclFile", Local.DeclFile},
+         {"DeclLine", int64_t(Local.DeclLine)},
+         {"Size", Local.Size ? toHex(*Local.Size) : ""},
+         {"TagOffset", Local.TagOffset ? toHex(*Local.TagOffset) : ""}});
+    if (Local.FrameOffset)
+      FrameObject["FrameOffset"] = *Local.FrameOffset;
+    Frame.push_back(std::move(FrameObject));
+  }
+  json::Object Json = toJSON(Request);
+  Json["Frame"] = std::move(Frame);
+  if (ObjectList)
+    ObjectList->push_back(std::move(Json));
+  else
+    printJSON(std::move(Json));
+}
+
+void JSONPrinter::printInvalidCommand(const Request &Request,
+                                      StringRef Command) {
+  printError(Request,
+             StringError("unable to parse arguments: " + Command,
+                         std::make_error_code(std::errc::invalid_argument)),
+             "");
+}
+
+bool JSONPrinter::printError(const Request &Request,
+                             const ErrorInfoBase &ErrorInfo,
+                             StringRef ErrorBanner) {
+  json::Object Json = toJSON(Request, ErrorInfo.message());
+  if (ObjectList)
+    ObjectList->push_back(std::move(Json));
+  else
+    printJSON(std::move(Json));
+  return false;
+}
+
+void JSONPrinter::listBegin() {
+  assert(!ObjectList);
+  ObjectList = std::make_unique<json::Array>();
+}
+
+void JSONPrinter::listEnd() {
+  assert(ObjectList);
+  printJSON(std::move(*ObjectList));
+  ObjectList.reset();
 }
 
 } // end namespace symbolize
diff --git a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
index 93d05e4..a9c7883 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
@@ -16,6 +16,7 @@
 #include "llvm/BinaryFormat/COFF.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/Object/COFF.h"
+#include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Object/SymbolSize.h"
 #include "llvm/Support/Casting.h"
@@ -69,24 +70,19 @@
         return std::move(E);
   }
 
-  std::vector<std::pair<SymbolDesc, StringRef>> &Fs = res->Functions,
-                                                &Os = res->Objects;
-  auto Uniquify = [](std::vector<std::pair<SymbolDesc, StringRef>> &S) {
-    // Sort by (Addr,Size,Name). If several SymbolDescs share the same Addr,
-    // pick the one with the largest Size. This helps us avoid symbols with no
-    // size information (Size=0).
-    llvm::sort(S);
-    auto I = S.begin(), E = S.end(), J = S.begin();
-    while (I != E) {
-      auto OI = I;
-      while (++I != E && OI->first.Addr == I->first.Addr) {
-      }
-      *J++ = I[-1];
+  std::vector<SymbolDesc> &SS = res->Symbols;
+  // Sort by (Addr,Size,Name). If several SymbolDescs share the same Addr,
+  // pick the one with the largest Size. This helps us avoid symbols with no
+  // size information (Size=0).
+  llvm::stable_sort(SS);
+  auto I = SS.begin(), E = SS.end(), J = SS.begin();
+  while (I != E) {
+    auto OI = I;
+    while (++I != E && OI->Addr == I->Addr) {
     }
-    S.erase(J, S.end());
-  };
-  Uniquify(Fs);
-  Uniquify(Os);
+    *J++ = I[-1];
+  }
+  SS.erase(J, SS.end());
 
   return std::move(res);
 }
@@ -138,8 +134,7 @@
     uint32_t NextOffset = I != E ? I->Offset : Export.Offset + 1;
     uint64_t SymbolStart = ImageBase + Export.Offset;
     uint64_t SymbolSize = NextOffset - Export.Offset;
-    SymbolDesc SD = {SymbolStart, SymbolSize};
-    Functions.emplace_back(SD, Export.Name);
+    Symbols.push_back({SymbolStart, SymbolSize, Export.Name, 0});
   }
   return Error::success();
 }
@@ -149,16 +144,46 @@
                                         DataExtractor *OpdExtractor,
                                         uint64_t OpdAddress) {
   // Avoid adding symbols from an unknown/undefined section.
-  const ObjectFile *Obj = Symbol.getObject();
+  const ObjectFile &Obj = *Symbol.getObject();
+  Expected<StringRef> SymbolNameOrErr = Symbol.getName();
+  if (!SymbolNameOrErr)
+    return SymbolNameOrErr.takeError();
+  StringRef SymbolName = *SymbolNameOrErr;
+
+  uint32_t ELFSymIdx =
+      Obj.isELF() ? ELFSymbolRef(Symbol).getRawDataRefImpl().d.b : 0;
   Expected<section_iterator> Sec = Symbol.getSection();
-  if (!Sec || (Obj && Obj->section_end() == *Sec))
+  if (!Sec || Obj.section_end() == *Sec) {
+    if (Obj.isELF()) {
+      // Store the (index, filename) pair for a file symbol.
+      ELFSymbolRef ESym(Symbol);
+      if (ESym.getELFType() == ELF::STT_FILE)
+        FileSymbols.emplace_back(ELFSymIdx, SymbolName);
+    }
     return Error::success();
+  }
+
   Expected<SymbolRef::Type> SymbolTypeOrErr = Symbol.getType();
   if (!SymbolTypeOrErr)
     return SymbolTypeOrErr.takeError();
   SymbolRef::Type SymbolType = *SymbolTypeOrErr;
-  if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data)
+  if (Obj.isELF()) {
+    // Allow function and data symbols. Additionally allow STT_NONE, which are
+    // common for functions defined in assembly.
+    uint8_t Type = ELFSymbolRef(Symbol).getELFType();
+    if (Type != ELF::STT_NOTYPE && Type != ELF::STT_FUNC &&
+        Type != ELF::STT_OBJECT && Type != ELF::STT_GNU_IFUNC)
+      return Error::success();
+    // Some STT_NOTYPE symbols are not desired. This excludes STT_SECTION and
+    // ARM mapping symbols.
+    uint32_t Flags = cantFail(Symbol.getFlags());
+    if (Flags & SymbolRef::SF_FormatSpecific)
+      return Error::success();
+  } else if (SymbolType != SymbolRef::ST_Function &&
+             SymbolType != SymbolRef::ST_Data) {
     return Error::success();
+  }
+
   Expected<uint64_t> SymbolAddressOrErr = Symbol.getAddress();
   if (!SymbolAddressOrErr)
     return SymbolAddressOrErr.takeError();
@@ -179,18 +204,13 @@
     if (OpdExtractor->isValidOffsetForAddress(OpdOffset))
       SymbolAddress = OpdExtractor->getAddress(&OpdOffset);
   }
-  Expected<StringRef> SymbolNameOrErr = Symbol.getName();
-  if (!SymbolNameOrErr)
-    return SymbolNameOrErr.takeError();
-  StringRef SymbolName = *SymbolNameOrErr;
   // Mach-O symbol table names have leading underscore, skip it.
   if (Module->isMachO() && !SymbolName.empty() && SymbolName[0] == '_')
     SymbolName = SymbolName.drop_front();
-  // FIXME: If a function has alias, there are two entries in symbol table
-  // with same address size. Make sure we choose the correct one.
-  auto &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects;
-  SymbolDesc SD = { SymbolAddress, SymbolSize };
-  M.emplace_back(SD, SymbolName);
+
+  if (Obj.isELF() && ELFSymbolRef(Symbol).getBinding() != ELF::STB_LOCAL)
+    ELFSymIdx = 0;
+  Symbols.push_back({SymbolAddress, SymbolSize, SymbolName, ELFSymIdx});
   return Error::success();
 }
 
@@ -206,23 +226,32 @@
   return 0;
 }
 
-bool SymbolizableObjectFile::getNameFromSymbolTable(SymbolRef::Type Type,
-                                                    uint64_t Address,
-                                                    std::string &Name,
-                                                    uint64_t &Addr,
-                                                    uint64_t &Size) const {
-  const auto &Symbols = Type == SymbolRef::ST_Function ? Functions : Objects;
-  std::pair<SymbolDesc, StringRef> SD{{Address, UINT64_C(-1)}, StringRef()};
+bool SymbolizableObjectFile::getNameFromSymbolTable(
+    uint64_t Address, std::string &Name, uint64_t &Addr, uint64_t &Size,
+    std::string &FileName) const {
+  SymbolDesc SD{Address, UINT64_C(-1), StringRef(), 0};
   auto SymbolIterator = llvm::upper_bound(Symbols, SD);
   if (SymbolIterator == Symbols.begin())
     return false;
   --SymbolIterator;
-  if (SymbolIterator->first.Size != 0 &&
-      SymbolIterator->first.Addr + SymbolIterator->first.Size <= Address)
+  if (SymbolIterator->Size != 0 &&
+      SymbolIterator->Addr + SymbolIterator->Size <= Address)
     return false;
-  Name = SymbolIterator->second.str();
-  Addr = SymbolIterator->first.Addr;
-  Size = SymbolIterator->first.Size;
+  Name = SymbolIterator->Name.str();
+  Addr = SymbolIterator->Addr;
+  Size = SymbolIterator->Size;
+
+  if (SymbolIterator->ELFLocalSymIdx != 0) {
+    // If this is an ELF local symbol, find the STT_FILE symbol preceding
+    // SymbolIterator to get the filename. The ELF spec requires the STT_FILE
+    // symbol (if present) precedes the other STB_LOCAL symbols for the file.
+    assert(Module->isELF());
+    auto It = llvm::upper_bound(
+        FileSymbols,
+        std::make_pair(SymbolIterator->ELFLocalSymIdx, StringRef()));
+    if (It != FileSymbols.begin())
+      FileName = It[-1].second.str();
+  }
   return true;
 }
 
@@ -248,11 +277,14 @@
 
   // Override function name from symbol table if necessary.
   if (shouldOverrideWithSymbolTable(LineInfoSpecifier.FNKind, UseSymbolTable)) {
-    std::string FunctionName;
+    std::string FunctionName, FileName;
     uint64_t Start, Size;
-    if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset.Address,
-                               FunctionName, Start, Size)) {
+    if (getNameFromSymbolTable(ModuleOffset.Address, FunctionName, Start, Size,
+                               FileName)) {
       LineInfo.FunctionName = FunctionName;
+      LineInfo.StartAddress = Start;
+      if (LineInfo.FileName == DILineInfo::BadString && !FileName.empty())
+        LineInfo.FileName = FileName;
     }
   }
   return LineInfo;
@@ -273,12 +305,16 @@
 
   // Override the function name in lower frame with name from symbol table.
   if (shouldOverrideWithSymbolTable(LineInfoSpecifier.FNKind, UseSymbolTable)) {
-    std::string FunctionName;
+    std::string FunctionName, FileName;
     uint64_t Start, Size;
-    if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset.Address,
-                               FunctionName, Start, Size)) {
-      InlinedContext.getMutableFrame(InlinedContext.getNumberOfFrames() - 1)
-          ->FunctionName = FunctionName;
+    if (getNameFromSymbolTable(ModuleOffset.Address, FunctionName, Start, Size,
+                               FileName)) {
+      DILineInfo *LI = InlinedContext.getMutableFrame(
+          InlinedContext.getNumberOfFrames() - 1);
+      LI->FunctionName = FunctionName;
+      LI->StartAddress = Start;
+      if (LI->FileName == DILineInfo::BadString && !FileName.empty())
+        LI->FileName = FileName;
     }
   }
 
@@ -288,8 +324,9 @@
 DIGlobal SymbolizableObjectFile::symbolizeData(
     object::SectionedAddress ModuleOffset) const {
   DIGlobal Res;
-  getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset.Address, Res.Name,
-                         Res.Start, Res.Size);
+  std::string FileName;
+  getNameFromSymbolTable(ModuleOffset.Address, Res.Name, Res.Start, Res.Size,
+                         FileName);
   return Res;
 }
 
diff --git a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h
index be3c66d..8fb003f 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h
+++ b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h
@@ -55,9 +55,9 @@
   bool shouldOverrideWithSymbolTable(FunctionNameKind FNKind,
                                      bool UseSymbolTable) const;
 
-  bool getNameFromSymbolTable(object::SymbolRef::Type Type, uint64_t Address,
-                              std::string &Name, uint64_t &Addr,
-                              uint64_t &Size) const;
+  bool getNameFromSymbolTable(uint64_t Address, std::string &Name,
+                              uint64_t &Addr, uint64_t &Size,
+                              std::string &FileName) const;
   // For big-endian PowerPC64 ELF, OpdAddress is the address of the .opd
   // (function descriptor) section and OpdExtractor refers to its contents.
   Error addSymbol(const object::SymbolRef &Symbol, uint64_t SymbolSize,
@@ -78,12 +78,18 @@
     // the following symbol.
     uint64_t Size;
 
+    StringRef Name;
+    // Non-zero if this is an ELF local symbol. See the comment in
+    // getNameFromSymbolTable.
+    uint32_t ELFLocalSymIdx;
+
     bool operator<(const SymbolDesc &RHS) const {
       return Addr != RHS.Addr ? Addr < RHS.Addr : Size < RHS.Size;
     }
   };
-  std::vector<std::pair<SymbolDesc, StringRef>> Functions;
-  std::vector<std::pair<SymbolDesc, StringRef>> Objects;
+  std::vector<SymbolDesc> Symbols;
+  // (index, filename) pairs of ELF STT_FILE symbols.
+  std::vector<std::pair<uint32_t, StringRef>> FileSymbols;
 
   SymbolizableObjectFile(const object::ObjectFile *Obj,
                          std::unique_ptr<DIContext> DICtx,
diff --git a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
index da157a5..72ca722 100644
--- a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
+++ b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
@@ -39,9 +39,17 @@
 namespace llvm {
 namespace symbolize {
 
+template <typename T>
 Expected<DILineInfo>
-LLVMSymbolizer::symbolizeCodeCommon(SymbolizableModule *Info,
+LLVMSymbolizer::symbolizeCodeCommon(const T &ModuleSpecifier,
                                     object::SectionedAddress ModuleOffset) {
+
+  auto InfoOrErr = getOrCreateModuleInfo(ModuleSpecifier);
+  if (!InfoOrErr)
+    return InfoOrErr.takeError();
+
+  SymbolizableModule *Info = *InfoOrErr;
+
   // A null module means an error has already been reported. Return an empty
   // result.
   if (!Info)
@@ -63,37 +71,24 @@
 Expected<DILineInfo>
 LLVMSymbolizer::symbolizeCode(const ObjectFile &Obj,
                               object::SectionedAddress ModuleOffset) {
-  StringRef ModuleName = Obj.getFileName();
-  auto I = Modules.find(ModuleName);
-  if (I != Modules.end())
-    return symbolizeCodeCommon(I->second.get(), ModuleOffset);
-
-  std::unique_ptr<DIContext> Context = DWARFContext::create(Obj);
-  Expected<SymbolizableModule *> InfoOrErr =
-                     createModuleInfo(&Obj, std::move(Context), ModuleName);
-  if (!InfoOrErr)
-    return InfoOrErr.takeError();
-  return symbolizeCodeCommon(*InfoOrErr, ModuleOffset);
+  return symbolizeCodeCommon(Obj, ModuleOffset);
 }
 
 Expected<DILineInfo>
 LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
                               object::SectionedAddress ModuleOffset) {
-  Expected<SymbolizableModule *> InfoOrErr = getOrCreateModuleInfo(ModuleName);
-  if (!InfoOrErr)
-    return InfoOrErr.takeError();
-  return symbolizeCodeCommon(*InfoOrErr, ModuleOffset);
+  return symbolizeCodeCommon(ModuleName, ModuleOffset);
 }
 
-Expected<DIInliningInfo>
-LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
-                                     object::SectionedAddress ModuleOffset) {
-  SymbolizableModule *Info;
-  if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
-    Info = InfoOrErr.get();
-  else
+template <typename T>
+Expected<DIInliningInfo> LLVMSymbolizer::symbolizeInlinedCodeCommon(
+    const T &ModuleSpecifier, object::SectionedAddress ModuleOffset) {
+  auto InfoOrErr = getOrCreateModuleInfo(ModuleSpecifier);
+  if (!InfoOrErr)
     return InfoOrErr.takeError();
 
+  SymbolizableModule *Info = *InfoOrErr;
+
   // A null module means an error has already been reported. Return an empty
   // result.
   if (!Info)
@@ -116,15 +111,28 @@
   return InlinedContext;
 }
 
+Expected<DIInliningInfo>
+LLVMSymbolizer::symbolizeInlinedCode(const ObjectFile &Obj,
+                                     object::SectionedAddress ModuleOffset) {
+  return symbolizeInlinedCodeCommon(Obj, ModuleOffset);
+}
+
+Expected<DIInliningInfo>
+LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
+                                     object::SectionedAddress ModuleOffset) {
+  return symbolizeInlinedCodeCommon(ModuleName, ModuleOffset);
+}
+
+template <typename T>
 Expected<DIGlobal>
-LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
-                              object::SectionedAddress ModuleOffset) {
-  SymbolizableModule *Info;
-  if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
-    Info = InfoOrErr.get();
-  else
+LLVMSymbolizer::symbolizeDataCommon(const T &ModuleSpecifier,
+                                    object::SectionedAddress ModuleOffset) {
+
+  auto InfoOrErr = getOrCreateModuleInfo(ModuleSpecifier);
+  if (!InfoOrErr)
     return InfoOrErr.takeError();
 
+  SymbolizableModule *Info = *InfoOrErr;
   // A null module means an error has already been reported. Return an empty
   // result.
   if (!Info)
@@ -142,15 +150,27 @@
   return Global;
 }
 
+Expected<DIGlobal>
+LLVMSymbolizer::symbolizeData(const ObjectFile &Obj,
+                              object::SectionedAddress ModuleOffset) {
+  return symbolizeDataCommon(Obj, ModuleOffset);
+}
+
+Expected<DIGlobal>
+LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
+                              object::SectionedAddress ModuleOffset) {
+  return symbolizeDataCommon(ModuleName, ModuleOffset);
+}
+
+template <typename T>
 Expected<std::vector<DILocal>>
-LLVMSymbolizer::symbolizeFrame(const std::string &ModuleName,
-                               object::SectionedAddress ModuleOffset) {
-  SymbolizableModule *Info;
-  if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
-    Info = InfoOrErr.get();
-  else
+LLVMSymbolizer::symbolizeFrameCommon(const T &ModuleSpecifier,
+                                     object::SectionedAddress ModuleOffset) {
+  auto InfoOrErr = getOrCreateModuleInfo(ModuleSpecifier);
+  if (!InfoOrErr)
     return InfoOrErr.takeError();
 
+  SymbolizableModule *Info = *InfoOrErr;
   // A null module means an error has already been reported. Return an empty
   // result.
   if (!Info)
@@ -165,6 +185,18 @@
   return Info->symbolizeFrame(ModuleOffset);
 }
 
+Expected<std::vector<DILocal>>
+LLVMSymbolizer::symbolizeFrame(const ObjectFile &Obj,
+                               object::SectionedAddress ModuleOffset) {
+  return symbolizeFrameCommon(Obj, ModuleOffset);
+}
+
+Expected<std::vector<DILocal>>
+LLVMSymbolizer::symbolizeFrame(const std::string &ModuleName,
+                               object::SectionedAddress ModuleOffset) {
+  return symbolizeFrameCommon(ModuleName, ModuleOffset);
+}
+
 void LLVMSymbolizer::flush() {
   ObjectForUBPathAndArch.clear();
   BinaryForPath.clear();
@@ -178,8 +210,8 @@
 // /path/to/foo.dSYM/Contents/Resources/DWARF/foo.
 // For Path="/path/to/bar.dSYM" and Basename="foo" assume that debug info is in
 // /path/to/bar.dSYM/Contents/Resources/DWARF/foo.
-std::string getDarwinDWARFResourceForPath(
-    const std::string &Path, const std::string &Basename) {
+std::string getDarwinDWARFResourceForPath(const std::string &Path,
+                                          const std::string &Basename) {
   SmallString<16> ResourceName = StringRef(Path);
   if (sys::path::extension(Path) != ".dSYM") {
     ResourceName += ".dSYM";
@@ -298,7 +330,8 @@
       continue;
     Error Err = Error::success();
     for (auto N : Obj.notes(P, Err))
-      if (N.getType() == ELF::NT_GNU_BUILD_ID && N.getName() == ELF::ELF_NOTE_GNU)
+      if (N.getType() == ELF::NT_GNU_BUILD_ID &&
+          N.getName() == ELF::ELF_NOTE_GNU)
         return N.getDesc();
     consumeError(std::move(Err));
   }
@@ -321,8 +354,7 @@
 }
 
 bool findDebugBinary(const std::vector<std::string> &DebugFileDirectory,
-                     const ArrayRef<uint8_t> BuildID,
-                     std::string &Result) {
+                     const ArrayRef<uint8_t> BuildID, std::string &Result) {
   auto getDebugPath = [&](StringRef Directory) {
     SmallString<128> Path{Directory};
     sys::path::append(Path, ".build-id",
@@ -334,11 +366,11 @@
   if (DebugFileDirectory.empty()) {
     SmallString<128> Path = getDebugPath(
 #if defined(__NetBSD__)
-      // Try /usr/libdata/debug/.build-id/../...
-      "/usr/libdata/debug"
+        // Try /usr/libdata/debug/.build-id/../...
+        "/usr/libdata/debug"
 #else
-      // Try /usr/lib/debug/.build-id/../...
-      "/usr/lib/debug"
+        // Try /usr/lib/debug/.build-id/../...
+        "/usr/lib/debug"
 #endif
     );
     if (llvm::sys::fs::exists(Path)) {
@@ -361,7 +393,8 @@
 } // end anonymous namespace
 
 ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath,
-    const MachOObjectFile *MachExeObj, const std::string &ArchName) {
+                                           const MachOObjectFile *MachExeObj,
+                                           const std::string &ArchName) {
   // On Darwin we may find DWARF in separate object file in
   // resource directory.
   std::vector<std::string> DsymPaths;
@@ -571,6 +604,18 @@
   return createModuleInfo(Objects.first, std::move(Context), ModuleName);
 }
 
+Expected<SymbolizableModule *>
+LLVMSymbolizer::getOrCreateModuleInfo(const ObjectFile &Obj) {
+  StringRef ObjName = Obj.getFileName();
+  auto I = Modules.find(ObjName);
+  if (I != Modules.end())
+    return I->second.get();
+
+  std::unique_ptr<DIContext> Context = DWARFContext::create(Obj);
+  // FIXME: handle COFF object with PDB info to use PDBContext
+  return createModuleInfo(&Obj, std::move(Context), ObjName);
+}
+
 namespace {
 
 // Undo these various manglings for Win32 extern "C" functions:
@@ -609,7 +654,8 @@
   // approach to check if the name should be demangled.
   if (Name.substr(0, 2) == "_Z") {
     int status = 0;
-    char *DemangledName = itaniumDemangle(Name.c_str(), nullptr, nullptr, &status);
+    char *DemangledName =
+        itaniumDemangle(Name.c_str(), nullptr, nullptr, &status);
     if (status != 0)
       return Name;
     std::string Result = DemangledName;