1 //===-- SourcePrinter.cpp - source interleaving utilities ----------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the LiveVariablePrinter and SourcePrinter classes to
10 // keep track of DWARF info as the current address is updated, and print out the
11 // source file line and variable liveness as needed.
13 //===----------------------------------------------------------------------===//
15 #include "SourcePrinter.h"
16 #include "llvm-objdump.h"
17 #include "llvm/ADT/SmallSet.h"
18 #include "llvm/ADT/StringSet.h"
19 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
20 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
21 #include "llvm/MC/MCSubtargetInfo.h"
22 #include "llvm/Support/FormatVariadic.h"
24 #define DEBUG_TYPE "objdump"
29 bool LiveVariable::liveAtAddress(object::SectionedAddress Addr
) {
30 if (LocExpr
.Range
== std::nullopt
)
32 return LocExpr
.Range
->SectionIndex
== Addr
.SectionIndex
&&
33 LocExpr
.Range
->LowPC
<= Addr
.Address
&&
34 LocExpr
.Range
->HighPC
> Addr
.Address
;
37 void LiveVariable::print(raw_ostream
&OS
, const MCRegisterInfo
&MRI
) const {
38 DataExtractor
Data({LocExpr
.Expr
.data(), LocExpr
.Expr
.size()},
39 Unit
->getContext().isLittleEndian(), 0);
40 DWARFExpression
Expression(Data
, Unit
->getAddressByteSize());
42 auto GetRegName
= [&MRI
, &OS
](uint64_t DwarfRegNum
, bool IsEH
) -> StringRef
{
43 if (std::optional
<unsigned> LLVMRegNum
=
44 MRI
.getLLVMRegNum(DwarfRegNum
, IsEH
))
45 if (const char *RegName
= MRI
.getName(*LLVMRegNum
))
46 return StringRef(RegName
);
47 OS
<< "<unknown register " << DwarfRegNum
<< ">";
51 Expression
.printCompact(OS
, GetRegName
);
54 void LiveVariablePrinter::addVariable(DWARFDie FuncDie
, DWARFDie VarDie
) {
55 uint64_t FuncLowPC
, FuncHighPC
, SectionIndex
;
56 FuncDie
.getLowAndHighPC(FuncLowPC
, FuncHighPC
, SectionIndex
);
57 const char *VarName
= VarDie
.getName(DINameKind::ShortName
);
58 DWARFUnit
*U
= VarDie
.getDwarfUnit();
60 Expected
<DWARFLocationExpressionsVector
> Locs
=
61 VarDie
.getLocations(dwarf::DW_AT_location
);
63 // If the variable doesn't have any locations, just ignore it. We don't
64 // report an error or warning here as that could be noisy on optimised
66 consumeError(Locs
.takeError());
70 for (const DWARFLocationExpression
&LocExpr
: *Locs
) {
72 LiveVariables
.emplace_back(LocExpr
, VarName
, U
, FuncDie
);
74 // If the LocExpr does not have an associated range, it is valid for
75 // the whole of the function.
76 // TODO: technically it is not valid for any range covered by another
77 // LocExpr, does that happen in reality?
78 DWARFLocationExpression WholeFuncExpr
{
79 DWARFAddressRange(FuncLowPC
, FuncHighPC
, SectionIndex
), LocExpr
.Expr
};
80 LiveVariables
.emplace_back(WholeFuncExpr
, VarName
, U
, FuncDie
);
85 void LiveVariablePrinter::addFunction(DWARFDie D
) {
86 for (const DWARFDie
&Child
: D
.children()) {
87 if (Child
.getTag() == dwarf::DW_TAG_variable
||
88 Child
.getTag() == dwarf::DW_TAG_formal_parameter
)
89 addVariable(D
, Child
);
95 // Get the column number (in characters) at which the first live variable
96 // line should be printed.
97 unsigned LiveVariablePrinter::getIndentLevel() const {
98 return DbgIndent
+ getInstStartColumn(STI
);
101 // Indent to the first live-range column to the right of the currently
102 // printed line, and return the index of that column.
103 // TODO: formatted_raw_ostream uses "column" to mean a number of characters
104 // since the last \n, and we use it to mean the number of slots in which we
105 // put live variable lines. Pick a less overloaded word.
106 unsigned LiveVariablePrinter::moveToFirstVarColumn(formatted_raw_ostream
&OS
) {
107 // Logical column number: column zero is the first column we print in, each
108 // logical column is 2 physical columns wide.
109 unsigned FirstUnprintedLogicalColumn
=
110 std::max((int)(OS
.getColumn() - getIndentLevel() + 1) / 2, 0);
111 // Physical column number: the actual column number in characters, with
112 // zero being the left-most side of the screen.
113 unsigned FirstUnprintedPhysicalColumn
=
114 getIndentLevel() + FirstUnprintedLogicalColumn
* 2;
116 if (FirstUnprintedPhysicalColumn
> OS
.getColumn())
117 OS
.PadToColumn(FirstUnprintedPhysicalColumn
);
119 return FirstUnprintedLogicalColumn
;
122 unsigned LiveVariablePrinter::findFreeColumn() {
123 for (unsigned ColIdx
= 0; ColIdx
< ActiveCols
.size(); ++ColIdx
)
124 if (!ActiveCols
[ColIdx
].isActive())
127 size_t OldSize
= ActiveCols
.size();
128 ActiveCols
.grow(std::max
<size_t>(OldSize
* 2, 1));
132 void LiveVariablePrinter::dump() const {
133 for (const LiveVariable
&LV
: LiveVariables
) {
134 dbgs() << LV
.VarName
<< " @ " << LV
.LocExpr
.Range
<< ": ";
135 LV
.print(dbgs(), MRI
);
140 void LiveVariablePrinter::addCompileUnit(DWARFDie D
) {
141 if (D
.getTag() == dwarf::DW_TAG_subprogram
)
144 for (const DWARFDie
&Child
: D
.children())
148 /// Update to match the state of the instruction between ThisAddr and
149 /// NextAddr. In the common case, any live range active at ThisAddr is
150 /// live-in to the instruction, and any live range active at NextAddr is
151 /// live-out of the instruction. If IncludeDefinedVars is false, then live
152 /// ranges starting at NextAddr will be ignored.
153 void LiveVariablePrinter::update(object::SectionedAddress ThisAddr
,
154 object::SectionedAddress NextAddr
,
155 bool IncludeDefinedVars
) {
156 // First, check variables which have already been assigned a column, so
157 // that we don't change their order.
158 SmallSet
<unsigned, 8> CheckedVarIdxs
;
159 for (unsigned ColIdx
= 0, End
= ActiveCols
.size(); ColIdx
< End
; ++ColIdx
) {
160 if (!ActiveCols
[ColIdx
].isActive())
162 CheckedVarIdxs
.insert(ActiveCols
[ColIdx
].VarIdx
);
163 LiveVariable
&LV
= LiveVariables
[ActiveCols
[ColIdx
].VarIdx
];
164 ActiveCols
[ColIdx
].LiveIn
= LV
.liveAtAddress(ThisAddr
);
165 ActiveCols
[ColIdx
].LiveOut
= LV
.liveAtAddress(NextAddr
);
166 LLVM_DEBUG(dbgs() << "pass 1, " << ThisAddr
.Address
<< "-"
167 << NextAddr
.Address
<< ", " << LV
.VarName
<< ", Col "
168 << ColIdx
<< ": LiveIn=" << ActiveCols
[ColIdx
].LiveIn
169 << ", LiveOut=" << ActiveCols
[ColIdx
].LiveOut
<< "\n");
171 if (!ActiveCols
[ColIdx
].LiveIn
&& !ActiveCols
[ColIdx
].LiveOut
)
172 ActiveCols
[ColIdx
].VarIdx
= Column::NullVarIdx
;
175 // Next, look for variables which don't already have a column, but which
177 if (IncludeDefinedVars
) {
178 for (unsigned VarIdx
= 0, End
= LiveVariables
.size(); VarIdx
< End
;
180 if (CheckedVarIdxs
.count(VarIdx
))
182 LiveVariable
&LV
= LiveVariables
[VarIdx
];
183 bool LiveIn
= LV
.liveAtAddress(ThisAddr
);
184 bool LiveOut
= LV
.liveAtAddress(NextAddr
);
185 if (!LiveIn
&& !LiveOut
)
188 unsigned ColIdx
= findFreeColumn();
189 LLVM_DEBUG(dbgs() << "pass 2, " << ThisAddr
.Address
<< "-"
190 << NextAddr
.Address
<< ", " << LV
.VarName
<< ", Col "
191 << ColIdx
<< ": LiveIn=" << LiveIn
192 << ", LiveOut=" << LiveOut
<< "\n");
193 ActiveCols
[ColIdx
].VarIdx
= VarIdx
;
194 ActiveCols
[ColIdx
].LiveIn
= LiveIn
;
195 ActiveCols
[ColIdx
].LiveOut
= LiveOut
;
196 ActiveCols
[ColIdx
].MustDrawLabel
= true;
201 enum class LineChar
{
210 const char *LiveVariablePrinter::getLineChar(LineChar C
) const {
211 bool IsASCII
= DbgVariables
== DVASCII
;
213 case LineChar::RangeStart
:
214 return IsASCII
? "^" : (const char *)u8
"\u2548";
215 case LineChar::RangeMid
:
216 return IsASCII
? "|" : (const char *)u8
"\u2503";
217 case LineChar::RangeEnd
:
218 return IsASCII
? "v" : (const char *)u8
"\u253b";
219 case LineChar::LabelVert
:
220 return IsASCII
? "|" : (const char *)u8
"\u2502";
221 case LineChar::LabelCornerNew
:
222 return IsASCII
? "/" : (const char *)u8
"\u250c";
223 case LineChar::LabelCornerActive
:
224 return IsASCII
? "|" : (const char *)u8
"\u2520";
225 case LineChar::LabelHoriz
:
226 return IsASCII
? "-" : (const char *)u8
"\u2500";
228 llvm_unreachable("Unhandled LineChar enum");
231 /// Print live ranges to the right of an existing line. This assumes the
232 /// line is not an instruction, so doesn't start or end any live ranges, so
233 /// we only need to print active ranges or empty columns. If AfterInst is
234 /// true, this is being printed after the last instruction fed to update(),
235 /// otherwise this is being printed before it.
236 void LiveVariablePrinter::printAfterOtherLine(formatted_raw_ostream
&OS
,
238 if (ActiveCols
.size()) {
239 unsigned FirstUnprintedColumn
= moveToFirstVarColumn(OS
);
240 for (size_t ColIdx
= FirstUnprintedColumn
, End
= ActiveCols
.size();
241 ColIdx
< End
; ++ColIdx
) {
242 if (ActiveCols
[ColIdx
].isActive()) {
243 if ((AfterInst
&& ActiveCols
[ColIdx
].LiveOut
) ||
244 (!AfterInst
&& ActiveCols
[ColIdx
].LiveIn
))
245 OS
<< getLineChar(LineChar::RangeMid
);
246 else if (!AfterInst
&& ActiveCols
[ColIdx
].LiveOut
)
247 OS
<< getLineChar(LineChar::LabelVert
);
257 /// Print any live variable range info needed to the right of a
258 /// non-instruction line of disassembly. This is where we print the variable
259 /// names and expressions, with thin line-drawing characters connecting them
260 /// to the live range which starts at the next instruction. If MustPrint is
261 /// true, we have to print at least one line (with the continuation of any
262 /// already-active live ranges) because something has already been printed
263 /// earlier on this line.
264 void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream
&OS
,
266 bool PrintedSomething
= false;
267 for (unsigned ColIdx
= 0, End
= ActiveCols
.size(); ColIdx
< End
; ++ColIdx
) {
268 if (ActiveCols
[ColIdx
].isActive() && ActiveCols
[ColIdx
].MustDrawLabel
) {
269 // First we need to print the live range markers for any active
270 // columns to the left of this one.
271 OS
.PadToColumn(getIndentLevel());
272 for (unsigned ColIdx2
= 0; ColIdx2
< ColIdx
; ++ColIdx2
) {
273 if (ActiveCols
[ColIdx2
].isActive()) {
274 if (ActiveCols
[ColIdx2
].MustDrawLabel
&& !ActiveCols
[ColIdx2
].LiveIn
)
275 OS
<< getLineChar(LineChar::LabelVert
) << " ";
277 OS
<< getLineChar(LineChar::RangeMid
) << " ";
282 // Then print the variable name and location of the new live range,
283 // with box drawing characters joining it to the live range line.
284 OS
<< getLineChar(ActiveCols
[ColIdx
].LiveIn
? LineChar::LabelCornerActive
285 : LineChar::LabelCornerNew
)
286 << getLineChar(LineChar::LabelHoriz
) << " ";
287 WithColor(OS
, raw_ostream::GREEN
)
288 << LiveVariables
[ActiveCols
[ColIdx
].VarIdx
].VarName
;
291 WithColor
ExprColor(OS
, raw_ostream::CYAN
);
292 LiveVariables
[ActiveCols
[ColIdx
].VarIdx
].print(OS
, MRI
);
295 // If there are any columns to the right of the expression we just
296 // printed, then continue their live range lines.
297 unsigned FirstUnprintedColumn
= moveToFirstVarColumn(OS
);
298 for (unsigned ColIdx2
= FirstUnprintedColumn
, End
= ActiveCols
.size();
299 ColIdx2
< End
; ++ColIdx2
) {
300 if (ActiveCols
[ColIdx2
].isActive() && ActiveCols
[ColIdx2
].LiveIn
)
301 OS
<< getLineChar(LineChar::RangeMid
) << " ";
307 PrintedSomething
= true;
311 for (unsigned ColIdx
= 0, End
= ActiveCols
.size(); ColIdx
< End
; ++ColIdx
)
312 if (ActiveCols
[ColIdx
].isActive())
313 ActiveCols
[ColIdx
].MustDrawLabel
= false;
315 // If we must print something (because we printed a line/column number),
316 // but don't have any new variables to print, then print a line which
317 // just continues any existing live ranges.
318 if (MustPrint
&& !PrintedSomething
)
319 printAfterOtherLine(OS
, false);
322 /// Print the live variable ranges to the right of a disassembled instruction.
323 void LiveVariablePrinter::printAfterInst(formatted_raw_ostream
&OS
) {
324 if (!ActiveCols
.size())
326 unsigned FirstUnprintedColumn
= moveToFirstVarColumn(OS
);
327 for (unsigned ColIdx
= FirstUnprintedColumn
, End
= ActiveCols
.size();
328 ColIdx
< End
; ++ColIdx
) {
329 if (!ActiveCols
[ColIdx
].isActive())
331 else if (ActiveCols
[ColIdx
].LiveIn
&& ActiveCols
[ColIdx
].LiveOut
)
332 OS
<< getLineChar(LineChar::RangeMid
) << " ";
333 else if (ActiveCols
[ColIdx
].LiveOut
)
334 OS
<< getLineChar(LineChar::RangeStart
) << " ";
335 else if (ActiveCols
[ColIdx
].LiveIn
)
336 OS
<< getLineChar(LineChar::RangeEnd
) << " ";
338 llvm_unreachable("var must be live in or out!");
342 bool SourcePrinter::cacheSource(const DILineInfo
&LineInfo
) {
343 std::unique_ptr
<MemoryBuffer
> Buffer
;
344 if (LineInfo
.Source
) {
345 Buffer
= MemoryBuffer::getMemBuffer(*LineInfo
.Source
);
347 auto BufferOrError
= MemoryBuffer::getFile(LineInfo
.FileName
);
348 if (!BufferOrError
) {
349 if (MissingSources
.insert(LineInfo
.FileName
).second
)
350 reportWarning("failed to find source " + LineInfo
.FileName
,
354 Buffer
= std::move(*BufferOrError
);
356 // Chomp the file to get lines
357 const char *BufferStart
= Buffer
->getBufferStart(),
358 *BufferEnd
= Buffer
->getBufferEnd();
359 std::vector
<StringRef
> &Lines
= LineCache
[LineInfo
.FileName
];
360 const char *Start
= BufferStart
;
361 for (const char *I
= BufferStart
; I
!= BufferEnd
; ++I
)
363 Lines
.emplace_back(Start
, I
- Start
- (BufferStart
< I
&& I
[-1] == '\r'));
366 if (Start
< BufferEnd
)
367 Lines
.emplace_back(Start
, BufferEnd
- Start
);
368 SourceCache
[LineInfo
.FileName
] = std::move(Buffer
);
372 void SourcePrinter::printSourceLine(formatted_raw_ostream
&OS
,
373 object::SectionedAddress Address
,
374 StringRef ObjectFilename
,
375 LiveVariablePrinter
&LVP
,
376 StringRef Delimiter
) {
380 DILineInfo LineInfo
= DILineInfo();
381 Expected
<DILineInfo
> ExpectedLineInfo
=
382 Symbolizer
->symbolizeCode(*Obj
, Address
);
383 std::string ErrorMessage
;
384 if (ExpectedLineInfo
) {
385 LineInfo
= *ExpectedLineInfo
;
386 } else if (!WarnedInvalidDebugInfo
) {
387 WarnedInvalidDebugInfo
= true;
389 reportWarning("failed to parse debug information: " +
390 toString(ExpectedLineInfo
.takeError()),
394 if (!objdump::Prefix
.empty() &&
395 sys::path::is_absolute_gnu(LineInfo
.FileName
)) {
396 // FileName has at least one character since is_absolute_gnu is false for
398 assert(!LineInfo
.FileName
.empty());
399 if (PrefixStrip
> 0) {
401 auto StrippedNameStart
= LineInfo
.FileName
.begin();
403 // Path.h iterator skips extra separators. Therefore it cannot be used
404 // here to keep compatibility with GNU Objdump.
405 for (auto Pos
= StrippedNameStart
+ 1, End
= LineInfo
.FileName
.end();
406 Pos
!= End
&& Level
< PrefixStrip
; ++Pos
) {
407 if (sys::path::is_separator(*Pos
)) {
408 StrippedNameStart
= Pos
;
414 std::string(StrippedNameStart
, LineInfo
.FileName
.end());
417 SmallString
<128> FilePath
;
418 sys::path::append(FilePath
, Prefix
, LineInfo
.FileName
);
420 LineInfo
.FileName
= std::string(FilePath
);
424 printLines(OS
, LineInfo
, Delimiter
, LVP
);
426 printSources(OS
, LineInfo
, ObjectFilename
, Delimiter
, LVP
);
427 OldLineInfo
= LineInfo
;
430 void SourcePrinter::printLines(formatted_raw_ostream
&OS
,
431 const DILineInfo
&LineInfo
, StringRef Delimiter
,
432 LiveVariablePrinter
&LVP
) {
433 bool PrintFunctionName
= LineInfo
.FunctionName
!= DILineInfo::BadString
&&
434 LineInfo
.FunctionName
!= OldLineInfo
.FunctionName
;
435 if (PrintFunctionName
) {
436 OS
<< Delimiter
<< LineInfo
.FunctionName
;
437 // If demangling is successful, FunctionName will end with "()". Print it
438 // only if demangling did not run or was unsuccessful.
439 if (!StringRef(LineInfo
.FunctionName
).endswith("()"))
443 if (LineInfo
.FileName
!= DILineInfo::BadString
&& LineInfo
.Line
!= 0 &&
444 (OldLineInfo
.Line
!= LineInfo
.Line
||
445 OldLineInfo
.FileName
!= LineInfo
.FileName
|| PrintFunctionName
)) {
446 OS
<< Delimiter
<< LineInfo
.FileName
<< ":" << LineInfo
.Line
;
447 LVP
.printBetweenInsts(OS
, true);
451 // Get the source line text for LineInfo:
452 // - use LineInfo::LineSource if available;
453 // - use LineCache if LineInfo::Source otherwise.
454 StringRef
SourcePrinter::getLine(const DILineInfo
&LineInfo
,
455 StringRef ObjectFilename
) {
456 if (LineInfo
.LineSource
)
457 return LineInfo
.LineSource
.value();
459 if (SourceCache
.find(LineInfo
.FileName
) == SourceCache
.end())
460 if (!cacheSource(LineInfo
))
463 auto LineBuffer
= LineCache
.find(LineInfo
.FileName
);
464 if (LineBuffer
== LineCache
.end())
467 if (LineInfo
.Line
> LineBuffer
->second
.size()) {
469 formatv("debug info line number {0} exceeds the number of lines in {1}",
470 LineInfo
.Line
, LineInfo
.FileName
),
475 // Vector begins at 0, line numbers are non-zero
476 return LineBuffer
->second
[LineInfo
.Line
- 1];
479 void SourcePrinter::printSources(formatted_raw_ostream
&OS
,
480 const DILineInfo
&LineInfo
,
481 StringRef ObjectFilename
, StringRef Delimiter
,
482 LiveVariablePrinter
&LVP
) {
483 if (LineInfo
.FileName
== DILineInfo::BadString
|| LineInfo
.Line
== 0 ||
484 (OldLineInfo
.Line
== LineInfo
.Line
&&
485 OldLineInfo
.FileName
== LineInfo
.FileName
))
488 StringRef Line
= getLine(LineInfo
, ObjectFilename
);
490 OS
<< Delimiter
<< Line
;
491 LVP
.printBetweenInsts(OS
, true);
495 SourcePrinter::SourcePrinter(const object::ObjectFile
*Obj
,
496 StringRef DefaultArch
)
498 symbolize::LLVMSymbolizer::Options SymbolizerOpts
;
499 SymbolizerOpts
.PrintFunctions
=
500 DILineInfoSpecifier::FunctionNameKind::LinkageName
;
501 SymbolizerOpts
.Demangle
= Demangle
;
502 SymbolizerOpts
.DefaultArch
= std::string(DefaultArch
);
503 Symbolizer
.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts
));
506 } // namespace objdump