PDBContext.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. //===-- PDBContext.cpp ------------------------------------------*- C++ -*-===//
  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. #include "llvm/DebugInfo/PDB/PDBContext.h"
  9. #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
  10. #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
  11. #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
  12. #include "llvm/DebugInfo/PDB/PDBSymbol.h"
  13. #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
  14. #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
  15. #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
  16. #include "llvm/Object/COFF.h"
  17. using namespace llvm;
  18. using namespace llvm::object;
  19. using namespace llvm::pdb;
  20. PDBContext::PDBContext(const COFFObjectFile &Object,
  21. std::unique_ptr<IPDBSession> PDBSession)
  22. : DIContext(CK_PDB), Session(std::move(PDBSession)) {
  23. ErrorOr<uint64_t> ImageBase = Object.getImageBase();
  24. if (ImageBase)
  25. Session->setLoadAddress(ImageBase.get());
  26. }
  27. void PDBContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){}
  28. DILineInfo PDBContext::getLineInfoForAddress(object::SectionedAddress Address,
  29. DILineInfoSpecifier Specifier) {
  30. DILineInfo Result;
  31. Result.FunctionName = getFunctionName(Address.Address, Specifier.FNKind);
  32. uint32_t Length = 1;
  33. std::unique_ptr<PDBSymbol> Symbol =
  34. Session->findSymbolByAddress(Address.Address, PDB_SymType::None);
  35. if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(Symbol.get())) {
  36. Length = Func->getLength();
  37. } else if (auto Data = dyn_cast_or_null<PDBSymbolData>(Symbol.get())) {
  38. Length = Data->getLength();
  39. }
  40. // If we couldn't find a symbol, then just assume 1 byte, so that we get
  41. // only the line number of the first instruction.
  42. auto LineNumbers = Session->findLineNumbersByAddress(Address.Address, Length);
  43. if (!LineNumbers || LineNumbers->getChildCount() == 0)
  44. return Result;
  45. auto LineInfo = LineNumbers->getNext();
  46. assert(LineInfo);
  47. auto SourceFile = Session->getSourceFileById(LineInfo->getSourceFileId());
  48. if (SourceFile &&
  49. Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None)
  50. Result.FileName = SourceFile->getFileName();
  51. Result.Column = LineInfo->getColumnNumber();
  52. Result.Line = LineInfo->getLineNumber();
  53. return Result;
  54. }
  55. DILineInfoTable
  56. PDBContext::getLineInfoForAddressRange(object::SectionedAddress Address,
  57. uint64_t Size,
  58. DILineInfoSpecifier Specifier) {
  59. if (Size == 0)
  60. return DILineInfoTable();
  61. DILineInfoTable Table;
  62. auto LineNumbers = Session->findLineNumbersByAddress(Address.Address, Size);
  63. if (!LineNumbers || LineNumbers->getChildCount() == 0)
  64. return Table;
  65. while (auto LineInfo = LineNumbers->getNext()) {
  66. DILineInfo LineEntry = getLineInfoForAddress(
  67. {LineInfo->getVirtualAddress(), Address.SectionIndex}, Specifier);
  68. Table.push_back(std::make_pair(LineInfo->getVirtualAddress(), LineEntry));
  69. }
  70. return Table;
  71. }
  72. DIInliningInfo
  73. PDBContext::getInliningInfoForAddress(object::SectionedAddress Address,
  74. DILineInfoSpecifier Specifier) {
  75. DIInliningInfo InlineInfo;
  76. DILineInfo CurrentLine = getLineInfoForAddress(Address, Specifier);
  77. // Find the function at this address.
  78. std::unique_ptr<PDBSymbol> ParentFunc =
  79. Session->findSymbolByAddress(Address.Address, PDB_SymType::Function);
  80. if (!ParentFunc) {
  81. InlineInfo.addFrame(CurrentLine);
  82. return InlineInfo;
  83. }
  84. auto Frames = ParentFunc->findInlineFramesByVA(Address.Address);
  85. if (!Frames || Frames->getChildCount() == 0) {
  86. InlineInfo.addFrame(CurrentLine);
  87. return InlineInfo;
  88. }
  89. while (auto Frame = Frames->getNext()) {
  90. uint32_t Length = 1;
  91. auto LineNumbers = Frame->findInlineeLinesByVA(Address.Address, Length);
  92. if (!LineNumbers || LineNumbers->getChildCount() == 0)
  93. break;
  94. std::unique_ptr<IPDBLineNumber> Line = LineNumbers->getNext();
  95. assert(Line);
  96. DILineInfo LineInfo;
  97. LineInfo.FunctionName = Frame->getName();
  98. auto SourceFile = Session->getSourceFileById(Line->getSourceFileId());
  99. if (SourceFile &&
  100. Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None)
  101. LineInfo.FileName = SourceFile->getFileName();
  102. LineInfo.Line = Line->getLineNumber();
  103. LineInfo.Column = Line->getColumnNumber();
  104. InlineInfo.addFrame(LineInfo);
  105. }
  106. InlineInfo.addFrame(CurrentLine);
  107. return InlineInfo;
  108. }
  109. std::vector<DILocal>
  110. PDBContext::getLocalsForAddress(object::SectionedAddress Address) {
  111. return std::vector<DILocal>();
  112. }
  113. std::string PDBContext::getFunctionName(uint64_t Address,
  114. DINameKind NameKind) const {
  115. if (NameKind == DINameKind::None)
  116. return std::string();
  117. std::unique_ptr<PDBSymbol> FuncSymbol =
  118. Session->findSymbolByAddress(Address, PDB_SymType::Function);
  119. auto *Func = dyn_cast_or_null<PDBSymbolFunc>(FuncSymbol.get());
  120. if (NameKind == DINameKind::LinkageName) {
  121. // It is not possible to get the mangled linkage name through a
  122. // PDBSymbolFunc. For that we have to specifically request a
  123. // PDBSymbolPublicSymbol.
  124. auto PublicSym =
  125. Session->findSymbolByAddress(Address, PDB_SymType::PublicSymbol);
  126. if (auto *PS = dyn_cast_or_null<PDBSymbolPublicSymbol>(PublicSym.get())) {
  127. // If we also have a function symbol, prefer the use of public symbol name
  128. // only if it refers to the same address. The public symbol uses the
  129. // linkage name while the function does not.
  130. if (!Func || Func->getVirtualAddress() == PS->getVirtualAddress())
  131. return PS->getName();
  132. }
  133. }
  134. return Func ? Func->getName() : std::string();
  135. }