LLVM  16.0.0git
Symbolize.cpp
Go to the documentation of this file.
1 //===-- LLVMSymbolize.cpp -------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Implementation for LLVM symbolization library.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 
15 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/DebugInfo/PDB/PDB.h"
20 #include "llvm/Demangle/Demangle.h"
21 #include "llvm/Object/BuildID.h"
22 #include "llvm/Object/COFF.h"
24 #include "llvm/Object/MachO.h"
26 #include "llvm/Support/CRC.h"
27 #include "llvm/Support/Casting.h"
29 #include "llvm/Support/Errc.h"
32 #include "llvm/Support/Path.h"
33 #include <algorithm>
34 #include <cassert>
35 #include <cstring>
36 
37 namespace llvm {
38 namespace codeview {
39 union DebugInfo;
40 }
41 namespace symbolize {
42 
44 
46  : Opts(Opts),
47  BIDFetcher(std::make_unique<BuildIDFetcher>(Opts.DebugFileDirectory)) {}
48 
50 
51 template <typename T>
53 LLVMSymbolizer::symbolizeCodeCommon(const T &ModuleSpecifier,
54  object::SectionedAddress ModuleOffset) {
55 
56  auto InfoOrErr = getOrCreateModuleInfo(ModuleSpecifier);
57  if (!InfoOrErr)
58  return InfoOrErr.takeError();
59 
60  SymbolizableModule *Info = *InfoOrErr;
61 
62  // A null module means an error has already been reported. Return an empty
63  // result.
64  if (!Info)
65  return DILineInfo();
66 
67  // If the user is giving us relative addresses, add the preferred base of the
68  // object to the offset before we do the query. It's what DIContext expects.
69  if (Opts.RelativeAddresses)
70  ModuleOffset.Address += Info->getModulePreferredBase();
71 
72  DILineInfo LineInfo = Info->symbolizeCode(
73  ModuleOffset, DILineInfoSpecifier(Opts.PathStyle, Opts.PrintFunctions),
74  Opts.UseSymbolTable);
75  if (Opts.Demangle)
76  LineInfo.FunctionName = DemangleName(LineInfo.FunctionName, Info);
77  return LineInfo;
78 }
79 
82  object::SectionedAddress ModuleOffset) {
83  return symbolizeCodeCommon(Obj, ModuleOffset);
84 }
85 
88  object::SectionedAddress ModuleOffset) {
89  return symbolizeCodeCommon(ModuleName, ModuleOffset);
90 }
91 
94  object::SectionedAddress ModuleOffset) {
95  return symbolizeCodeCommon(BuildID, ModuleOffset);
96 }
97 
98 template <typename T>
99 Expected<DIInliningInfo> LLVMSymbolizer::symbolizeInlinedCodeCommon(
100  const T &ModuleSpecifier, object::SectionedAddress ModuleOffset) {
101  auto InfoOrErr = getOrCreateModuleInfo(ModuleSpecifier);
102  if (!InfoOrErr)
103  return InfoOrErr.takeError();
104 
105  SymbolizableModule *Info = *InfoOrErr;
106 
107  // A null module means an error has already been reported. Return an empty
108  // result.
109  if (!Info)
110  return DIInliningInfo();
111 
112  // If the user is giving us relative addresses, add the preferred base of the
113  // object to the offset before we do the query. It's what DIContext expects.
114  if (Opts.RelativeAddresses)
115  ModuleOffset.Address += Info->getModulePreferredBase();
116 
117  DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(
118  ModuleOffset, DILineInfoSpecifier(Opts.PathStyle, Opts.PrintFunctions),
119  Opts.UseSymbolTable);
120  if (Opts.Demangle) {
121  for (int i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) {
122  auto *Frame = InlinedContext.getMutableFrame(i);
123  Frame->FunctionName = DemangleName(Frame->FunctionName, Info);
124  }
125  }
126  return InlinedContext;
127 }
128 
129 Expected<DIInliningInfo>
131  object::SectionedAddress ModuleOffset) {
132  return symbolizeInlinedCodeCommon(Obj, ModuleOffset);
133 }
134 
137  object::SectionedAddress ModuleOffset) {
138  return symbolizeInlinedCodeCommon(ModuleName, ModuleOffset);
139 }
140 
143  object::SectionedAddress ModuleOffset) {
144  return symbolizeInlinedCodeCommon(BuildID, ModuleOffset);
145 }
146 
147 template <typename T>
149 LLVMSymbolizer::symbolizeDataCommon(const T &ModuleSpecifier,
150  object::SectionedAddress ModuleOffset) {
151 
152  auto InfoOrErr = getOrCreateModuleInfo(ModuleSpecifier);
153  if (!InfoOrErr)
154  return InfoOrErr.takeError();
155 
156  SymbolizableModule *Info = *InfoOrErr;
157  // A null module means an error has already been reported. Return an empty
158  // result.
159  if (!Info)
160  return DIGlobal();
161 
162  // If the user is giving us relative addresses, add the preferred base of
163  // the object to the offset before we do the query. It's what DIContext
164  // expects.
165  if (Opts.RelativeAddresses)
166  ModuleOffset.Address += Info->getModulePreferredBase();
167 
168  DIGlobal Global = Info->symbolizeData(ModuleOffset);
169  if (Opts.Demangle)
170  Global.Name = DemangleName(Global.Name, Info);
171  return Global;
172 }
173 
176  object::SectionedAddress ModuleOffset) {
177  return symbolizeDataCommon(Obj, ModuleOffset);
178 }
179 
182  object::SectionedAddress ModuleOffset) {
183  return symbolizeDataCommon(ModuleName, ModuleOffset);
184 }
185 
188  object::SectionedAddress ModuleOffset) {
189  return symbolizeDataCommon(BuildID, ModuleOffset);
190 }
191 
192 template <typename T>
194 LLVMSymbolizer::symbolizeFrameCommon(const T &ModuleSpecifier,
195  object::SectionedAddress ModuleOffset) {
196  auto InfoOrErr = getOrCreateModuleInfo(ModuleSpecifier);
197  if (!InfoOrErr)
198  return InfoOrErr.takeError();
199 
200  SymbolizableModule *Info = *InfoOrErr;
201  // A null module means an error has already been reported. Return an empty
202  // result.
203  if (!Info)
204  return std::vector<DILocal>();
205 
206  // If the user is giving us relative addresses, add the preferred base of
207  // the object to the offset before we do the query. It's what DIContext
208  // expects.
209  if (Opts.RelativeAddresses)
210  ModuleOffset.Address += Info->getModulePreferredBase();
211 
212  return Info->symbolizeFrame(ModuleOffset);
213 }
214 
217  object::SectionedAddress ModuleOffset) {
218  return symbolizeFrameCommon(Obj, ModuleOffset);
219 }
220 
223  object::SectionedAddress ModuleOffset) {
224  return symbolizeFrameCommon(ModuleName, ModuleOffset);
225 }
226 
229  object::SectionedAddress ModuleOffset) {
230  return symbolizeFrameCommon(BuildID, ModuleOffset);
231 }
232 
234  ObjectForUBPathAndArch.clear();
235  LRUBinaries.clear();
236  CacheSize = 0;
237  BinaryForPath.clear();
238  ObjectPairForPathArch.clear();
239  Modules.clear();
240  BuildIDPaths.clear();
241 }
242 
243 namespace {
244 
245 // For Path="/path/to/foo" and Basename="foo" assume that debug info is in
246 // /path/to/foo.dSYM/Contents/Resources/DWARF/foo.
247 // For Path="/path/to/bar.dSYM" and Basename="foo" assume that debug info is in
248 // /path/to/bar.dSYM/Contents/Resources/DWARF/foo.
249 std::string getDarwinDWARFResourceForPath(const std::string &Path,
250  const std::string &Basename) {
251  SmallString<16> ResourceName = StringRef(Path);
252  if (sys::path::extension(Path) != ".dSYM") {
253  ResourceName += ".dSYM";
254  }
255  sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
256  sys::path::append(ResourceName, Basename);
257  return std::string(ResourceName.str());
258 }
259 
260 bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
261  ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
263  if (!MB)
264  return false;
265  return CRCHash == llvm::crc32(arrayRefFromStringRef(MB.get()->getBuffer()));
266 }
267 
268 bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName,
269  uint32_t &CRCHash) {
270  if (!Obj)
271  return false;
272  for (const SectionRef &Section : Obj->sections()) {
273  StringRef Name;
274  consumeError(Section.getName().moveInto(Name));
275 
276  Name = Name.substr(Name.find_first_not_of("._"));
277  if (Name == "gnu_debuglink") {
278  Expected<StringRef> ContentsOrErr = Section.getContents();
279  if (!ContentsOrErr) {
280  consumeError(ContentsOrErr.takeError());
281  return false;
282  }
283  DataExtractor DE(*ContentsOrErr, Obj->isLittleEndian(), 0);
284  uint64_t Offset = 0;
285  if (const char *DebugNameStr = DE.getCStr(&Offset)) {
286  // 4-byte align the offset.
287  Offset = (Offset + 3) & ~0x3;
288  if (DE.isValidOffsetForDataOfSize(Offset, 4)) {
289  DebugName = DebugNameStr;
290  CRCHash = DE.getU32(&Offset);
291  return true;
292  }
293  }
294  break;
295  }
296  }
297  return false;
298 }
299 
300 bool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj,
301  const MachOObjectFile *Obj) {
302  ArrayRef<uint8_t> dbg_uuid = DbgObj->getUuid();
303  ArrayRef<uint8_t> bin_uuid = Obj->getUuid();
304  if (dbg_uuid.empty() || bin_uuid.empty())
305  return false;
306  return !memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size());
307 }
308 
309 } // end anonymous namespace
310 
311 ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath,
312  const MachOObjectFile *MachExeObj,
313  const std::string &ArchName) {
314  // On Darwin we may find DWARF in separate object file in
315  // resource directory.
316  std::vector<std::string> DsymPaths;
317  StringRef Filename = sys::path::filename(ExePath);
318  DsymPaths.push_back(
319  getDarwinDWARFResourceForPath(ExePath, std::string(Filename)));
320  for (const auto &Path : Opts.DsymHints) {
321  DsymPaths.push_back(
322  getDarwinDWARFResourceForPath(Path, std::string(Filename)));
323  }
324  for (const auto &Path : DsymPaths) {
325  auto DbgObjOrErr = getOrCreateObject(Path, ArchName);
326  if (!DbgObjOrErr) {
327  // Ignore errors, the file might not exist.
328  consumeError(DbgObjOrErr.takeError());
329  continue;
330  }
331  ObjectFile *DbgObj = DbgObjOrErr.get();
332  if (!DbgObj)
333  continue;
334  const MachOObjectFile *MachDbgObj = dyn_cast<const MachOObjectFile>(DbgObj);
335  if (!MachDbgObj)
336  continue;
337  if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj))
338  return DbgObj;
339  }
340  return nullptr;
341 }
342 
343 ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(const std::string &Path,
344  const ObjectFile *Obj,
345  const std::string &ArchName) {
346  std::string DebuglinkName;
347  uint32_t CRCHash;
348  std::string DebugBinaryPath;
349  if (!getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash))
350  return nullptr;
351  if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath))
352  return nullptr;
353  auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
354  if (!DbgObjOrErr) {
355  // Ignore errors, the file might not exist.
356  consumeError(DbgObjOrErr.takeError());
357  return nullptr;
358  }
359  return DbgObjOrErr.get();
360 }
361 
362 ObjectFile *LLVMSymbolizer::lookUpBuildIDObject(const std::string &Path,
363  const ELFObjectFileBase *Obj,
364  const std::string &ArchName) {
365  auto BuildID = getBuildID(Obj);
366  if (!BuildID)
367  return nullptr;
368  if (BuildID->size() < 2)
369  return nullptr;
370  std::string DebugBinaryPath;
371  if (!getOrFindDebugBinary(*BuildID, DebugBinaryPath))
372  return nullptr;
373  auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
374  if (!DbgObjOrErr) {
375  consumeError(DbgObjOrErr.takeError());
376  return nullptr;
377  }
378  return DbgObjOrErr.get();
379 }
380 
381 bool LLVMSymbolizer::findDebugBinary(const std::string &OrigPath,
382  const std::string &DebuglinkName,
383  uint32_t CRCHash, std::string &Result) {
384  SmallString<16> OrigDir(OrigPath);
386  SmallString<16> DebugPath = OrigDir;
387  // Try relative/path/to/original_binary/debuglink_name
388  llvm::sys::path::append(DebugPath, DebuglinkName);
389  if (checkFileCRC(DebugPath, CRCHash)) {
390  Result = std::string(DebugPath.str());
391  return true;
392  }
393  // Try relative/path/to/original_binary/.debug/debuglink_name
394  DebugPath = OrigDir;
395  llvm::sys::path::append(DebugPath, ".debug", DebuglinkName);
396  if (checkFileCRC(DebugPath, CRCHash)) {
397  Result = std::string(DebugPath.str());
398  return true;
399  }
400  // Make the path absolute so that lookups will go to
401  // "/usr/lib/debug/full/path/to/debug", not
402  // "/usr/lib/debug/to/debug"
404  if (!Opts.FallbackDebugPath.empty()) {
405  // Try <FallbackDebugPath>/absolute/path/to/original_binary/debuglink_name
406  DebugPath = Opts.FallbackDebugPath;
407  } else {
408 #if defined(__NetBSD__)
409  // Try /usr/libdata/debug/absolute/path/to/original_binary/debuglink_name
410  DebugPath = "/usr/libdata/debug";
411 #else
412  // Try /usr/lib/debug/absolute/path/to/original_binary/debuglink_name
413  DebugPath = "/usr/lib/debug";
414 #endif
415  }
417  DebuglinkName);
418  if (checkFileCRC(DebugPath, CRCHash)) {
419  Result = std::string(DebugPath.str());
420  return true;
421  }
422  return false;
423 }
424 
426  return StringRef(reinterpret_cast<const char *>(BuildID.data()),
427  BuildID.size());
428 }
429 
430 bool LLVMSymbolizer::getOrFindDebugBinary(const ArrayRef<uint8_t> BuildID,
431  std::string &Result) {
432  StringRef BuildIDStr = getBuildIDStr(BuildID);
433  auto I = BuildIDPaths.find(BuildIDStr);
434  if (I != BuildIDPaths.end()) {
435  Result = I->second;
436  return true;
437  }
438  if (!BIDFetcher)
439  return false;
440  if (Optional<std::string> Path = BIDFetcher->fetch(BuildID)) {
441  Result = *Path;
442  auto InsertResult = BuildIDPaths.insert({BuildIDStr, Result});
443  assert(InsertResult.second);
444  (void)InsertResult;
445  return true;
446  }
447 
448  return false;
449 }
450 
451 Expected<LLVMSymbolizer::ObjectPair>
452 LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path,
453  const std::string &ArchName) {
454  auto I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
455  if (I != ObjectPairForPathArch.end()) {
456  recordAccess(BinaryForPath.find(Path)->second);
457  return I->second;
458  }
459 
460  auto ObjOrErr = getOrCreateObject(Path, ArchName);
461  if (!ObjOrErr) {
462  ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName),
463  ObjectPair(nullptr, nullptr));
464  return ObjOrErr.takeError();
465  }
466 
467  ObjectFile *Obj = ObjOrErr.get();
468  assert(Obj != nullptr);
469  ObjectFile *DbgObj = nullptr;
470 
471  if (auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
472  DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
473  else if (auto ELFObj = dyn_cast<const ELFObjectFileBase>(Obj))
474  DbgObj = lookUpBuildIDObject(Path, ELFObj, ArchName);
475  if (!DbgObj)
476  DbgObj = lookUpDebuglinkObject(Path, Obj, ArchName);
477  if (!DbgObj)
478  DbgObj = Obj;
479  ObjectPair Res = std::make_pair(Obj, DbgObj);
480  std::string DbgObjPath = DbgObj->getFileName().str();
481  auto Pair =
482  ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName), Res);
483  BinaryForPath.find(DbgObjPath)->second.pushEvictor([this, I = Pair.first]() {
484  ObjectPairForPathArch.erase(I);
485  });
486  return Res;
487 }
488 
489 Expected<ObjectFile *>
490 LLVMSymbolizer::getOrCreateObject(const std::string &Path,
491  const std::string &ArchName) {
492  Binary *Bin;
493  auto Pair = BinaryForPath.emplace(Path, OwningBinary<Binary>());
494  if (!Pair.second) {
495  Bin = Pair.first->second->getBinary();
496  recordAccess(Pair.first->second);
497  } else {
498  Expected<OwningBinary<Binary>> BinOrErr = createBinary(Path);
499  if (!BinOrErr)
500  return BinOrErr.takeError();
501 
502  CachedBinary &CachedBin = Pair.first->second;
503  CachedBin = std::move(BinOrErr.get());
504  CachedBin.pushEvictor([this, I = Pair.first]() { BinaryForPath.erase(I); });
505  LRUBinaries.push_back(CachedBin);
506  CacheSize += CachedBin.size();
507  Bin = CachedBin->getBinary();
508  }
509 
510  if (!Bin)
511  return static_cast<ObjectFile *>(nullptr);
512 
513  if (MachOUniversalBinary *UB = dyn_cast_or_null<MachOUniversalBinary>(Bin)) {
514  auto I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName));
515  if (I != ObjectForUBPathAndArch.end())
516  return I->second.get();
517 
518  Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
519  UB->getMachOObjectForArch(ArchName);
520  if (!ObjOrErr) {
521  ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
522  std::unique_ptr<ObjectFile>());
523  return ObjOrErr.takeError();
524  }
525  ObjectFile *Res = ObjOrErr->get();
526  auto Pair = ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
527  std::move(ObjOrErr.get()));
528  BinaryForPath.find(Path)->second.pushEvictor(
529  [this, Iter = Pair.first]() { ObjectForUBPathAndArch.erase(Iter); });
530  return Res;
531  }
532  if (Bin->isObject()) {
533  return cast<ObjectFile>(Bin);
534  }
535  return errorCodeToError(object_error::arch_not_found);
536 }
537 
538 Expected<SymbolizableModule *>
539 LLVMSymbolizer::createModuleInfo(const ObjectFile *Obj,
540  std::unique_ptr<DIContext> Context,
541  StringRef ModuleName) {
542  auto InfoOrErr = SymbolizableObjectFile::create(Obj, std::move(Context),
543  Opts.UntagAddresses);
544  std::unique_ptr<SymbolizableModule> SymMod;
545  if (InfoOrErr)
546  SymMod = std::move(*InfoOrErr);
547  auto InsertResult = Modules.insert(
548  std::make_pair(std::string(ModuleName), std::move(SymMod)));
549  assert(InsertResult.second);
550  if (!InfoOrErr)
551  return InfoOrErr.takeError();
552  return InsertResult.first->second.get();
553 }
554 
555 Expected<SymbolizableModule *>
556 LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
557  std::string BinaryName = ModuleName;
558  std::string ArchName = Opts.DefaultArch;
559  size_t ColonPos = ModuleName.find_last_of(':');
560  // Verify that substring after colon form a valid arch name.
561  if (ColonPos != std::string::npos) {
562  std::string ArchStr = ModuleName.substr(ColonPos + 1);
563  if (Triple(ArchStr).getArch() != Triple::UnknownArch) {
564  BinaryName = ModuleName.substr(0, ColonPos);
565  ArchName = ArchStr;
566  }
567  }
568 
569  auto I = Modules.find(ModuleName);
570  if (I != Modules.end()) {
571  recordAccess(BinaryForPath.find(BinaryName)->second);
572  return I->second.get();
573  }
574 
575  auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, ArchName);
576  if (!ObjectsOrErr) {
577  // Failed to find valid object file.
578  Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>());
579  return ObjectsOrErr.takeError();
580  }
581  ObjectPair Objects = ObjectsOrErr.get();
582 
583  std::unique_ptr<DIContext> Context;
584  // If this is a COFF object containing PDB info, use a PDBContext to
585  // symbolize. Otherwise, use DWARF.
586  if (auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
587  const codeview::DebugInfo *DebugInfo;
588  StringRef PDBFileName;
589  auto EC = CoffObject->getDebugPDBInfo(DebugInfo, PDBFileName);
590  if (!EC && DebugInfo != nullptr && !PDBFileName.empty()) {
591  using namespace pdb;
592  std::unique_ptr<IPDBSession> Session;
593 
594  PDB_ReaderType ReaderType =
595  Opts.UseDIA ? PDB_ReaderType::DIA : PDB_ReaderType::Native;
596  if (auto Err = loadDataForEXE(ReaderType, Objects.first->getFileName(),
597  Session)) {
598  Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>());
599  // Return along the PDB filename to provide more context
600  return createFileError(PDBFileName, std::move(Err));
601  }
602  Context.reset(new PDBContext(*CoffObject, std::move(Session)));
603  }
604  }
605  if (!Context)
608  nullptr, Opts.DWPName);
609  auto ModuleOrErr =
610  createModuleInfo(Objects.first, std::move(Context), ModuleName);
611  if (ModuleOrErr) {
612  auto I = Modules.find(ModuleName);
613  BinaryForPath.find(BinaryName)->second.pushEvictor([this, I]() {
614  Modules.erase(I);
615  });
616  }
617  return ModuleOrErr;
618 }
619 
620 Expected<SymbolizableModule *>
621 LLVMSymbolizer::getOrCreateModuleInfo(const ObjectFile &Obj) {
622  StringRef ObjName = Obj.getFileName();
623  auto I = Modules.find(ObjName);
624  if (I != Modules.end())
625  return I->second.get();
626 
627  std::unique_ptr<DIContext> Context = DWARFContext::create(Obj);
628  // FIXME: handle COFF object with PDB info to use PDBContext
629  return createModuleInfo(&Obj, std::move(Context), ObjName);
630 }
631 
632 Expected<SymbolizableModule *>
633 LLVMSymbolizer::getOrCreateModuleInfo(ArrayRef<uint8_t> BuildID) {
634  std::string Path;
635  if (!getOrFindDebugBinary(BuildID, Path)) {
637  Twine("could not find build ID '") +
638  toHex(BuildID) + "'");
639  }
640  return getOrCreateModuleInfo(Path);
641 }
642 
643 namespace {
644 
645 // Undo these various manglings for Win32 extern "C" functions:
646 // cdecl - _foo
647 // stdcall - _foo@12
648 // fastcall - @foo@12
649 // vectorcall - foo@@12
650 // These are all different linkage names for 'foo'.
651 StringRef demanglePE32ExternCFunc(StringRef SymbolName) {
652  // Remove any '_' or '@' prefix.
653  char Front = SymbolName.empty() ? '\0' : SymbolName[0];
654  if (Front == '_' || Front == '@')
655  SymbolName = SymbolName.drop_front();
656 
657  // Remove any '@[0-9]+' suffix.
658  if (Front != '?') {
659  size_t AtPos = SymbolName.rfind('@');
660  if (AtPos != StringRef::npos &&
661  all_of(drop_begin(SymbolName, AtPos + 1), isDigit))
662  SymbolName = SymbolName.substr(0, AtPos);
663  }
664 
665  // Remove any ending '@' for vectorcall.
666  if (SymbolName.endswith("@"))
667  SymbolName = SymbolName.drop_back();
668 
669  return SymbolName;
670 }
671 
672 } // end anonymous namespace
673 
674 std::string
675 LLVMSymbolizer::DemangleName(const std::string &Name,
676  const SymbolizableModule *DbiModuleDescriptor) {
677  std::string Result;
678  if (nonMicrosoftDemangle(Name.c_str(), Result))
679  return Result;
680 
681  if (!Name.empty() && Name.front() == '?') {
682  // Only do MSVC C++ demangling on symbols starting with '?'.
683  int status = 0;
684  char *DemangledName = microsoftDemangle(
685  Name.c_str(), nullptr, nullptr, nullptr, &status,
688  if (status != 0)
689  return Name;
690  Result = DemangledName;
691  free(DemangledName);
692  return Result;
693  }
694 
695  if (DbiModuleDescriptor && DbiModuleDescriptor->isWin32Module())
696  return std::string(demanglePE32ExternCFunc(Name));
697  return Name;
698 }
699 
700 void LLVMSymbolizer::recordAccess(CachedBinary &Bin) {
701  if (Bin->getBinary())
702  LRUBinaries.splice(LRUBinaries.end(), LRUBinaries, Bin.getIterator());
703 }
704 
706  // Evict the LRU binary until the max cache size is reached or there's <= 1
707  // item in the cache. The MRU binary is always kept to avoid thrashing if it's
708  // larger than the cache size.
709  while (CacheSize > Opts.MaxCacheSize && !LRUBinaries.empty() &&
710  std::next(LRUBinaries.begin()) != LRUBinaries.end()) {
711  CachedBinary &Bin = LRUBinaries.front();
712  CacheSize -= Bin.size();
713  LRUBinaries.pop_front();
714  Bin.evict();
715  }
716 }
717 
718 void CachedBinary::pushEvictor(std::function<void()> NewEvictor) {
719  if (Evictor) {
720  this->Evictor = [OldEvictor = std::move(this->Evictor),
721  NewEvictor = std::move(NewEvictor)]() {
722  NewEvictor();
723  OldEvictor();
724  };
725  } else {
726  this->Evictor = std::move(NewEvictor);
727  }
728 }
729 
730 } // namespace symbolize
731 } // namespace llvm
i
i
Definition: README.txt:29
MemoryBuffer.h
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::drop_begin
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition: STLExtras.h:387
llvm::DWARFContext::create
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)
Definition: DWARFContext.cpp:1999
llvm::sys::path::extension
StringRef extension(StringRef path, Style style=Style::native)
Get extension.
Definition: Path.cpp:590
FileSystem.h
llvm::Triple::UnknownArch
@ UnknownArch
Definition: Triple.h:47
llvm::symbolize::LLVMSymbolizer::Options::UntagAddresses
bool UntagAddresses
Definition: Symbolize.h:58
llvm::MSDF_NoAccessSpecifier
@ MSDF_NoAccessSpecifier
Definition: Demangle.h:37
llvm::DIInliningInfo
A format-neutral container for inlined code description.
Definition: DIContext.h:87
llvm::DILineInfoSpecifier
Controls which fields of DILineInfo container should be filled with data.
Definition: DIContext.h:139
llvm::StringRef::npos
static constexpr size_t npos
Definition: StringRef.h:52
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
Path.h
llvm::symbolize::CachedBinary::pushEvictor
void pushEvictor(std::function< void()> Evictor)
Definition: Symbolize.cpp:718
llvm::object::SectionedAddress::Address
uint64_t Address
Definition: ObjectFile.h:147
llvm::object::getBuildID
Optional< BuildIDRef > getBuildID(const ObjectFile *Obj)
Returns the build ID, if any, contained in the given object file.
Definition: BuildID.cpp:48
llvm::crc32
uint32_t crc32(ArrayRef< uint8_t > Data)
Definition: CRC.cpp:101
DWARFContext.h
llvm::object::BuildIDFetcher
BuildIDFetcher searches local cache directories for debug info.
Definition: BuildID.h:36
memcmp
Merge contiguous icmps into a memcmp
Definition: MergeICmps.cpp:903
llvm::logicalview::LVAttributeKind::Filename
@ Filename
Errc.h
llvm::StringMap::end
iterator end()
Definition: StringMap.h:204
llvm::symbolize::SymbolizableObjectFile::create
static Expected< std::unique_ptr< SymbolizableObjectFile > > create(const object::ObjectFile *Obj, std::unique_ptr< DIContext > DICtx, bool UntagAddresses)
Definition: SymbolizableObjectFile.cpp:31
llvm::errc::no_such_file_or_directory
@ no_such_file_or_directory
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::symbolize::LLVMSymbolizer::flush
void flush()
Definition: Symbolize.cpp:233
STLExtras.h
llvm::StringMap::find
iterator find(StringRef Key)
Definition: StringMap.h:217
llvm::msgpack::Type::Binary
@ Binary
llvm::symbolize::LLVMSymbolizer::pruneCache
void pruneCache()
Definition: Symbolize.cpp:705
llvm::symbolize::CachedBinary
Definition: Symbolize.h:220
llvm::consumeError
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1042
llvm::DWARFContext::ProcessDebugRelocations::Process
@ Process
llvm::symbolize::LLVMSymbolizer::Options::DsymHints
std::vector< std::string > DsymHints
Definition: Symbolize.h:61
llvm::object::BuildID
SmallVector< uint8_t, 10 > BuildID
A build ID in binary form.
Definition: BuildID.h:25
MachO.h
llvm::SubDirectoryType::Bin
@ Bin
llvm::DILineInfo::FunctionName
std::string FunctionName
Definition: DIContext.h:37
llvm::symbolize::LLVMSymbolizer::symbolizeCode
Expected< DILineInfo > symbolizeCode(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
Definition: Symbolize.cpp:81
llvm::sys::path::append
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:456
SymbolizableObjectFile.h
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
llvm::ARMBuildAttrs::Section
@ Section
Legacy Tags.
Definition: ARMBuildAttributes.h:82
llvm::pdb::loadDataForEXE
Error loadDataForEXE(PDB_ReaderType Type, StringRef Path, std::unique_ptr< IPDBSession > &Session)
Definition: PDB.cpp:35
PDB.h
x3
In x86 we generate this spiffy xmm0 xmm0 ret in x86 we generate this which could be xmm1 movss xmm1 xmm0 ret In sse4 we could use insertps to make both better Here s another testcase that could use x3
Definition: README-SSE.txt:547
llvm::all_of
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1709
llvm::symbolize::LLVMSymbolizer::Options::UseSymbolTable
bool UseSymbolTable
Definition: Symbolize.h:55
llvm::symbolize::LLVMSymbolizer::symbolizeFrame
Expected< std::vector< DILocal > > symbolizeFrame(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
Definition: Symbolize.cpp:216
llvm::symbolize::LLVMSymbolizer::Options::DefaultArch
std::string DefaultArch
Definition: Symbolize.h:60
llvm::createFileError
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Definition: Error.h:1319
llvm::StringMap::insert
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition: StringMap.h:275
llvm::errorCodeToError
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:92
llvm::symbolize::getBuildIDStr
static StringRef getBuildIDStr(ArrayRef< uint8_t > BuildID)
Definition: Symbolize.cpp:425
MachOUniversal.h
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
CRC.h
llvm::StringMap::clear
void clear()
Definition: StringMap.h:348
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::symbolize::LLVMSymbolizer::Options::PrintFunctions
FunctionNameKind PrintFunctions
Definition: Symbolize.h:53
llvm::symbolize::LLVMSymbolizer::Options::RelativeAddresses
bool RelativeAddresses
Definition: Symbolize.h:57
llvm::pdb::PDB_ReaderType
PDB_ReaderType
Specifies which PDB reader implementation is to be used.
Definition: PDBTypes.h:80
llvm::pdb::PDB_ColorItem::Path
@ Path
llvm::MSDF_NoCallingConvention
@ MSDF_NoCallingConvention
Definition: Demangle.h:38
llvm::SmallString< 16 >
BuildID.h
llvm::symbolize::LLVMSymbolizer::Options::Demangle
bool Demangle
Definition: Symbolize.h:56
llvm::symbolize::LLVMSymbolizer::LLVMSymbolizer
LLVMSymbolizer()
llvm::AMDGPU::Hwreg::Offset
Offset
Definition: SIDefines.h:416
uint64_t
llvm::symbolize::SymbolizableModule
Definition: SymbolizableModule.h:23
llvm::MSDF_NoReturnType
@ MSDF_NoReturnType
Definition: Demangle.h:39
llvm::symbolize::toHex
static std::string toHex(uint64_t V)
Definition: DIPrinter.cpp:278
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::DILineInfo
A format-neutral container for source line information.
Definition: DIContext.h:31
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ModuleName
Definition: ItaniumDemangle.h:999
llvm::MemoryBuffer::getFileOrSTDIN
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, Optional< Align > Alignment=None)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
Definition: MemoryBuffer.cpp:148
llvm::codeview::CompileSym2Flags::EC
@ EC
llvm::symbolize::LLVMSymbolizer::symbolizeData
Expected< DIGlobal > symbolizeData(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
Definition: Symbolize.cpp:175
function
print Print MemDeps of function
Definition: MemDepPrinter.cpp:82
llvm::codeview::CodeViewContainer::ObjectFile
@ ObjectFile
llvm::sys::fs::make_absolute
void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
Definition: Path.cpp:906
isDigit
static bool isDigit(const char C)
Definition: RustDemangle.cpp:173
Demangle.h
llvm::ArrayRef< uint8_t >
Symbolize.h
PDBContext.h
llvm::symbolize::LLVMSymbolizer::symbolizeInlinedCode
Expected< DIInliningInfo > symbolizeInlinedCode(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
Definition: Symbolize.cpp:130
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::object::ObjectFile
This class is the base class for all object file types.
Definition: ObjectFile.h:228
llvm::MSDemangleFlags
MSDemangleFlags
Definition: Demangle.h:34
uint32_t
llvm::symbolize::LLVMSymbolizer::Options::FallbackDebugPath
std::string FallbackDebugPath
Definition: Symbolize.h:62
ELFObjectFile.h
llvm::sampleprof::InlinedContext
@ InlinedContext
Definition: SampleProf.h:442
llvm::AMDGPU::HSAMD::Kernel::Key::SymbolName
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
Definition: AMDGPUMetadata.h:386
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1238
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
std
Definition: BitVector.h:851
llvm::DIGlobal
Container for description of a global variable.
Definition: DIContext.h:113
llvm::symbolize::LLVMSymbolizer::Options::PathStyle
FileLineInfoKind PathStyle
Definition: Symbolize.h:54
Casting.h
DataExtractor.h
llvm::symbolize::LLVMSymbolizer::DemangleName
static std::string DemangleName(const std::string &Name, const SymbolizableModule *DbiModuleDescriptor)
Definition: Symbolize.cpp:675
llvm::SmallString::str
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:260
llvm::symbolize::LLVMSymbolizer::~LLVMSymbolizer
~LLVMSymbolizer()
llvm::microsoftDemangle
char * microsoftDemangle(const char *mangled_name, size_t *n_read, char *buf, size_t *n_buf, int *status, MSDemangleFlags Flags=MSDF_None)
Demangles the Microsoft symbol pointed at by mangled_name and returns it.
Definition: MicrosoftDemangle.cpp:2328
llvm::symbolize::SymbolizableModule::isWin32Module
virtual bool isWin32Module() const =0
llvm::sys::path::filename
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:577
COFF.h
llvm::symbolize::LLVMSymbolizer::Options::DWPName
std::string DWPName
Definition: Symbolize.h:63
llvm::sys::fs::status
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
llvm::object::SectionedAddress
Definition: ObjectFile.h:144
llvm::nonMicrosoftDemangle
bool nonMicrosoftDemangle(const char *MangledName, std::string &Result)
Definition: Demangle.cpp:49
llvm::object::createBinary
Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)
Create a Binary from Source, autodetecting the file type.
Definition: Binary.cpp:45
llvm::sys::path::remove_filename
void remove_filename(SmallVectorImpl< char > &path, Style style=Style::native)
Remove the last component from path unless it is the root dir.
Definition: Path.cpp:474
llvm::symbolize::LLVMSymbolizer::Options
Definition: Symbolize.h:52
llvm::sys::path::relative_path
StringRef relative_path(StringRef path, Style style=Style::native)
Get relative path.
Definition: Path.cpp:413
llvm::symbolize::LLVMSymbolizer::Options::MaxCacheSize
size_t MaxCacheSize
Definition: Symbolize.h:65
n
The same transformation can work with an even modulo with the addition of a and shrink the compare RHS by the same amount Unless the target supports that transformation probably isn t worthwhile The transformation can also easily be made to work with non zero equality for n
Definition: README.txt:685
llvm::MSDF_NoMemberType
@ MSDF_NoMemberType
Definition: Demangle.h:40