Importing rustc-1.56.0

Change-Id: I98941481270706fa55f8fb2cb91686ae3bd30f38
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;