DIPrinter.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. //===- lib/DebugInfo/Symbolize/DIPrinter.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. // This file defines the DIPrinter class, which is responsible for printing
  10. // structures defined in DebugInfo/DIContext.h
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/DebugInfo/Symbolize/DIPrinter.h"
  14. #include "llvm/ADT/StringRef.h"
  15. #include "llvm/DebugInfo/DIContext.h"
  16. #include "llvm/Support/ErrorOr.h"
  17. #include "llvm/Support/Format.h"
  18. #include "llvm/Support/LineIterator.h"
  19. #include "llvm/Support/MemoryBuffer.h"
  20. #include "llvm/Support/Path.h"
  21. #include "llvm/Support/raw_ostream.h"
  22. #include <algorithm>
  23. #include <cmath>
  24. #include <cstddef>
  25. #include <cstdint>
  26. #include <memory>
  27. #include <string>
  28. namespace llvm {
  29. namespace symbolize {
  30. // Prints source code around in the FileName the Line.
  31. void DIPrinter::printContext(const std::string &FileName, int64_t Line) {
  32. if (PrintSourceContext <= 0)
  33. return;
  34. ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
  35. MemoryBuffer::getFile(FileName);
  36. if (!BufOrErr)
  37. return;
  38. std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
  39. int64_t FirstLine =
  40. std::max(static_cast<int64_t>(1), Line - PrintSourceContext / 2);
  41. int64_t LastLine = FirstLine + PrintSourceContext;
  42. size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
  43. for (line_iterator I = line_iterator(*Buf, false);
  44. !I.is_at_eof() && I.line_number() <= LastLine; ++I) {
  45. int64_t L = I.line_number();
  46. if (L >= FirstLine && L <= LastLine) {
  47. OS << format_decimal(L, MaxLineNumberWidth);
  48. if (L == Line)
  49. OS << " >: ";
  50. else
  51. OS << " : ";
  52. OS << *I << "\n";
  53. }
  54. }
  55. }
  56. void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
  57. if (PrintFunctionNames) {
  58. std::string FunctionName = Info.FunctionName;
  59. if (FunctionName == DILineInfo::BadString)
  60. FunctionName = DILineInfo::Addr2LineBadString;
  61. StringRef Delimiter = PrintPretty ? " at " : "\n";
  62. StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : "";
  63. OS << Prefix << FunctionName << Delimiter;
  64. }
  65. std::string Filename = Info.FileName;
  66. if (Filename == DILineInfo::BadString)
  67. Filename = DILineInfo::Addr2LineBadString;
  68. if (!Verbose) {
  69. OS << Filename << ":" << Info.Line;
  70. if (Style == OutputStyle::LLVM)
  71. OS << ":" << Info.Column;
  72. else if (Style == OutputStyle::GNU && Info.Discriminator != 0)
  73. OS << " (discriminator " << Info.Discriminator << ")";
  74. OS << "\n";
  75. printContext(Filename, Info.Line);
  76. return;
  77. }
  78. OS << " Filename: " << Filename << "\n";
  79. if (Info.StartLine) {
  80. OS << " Function start filename: " << Info.StartFileName << "\n";
  81. OS << " Function start line: " << Info.StartLine << "\n";
  82. }
  83. OS << " Line: " << Info.Line << "\n";
  84. OS << " Column: " << Info.Column << "\n";
  85. if (Info.Discriminator)
  86. OS << " Discriminator: " << Info.Discriminator << "\n";
  87. }
  88. DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
  89. print(Info, false);
  90. return *this;
  91. }
  92. DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
  93. uint32_t FramesNum = Info.getNumberOfFrames();
  94. if (FramesNum == 0) {
  95. print(DILineInfo(), false);
  96. return *this;
  97. }
  98. for (uint32_t i = 0; i < FramesNum; i++)
  99. print(Info.getFrame(i), i > 0);
  100. return *this;
  101. }
  102. DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
  103. std::string Name = Global.Name;
  104. if (Name == DILineInfo::BadString)
  105. Name = DILineInfo::Addr2LineBadString;
  106. OS << Name << "\n";
  107. OS << Global.Start << " " << Global.Size << "\n";
  108. return *this;
  109. }
  110. DIPrinter &DIPrinter::operator<<(const DILocal &Local) {
  111. if (Local.FunctionName.empty())
  112. OS << "??\n";
  113. else
  114. OS << Local.FunctionName << '\n';
  115. if (Local.Name.empty())
  116. OS << "??\n";
  117. else
  118. OS << Local.Name << '\n';
  119. if (Local.DeclFile.empty())
  120. OS << "??";
  121. else
  122. OS << Local.DeclFile;
  123. OS << ':' << Local.DeclLine << '\n';
  124. if (Local.FrameOffset)
  125. OS << *Local.FrameOffset << ' ';
  126. else
  127. OS << "?? ";
  128. if (Local.Size)
  129. OS << *Local.Size << ' ';
  130. else
  131. OS << "?? ";
  132. if (Local.TagOffset)
  133. OS << *Local.TagOffset << '\n';
  134. else
  135. OS << "??\n";
  136. return *this;
  137. }
  138. } // end namespace symbolize
  139. } // end namespace llvm