SourcePrinter.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. //===-- SourcePrinter.h - source interleaving utilities --------*- 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. #ifndef LLVM_TOOLS_LLVM_OBJDUMP_SOURCEPRINTER_H
  9. #define LLVM_TOOLS_LLVM_OBJDUMP_SOURCEPRINTER_H
  10. #include "llvm/ADT/IndexedMap.h"
  11. #include "llvm/ADT/StringSet.h"
  12. #include "llvm/DebugInfo/DWARF/DWARFContext.h"
  13. #include "llvm/DebugInfo/Symbolize/Symbolize.h"
  14. #include "llvm/MC/MCRegisterInfo.h"
  15. #include "llvm/MC/MCSubtargetInfo.h"
  16. #include "llvm/Support/FormattedStream.h"
  17. #include <unordered_map>
  18. #include <vector>
  19. namespace llvm {
  20. namespace objdump {
  21. /// Stores a single expression representing the location of a source-level
  22. /// variable, along with the PC range for which that expression is valid.
  23. struct LiveVariable {
  24. DWARFLocationExpression LocExpr;
  25. const char *VarName;
  26. DWARFUnit *Unit;
  27. const DWARFDie FuncDie;
  28. LiveVariable(const DWARFLocationExpression &LocExpr, const char *VarName,
  29. DWARFUnit *Unit, const DWARFDie FuncDie)
  30. : LocExpr(LocExpr), VarName(VarName), Unit(Unit), FuncDie(FuncDie) {}
  31. bool liveAtAddress(object::SectionedAddress Addr);
  32. void print(raw_ostream &OS, const MCRegisterInfo &MRI) const;
  33. };
  34. /// Helper class for printing source variable locations alongside disassembly.
  35. class LiveVariablePrinter {
  36. // Information we want to track about one column in which we are printing a
  37. // variable live range.
  38. struct Column {
  39. unsigned VarIdx = NullVarIdx;
  40. bool LiveIn = false;
  41. bool LiveOut = false;
  42. bool MustDrawLabel = false;
  43. bool isActive() const { return VarIdx != NullVarIdx; }
  44. static constexpr unsigned NullVarIdx = std::numeric_limits<unsigned>::max();
  45. };
  46. // All live variables we know about in the object/image file.
  47. std::vector<LiveVariable> LiveVariables;
  48. // The columns we are currently drawing.
  49. IndexedMap<Column> ActiveCols;
  50. const MCRegisterInfo &MRI;
  51. const MCSubtargetInfo &STI;
  52. void addVariable(DWARFDie FuncDie, DWARFDie VarDie);
  53. void addFunction(DWARFDie D);
  54. // Get the column number (in characters) at which the first live variable
  55. // line should be printed.
  56. unsigned getIndentLevel() const;
  57. // Indent to the first live-range column to the right of the currently
  58. // printed line, and return the index of that column.
  59. // TODO: formatted_raw_ostream uses "column" to mean a number of characters
  60. // since the last \n, and we use it to mean the number of slots in which we
  61. // put live variable lines. Pick a less overloaded word.
  62. unsigned moveToFirstVarColumn(formatted_raw_ostream &OS);
  63. unsigned findFreeColumn();
  64. public:
  65. LiveVariablePrinter(const MCRegisterInfo &MRI, const MCSubtargetInfo &STI)
  66. : ActiveCols(Column()), MRI(MRI), STI(STI) {}
  67. void dump() const;
  68. void addCompileUnit(DWARFDie D);
  69. /// Update to match the state of the instruction between ThisAddr and
  70. /// NextAddr. In the common case, any live range active at ThisAddr is
  71. /// live-in to the instruction, and any live range active at NextAddr is
  72. /// live-out of the instruction. If IncludeDefinedVars is false, then live
  73. /// ranges starting at NextAddr will be ignored.
  74. void update(object::SectionedAddress ThisAddr,
  75. object::SectionedAddress NextAddr, bool IncludeDefinedVars);
  76. enum class LineChar {
  77. RangeStart,
  78. RangeMid,
  79. RangeEnd,
  80. LabelVert,
  81. LabelCornerNew,
  82. LabelCornerActive,
  83. LabelHoriz,
  84. };
  85. const char *getLineChar(LineChar C) const;
  86. /// Print live ranges to the right of an existing line. This assumes the
  87. /// line is not an instruction, so doesn't start or end any live ranges, so
  88. /// we only need to print active ranges or empty columns. If AfterInst is
  89. /// true, this is being printed after the last instruction fed to update(),
  90. /// otherwise this is being printed before it.
  91. void printAfterOtherLine(formatted_raw_ostream &OS, bool AfterInst);
  92. /// Print any live variable range info needed to the right of a
  93. /// non-instruction line of disassembly. This is where we print the variable
  94. /// names and expressions, with thin line-drawing characters connecting them
  95. /// to the live range which starts at the next instruction. If MustPrint is
  96. /// true, we have to print at least one line (with the continuation of any
  97. /// already-active live ranges) because something has already been printed
  98. /// earlier on this line.
  99. void printBetweenInsts(formatted_raw_ostream &OS, bool MustPrint);
  100. /// Print the live variable ranges to the right of a disassembled instruction.
  101. void printAfterInst(formatted_raw_ostream &OS);
  102. };
  103. class SourcePrinter {
  104. protected:
  105. DILineInfo OldLineInfo;
  106. const object::ObjectFile *Obj = nullptr;
  107. std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer;
  108. // File name to file contents of source.
  109. std::unordered_map<std::string, std::unique_ptr<MemoryBuffer>> SourceCache;
  110. // Mark the line endings of the cached source.
  111. std::unordered_map<std::string, std::vector<StringRef>> LineCache;
  112. // Keep track of missing sources.
  113. StringSet<> MissingSources;
  114. // Only emit 'invalid debug info' warning once.
  115. bool WarnedInvalidDebugInfo = false;
  116. private:
  117. bool cacheSource(const DILineInfo &LineInfoFile);
  118. void printLines(formatted_raw_ostream &OS, const DILineInfo &LineInfo,
  119. StringRef Delimiter, LiveVariablePrinter &LVP);
  120. void printSources(formatted_raw_ostream &OS, const DILineInfo &LineInfo,
  121. StringRef ObjectFilename, StringRef Delimiter,
  122. LiveVariablePrinter &LVP);
  123. public:
  124. SourcePrinter() = default;
  125. SourcePrinter(const object::ObjectFile *Obj, StringRef DefaultArch);
  126. virtual ~SourcePrinter() = default;
  127. virtual void printSourceLine(formatted_raw_ostream &OS,
  128. object::SectionedAddress Address,
  129. StringRef ObjectFilename,
  130. LiveVariablePrinter &LVP,
  131. StringRef Delimiter = "; ");
  132. };
  133. } // namespace objdump
  134. } // namespace llvm
  135. #endif