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;