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/DebugInfo/DWARF/DWARFExpression.h"
19 #include "llvm/Support/FormatVariadic.h"
21 #define DEBUG_TYPE "objdump"
26 bool LiveVariable::liveAtAddress(object::SectionedAddress Addr
) {
27 if (LocExpr
.Range
== std::nullopt
)
29 return LocExpr
.Range
->SectionIndex
== Addr
.SectionIndex
&&
30 LocExpr
.Range
->LowPC
<= Addr
.Address
&&
31 LocExpr
.Range
->HighPC
> Addr
.Address
;
34 void LiveVariable::print(raw_ostream
&OS
, const MCRegisterInfo
&MRI
) const {
35 DataExtractor
Data({LocExpr
.Expr
.data(), LocExpr
.Expr
.size()},
36 Unit
->getContext().isLittleEndian(), 0);
37 DWARFExpression
Expression(Data
, Unit
->getAddressByteSize());
39 auto GetRegName
= [&MRI
, &OS
](uint64_t DwarfRegNum
, bool IsEH
) -> StringRef
{
40 if (std::optional
<MCRegister
> LLVMRegNum
=
41 MRI
.getLLVMRegNum(DwarfRegNum
, IsEH
))
42 if (const char *RegName
= MRI
.getName(*LLVMRegNum
))
43 return StringRef(RegName
);
44 OS
<< "<unknown register " << DwarfRegNum
<< ">";
48 Expression
.printCompact(OS
, GetRegName
);
51 void LiveVariablePrinter::addVariable(DWARFDie FuncDie
, DWARFDie VarDie
) {
52 uint64_t FuncLowPC
, FuncHighPC
, SectionIndex
;
53 FuncDie
.getLowAndHighPC(FuncLowPC
, FuncHighPC
, SectionIndex
);
54 const char *VarName
= VarDie
.getName(DINameKind::ShortName
);
55 DWARFUnit
*U
= VarDie
.getDwarfUnit();
57 Expected
<DWARFLocationExpressionsVector
> Locs
=
58 VarDie
.getLocations(dwarf::DW_AT_location
);
60 // If the variable doesn't have any locations, just ignore it. We don't
61 // report an error or warning here as that could be noisy on optimised
63 consumeError(Locs
.takeError());
67 for (const DWARFLocationExpression
&LocExpr
: *Locs
) {
69 LiveVariables
.emplace_back(LocExpr
, VarName
, U
, FuncDie
);
71 // If the LocExpr does not have an associated range, it is valid for
72 // the whole of the function.
73 // TODO: technically it is not valid for any range covered by another
74 // LocExpr, does that happen in reality?
75 DWARFLocationExpression WholeFuncExpr
{
76 DWARFAddressRange(FuncLowPC
, FuncHighPC
, SectionIndex
), LocExpr
.Expr
};
77 LiveVariables
.emplace_back(WholeFuncExpr
, VarName
, U
, FuncDie
);
82 void LiveVariablePrinter::addFunction(DWARFDie D
) {
83 for (const DWARFDie
&Child
: D
.children()) {
84 if (Child
.getTag() == dwarf::DW_TAG_variable
||
85 Child
.getTag() == dwarf::DW_TAG_formal_parameter
)
86 addVariable(D
, Child
);
92 // Get the column number (in characters) at which the first live variable
93 // line should be printed.
94 unsigned LiveVariablePrinter::getIndentLevel() const {
95 return DbgIndent
+ getInstStartColumn(STI
);
98 // Indent to the first live-range column to the right of the currently
99 // printed line, and return the index of that column.
100 // TODO: formatted_raw_ostream uses "column" to mean a number of characters
101 // since the last \n, and we use it to mean the number of slots in which we
102 // put live variable lines. Pick a less overloaded word.
103 unsigned LiveVariablePrinter::moveToFirstVarColumn(formatted_raw_ostream
&OS
) {
104 // Logical column number: column zero is the first column we print in, each
105 // logical column is 2 physical columns wide.
106 unsigned FirstUnprintedLogicalColumn
=
107 std::max((int)(OS
.getColumn() - getIndentLevel() + 1) / 2, 0);
108 // Physical column number: the actual column number in characters, with
109 // zero being the left-most side of the screen.
110 unsigned FirstUnprintedPhysicalColumn
=
111 getIndentLevel() + FirstUnprintedLogicalColumn
* 2;
113 if (FirstUnprintedPhysicalColumn
> OS
.getColumn())
114 OS
.PadToColumn(FirstUnprintedPhysicalColumn
);
116 return FirstUnprintedLogicalColumn
;
119 unsigned LiveVariablePrinter::findFreeColumn() {
120 for (unsigned ColIdx
= 0; ColIdx
< ActiveCols
.size(); ++ColIdx
)
121 if (!ActiveCols
[ColIdx
].isActive())
124 size_t OldSize
= ActiveCols
.size();
125 ActiveCols
.grow(std::max
<size_t>(OldSize
* 2, 1));
129 void LiveVariablePrinter::dump() const {
130 for (const LiveVariable
&LV
: LiveVariables
) {
131 dbgs() << LV
.VarName
<< " @ " << LV
.LocExpr
.Range
<< ": ";
132 LV
.print(dbgs(), MRI
);
137 void LiveVariablePrinter::addCompileUnit(DWARFDie D
) {
138 if (D
.getTag() == dwarf::DW_TAG_subprogram
)
141 for (const DWARFDie
&Child
: D
.children())
145 /// Update to match the state of the instruction between ThisAddr and
146 /// NextAddr. In the common case, any live range active at ThisAddr is
147 /// live-in to the instruction, and any live range active at NextAddr is
148 /// live-out of the instruction. If IncludeDefinedVars is false, then live
149 /// ranges starting at NextAddr will be ignored.
150 void LiveVariablePrinter::update(object::SectionedAddress ThisAddr
,
151 object::SectionedAddress NextAddr
,
152 bool IncludeDefinedVars
) {
153 // First, check variables which have already been assigned a column, so
154 // that we don't change their order.
155 SmallSet
<unsigned, 8> CheckedVarIdxs
;
156 for (unsigned ColIdx
= 0, End
= ActiveCols
.size(); ColIdx
< End
; ++ColIdx
) {
157 if (!ActiveCols
[ColIdx
].isActive())
159 CheckedVarIdxs
.insert(ActiveCols
[ColIdx
].VarIdx
);
160 LiveVariable
&LV
= LiveVariables
[ActiveCols
[ColIdx
].VarIdx
];
161 ActiveCols
[ColIdx
].LiveIn
= LV
.liveAtAddress(ThisAddr
);
162 ActiveCols
[ColIdx
].LiveOut
= LV
.liveAtAddress(NextAddr
);
163 LLVM_DEBUG(dbgs() << "pass 1, " << ThisAddr
.Address
<< "-"
164 << NextAddr
.Address
<< ", " << LV
.VarName
<< ", Col "
165 << ColIdx
<< ": LiveIn=" << ActiveCols
[ColIdx
].LiveIn
166 << ", LiveOut=" << ActiveCols
[ColIdx
].LiveOut
<< "\n");
168 if (!ActiveCols
[ColIdx
].LiveIn
&& !ActiveCols
[ColIdx
].LiveOut
)
169 ActiveCols
[ColIdx
].VarIdx
= Column::NullVarIdx
;
172 // Next, look for variables which don't already have a column, but which
174 if (IncludeDefinedVars
) {
175 for (unsigned VarIdx
= 0, End
= LiveVariables
.size(); VarIdx
< End
;
177 if (CheckedVarIdxs
.count(VarIdx
))
179 LiveVariable
&LV
= LiveVariables
[VarIdx
];
180 bool LiveIn
= LV
.liveAtAddress(ThisAddr
);
181 bool LiveOut
= LV
.liveAtAddress(NextAddr
);
182 if (!LiveIn
&& !LiveOut
)
185 unsigned ColIdx
= findFreeColumn();
186 LLVM_DEBUG(dbgs() << "pass 2, " << ThisAddr
.Address
<< "-"
187 << NextAddr
.Address
<< ", " << LV
.VarName
<< ", Col "
188 << ColIdx
<< ": LiveIn=" << LiveIn
189 << ", LiveOut=" << LiveOut
<< "\n");
190 ActiveCols
[ColIdx
].VarIdx
= VarIdx
;
191 ActiveCols
[ColIdx
].LiveIn
= LiveIn
;
192 ActiveCols
[ColIdx
].LiveOut
= LiveOut
;
193 ActiveCols
[ColIdx
].MustDrawLabel
= true;
198 enum class LineChar
{
207 const char *LiveVariablePrinter::getLineChar(LineChar C
) const {
208 bool IsASCII
= DbgVariables
== DVASCII
;
210 case LineChar::RangeStart
:
211 return IsASCII
? "^" : (const char *)u8
"\u2548";
212 case LineChar::RangeMid
:
213 return IsASCII
? "|" : (const char *)u8
"\u2503";
214 case LineChar::RangeEnd
:
215 return IsASCII
? "v" : (const char *)u8
"\u253b";
216 case LineChar::LabelVert
:
217 return IsASCII
? "|" : (const char *)u8
"\u2502";
218 case LineChar::LabelCornerNew
:
219 return IsASCII
? "/" : (const char *)u8
"\u250c";
220 case LineChar::LabelCornerActive
:
221 return IsASCII
? "|" : (const char *)u8
"\u2520";
222 case LineChar::LabelHoriz
:
223 return IsASCII
? "-" : (const char *)u8
"\u2500";
225 llvm_unreachable("Unhandled LineChar enum");
228 /// Print live ranges to the right of an existing line. This assumes the
229 /// line is not an instruction, so doesn't start or end any live ranges, so
230 /// we only need to print active ranges or empty columns. If AfterInst is
231 /// true, this is being printed after the last instruction fed to update(),
232 /// otherwise this is being printed before it.
233 void LiveVariablePrinter::printAfterOtherLine(formatted_raw_ostream
&OS
,
235 if (ActiveCols
.size()) {
236 unsigned FirstUnprintedColumn
= moveToFirstVarColumn(OS
);
237 for (size_t ColIdx
= FirstUnprintedColumn
, End
= ActiveCols
.size();
238 ColIdx
< End
; ++ColIdx
) {
239 if (ActiveCols
[ColIdx
].isActive()) {
240 if ((AfterInst
&& ActiveCols
[ColIdx
].LiveOut
) ||
241 (!AfterInst
&& ActiveCols
[ColIdx
].LiveIn
))
242 OS
<< getLineChar(LineChar::RangeMid
);
243 else if (!AfterInst
&& ActiveCols
[ColIdx
].LiveOut
)
244 OS
<< getLineChar(LineChar::LabelVert
);
254 /// Print any live variable range info needed to the right of a
255 /// non-instruction line of disassembly. This is where we print the variable
256 /// names and expressions, with thin line-drawing characters connecting them
257 /// to the live range which starts at the next instruction. If MustPrint is
258 /// true, we have to print at least one line (with the continuation of any
259 /// already-active live ranges) because something has already been printed
260 /// earlier on this line.
261 void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream
&OS
,
263 bool PrintedSomething
= false;
264 for (unsigned ColIdx
= 0, End
= ActiveCols
.size(); ColIdx
< End
; ++ColIdx
) {
265 if (ActiveCols
[ColIdx
].isActive() && ActiveCols
[ColIdx
].MustDrawLabel
) {
266 // First we need to print the live range markers for any active
267 // columns to the left of this one.
268 OS
.PadToColumn(getIndentLevel());
269 for (unsigned ColIdx2
= 0; ColIdx2
< ColIdx
; ++ColIdx2
) {
270 if (ActiveCols
[ColIdx2
].isActive()) {
271 if (ActiveCols
[ColIdx2
].MustDrawLabel
&& !ActiveCols
[ColIdx2
].LiveIn
)
272 OS
<< getLineChar(LineChar::LabelVert
) << " ";
274 OS
<< getLineChar(LineChar::RangeMid
) << " ";
279 // Then print the variable name and location of the new live range,
280 // with box drawing characters joining it to the live range line.
281 OS
<< getLineChar(ActiveCols
[ColIdx
].LiveIn
? LineChar::LabelCornerActive
282 : LineChar::LabelCornerNew
)
283 << getLineChar(LineChar::LabelHoriz
) << " ";
284 WithColor(OS
, raw_ostream::GREEN
)
285 << LiveVariables
[ActiveCols
[ColIdx
].VarIdx
].VarName
;
288 WithColor
ExprColor(OS
, raw_ostream::CYAN
);
289 LiveVariables
[ActiveCols
[ColIdx
].VarIdx
].print(OS
, MRI
);
292 // If there are any columns to the right of the expression we just
293 // printed, then continue their live range lines.
294 unsigned FirstUnprintedColumn
= moveToFirstVarColumn(OS
);
295 for (unsigned ColIdx2
= FirstUnprintedColumn
, End
= ActiveCols
.size();
296 ColIdx2
< End
; ++ColIdx2
) {
297 if (ActiveCols
[ColIdx2
].isActive() && ActiveCols
[ColIdx2
].LiveIn
)
298 OS
<< getLineChar(LineChar::RangeMid
) << " ";
304 PrintedSomething
= true;
308 for (unsigned ColIdx
= 0, End
= ActiveCols
.size(); ColIdx
< End
; ++ColIdx
)
309 if (ActiveCols
[ColIdx
].isActive())
310 ActiveCols
[ColIdx
].MustDrawLabel
= false;
312 // If we must print something (because we printed a line/column number),
313 // but don't have any new variables to print, then print a line which
314 // just continues any existing live ranges.
315 if (MustPrint
&& !PrintedSomething
)
316 printAfterOtherLine(OS
, false);
319 /// Print the live variable ranges to the right of a disassembled instruction.
320 void LiveVariablePrinter::printAfterInst(formatted_raw_ostream
&OS
) {
321 if (!ActiveCols
.size())
323 unsigned FirstUnprintedColumn
= moveToFirstVarColumn(OS
);
324 for (unsigned ColIdx
= FirstUnprintedColumn
, End
= ActiveCols
.size();
325 ColIdx
< End
; ++ColIdx
) {
326 if (!ActiveCols
[ColIdx
].isActive())
328 else if (ActiveCols
[ColIdx
].LiveIn
&& ActiveCols
[ColIdx
].LiveOut
)
329 OS
<< getLineChar(LineChar::RangeMid
) << " ";
330 else if (ActiveCols
[ColIdx
].LiveOut
)
331 OS
<< getLineChar(LineChar::RangeStart
) << " ";
332 else if (ActiveCols
[ColIdx
].LiveIn
)
333 OS
<< getLineChar(LineChar::RangeEnd
) << " ";
335 llvm_unreachable("var must be live in or out!");
339 bool SourcePrinter::cacheSource(const DILineInfo
&LineInfo
) {
340 std::unique_ptr
<MemoryBuffer
> Buffer
;
341 if (LineInfo
.Source
) {
342 Buffer
= MemoryBuffer::getMemBuffer(*LineInfo
.Source
);
345 MemoryBuffer::getFile(LineInfo
.FileName
, /*IsText=*/true);
346 if (!BufferOrError
) {
347 if (MissingSources
.insert(LineInfo
.FileName
).second
)
348 reportWarning("failed to find source " + LineInfo
.FileName
,
352 Buffer
= std::move(*BufferOrError
);
354 // Chomp the file to get lines
355 const char *BufferStart
= Buffer
->getBufferStart(),
356 *BufferEnd
= Buffer
->getBufferEnd();
357 std::vector
<StringRef
> &Lines
= LineCache
[LineInfo
.FileName
];
358 const char *Start
= BufferStart
;
359 for (const char *I
= BufferStart
; I
!= BufferEnd
; ++I
)
361 Lines
.emplace_back(Start
, I
- Start
- (BufferStart
< I
&& I
[-1] == '\r'));
364 if (Start
< BufferEnd
)
365 Lines
.emplace_back(Start
, BufferEnd
- Start
);
366 SourceCache
[LineInfo
.FileName
] = std::move(Buffer
);
370 void SourcePrinter::printSourceLine(formatted_raw_ostream
&OS
,
371 object::SectionedAddress Address
,
372 StringRef ObjectFilename
,
373 LiveVariablePrinter
&LVP
,
374 StringRef Delimiter
) {
378 DILineInfo LineInfo
= DILineInfo();
379 Expected
<DILineInfo
> ExpectedLineInfo
=
380 Symbolizer
->symbolizeCode(*Obj
, Address
);
381 std::string ErrorMessage
;
382 if (ExpectedLineInfo
) {
383 LineInfo
= *ExpectedLineInfo
;
384 } else if (!WarnedInvalidDebugInfo
) {
385 WarnedInvalidDebugInfo
= true;
387 reportWarning("failed to parse debug information: " +
388 toString(ExpectedLineInfo
.takeError()),
392 if (!objdump::Prefix
.empty() &&
393 sys::path::is_absolute_gnu(LineInfo
.FileName
)) {
394 // FileName has at least one character since is_absolute_gnu is false for
396 assert(!LineInfo
.FileName
.empty());
397 if (PrefixStrip
> 0) {
399 auto StrippedNameStart
= LineInfo
.FileName
.begin();
401 // Path.h iterator skips extra separators. Therefore it cannot be used
402 // here to keep compatibility with GNU Objdump.
403 for (auto Pos
= StrippedNameStart
+ 1, End
= LineInfo
.FileName
.end();
404 Pos
!= End
&& Level
< PrefixStrip
; ++Pos
) {
405 if (sys::path::is_separator(*Pos
)) {
406 StrippedNameStart
= Pos
;
412 std::string(StrippedNameStart
, LineInfo
.FileName
.end());
415 SmallString
<128> FilePath
;
416 sys::path::append(FilePath
, Prefix
, LineInfo
.FileName
);
418 LineInfo
.FileName
= std::string(FilePath
);
422 printLines(OS
, LineInfo
, Delimiter
, LVP
);
424 printSources(OS
, LineInfo
, ObjectFilename
, Delimiter
, LVP
);
425 OldLineInfo
= LineInfo
;
428 void SourcePrinter::printLines(formatted_raw_ostream
&OS
,
429 const DILineInfo
&LineInfo
, StringRef Delimiter
,
430 LiveVariablePrinter
&LVP
) {
431 bool PrintFunctionName
= LineInfo
.FunctionName
!= DILineInfo::BadString
&&
432 LineInfo
.FunctionName
!= OldLineInfo
.FunctionName
;
433 if (PrintFunctionName
) {
434 OS
<< Delimiter
<< LineInfo
.FunctionName
;
435 // If demangling is successful, FunctionName will end with "()". Print it
436 // only if demangling did not run or was unsuccessful.
437 if (!StringRef(LineInfo
.FunctionName
).ends_with("()"))
441 if (LineInfo
.FileName
!= DILineInfo::BadString
&& LineInfo
.Line
!= 0 &&
442 (OldLineInfo
.Line
!= LineInfo
.Line
||
443 OldLineInfo
.FileName
!= LineInfo
.FileName
|| PrintFunctionName
)) {
444 OS
<< Delimiter
<< LineInfo
.FileName
<< ":" << LineInfo
.Line
;
445 LVP
.printBetweenInsts(OS
, true);
449 // Get the source line text for LineInfo:
450 // - use LineInfo::LineSource if available;
451 // - use LineCache if LineInfo::Source otherwise.
452 StringRef
SourcePrinter::getLine(const DILineInfo
&LineInfo
,
453 StringRef ObjectFilename
) {
454 if (LineInfo
.LineSource
)
455 return LineInfo
.LineSource
.value();
457 if (SourceCache
.find(LineInfo
.FileName
) == SourceCache
.end())
458 if (!cacheSource(LineInfo
))
461 auto LineBuffer
= LineCache
.find(LineInfo
.FileName
);
462 if (LineBuffer
== LineCache
.end())
465 if (LineInfo
.Line
> LineBuffer
->second
.size()) {
467 formatv("debug info line number {0} exceeds the number of lines in {1}",
468 LineInfo
.Line
, LineInfo
.FileName
),
473 // Vector begins at 0, line numbers are non-zero
474 return LineBuffer
->second
[LineInfo
.Line
- 1];
477 void SourcePrinter::printSources(formatted_raw_ostream
&OS
,
478 const DILineInfo
&LineInfo
,
479 StringRef ObjectFilename
, StringRef Delimiter
,
480 LiveVariablePrinter
&LVP
) {
481 if (LineInfo
.FileName
== DILineInfo::BadString
|| LineInfo
.Line
== 0 ||
482 (OldLineInfo
.Line
== LineInfo
.Line
&&
483 OldLineInfo
.FileName
== LineInfo
.FileName
))
486 StringRef Line
= getLine(LineInfo
, ObjectFilename
);
488 OS
<< Delimiter
<< Line
;
489 LVP
.printBetweenInsts(OS
, true);
493 SourcePrinter::SourcePrinter(const object::ObjectFile
*Obj
,
494 StringRef DefaultArch
)
496 symbolize::LLVMSymbolizer::Options SymbolizerOpts
;
497 SymbolizerOpts
.PrintFunctions
=
498 DILineInfoSpecifier::FunctionNameKind::LinkageName
;
499 SymbolizerOpts
.Demangle
= Demangle
;
500 SymbolizerOpts
.DefaultArch
= std::string(DefaultArch
);
501 Symbolizer
.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts
));
504 } // namespace objdump