54LLVMSymbolizer::symbolizeCodeCommon(
const T &ModuleSpecifier,
59 return InfoOrErr.takeError();
71 ModuleOffset.
Address +=
Info->getModulePreferredBase();
84 return symbolizeCodeCommon(Obj, ModuleOffset);
90 return symbolizeCodeCommon(
ModuleName, ModuleOffset);
96 return symbolizeCodeCommon(
BuildID, ModuleOffset);
104 return InfoOrErr.takeError();
116 ModuleOffset.
Address +=
Info->getModulePreferredBase();
122 for (
int i = 0, n =
InlinedContext.getNumberOfFrames(); i < n; i++) {
130Expected<DIInliningInfo>
133 return symbolizeInlinedCodeCommon(Obj, ModuleOffset);
139 return symbolizeInlinedCodeCommon(
ModuleName, ModuleOffset);
145 return symbolizeInlinedCodeCommon(
BuildID, ModuleOffset);
150LLVMSymbolizer::symbolizeDataCommon(
const T &ModuleSpecifier,
155 return InfoOrErr.takeError();
167 ModuleOffset.
Address +=
Info->getModulePreferredBase();
178 return symbolizeDataCommon(Obj, ModuleOffset);
184 return symbolizeDataCommon(
ModuleName, ModuleOffset);
190 return symbolizeDataCommon(
BuildID, ModuleOffset);
195LLVMSymbolizer::symbolizeFrameCommon(
const T &ModuleSpecifier,
199 return InfoOrErr.takeError();
205 return std::vector<DILocal>();
211 ModuleOffset.
Address +=
Info->getModulePreferredBase();
213 return Info->symbolizeFrame(ModuleOffset);
219 return symbolizeFrameCommon(Obj, ModuleOffset);
225 return symbolizeFrameCommon(
ModuleName, ModuleOffset);
231 return symbolizeFrameCommon(
BuildID, ModuleOffset);
236LLVMSymbolizer::findSymbolCommon(
const T &ModuleSpecifier,
StringRef Symbol,
240 return InfoOrErr.takeError();
243 std::vector<DILineInfo> Result;
257 Result.push_back(LineInfo);
264Expected<std::vector<DILineInfo>>
267 return findSymbolCommon(Obj, Symbol,
Offset);
283 ObjectForUBPathAndArch.clear();
286 BinaryForPath.clear();
287 ObjectPairForPathArch.clear();
289 BuildIDPaths.
clear();
298std::string getDarwinDWARFResourceForPath(
const std::string &Path,
299 const std::string &Basename) {
302 ResourceName +=
".dSYM";
306 return std::string(ResourceName);
309bool checkFileCRC(StringRef Path,
uint32_t CRCHash) {
310 ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
314 return CRCHash ==
llvm::crc32(arrayRefFromStringRef(MB.get()->getBuffer()));
317bool getGNUDebuglinkContents(
const ObjectFile *Obj, std::string &DebugName,
321 for (
const SectionRef &Section : Obj->sections()) {
326 if (
Name ==
"gnu_debuglink") {
327 Expected<StringRef> ContentsOrErr =
Section.getContents();
328 if (!ContentsOrErr) {
332 DataExtractor DE(*ContentsOrErr, Obj->isLittleEndian(), 0);
334 if (
const char *DebugNameStr = DE.getCStr(&
Offset)) {
337 if (DE.isValidOffsetForDataOfSize(
Offset, 4)) {
338 DebugName = DebugNameStr;
339 CRCHash = DE.getU32(&
Offset);
349bool darwinDsymMatchesBinary(
const MachOObjectFile *DbgObj,
350 const MachOObjectFile *Obj) {
351 ArrayRef<uint8_t> dbg_uuid = DbgObj->getUuid();
352 ArrayRef<uint8_t> bin_uuid = Obj->getUuid();
353 if (dbg_uuid.empty() || bin_uuid.empty())
355 return !
memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size());
360ObjectFile *LLVMSymbolizer::lookUpDsymFile(
const std::string &ExePath,
361 const MachOObjectFile *MachExeObj,
362 const std::string &ArchName) {
365 std::vector<std::string> DsymPaths;
368 getDarwinDWARFResourceForPath(ExePath, std::string(Filename)));
369 for (
const auto &Path : Opts.
DsymHints) {
371 getDarwinDWARFResourceForPath(Path, std::string(Filename)));
373 for (
const auto &Path : DsymPaths) {
374 auto DbgObjOrErr = getOrCreateObject(Path, ArchName);
383 const MachOObjectFile *MachDbgObj = dyn_cast<const MachOObjectFile>(DbgObj);
386 if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj))
392ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(
const std::string &Path,
393 const ObjectFile *Obj,
394 const std::string &ArchName) {
395 std::string DebuglinkName;
397 std::string DebugBinaryPath;
398 if (!getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash))
400 if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath))
402 auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
408 return DbgObjOrErr.get();
411ObjectFile *LLVMSymbolizer::lookUpBuildIDObject(
const std::string &Path,
412 const ELFObjectFileBase *Obj,
413 const std::string &ArchName) {
417 std::string DebugBinaryPath;
418 if (!getOrFindDebugBinary(
BuildID, DebugBinaryPath))
420 auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
425 return DbgObjOrErr.get();
428bool LLVMSymbolizer::findDebugBinary(
const std::string &OrigPath,
429 const std::string &DebuglinkName,
430 uint32_t CRCHash, std::string &Result) {
431 SmallString<16> OrigDir(OrigPath);
433 SmallString<16> DebugPath = OrigDir;
436 if (checkFileCRC(DebugPath, CRCHash)) {
437 Result = std::string(DebugPath);
443 if (checkFileCRC(DebugPath, CRCHash)) {
444 Result = std::string(DebugPath);
455#if defined(__NetBSD__)
457 DebugPath =
"/usr/libdata/debug";
460 DebugPath =
"/usr/lib/debug";
465 if (checkFileCRC(DebugPath, CRCHash)) {
466 Result = std::string(DebugPath);
478 std::string &Result) {
480 auto I = BuildIDPaths.
find(BuildIDStr);
481 if (
I != BuildIDPaths.
end()) {
487 if (std::optional<std::string> Path = BIDFetcher->fetch(
BuildID)) {
489 auto InsertResult = BuildIDPaths.
insert({BuildIDStr, Result});
490 assert(InsertResult.second);
498Expected<LLVMSymbolizer::ObjectPair>
499LLVMSymbolizer::getOrCreateObjectPair(
const std::string &Path,
500 const std::string &ArchName) {
501 auto I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
502 if (
I != ObjectPairForPathArch.end()) {
503 recordAccess(BinaryForPath.find(Path)->second);
507 auto ObjOrErr = getOrCreateObject(Path, ArchName);
509 ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName),
510 ObjectPair(
nullptr,
nullptr));
511 return ObjOrErr.takeError();
518 if (
auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
519 DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
520 else if (
auto ELFObj = dyn_cast<const ELFObjectFileBase>(Obj))
521 DbgObj = lookUpBuildIDObject(Path, ELFObj, ArchName);
523 DbgObj = lookUpDebuglinkObject(Path, Obj, ArchName);
526 ObjectPair Res = std::make_pair(Obj, DbgObj);
527 std::string DbgObjPath = DbgObj->getFileName().str();
529 ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName), Res);
530 BinaryForPath.find(DbgObjPath)->second.pushEvictor([
this,
I = Pair.first]() {
531 ObjectPairForPathArch.erase(I);
536Expected<ObjectFile *>
537LLVMSymbolizer::getOrCreateObject(
const std::string &Path,
538 const std::string &ArchName) {
540 auto Pair = BinaryForPath.emplace(Path, OwningBinary<Binary>());
542 Bin = Pair.first->second->getBinary();
543 recordAccess(Pair.first->second);
545 Expected<OwningBinary<Binary>> BinOrErr =
createBinary(Path);
547 return BinOrErr.takeError();
549 CachedBinary &CachedBin = Pair.first->second;
550 CachedBin = std::move(BinOrErr.get());
551 CachedBin.pushEvictor([
this,
I = Pair.first]() { BinaryForPath.erase(I); });
552 LRUBinaries.push_back(CachedBin);
553 CacheSize += CachedBin.size();
554 Bin = CachedBin->getBinary();
560 if (MachOUniversalBinary *UB = dyn_cast_or_null<MachOUniversalBinary>(
Bin)) {
561 auto I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName));
562 if (
I != ObjectForUBPathAndArch.end())
563 return I->second.get();
565 Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
566 UB->getMachOObjectForArch(ArchName);
568 ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
569 std::unique_ptr<ObjectFile>());
570 return ObjOrErr.takeError();
573 auto Pair = ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
574 std::move(ObjOrErr.get()));
575 BinaryForPath.find(Path)->second.pushEvictor(
576 [
this, Iter = Pair.first]() { ObjectForUBPathAndArch.erase(Iter); });
579 if (
Bin->isObject()) {
580 return cast<ObjectFile>(
Bin);
585Expected<SymbolizableModule *>
586LLVMSymbolizer::createModuleInfo(
const ObjectFile *Obj,
587 std::unique_ptr<DIContext> Context,
591 std::unique_ptr<SymbolizableModule> SymMod;
593 SymMod = std::move(*InfoOrErr);
594 auto InsertResult = Modules.insert(
595 std::make_pair(std::string(
ModuleName), std::move(SymMod)));
596 assert(InsertResult.second);
598 return InfoOrErr.takeError();
599 return InsertResult.first->second.get();
602Expected<SymbolizableModule *>
606 size_t ColonPos =
ModuleName.find_last_of(
':');
608 if (ColonPos != std::string::npos) {
609 std::string ArchStr =
ModuleName.substr(ColonPos + 1);
617 if (
I != Modules.end()) {
618 recordAccess(BinaryForPath.find(BinaryName)->second);
619 return I->second.get();
622 auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, ArchName);
625 Modules.emplace(
ModuleName, std::unique_ptr<SymbolizableModule>());
626 return ObjectsOrErr.takeError();
628 ObjectPair Objects = ObjectsOrErr.get();
630 std::unique_ptr<DIContext>
Context;
633 if (
auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
636 auto EC = CoffObject->getDebugPDBInfo(
DebugInfo, PDBFileName);
640 if (Expected<StringRef> SectionName = Section.getName())
641 return SectionName.get() ==
".debug_info";
644 if (!EC && !HasDwarf &&
DebugInfo !=
nullptr && !PDBFileName.
empty()) {
646 std::unique_ptr<IPDBSession> Session;
648 PDB_ReaderType ReaderType =
649 Opts.
UseDIA ? PDB_ReaderType::DIA : PDB_ReaderType::Native;
650 if (
auto Err = loadDataForEXE(ReaderType, Objects.first->getFileName(),
652 Modules.emplace(
ModuleName, std::unique_ptr<SymbolizableModule>());
656 Context.reset(
new PDBContext(*CoffObject, std::move(Session)));
667 BinaryForPath.find(BinaryName)->second.pushEvictor([
this,
I]() {
684 auto I = Modules.find(ObjName);
685 if (
I != Modules.end())
686 return I->second.get();
688 std::unique_ptr<DIContext>
Context;
694 return createModuleInfo(&Obj, std::move(Context), ObjName);
697Expected<SymbolizableModule *>
700 if (!getOrFindDebugBinary(
BuildID, Path)) {
702 "could not find build ID");
715StringRef demanglePE32ExternCFunc(StringRef SymbolName) {
719 bool HasAtNumSuffix =
false;
725 HasAtNumSuffix =
true;
730 bool IsVectorCall =
false;
731 if (HasAtNumSuffix &&
SymbolName.ends_with(
"@")) {
737 if (!IsVectorCall && (Front ==
'_' || Front ==
'@'))
752 if (!
Name.empty() &&
Name.front() ==
'?') {
756 Name,
nullptr, &status,
761 Result = DemangledName;
766 if (DbiModuleDescriptor && DbiModuleDescriptor->
isWin32Module()) {
767 std::string DemangledCName(demanglePE32ExternCFunc(
Name));
772 return DemangledCName;
778 if (
Bin->getBinary())
779 LRUBinaries.splice(LRUBinaries.end(), LRUBinaries,
Bin.getIterator());
786 while (CacheSize > Opts.
MaxCacheSize && !LRUBinaries.empty() &&
787 std::next(LRUBinaries.begin()) != LRUBinaries.end()) {
789 CacheSize -=
Bin.size();
790 LRUBinaries.pop_front();
797 this->Evictor = [OldEvictor = std::move(this->Evictor),
798 NewEvictor = std::move(NewEvictor)]() {
803 this->Evictor = std::move(NewEvictor);
This file declares a library for handling Build IDs and using them to find debug info.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
Merge contiguous icmps into a memcmp
static bool isDigit(const char C)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
static std::unique_ptr< BTFContext > create(const object::ObjectFile &Obj, std::function< void(Error)> ErrorHandler=WithColor::defaultErrorHandler)
static bool hasBTFSections(const ObjectFile &Obj)
A format-neutral container for inlined code description.
static std::unique_ptr< DWARFContext > create(const object::ObjectFile &Obj, ProcessDebugRelocations RelocAction=ProcessDebugRelocations::Process, const LoadedObjectInfo *L=nullptr, std::string DWPName="", std::function< void(Error)> RecoverableErrorHandler=WithColor::defaultErrorHandler, std::function< void(Error)> WarningHandler=WithColor::defaultWarningHandler, bool ThreadSafe=false)
Tagged union holding either a T or a Error.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
iterator find(StringRef Key)
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
static constexpr size_t npos
Triple - Helper class for working with autoconf configuration names.
bool isBPF() const
Tests whether the target is eBPF.
StringRef getFileName() const
BuildIDFetcher searches local cache directories for debug info.
This class is the base class for all object file types.
Triple makeTriple() const
Create a triple from the data in this object file.
virtual bool hasDebugInfo() const
This is a value type class that represents a single section in the list of sections in the object fil...
void pushEvictor(std::function< void()> Evictor)
Expected< std::vector< DILineInfo > > findSymbol(const ObjectFile &Obj, StringRef Symbol, uint64_t Offset)
Expected< DIInliningInfo > symbolizeInlinedCode(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
Expected< SymbolizableModule * > getOrCreateModuleInfo(const std::string &ModuleName)
Returns a SymbolizableModule or an error if loading debug info failed.
Expected< DILineInfo > symbolizeCode(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
static std::string DemangleName(const std::string &Name, const SymbolizableModule *DbiModuleDescriptor)
Expected< DIGlobal > symbolizeData(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
Expected< std::vector< DILocal > > symbolizeFrame(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
virtual bool isWin32Module() const =0
static Expected< std::unique_ptr< SymbolizableObjectFile > > create(const object::ObjectFile *Obj, std::unique_ptr< DIContext > DICtx, bool UntagAddresses)
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
SmallVector< uint8_t, 10 > BuildID
A build ID in binary form.
BuildIDRef getBuildID(const ObjectFile *Obj)
Returns the build ID, if any, contained in the given object file.
Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)
Create a Binary from Source, autodetecting the file type.
static bool useBTFContext(const ObjectFile &Obj)
static StringRef getBuildIDStr(ArrayRef< uint8_t > BuildID)
void make_absolute(const Twine ¤t_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
void remove_filename(SmallVectorImpl< char > &path, Style style=Style::native)
Remove the last component from path unless it is the root dir.
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
StringRef extension(StringRef path, Style style=Style::native)
Get extension.
StringRef relative_path(StringRef path, Style style=Style::native)
Get relative path.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result, bool CanHaveLeadingDot=true, bool ParseParams=true)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
@ no_such_file_or_directory
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
@ Global
Append to llvm.global_dtors.
uint32_t crc32(ArrayRef< uint8_t > Data)
char * microsoftDemangle(std::string_view mangled_name, size_t *n_read, int *status, MSDemangleFlags Flags=MSDF_None)
Demangles the Microsoft symbol pointed at by mangled_name and returns it.
@ MSDF_NoCallingConvention
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
void consumeError(Error Err)
Consume a Error without doing anything.
Implement std::hash so that hash_code can be used in STL containers.
Container for description of a global variable.
Controls which fields of DILineInfo container should be filled with data.
A format-neutral container for source line information.
static constexpr const char *const BadString
std::vector< std::string > DsymHints
std::string FallbackDebugPath
FunctionNameKind PrintFunctions
FileLineInfoKind PathStyle