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/DenseMap.h"
13#include "llvm/ADT/IndexedMap.h"
14#include "llvm/ADT/MapVector.h"
15#include "llvm/ADT/StringSet.h"
16#include "llvm/DebugInfo/DWARF/DWARFContext.h"
17#include "llvm/DebugInfo/Symbolize/Symbolize.h"
18#include "llvm/MC/MCRegisterInfo.h"
19#include "llvm/MC/MCSubtargetInfo.h"
20#include "llvm/Support/FormattedStream.h"
21#include <set>
22#include <unordered_map>
23#include <vector>
24
25namespace llvm {
26namespace objdump {
27
28/// Base class for representing the location of a source-level variable or
29/// an inlined function.
30class LiveElement {
31protected:
32 const char *Name;
33 DWARFUnit *Unit;
34 const DWARFDie FuncDie;
35
36public:
37 LiveElement(const char *Name, DWARFUnit *Unit, const DWARFDie FuncDie)
38 : Name(Name), Unit(Unit), FuncDie(FuncDie) {}
39
40 virtual ~LiveElement() = default;
41 const char *getName() const { return Name; }
42
43 virtual bool liveAtAddress(object::SectionedAddress Addr) const = 0;
44 virtual void print(raw_ostream &OS, const MCRegisterInfo &MRI) const = 0;
45 virtual void dump(raw_ostream &OS) const = 0;
46 virtual void printElementLine(raw_ostream &OS,
47 object::SectionedAddress Address,
48 bool IsEnd) const {}
49};
50
51class InlinedFunction : public LiveElement {
52private:
53 DWARFDie InlinedFuncDie;
54 DWARFAddressRange Range;
55
56public:
57 InlinedFunction(const char *FunctionName, DWARFUnit *Unit,
58 const DWARFDie FuncDie, const DWARFDie InlinedFuncDie,
59 DWARFAddressRange &Range)
60 : LiveElement(FunctionName, Unit, FuncDie),
61 InlinedFuncDie(InlinedFuncDie), Range(Range) {}
62
63 bool liveAtAddress(object::SectionedAddress Addr) const override;
64 void print(raw_ostream &OS, const MCRegisterInfo &MRI) const override;
65 void dump(raw_ostream &OS) const override;
66 void printElementLine(raw_ostream &OS, object::SectionedAddress Address,
67 bool IsEnd) const override;
68};
69
70/// Stores a single expression representing the location of a source-level
71/// variable, along with the PC range for which that expression is valid.
72class LiveVariable : public LiveElement {
73private:
74 DWARFLocationExpression LocExpr;
75
76public:
77 LiveVariable(const DWARFLocationExpression &LocExpr, const char *VarName,
78 DWARFUnit *Unit, const DWARFDie FuncDie)
79 : LiveElement(VarName, Unit, FuncDie), LocExpr(LocExpr) {}
80
81 bool liveAtAddress(object::SectionedAddress Addr) const override;
82 void print(raw_ostream &OS, const MCRegisterInfo &MRI) const override;
83 void dump(raw_ostream &OS) const override;
84 const DWARFLocationExpression &getLocExpr() const { return LocExpr; }
85};
86
87/// Helper class for printing source locations for variables and inlined
88/// subroutines alongside disassembly.
89class LiveElementPrinter {
90 // Information we want to track about one column in which we are printing an
91 // element live range.
92 struct Column {
93 unsigned ElementIdx = NullElementIdx;
94 bool LiveIn = false;
95 bool LiveOut = false;
96 bool MustDrawLabel = false;
97
98 bool isActive() const { return ElementIdx != NullElementIdx; }
99
100 static constexpr unsigned NullElementIdx =
101 std::numeric_limits<unsigned>::max();
102
103 // Clear the column's data.
104 void clear() {
105 ElementIdx = NullElementIdx;
106 LiveIn = false;
107 LiveOut = false;
108 MustDrawLabel = false;
109 }
110 };
111
112 // Vector that owns all LiveElement objects for memory management.
113 std::vector<std::unique_ptr<LiveElement>> LiveElements;
114 // Map for fast lookup of live elements by their starting address (LowPC).
115 llvm::MapVector<uint64_t, std::vector<LiveElement *>> LiveElementsByAddress;
116 // Map for fast lookup of live elements by their ending address (HighPC).
117 llvm::MapVector<uint64_t, std::vector<LiveElement *>>
118 LiveElementsByEndAddress;
119 // Map from a LiveElement pointer to its index in the LiveElements vector.
120 llvm::DenseMap<LiveElement *, unsigned> ElementPtrToIndex;
121 // Map from a live element index to column index for efficient lookup.
122 llvm::DenseMap<unsigned, unsigned> ElementToColumn;
123 // Vector of columns currently used for printing live ranges.
124 std::vector<Column> ActiveCols;
125 // Set of available column indices kept sorted for efficient reuse.
126 std::set<unsigned> FreeCols;
127 // Vector of available column indices that can be reused.
128 std::vector<unsigned> ColumnsToFreeNextCycle;
129
130 const MCRegisterInfo &MRI;
131 const MCSubtargetInfo &STI;
132
133 void registerNewVariable();
134
135 void addInlinedFunction(DWARFDie FuncDie, DWARFDie InlinedFuncDie);
136 void addVariable(DWARFDie FuncDie, DWARFDie VarDie);
137
138 void addFunction(DWARFDie D);
139
140 // Get the column number (in characters) at which the first live element
141 // line should be printed.
142 unsigned getIndentLevel() const;
143
144 // Indent to the first live-range column to the right of the currently
145 // printed line, and return the index of that column.
146 // TODO: formatted_raw_ostream uses "column" to mean a number of characters
147 // since the last \n, and we use it to mean the number of slots in which we
148 // put live element lines. Pick a less overloaded word.
149 unsigned moveToFirstVarColumn(formatted_raw_ostream &OS);
150
151 // Get an existing column for a live element, or find a free one.
152 unsigned getOrCreateColumn(unsigned ElementIdx);
153
154 // Free a column when its element is no longer live.
155 void freeColumn(unsigned ColIdx);
156
157 // Returns the indices of all currently active elements, sorted by their DWARF
158 // discovery order.
159 std::vector<unsigned> getSortedActiveElementIndices() const;
160
161public:
162 LiveElementPrinter(const MCRegisterInfo &MRI, const MCSubtargetInfo &STI)
163 : MRI(MRI), STI(STI) {}
164
165 void dump() const;
166
167 void addCompileUnit(DWARFDie D);
168
169 /// Update to match the state of the instruction between ThisAddr and
170 /// NextAddr. In the common case, any live range active at ThisAddr is
171 /// live-in to the instruction, and any live range active at NextAddr is
172 /// live-out of the instruction. If IncludeDefinedVars is false, then live
173 /// ranges starting at NextAddr will be ignored.
174 void update(object::SectionedAddress ThisAddr,
175 object::SectionedAddress NextAddr, bool IncludeDefinedVars);
176
177 enum class LineChar {
178 RangeStart,
179 RangeMid,
180 RangeEnd,
181 LabelVert,
182 LabelCornerNew,
183 LabelCornerActive,
184 LabelHoriz,
185 };
186 const char *getLineChar(LineChar C) const;
187
188 /// Print live ranges to the right of an existing line. This assumes the
189 /// line is not an instruction, so doesn't start or end any live ranges, so
190 /// we only need to print active ranges or empty columns. If AfterInst is
191 /// true, this is being printed after the last instruction fed to update(),
192 /// otherwise this is being printed before it.
193 void printAfterOtherLine(formatted_raw_ostream &OS, bool AfterInst);
194
195 /// Print any live element range info needed to the right of a
196 /// non-instruction line of disassembly. This is where we print the variable
197 /// names and expressions, with thin line-drawing characters connecting them
198 /// to the live range which starts at the next instruction. If MustPrint is
199 /// true, we have to print at least one line (with the continuation of any
200 /// already-active live ranges) because something has already been printed
201 /// earlier on this line.
202 void printBetweenInsts(formatted_raw_ostream &OS, bool MustPrint);
203
204 /// Print the live element ranges to the right of a disassembled instruction.
205 void printAfterInst(formatted_raw_ostream &OS);
206
207 /// Print a line to idenfity the start/end of a live element.
208 void printBoundaryLine(formatted_raw_ostream &OS,
209 object::SectionedAddress Addr, bool IsEnd);
210};
211
212class SourcePrinter {
213protected:
214 DILineInfo OldLineInfo;
215 const object::ObjectFile *Obj = nullptr;
216 std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer;
217 // File name to file contents of source.
218 std::unordered_map<std::string, std::unique_ptr<MemoryBuffer>> SourceCache;
219 // Mark the line endings of the cached source.
220 std::unordered_map<std::string, std::vector<StringRef>> LineCache;
221 // Keep track of missing sources.
222 StringSet<> MissingSources;
223 // Only emit 'invalid debug info' warning once.
224 bool WarnedInvalidDebugInfo = false;
225
226private:
227 bool cacheSource(const DILineInfo &LineInfoFile);
228
229 void printLines(formatted_raw_ostream &OS, object::SectionedAddress Address,
230 const DILineInfo &LineInfo, StringRef Delimiter,
231 LiveElementPrinter &LEP);
232
233 void printSources(formatted_raw_ostream &OS, const DILineInfo &LineInfo,
234 StringRef ObjectFilename, StringRef Delimiter,
235 LiveElementPrinter &LEP);
236
237 // Returns line source code corresponding to `LineInfo`.
238 // Returns empty string if source code cannot be found.
239 StringRef getLine(const DILineInfo &LineInfo, StringRef ObjectFilename);
240
241public:
242 SourcePrinter() = default;
243 SourcePrinter(const object::ObjectFile *Obj, StringRef DefaultArch);
244 virtual ~SourcePrinter() = default;
245 virtual void printSourceLine(formatted_raw_ostream &OS,
246 object::SectionedAddress Address,
247 StringRef ObjectFilename,
248 LiveElementPrinter &LEP,
249 StringRef Delimiter = "; ");
250};
251
252} // namespace objdump
253} // namespace llvm
254
255#endif
256