42 template <
class ELFT>
class ELFFile;
54 LLVMSymbolizer::symbolizeCodeCommon(
const T &ModuleSpecifier,
57 auto InfoOrErr = getOrCreateModuleInfo(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);
102 auto InfoOrErr = getOrCreateModuleInfo(ModuleSpecifier);
104 return InfoOrErr.takeError();
116 ModuleOffset.
Address +=
Info->getModulePreferredBase();
130 Expected<DIInliningInfo>
133 return symbolizeInlinedCodeCommon(Obj, ModuleOffset);
139 return symbolizeInlinedCodeCommon(
ModuleName, ModuleOffset);
145 return symbolizeInlinedCodeCommon(
BuildID, ModuleOffset);
148 template <
typename T>
150 LLVMSymbolizer::symbolizeDataCommon(
const T &ModuleSpecifier,
153 auto InfoOrErr = getOrCreateModuleInfo(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);
193 template <
typename T>
195 LLVMSymbolizer::symbolizeFrameCommon(
const T &ModuleSpecifier,
197 auto InfoOrErr = getOrCreateModuleInfo(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();
250 std::string getDarwinDWARFResourceForPath(
const std::string &Path,
251 const std::string &Basename) {
254 ResourceName +=
".dSYM";
258 return std::string(ResourceName.
str());
261 bool checkFileCRC(StringRef Path,
uint32_t CRCHash) {
262 ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
266 return CRCHash ==
llvm::crc32(arrayRefFromStringRef(MB.get()->getBuffer()));
269 bool 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);
301 bool 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());
310 template <
typename ELFT>
311 Optional<ArrayRef<uint8_t>>
getBuildID(
const ELFFile<ELFT> &Obj) {
312 auto PhdrsOrErr = Obj.program_headers();
317 for (
const auto &
P : *PhdrsOrErr) {
321 for (
auto N : Obj.notes(
P, Err))
347 ObjectFile *LLVMSymbolizer::lookUpDsymFile(
const std::string &ExePath,
348 const MachOObjectFile *MachExeObj,
349 const std::string &ArchName) {
352 std::vector<std::string> DsymPaths;
355 getDarwinDWARFResourceForPath(ExePath, std::string(Filename)));
356 for (
const auto &Path : Opts.
DsymHints) {
358 getDarwinDWARFResourceForPath(Path, std::string(Filename)));
360 for (
const auto &Path : DsymPaths) {
361 auto DbgObjOrErr = getOrCreateObject(Path, ArchName);
370 const MachOObjectFile *MachDbgObj = dyn_cast<const MachOObjectFile>(DbgObj);
373 if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj))
379 ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(
const std::string &Path,
380 const ObjectFile *Obj,
381 const std::string &ArchName) {
382 std::string DebuglinkName;
384 std::string DebugBinaryPath;
385 if (!getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash))
387 if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath))
389 auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
395 return DbgObjOrErr.get();
398 ObjectFile *LLVMSymbolizer::lookUpBuildIDObject(
const std::string &Path,
399 const ELFObjectFileBase *Obj,
400 const std::string &ArchName) {
406 std::string DebugBinaryPath;
407 if (!getOrFindDebugBinary(*
BuildID, DebugBinaryPath))
409 auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
414 return DbgObjOrErr.get();
417 bool LLVMSymbolizer::findDebugBinary(
const std::string &OrigPath,
418 const std::string &DebuglinkName,
419 uint32_t CRCHash, std::string &Result) {
420 SmallString<16> OrigDir(OrigPath);
422 SmallString<16> DebugPath = OrigDir;
425 if (checkFileCRC(DebugPath, CRCHash)) {
426 Result = std::string(DebugPath.str());
432 if (checkFileCRC(DebugPath, CRCHash)) {
433 Result = std::string(DebugPath.str());
444 #if defined(__NetBSD__)
446 DebugPath =
"/usr/libdata/debug";
449 DebugPath =
"/usr/lib/debug";
454 if (checkFileCRC(DebugPath, CRCHash)) {
455 Result = std::string(DebugPath.str());
467 std::string &Result) {
469 auto I = BuildIDPaths.
find(BuildIDStr);
470 if (
I != BuildIDPaths.
end()) {
474 auto recordPath = [&](StringRef Path) {
476 auto InsertResult = BuildIDPaths.
insert({BuildIDStr, Result});
477 assert(InsertResult.second);
481 Optional<std::string>
Path;
489 for (
const std::unique_ptr<DIFetcher> &Fetcher : DIFetchers) {
500 Expected<LLVMSymbolizer::ObjectPair>
501 LLVMSymbolizer::getOrCreateObjectPair(
const std::string &Path,
502 const std::string &ArchName) {
503 auto I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
504 if (
I != ObjectPairForPathArch.end()) {
505 recordAccess(BinaryForPath.find(Path)->second);
509 auto ObjOrErr = getOrCreateObject(Path, ArchName);
511 ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName),
512 ObjectPair(
nullptr,
nullptr));
513 return ObjOrErr.takeError();
520 if (
auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
521 DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
522 else if (
auto ELFObj = dyn_cast<const ELFObjectFileBase>(Obj))
523 DbgObj = lookUpBuildIDObject(Path, ELFObj, ArchName);
525 DbgObj = lookUpDebuglinkObject(Path, Obj, ArchName);
528 ObjectPair Res = std::make_pair(Obj, DbgObj);
529 std::string DbgObjPath = DbgObj->getFileName().str();
531 ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName), Res);
532 BinaryForPath.find(DbgObjPath)->second.pushEvictor([
this,
I = Pair.first]() {
533 ObjectPairForPathArch.erase(I);
538 Expected<ObjectFile *>
539 LLVMSymbolizer::getOrCreateObject(
const std::string &Path,
540 const std::string &ArchName) {
542 auto Pair = BinaryForPath.emplace(Path, OwningBinary<Binary>());
544 Bin = Pair.first->second->getBinary();
545 recordAccess(Pair.first->second);
547 Expected<OwningBinary<Binary>> BinOrErr =
createBinary(Path);
549 return BinOrErr.takeError();
551 CachedBinary &CachedBin = Pair.first->second;
553 CachedBin.pushEvictor([
this,
I = Pair.first]() { BinaryForPath.erase(I); });
554 LRUBinaries.push_back(CachedBin);
555 CacheSize += CachedBin.size();
556 Bin = CachedBin->getBinary();
562 if (MachOUniversalBinary *UB = dyn_cast_or_null<MachOUniversalBinary>(Bin)) {
563 auto I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName));
564 if (
I != ObjectForUBPathAndArch.end())
565 return I->second.get();
567 Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
568 UB->getMachOObjectForArch(ArchName);
570 ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
571 std::unique_ptr<ObjectFile>());
572 return ObjOrErr.takeError();
575 auto Pair = ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
577 BinaryForPath.find(Path)->second.pushEvictor(
578 [
this, Iter = Pair.first]() { ObjectForUBPathAndArch.erase(Iter); });
581 if (
Bin->isObject()) {
582 return cast<ObjectFile>(Bin);
587 Expected<SymbolizableModule *>
588 LLVMSymbolizer::createModuleInfo(
const ObjectFile *Obj,
589 std::unique_ptr<DIContext>
Context,
593 std::unique_ptr<SymbolizableModule> SymMod;
596 auto InsertResult = Modules.insert(
598 assert(InsertResult.second);
600 return InfoOrErr.takeError();
601 return InsertResult.first->second.get();
604 Expected<SymbolizableModule *>
605 LLVMSymbolizer::getOrCreateModuleInfo(
const std::string &
ModuleName) {
608 size_t ColonPos =
ModuleName.find_last_of(
':');
610 if (ColonPos != std::string::npos) {
611 std::string ArchStr =
ModuleName.substr(ColonPos + 1);
619 if (
I != Modules.end()) {
620 recordAccess(BinaryForPath.find(BinaryName)->second);
621 return I->second.get();
624 auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, ArchName);
627 Modules.emplace(
ModuleName, std::unique_ptr<SymbolizableModule>());
628 return ObjectsOrErr.takeError();
630 ObjectPair Objects = ObjectsOrErr.get();
632 std::unique_ptr<DIContext>
Context;
635 if (
auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
636 const codeview::DebugInfo *DebugInfo;
637 StringRef PDBFileName;
638 auto EC = CoffObject->getDebugPDBInfo(DebugInfo, PDBFileName);
639 if (!EC && DebugInfo !=
nullptr && !PDBFileName.empty()) {
641 std::unique_ptr<IPDBSession> Session;
644 Opts.UseDIA ? PDB_ReaderType::DIA : PDB_ReaderType::Native;
645 if (
auto Err =
loadDataForEXE(ReaderType, Objects.first->getFileName(),
647 Modules.emplace(
ModuleName, std::unique_ptr<SymbolizableModule>());
662 BinaryForPath.find(BinaryName)->second.pushEvictor([
this,
I]() {
669 Expected<SymbolizableModule *>
670 LLVMSymbolizer::getOrCreateModuleInfo(
const ObjectFile &Obj) {
671 StringRef ObjName = Obj.getFileName();
672 auto I = Modules.find(ObjName);
673 if (
I != Modules.end())
674 return I->second.get();
681 Expected<SymbolizableModule *>
682 LLVMSymbolizer::getOrCreateModuleInfo(ArrayRef<uint8_t>
BuildID) {
684 if (!getOrFindDebugBinary(
BuildID, Path)) {
686 Twine(
"could not find build ID '") +
689 return getOrCreateModuleInfo(Path);
700 StringRef demanglePE32ExternCFunc(StringRef
SymbolName) {
703 if (Front ==
'_' || Front ==
'@')
730 if (!
Name.empty() &&
Name.front() ==
'?') {
734 Name.c_str(),
nullptr,
nullptr,
nullptr, &
status,
739 Result = DemangledName;
744 if (DbiModuleDescriptor && DbiModuleDescriptor->
isWin32Module())
745 return std::string(demanglePE32ExternCFunc(
Name));
750 if (
Bin->getBinary())
751 LRUBinaries.splice(LRUBinaries.end(), LRUBinaries,
Bin.getIterator());
758 while (CacheSize > Opts.
MaxCacheSize && !LRUBinaries.empty() &&
759 std::next(LRUBinaries.begin()) != LRUBinaries.end()) {
761 CacheSize -=
Bin.size();
762 LRUBinaries.pop_front();
769 this->Evictor = [OldEvictor =
std::move(this->Evictor),