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