53LLVMSymbolizer::symbolizeCodeCommon(
const T &ModuleSpecifier,
58 return InfoOrErr.takeError();
70 ModuleOffset.
Address +=
Info->getModulePreferredBase();
85 return symbolizeCodeCommon(Obj, ModuleOffset);
91 return symbolizeCodeCommon(
ModuleName, ModuleOffset);
97 return symbolizeCodeCommon(
BuildID, ModuleOffset);
105 return InfoOrErr.takeError();
117 ModuleOffset.
Address +=
Info->getModulePreferredBase();
125 for (
int i = 0, n =
InlinedContext.getNumberOfFrames(); i < n; i++) {
133Expected<DIInliningInfo>
136 return symbolizeInlinedCodeCommon(Obj, ModuleOffset);
142 return symbolizeInlinedCodeCommon(
ModuleName, ModuleOffset);
148 return symbolizeInlinedCodeCommon(
BuildID, ModuleOffset);
153LLVMSymbolizer::symbolizeDataCommon(
const T &ModuleSpecifier,
158 return InfoOrErr.takeError();
170 ModuleOffset.
Address +=
Info->getModulePreferredBase();
181 return symbolizeDataCommon(Obj, ModuleOffset);
187 return symbolizeDataCommon(
ModuleName, ModuleOffset);
193 return symbolizeDataCommon(
BuildID, ModuleOffset);
198LLVMSymbolizer::symbolizeFrameCommon(
const T &ModuleSpecifier,
202 return InfoOrErr.takeError();
208 return std::vector<DILocal>();
214 ModuleOffset.
Address +=
Info->getModulePreferredBase();
216 return Info->symbolizeFrame(ModuleOffset);
222 return symbolizeFrameCommon(Obj, ModuleOffset);
228 return symbolizeFrameCommon(
ModuleName, ModuleOffset);
234 return symbolizeFrameCommon(
BuildID, ModuleOffset);
239LLVMSymbolizer::findSymbolCommon(
const T &ModuleSpecifier,
StringRef Symbol,
243 return InfoOrErr.takeError();
246 std::vector<DILineInfo> Result;
260 Result.push_back(LineInfo);
267Expected<std::vector<DILineInfo>>
270 return findSymbolCommon(Obj, Symbol,
Offset);
286 ObjectForUBPathAndArch.clear();
289 BinaryForPath.clear();
290 ObjectPairForPathArch.clear();
292 BuildIDPaths.
clear();
301std::string getDarwinDWARFResourceForPath(
const std::string &Path,
302 const std::string &Basename) {
305 ResourceName +=
".dSYM";
309 return std::string(ResourceName);
312bool checkFileCRC(StringRef Path,
uint32_t CRCHash) {
313 ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
317 return CRCHash ==
llvm::crc32(arrayRefFromStringRef(MB.get()->getBuffer()));
320bool getGNUDebuglinkContents(
const ObjectFile *Obj, std::string &DebugName,
324 for (
const SectionRef &Section : Obj->sections()) {
329 if (
Name ==
"gnu_debuglink") {
330 Expected<StringRef> ContentsOrErr =
Section.getContents();
331 if (!ContentsOrErr) {
335 DataExtractor DE(*ContentsOrErr, Obj->isLittleEndian(), 0);
337 if (
const char *DebugNameStr = DE.getCStr(&
Offset)) {
340 if (DE.isValidOffsetForDataOfSize(
Offset, 4)) {
341 DebugName = DebugNameStr;
342 CRCHash = DE.getU32(&
Offset);
352bool darwinDsymMatchesBinary(
const MachOObjectFile *DbgObj,
353 const MachOObjectFile *Obj) {
354 ArrayRef<uint8_t> dbg_uuid = DbgObj->getUuid();
355 ArrayRef<uint8_t> bin_uuid = Obj->getUuid();
356 if (dbg_uuid.empty() || bin_uuid.empty())
358 return !
memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size());
363ObjectFile *LLVMSymbolizer::lookUpDsymFile(
const std::string &ExePath,
364 const MachOObjectFile *MachExeObj,
365 const std::string &ArchName) {
368 std::vector<std::string> DsymPaths;
371 getDarwinDWARFResourceForPath(ExePath, std::string(Filename)));
372 for (
const auto &Path : Opts.
DsymHints) {
374 getDarwinDWARFResourceForPath(Path, std::string(Filename)));
376 for (
const auto &Path : DsymPaths) {
377 auto DbgObjOrErr = getOrCreateObject(Path, ArchName);
386 const MachOObjectFile *MachDbgObj = dyn_cast<const MachOObjectFile>(DbgObj);
389 if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj))
395ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(
const std::string &Path,
396 const ObjectFile *Obj,
397 const std::string &ArchName) {
398 std::string DebuglinkName;
400 std::string DebugBinaryPath;
401 if (!getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash))
403 if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath))
405 auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
411 return DbgObjOrErr.get();
414ObjectFile *LLVMSymbolizer::lookUpBuildIDObject(
const std::string &Path,
415 const ELFObjectFileBase *Obj,
416 const std::string &ArchName) {
420 std::string DebugBinaryPath;
421 if (!getOrFindDebugBinary(
BuildID, DebugBinaryPath))
423 auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
428 return DbgObjOrErr.get();
431bool LLVMSymbolizer::findDebugBinary(
const std::string &OrigPath,
432 const std::string &DebuglinkName,
433 uint32_t CRCHash, std::string &Result) {
434 SmallString<16> OrigDir(OrigPath);
436 SmallString<16> DebugPath = OrigDir;
439 if (checkFileCRC(DebugPath, CRCHash)) {
440 Result = std::string(DebugPath);
446 if (checkFileCRC(DebugPath, CRCHash)) {
447 Result = std::string(DebugPath);
458#if defined(__NetBSD__)
460 DebugPath =
"/usr/libdata/debug";
463 DebugPath =
"/usr/lib/debug";
468 if (checkFileCRC(DebugPath, CRCHash)) {
469 Result = std::string(DebugPath);
481 std::string &Result) {
483 auto I = BuildIDPaths.
find(BuildIDStr);
484 if (
I != BuildIDPaths.
end()) {
490 if (std::optional<std::string> Path = BIDFetcher->fetch(
BuildID)) {
492 auto InsertResult = BuildIDPaths.
insert({BuildIDStr, Result});
493 assert(InsertResult.second);
501Expected<LLVMSymbolizer::ObjectPair>
502LLVMSymbolizer::getOrCreateObjectPair(
const std::string &Path,
503 const std::string &ArchName) {
504 auto I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
505 if (
I != ObjectPairForPathArch.end()) {
506 recordAccess(BinaryForPath.find(Path)->second);
510 auto ObjOrErr = getOrCreateObject(Path, ArchName);
512 ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName),
513 ObjectPair(
nullptr,
nullptr));
514 return ObjOrErr.takeError();
521 if (
auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
522 DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
523 else if (
auto ELFObj = dyn_cast<const ELFObjectFileBase>(Obj))
524 DbgObj = lookUpBuildIDObject(Path, ELFObj, ArchName);
526 DbgObj = lookUpDebuglinkObject(Path, Obj, ArchName);
529 ObjectPair Res = std::make_pair(Obj, DbgObj);
530 std::string DbgObjPath = DbgObj->getFileName().str();
532 ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName), Res);
533 BinaryForPath.find(DbgObjPath)->second.pushEvictor([
this,
I = Pair.first]() {
534 ObjectPairForPathArch.erase(I);
539Expected<ObjectFile *>
540LLVMSymbolizer::getOrCreateObject(
const std::string &Path,
541 const std::string &ArchName) {
543 auto Pair = BinaryForPath.emplace(Path, OwningBinary<Binary>());
545 Bin = Pair.first->second->getBinary();
546 recordAccess(Pair.first->second);
548 Expected<OwningBinary<Binary>> BinOrErr =
createBinary(Path);
550 return BinOrErr.takeError();
552 CachedBinary &CachedBin = Pair.first->second;
553 CachedBin = std::move(BinOrErr.get());
554 CachedBin.pushEvictor([
this,
I = Pair.first]() { BinaryForPath.erase(I); });
555 LRUBinaries.push_back(CachedBin);
556 CacheSize += CachedBin.size();
557 Bin = CachedBin->getBinary();
563 if (MachOUniversalBinary *UB = dyn_cast_or_null<MachOUniversalBinary>(
Bin)) {
564 auto I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName));
565 if (
I != ObjectForUBPathAndArch.end())
566 return I->second.get();
568 Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
569 UB->getMachOObjectForArch(ArchName);
571 ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
572 std::unique_ptr<ObjectFile>());
573 return ObjOrErr.takeError();
576 auto Pair = ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
577 std::move(ObjOrErr.get()));
578 BinaryForPath.find(Path)->second.pushEvictor(
579 [
this, Iter = Pair.first]() { ObjectForUBPathAndArch.erase(Iter); });
582 if (
Bin->isObject()) {
583 return cast<ObjectFile>(
Bin);
588Expected<SymbolizableModule *>
589LLVMSymbolizer::createModuleInfo(
const ObjectFile *Obj,
590 std::unique_ptr<DIContext> Context,
594 std::unique_ptr<SymbolizableModule> SymMod;
596 SymMod = std::move(*InfoOrErr);
597 auto InsertResult = Modules.insert(
598 std::make_pair(std::string(
ModuleName), std::move(SymMod)));
599 assert(InsertResult.second);
601 return InfoOrErr.takeError();
602 return InsertResult.first->second.get();
605Expected<SymbolizableModule *>
609 size_t ColonPos =
ModuleName.find_last_of(
':');
611 if (ColonPos != std::string::npos) {
620 if (
I != Modules.end()) {
621 recordAccess(BinaryForPath.find(BinaryName)->second);
622 return I->second.get();
626 getOrCreateObjectPair(std::string{BinaryName}, std::string{ArchName});
629 Modules.emplace(
ModuleName, std::unique_ptr<SymbolizableModule>());
630 return ObjectsOrErr.takeError();
632 ObjectPair Objects = ObjectsOrErr.get();
634 std::unique_ptr<DIContext> Context;
637 if (
auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
640 auto EC = CoffObject->getDebugPDBInfo(
DebugInfo, PDBFileName);
644 if (Expected<StringRef> SectionName = Section.getName())
645 return SectionName.get() ==
".debug_info";
648 if (!EC && !HasDwarf &&
DebugInfo !=
nullptr && !PDBFileName.
empty()) {
650 std::unique_ptr<IPDBSession> Session;
652 PDB_ReaderType ReaderType =
653 Opts.
UseDIA ? PDB_ReaderType::DIA : PDB_ReaderType::Native;
654 if (
auto Err = loadDataForEXE(ReaderType, Objects.first->getFileName(),
656 Modules.emplace(
ModuleName, std::unique_ptr<SymbolizableModule>());
660 Context.reset(
new PDBContext(*CoffObject, std::move(Session)));
668 createModuleInfo(Objects.first, std::move(Context),
ModuleName);
671 BinaryForPath.find(BinaryName)->second.pushEvictor([
this,
I]() {
688 auto I = Modules.find(ObjName);
689 if (
I != Modules.end())
690 return I->second.get();
692 std::unique_ptr<DIContext> Context;
698 return createModuleInfo(&Obj, std::move(Context), ObjName);
701Expected<SymbolizableModule *>
704 if (!getOrFindDebugBinary(
BuildID, Path)) {
706 "could not find build ID");
719StringRef demanglePE32ExternCFunc(StringRef SymbolName) {
723 bool HasAtNumSuffix =
false;
729 HasAtNumSuffix =
true;
734 bool IsVectorCall =
false;
735 if (HasAtNumSuffix &&
SymbolName.ends_with(
"@")) {
741 if (!IsVectorCall && (Front ==
'_' || Front ==
'@'))
756 if (!
Name.empty() &&
Name.front() ==
'?') {
760 Name,
nullptr, &status,
764 return std::string{
Name};
765 Result = DemangledName;
770 if (DbiModuleDescriptor && DbiModuleDescriptor->
isWin32Module()) {
771 std::string DemangledCName(demanglePE32ExternCFunc(
Name));
776 return DemangledCName;
778 return std::string{
Name};
782 if (
Bin->getBinary())
783 LRUBinaries.splice(LRUBinaries.end(), LRUBinaries,
Bin.getIterator());
790 while (CacheSize > Opts.
MaxCacheSize && !LRUBinaries.empty() &&
791 std::next(LRUBinaries.begin()) != LRUBinaries.end()) {
793 CacheSize -=
Bin.size();
794 LRUBinaries.pop_front();
801 this->Evictor = [OldEvictor = std::move(this->Evictor),
802 NewEvictor = std::move(NewEvictor)]() {
807 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)
static std::string DemangleName(StringRef Name, const SymbolizableModule *DbiModuleDescriptor)
Expected< std::vector< DILineInfo > > findSymbol(const ObjectFile &Obj, StringRef Symbol, uint64_t Offset)
Expected< DIInliningInfo > symbolizeInlinedCode(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
Expected< DILineInfo > symbolizeCode(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
Expected< DIGlobal > symbolizeData(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
Expected< std::vector< DILocal > > symbolizeFrame(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
Expected< SymbolizableModule * > getOrCreateModuleInfo(StringRef ModuleName)
Returns a SymbolizableModule or an error if loading debug info failed.
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