PrettyFunctionDumper.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. //===- PrettyFunctionDumper.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 "PrettyFunctionDumper.h"
  9. #include "PrettyBuiltinDumper.h"
  10. #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
  11. #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
  12. #include "llvm/DebugInfo/PDB/IPDBSession.h"
  13. #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
  14. #include "llvm/DebugInfo/PDB/PDBExtras.h"
  15. #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
  16. #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
  17. #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
  18. #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
  19. #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
  20. #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
  21. #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
  22. #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
  23. #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
  24. #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
  25. #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
  26. #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
  27. #include "llvm/Support/Format.h"
  28. #include "llvm/Support/FormatVariadic.h"
  29. using namespace llvm;
  30. using namespace llvm::codeview;
  31. using namespace llvm::pdb;
  32. namespace {
  33. template <class T>
  34. void dumpClassParentWithScopeOperator(const T &Symbol, LinePrinter &Printer,
  35. FunctionDumper &Dumper) {
  36. uint32_t ClassParentId = Symbol.getClassParentId();
  37. auto ClassParent =
  38. Symbol.getSession().template getConcreteSymbolById<PDBSymbolTypeUDT>(
  39. ClassParentId);
  40. if (!ClassParent)
  41. return;
  42. WithColor(Printer, PDB_ColorItem::Type).get() << ClassParent->getName();
  43. Printer << "::";
  44. }
  45. }
  46. FunctionDumper::FunctionDumper(LinePrinter &P)
  47. : PDBSymDumper(true), Printer(P) {}
  48. void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol,
  49. const char *Name, PointerType Pointer) {
  50. auto ReturnType = Symbol.getReturnType();
  51. if (!ReturnType)
  52. Printer << "<unknown-type>";
  53. else
  54. ReturnType->dump(*this);
  55. Printer << " ";
  56. uint32_t ClassParentId = Symbol.getClassParentId();
  57. auto ClassParent =
  58. Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
  59. ClassParentId);
  60. PDB_CallingConv CC = Symbol.getCallingConvention();
  61. bool ShouldDumpCallingConvention = true;
  62. if ((ClassParent && CC == CallingConvention::ThisCall) ||
  63. (!ClassParent && CC == CallingConvention::NearStdCall)) {
  64. ShouldDumpCallingConvention = false;
  65. }
  66. if (Pointer == PointerType::None) {
  67. if (ShouldDumpCallingConvention)
  68. WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
  69. if (ClassParent) {
  70. Printer << "(";
  71. WithColor(Printer, PDB_ColorItem::Identifier).get()
  72. << ClassParent->getName();
  73. Printer << "::)";
  74. }
  75. } else {
  76. Printer << "(";
  77. if (ShouldDumpCallingConvention)
  78. WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
  79. if (ClassParent) {
  80. WithColor(Printer, PDB_ColorItem::Identifier).get()
  81. << ClassParent->getName();
  82. Printer << "::";
  83. }
  84. if (Pointer == PointerType::Reference)
  85. Printer << "&";
  86. else
  87. Printer << "*";
  88. if (Name)
  89. WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
  90. Printer << ")";
  91. }
  92. Printer << "(";
  93. if (auto ChildEnum = Symbol.getArguments()) {
  94. uint32_t Index = 0;
  95. while (auto Arg = ChildEnum->getNext()) {
  96. Arg->dump(*this);
  97. if (++Index < ChildEnum->getChildCount())
  98. Printer << ", ";
  99. }
  100. }
  101. Printer << ")";
  102. if (Symbol.isConstType())
  103. WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
  104. if (Symbol.isVolatileType())
  105. WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
  106. }
  107. void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) {
  108. uint64_t FuncStart = Symbol.getVirtualAddress();
  109. uint64_t FuncEnd = FuncStart + Symbol.getLength();
  110. Printer << "func [";
  111. WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10);
  112. if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) {
  113. uint64_t Prologue = DebugStart->getVirtualAddress() - FuncStart;
  114. WithColor(Printer, PDB_ColorItem::Offset).get()
  115. << formatv("+{0,2}", Prologue);
  116. }
  117. Printer << " - ";
  118. WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10);
  119. if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) {
  120. uint64_t Epilogue = FuncEnd - DebugEnd->getVirtualAddress();
  121. WithColor(Printer, PDB_ColorItem::Offset).get()
  122. << formatv("-{0,2}", Epilogue);
  123. }
  124. WithColor(Printer, PDB_ColorItem::Comment).get()
  125. << formatv(" | sizeof={0,3}", Symbol.getLength());
  126. Printer << "] (";
  127. if (Symbol.hasFramePointer()) {
  128. WithColor(Printer, PDB_ColorItem::Register).get()
  129. << CPURegister{Symbol.getRawSymbol().getPlatform(),
  130. Symbol.getLocalBasePointerRegisterId()};
  131. } else {
  132. WithColor(Printer, PDB_ColorItem::Register).get() << "FPO";
  133. }
  134. Printer << ") ";
  135. if (Symbol.isVirtual() || Symbol.isPureVirtual())
  136. WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual ";
  137. auto Signature = Symbol.getSignature();
  138. if (!Signature) {
  139. WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
  140. if (Pointer == PointerType::Pointer)
  141. Printer << "*";
  142. else if (Pointer == FunctionDumper::PointerType::Reference)
  143. Printer << "&";
  144. return;
  145. }
  146. auto ReturnType = Signature->getReturnType();
  147. ReturnType->dump(*this);
  148. Printer << " ";
  149. auto ClassParent = Symbol.getClassParent();
  150. CallingConvention CC = Signature->getCallingConvention();
  151. if (Pointer != FunctionDumper::PointerType::None)
  152. Printer << "(";
  153. if ((ClassParent && CC != CallingConvention::ThisCall) ||
  154. (!ClassParent && CC != CallingConvention::NearStdCall)) {
  155. WithColor(Printer, PDB_ColorItem::Keyword).get()
  156. << Signature->getCallingConvention() << " ";
  157. }
  158. WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
  159. if (Pointer != FunctionDumper::PointerType::None) {
  160. if (Pointer == PointerType::Pointer)
  161. Printer << "*";
  162. else if (Pointer == FunctionDumper::PointerType::Reference)
  163. Printer << "&";
  164. Printer << ")";
  165. }
  166. Printer << "(";
  167. if (auto Arguments = Symbol.getArguments()) {
  168. uint32_t Index = 0;
  169. while (auto Arg = Arguments->getNext()) {
  170. auto ArgType = Arg->getType();
  171. ArgType->dump(*this);
  172. WithColor(Printer, PDB_ColorItem::Identifier).get() << " "
  173. << Arg->getName();
  174. if (++Index < Arguments->getChildCount())
  175. Printer << ", ";
  176. }
  177. if (Signature->isCVarArgs())
  178. Printer << ", ...";
  179. }
  180. Printer << ")";
  181. if (Symbol.isConstType())
  182. WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
  183. if (Symbol.isVolatileType())
  184. WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
  185. if (Symbol.isPureVirtual())
  186. Printer << " = 0";
  187. }
  188. void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol) {
  189. auto ElementType = Symbol.getElementType();
  190. ElementType->dump(*this);
  191. Printer << "[";
  192. WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getLength();
  193. Printer << "]";
  194. }
  195. void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
  196. BuiltinDumper Dumper(Printer);
  197. Dumper.start(Symbol);
  198. }
  199. void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol) {
  200. dumpClassParentWithScopeOperator(Symbol, Printer, *this);
  201. WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
  202. }
  203. void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) {
  204. // PDBSymbolTypeFunctionArg is just a shim over the real argument. Just drill
  205. // through to the real thing and dump it.
  206. uint32_t TypeId = Symbol.getTypeId();
  207. auto Type = Symbol.getSession().getSymbolById(TypeId);
  208. if (Type)
  209. Type->dump(*this);
  210. else
  211. Printer << "<unknown-type>";
  212. }
  213. void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
  214. dumpClassParentWithScopeOperator(Symbol, Printer, *this);
  215. WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
  216. }
  217. void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) {
  218. auto PointeeType = Symbol.getPointeeType();
  219. if (!PointeeType)
  220. return;
  221. if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {
  222. FunctionDumper NestedDumper(Printer);
  223. PointerType Pointer =
  224. Symbol.isReference() ? PointerType::Reference : PointerType::Pointer;
  225. NestedDumper.start(*FuncSig, nullptr, Pointer);
  226. } else {
  227. if (Symbol.isConstType())
  228. WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
  229. if (Symbol.isVolatileType())
  230. WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
  231. PointeeType->dump(*this);
  232. Printer << (Symbol.isReference() ? "&" : "*");
  233. if (Symbol.getRawSymbol().isRestrictedType())
  234. WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict";
  235. }
  236. }
  237. void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol) {
  238. WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
  239. }