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);
235 ObjectForUBPathAndArch.clear();
238 BinaryForPath.clear();
239 ObjectPairForPathArch.clear();
241 BuildIDPaths.
clear();
250std::string getDarwinDWARFResourceForPath(
const std::string &Path,
251 const std::string &Basename) {
254 ResourceName +=
".dSYM";
258 return std::string(ResourceName.
str());
261bool checkFileCRC(StringRef Path,
uint32_t CRCHash) {
262 ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
266 return CRCHash ==
llvm::crc32(arrayRefFromStringRef(MB.get()->getBuffer()));
269bool getGNUDebuglinkContents(
const ObjectFile *Obj, std::string &DebugName,
273 for (
const SectionRef &Section : Obj->sections()) {
278 if (
Name ==
"gnu_debuglink") {
279 Expected<StringRef> ContentsOrErr =
Section.getContents();
280 if (!ContentsOrErr) {
284 DataExtractor DE(*ContentsOrErr, Obj->isLittleEndian(), 0);
286 if (
const char *DebugNameStr = DE.getCStr(&
Offset)) {
289 if (DE.isValidOffsetForDataOfSize(
Offset, 4)) {
290 DebugName = DebugNameStr;
291 CRCHash = DE.getU32(&
Offset);
301bool darwinDsymMatchesBinary(
const MachOObjectFile *DbgObj,
302 const MachOObjectFile *Obj) {
303 ArrayRef<uint8_t> dbg_uuid = DbgObj->getUuid();
304 ArrayRef<uint8_t> bin_uuid = Obj->getUuid();
305 if (dbg_uuid.empty() || bin_uuid.empty())
307 return !
memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size());
312ObjectFile *LLVMSymbolizer::lookUpDsymFile(
const std::string &ExePath,
313 const MachOObjectFile *MachExeObj,
314 const std::string &ArchName) {
317 std::vector<std::string> DsymPaths;
320 getDarwinDWARFResourceForPath(ExePath, std::string(Filename)));
321 for (
const auto &Path : Opts.
DsymHints) {
323 getDarwinDWARFResourceForPath(Path, std::string(Filename)));
325 for (
const auto &Path : DsymPaths) {
326 auto DbgObjOrErr = getOrCreateObject(Path, ArchName);
335 const MachOObjectFile *MachDbgObj = dyn_cast<const MachOObjectFile>(DbgObj);
338 if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj))
344ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(
const std::string &Path,
345 const ObjectFile *Obj,
346 const std::string &ArchName) {
347 std::string DebuglinkName;
349 std::string DebugBinaryPath;
350 if (!getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash))
352 if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath))
354 auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
360 return DbgObjOrErr.get();
363ObjectFile *LLVMSymbolizer::lookUpBuildIDObject(
const std::string &Path,
364 const ELFObjectFileBase *Obj,
365 const std::string &ArchName) {
369 std::string DebugBinaryPath;
370 if (!getOrFindDebugBinary(
BuildID, DebugBinaryPath))
372 auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
377 return DbgObjOrErr.get();
380bool LLVMSymbolizer::findDebugBinary(
const std::string &OrigPath,
381 const std::string &DebuglinkName,
382 uint32_t CRCHash, std::string &Result) {
383 SmallString<16> OrigDir(OrigPath);
385 SmallString<16> DebugPath = OrigDir;
388 if (checkFileCRC(DebugPath, CRCHash)) {
389 Result = std::string(DebugPath.str());
395 if (checkFileCRC(DebugPath, CRCHash)) {
396 Result = std::string(DebugPath.str());
407#if defined(__NetBSD__)
409 DebugPath =
"/usr/libdata/debug";
412 DebugPath =
"/usr/lib/debug";
417 if (checkFileCRC(DebugPath, CRCHash)) {
418 Result = std::string(DebugPath.str());
430 std::string &Result) {
432 auto I = BuildIDPaths.
find(BuildIDStr);
433 if (
I != BuildIDPaths.
end()) {
439 if (std::optional<std::string> Path = BIDFetcher->fetch(
BuildID)) {
441 auto InsertResult = BuildIDPaths.
insert({BuildIDStr, Result});
442 assert(InsertResult.second);
450Expected<LLVMSymbolizer::ObjectPair>
451LLVMSymbolizer::getOrCreateObjectPair(
const std::string &Path,
452 const std::string &ArchName) {
453 auto I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
454 if (
I != ObjectPairForPathArch.end()) {
455 recordAccess(BinaryForPath.find(Path)->second);
459 auto ObjOrErr = getOrCreateObject(Path, ArchName);
461 ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName),
462 ObjectPair(
nullptr,
nullptr));
463 return ObjOrErr.takeError();
470 if (
auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
471 DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
472 else if (
auto ELFObj = dyn_cast<const ELFObjectFileBase>(Obj))
473 DbgObj = lookUpBuildIDObject(Path, ELFObj, ArchName);
475 DbgObj = lookUpDebuglinkObject(Path, Obj, ArchName);
478 ObjectPair Res = std::make_pair(Obj, DbgObj);
479 std::string DbgObjPath = DbgObj->getFileName().str();
481 ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName), Res);
482 BinaryForPath.find(DbgObjPath)->second.pushEvictor([
this,
I = Pair.first]() {
483 ObjectPairForPathArch.erase(I);
488Expected<ObjectFile *>
489LLVMSymbolizer::getOrCreateObject(
const std::string &Path,
490 const std::string &ArchName) {
492 auto Pair = BinaryForPath.emplace(Path, OwningBinary<Binary>());
494 Bin = Pair.first->second->getBinary();
495 recordAccess(Pair.first->second);
497 Expected<OwningBinary<Binary>> BinOrErr =
createBinary(Path);
499 return BinOrErr.takeError();
501 CachedBinary &CachedBin = Pair.first->second;
502 CachedBin = std::move(BinOrErr.get());
503 CachedBin.pushEvictor([
this,
I = Pair.first]() { BinaryForPath.erase(I); });
504 LRUBinaries.push_back(CachedBin);
505 CacheSize += CachedBin.size();
506 Bin = CachedBin->getBinary();
512 if (MachOUniversalBinary *UB = dyn_cast_or_null<MachOUniversalBinary>(
Bin)) {
513 auto I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName));
514 if (
I != ObjectForUBPathAndArch.end())
515 return I->second.get();
517 Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
518 UB->getMachOObjectForArch(ArchName);
520 ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
521 std::unique_ptr<ObjectFile>());
522 return ObjOrErr.takeError();
525 auto Pair = ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
526 std::move(ObjOrErr.get()));
527 BinaryForPath.find(Path)->second.pushEvictor(
528 [
this, Iter = Pair.first]() { ObjectForUBPathAndArch.erase(Iter); });
531 if (
Bin->isObject()) {
532 return cast<ObjectFile>(
Bin);
537Expected<SymbolizableModule *>
538LLVMSymbolizer::createModuleInfo(
const ObjectFile *Obj,
539 std::unique_ptr<DIContext> Context,
543 std::unique_ptr<SymbolizableModule> SymMod;
545 SymMod = std::move(*InfoOrErr);
546 auto InsertResult = Modules.insert(
547 std::make_pair(std::string(
ModuleName), std::move(SymMod)));
548 assert(InsertResult.second);
550 return InfoOrErr.takeError();
551 return InsertResult.first->second.get();
554Expected<SymbolizableModule *>
558 size_t ColonPos =
ModuleName.find_last_of(
':');
560 if (ColonPos != std::string::npos) {
561 std::string ArchStr =
ModuleName.substr(ColonPos + 1);
569 if (
I != Modules.end()) {
570 recordAccess(BinaryForPath.find(BinaryName)->second);
571 return I->second.get();
574 auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, ArchName);
577 Modules.emplace(
ModuleName, std::unique_ptr<SymbolizableModule>());
578 return ObjectsOrErr.takeError();
580 ObjectPair Objects = ObjectsOrErr.get();
582 std::unique_ptr<DIContext>
Context;
585 if (
auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
588 auto EC = CoffObject->getDebugPDBInfo(DebugInfo, PDBFileName);
589 if (!EC && DebugInfo !=
nullptr && !PDBFileName.
empty()) {
591 std::unique_ptr<IPDBSession> Session;
593 PDB_ReaderType ReaderType =
594 Opts.
UseDIA ? PDB_ReaderType::DIA : PDB_ReaderType::Native;
595 if (
auto Err = loadDataForEXE(ReaderType, Objects.first->getFileName(),
597 Modules.emplace(
ModuleName, std::unique_ptr<SymbolizableModule>());
601 Context.reset(
new PDBContext(*CoffObject, std::move(Session)));
612 BinaryForPath.find(BinaryName)->second.pushEvictor([
this,
I]() {
629 auto I = Modules.find(ObjName);
630 if (
I != Modules.end())
631 return I->second.get();
633 std::unique_ptr<DIContext>
Context;
639 return createModuleInfo(&Obj, std::move(Context), ObjName);
642Expected<SymbolizableModule *>
645 if (!getOrFindDebugBinary(
BuildID, Path)) {
647 "could not find build ID");
660StringRef demanglePE32ExternCFunc(StringRef SymbolName) {
664 bool HasAtNumSuffix =
false;
670 HasAtNumSuffix =
true;
675 bool IsVectorCall =
false;
676 if (HasAtNumSuffix &&
SymbolName.endswith(
"@")) {
682 if (!IsVectorCall && (Front ==
'_' || Front ==
'@'))
697 if (!
Name.empty() &&
Name.front() ==
'?') {
701 Name,
nullptr, &status,
706 Result = DemangledName;
711 if (DbiModuleDescriptor && DbiModuleDescriptor->
isWin32Module()) {
712 std::string DemangledCName(demanglePE32ExternCFunc(
Name));
717 return DemangledCName;
723 if (
Bin->getBinary())
724 LRUBinaries.splice(LRUBinaries.end(), LRUBinaries,
Bin.getIterator());
731 while (CacheSize > Opts.
MaxCacheSize && !LRUBinaries.empty() &&
732 std::next(LRUBinaries.begin()) != LRUBinaries.end()) {
734 CacheSize -=
Bin.size();
735 LRUBinaries.pop_front();
742 this->Evictor = [OldEvictor = std::move(this->Evictor),
743 NewEvictor = std::move(NewEvictor)]() {
748 this->Evictor = std::move(NewEvictor);
This file declares a library for handling Build IDs and using them to find debug info.
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...
StringRef str() const
Explicit conversion to StringRef.
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
void pushEvictor(std::function< void()> Evictor)
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 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 nonMicrosoftDemangle(std::string_view MangledName, std::string &Result)
@ 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.
std::vector< std::string > DsymHints
std::string FallbackDebugPath
FunctionNameKind PrintFunctions
FileLineInfoKind PathStyle