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