54LLVMSymbolizer::symbolizeCodeCommon(
const T &ModuleSpecifier,
59 return InfoOrErr.takeError();
71 ModuleOffset.
Address +=
Info->getModulePreferredBase();
86 return symbolizeCodeCommon(Obj, ModuleOffset);
92 return symbolizeCodeCommon(
ModuleName, ModuleOffset);
98 return symbolizeCodeCommon(
BuildID, ModuleOffset);
106 return InfoOrErr.takeError();
118 ModuleOffset.
Address +=
Info->getModulePreferredBase();
126 for (
int i = 0, n =
InlinedContext.getNumberOfFrames(); i < n; i++) {
134Expected<DIInliningInfo>
137 return symbolizeInlinedCodeCommon(Obj, ModuleOffset);
143 return symbolizeInlinedCodeCommon(
ModuleName, ModuleOffset);
149 return symbolizeInlinedCodeCommon(
BuildID, ModuleOffset);
154LLVMSymbolizer::symbolizeDataCommon(
const T &ModuleSpecifier,
159 return InfoOrErr.takeError();
171 ModuleOffset.
Address +=
Info->getModulePreferredBase();
182 return symbolizeDataCommon(Obj, ModuleOffset);
188 return symbolizeDataCommon(
ModuleName, ModuleOffset);
194 return symbolizeDataCommon(
BuildID, ModuleOffset);
199LLVMSymbolizer::symbolizeFrameCommon(
const T &ModuleSpecifier,
203 return InfoOrErr.takeError();
209 return std::vector<DILocal>();
215 ModuleOffset.
Address +=
Info->getModulePreferredBase();
217 return Info->symbolizeFrame(ModuleOffset);
223 return symbolizeFrameCommon(Obj, ModuleOffset);
229 return symbolizeFrameCommon(
ModuleName, ModuleOffset);
235 return symbolizeFrameCommon(
BuildID, ModuleOffset);
240LLVMSymbolizer::findSymbolCommon(
const T &ModuleSpecifier,
StringRef Symbol,
244 return InfoOrErr.takeError();
247 std::vector<DILineInfo> Result;
261 Result.push_back(LineInfo);
268Expected<std::vector<DILineInfo>>
271 return findSymbolCommon(Obj, Symbol,
Offset);
287 ObjectForUBPathAndArch.clear();
290 BinaryForPath.clear();
291 ObjectPairForPathArch.clear();
293 BuildIDPaths.
clear();
302std::string getDarwinDWARFResourceForPath(
const std::string &Path,
303 const std::string &Basename) {
306 ResourceName +=
".dSYM";
310 return std::string(ResourceName);
313bool checkFileCRC(StringRef Path,
uint32_t CRCHash) {
314 ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
318 return CRCHash ==
llvm::crc32(arrayRefFromStringRef(MB.get()->getBuffer()));
321bool getGNUDebuglinkContents(
const ObjectFile *Obj, std::string &DebugName,
325 for (
const SectionRef &Section : Obj->sections()) {
330 if (
Name ==
"gnu_debuglink") {
331 Expected<StringRef> ContentsOrErr =
Section.getContents();
332 if (!ContentsOrErr) {
336 DataExtractor DE(*ContentsOrErr, Obj->isLittleEndian(), 0);
338 if (
const char *DebugNameStr = DE.getCStr(&
Offset)) {
341 if (DE.isValidOffsetForDataOfSize(
Offset, 4)) {
342 DebugName = DebugNameStr;
343 CRCHash = DE.getU32(&
Offset);
353bool darwinDsymMatchesBinary(
const MachOObjectFile *DbgObj,
354 const MachOObjectFile *Obj) {
355 ArrayRef<uint8_t> dbg_uuid = DbgObj->getUuid();
356 ArrayRef<uint8_t> bin_uuid = Obj->getUuid();
357 if (dbg_uuid.empty() || bin_uuid.empty())
359 return !
memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size());
364ObjectFile *LLVMSymbolizer::lookUpDsymFile(
const std::string &ExePath,
365 const MachOObjectFile *MachExeObj,
366 const std::string &ArchName) {
369 std::vector<std::string> DsymPaths;
372 getDarwinDWARFResourceForPath(ExePath, std::string(Filename)));
373 for (
const auto &Path : Opts.
DsymHints) {
375 getDarwinDWARFResourceForPath(Path, std::string(Filename)));
377 for (
const auto &Path : DsymPaths) {
378 auto DbgObjOrErr = getOrCreateObject(Path, ArchName);
387 const MachOObjectFile *MachDbgObj = dyn_cast<const MachOObjectFile>(DbgObj);
390 if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj))
396ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(
const std::string &Path,
397 const ObjectFile *Obj,
398 const std::string &ArchName) {
399 std::string DebuglinkName;
401 std::string DebugBinaryPath;
402 if (!getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash))
404 if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath))
406 auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
412 return DbgObjOrErr.get();
415ObjectFile *LLVMSymbolizer::lookUpBuildIDObject(
const std::string &Path,
416 const ELFObjectFileBase *Obj,
417 const std::string &ArchName) {
421 std::string DebugBinaryPath;
422 if (!getOrFindDebugBinary(
BuildID, DebugBinaryPath))
424 auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
429 return DbgObjOrErr.get();
432bool LLVMSymbolizer::findDebugBinary(
const std::string &OrigPath,
433 const std::string &DebuglinkName,
434 uint32_t CRCHash, std::string &Result) {
435 SmallString<16> OrigDir(OrigPath);
437 SmallString<16> DebugPath = OrigDir;
440 if (checkFileCRC(DebugPath, CRCHash)) {
441 Result = std::string(DebugPath);
447 if (checkFileCRC(DebugPath, CRCHash)) {
448 Result = std::string(DebugPath);
459#if defined(__NetBSD__)
461 DebugPath =
"/usr/libdata/debug";
464 DebugPath =
"/usr/lib/debug";
469 if (checkFileCRC(DebugPath, CRCHash)) {
470 Result = std::string(DebugPath);
482 std::string &Result) {
484 auto I = BuildIDPaths.
find(BuildIDStr);
485 if (
I != BuildIDPaths.
end()) {
491 if (std::optional<std::string> Path = BIDFetcher->fetch(
BuildID)) {
493 auto InsertResult = BuildIDPaths.
insert({BuildIDStr, Result});
494 assert(InsertResult.second);
502Expected<LLVMSymbolizer::ObjectPair>
503LLVMSymbolizer::getOrCreateObjectPair(
const std::string &Path,
504 const std::string &ArchName) {
505 auto I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
506 if (
I != ObjectPairForPathArch.end()) {
507 recordAccess(BinaryForPath.find(Path)->second);
511 auto ObjOrErr = getOrCreateObject(Path, ArchName);
513 ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName),
514 ObjectPair(
nullptr,
nullptr));
515 return ObjOrErr.takeError();
522 if (
auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
523 DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
524 else if (
auto ELFObj = dyn_cast<const ELFObjectFileBase>(Obj))
525 DbgObj = lookUpBuildIDObject(Path, ELFObj, ArchName);
527 DbgObj = lookUpDebuglinkObject(Path, Obj, ArchName);
530 ObjectPair Res = std::make_pair(Obj, DbgObj);
531 std::string DbgObjPath = DbgObj->getFileName().str();
533 ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName), Res);
534 BinaryForPath.find(DbgObjPath)->second.pushEvictor([
this,
I = Pair.first]() {
535 ObjectPairForPathArch.erase(I);
540Expected<ObjectFile *>
541LLVMSymbolizer::getOrCreateObject(
const std::string &Path,
542 const std::string &ArchName) {
544 auto Pair = BinaryForPath.emplace(Path, OwningBinary<Binary>());
546 Bin = Pair.first->second->getBinary();
547 recordAccess(Pair.first->second);
549 Expected<OwningBinary<Binary>> BinOrErr =
createBinary(Path);
551 return BinOrErr.takeError();
553 CachedBinary &CachedBin = Pair.first->second;
554 CachedBin = std::move(BinOrErr.get());
555 CachedBin.pushEvictor([
this,
I = Pair.first]() { BinaryForPath.erase(I); });
556 LRUBinaries.push_back(CachedBin);
557 CacheSize += CachedBin.size();
558 Bin = CachedBin->getBinary();
564 if (MachOUniversalBinary *UB = dyn_cast_or_null<MachOUniversalBinary>(
Bin)) {
565 auto I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName));
566 if (
I != ObjectForUBPathAndArch.end())
567 return I->second.get();
569 Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
570 UB->getMachOObjectForArch(ArchName);
572 ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
573 std::unique_ptr<ObjectFile>());
574 return ObjOrErr.takeError();
577 auto Pair = ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
578 std::move(ObjOrErr.get()));
579 BinaryForPath.find(Path)->second.pushEvictor(
580 [
this, Iter = Pair.first]() { ObjectForUBPathAndArch.erase(Iter); });
583 if (
Bin->isObject()) {
584 return cast<ObjectFile>(
Bin);
589Expected<SymbolizableModule *>
590LLVMSymbolizer::createModuleInfo(
const ObjectFile *Obj,
591 std::unique_ptr<DIContext> Context,
595 std::unique_ptr<SymbolizableModule> SymMod;
597 SymMod = std::move(*InfoOrErr);
598 auto InsertResult = Modules.insert(
599 std::make_pair(std::string(
ModuleName), std::move(SymMod)));
600 assert(InsertResult.second);
602 return InfoOrErr.takeError();
603 return InsertResult.first->second.get();
606Expected<SymbolizableModule *>
610 size_t ColonPos =
ModuleName.find_last_of(
':');
612 if (ColonPos != std::string::npos) {
613 std::string ArchStr =
ModuleName.substr(ColonPos + 1);
621 if (
I != Modules.end()) {
622 recordAccess(BinaryForPath.find(BinaryName)->second);
623 return I->second.get();
626 auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, 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,
765 Result = DemangledName;
770 if (DbiModuleDescriptor && DbiModuleDescriptor->
isWin32Module()) {
771 std::string DemangledCName(demanglePE32ExternCFunc(
Name));
776 return DemangledCName;
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)
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