diff options
Diffstat (limited to 'llvm/tools/llvm-objdump/SourcePrinter.cpp')
-rw-r--r-- | llvm/tools/llvm-objdump/SourcePrinter.cpp | 238 |
1 files changed, 179 insertions, 59 deletions
diff --git a/llvm/tools/llvm-objdump/SourcePrinter.cpp b/llvm/tools/llvm-objdump/SourcePrinter.cpp index 3630502..b0ff89d 100644 --- a/llvm/tools/llvm-objdump/SourcePrinter.cpp +++ b/llvm/tools/llvm-objdump/SourcePrinter.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// // -// This file implements the LiveVariablePrinter and SourcePrinter classes to +// This file implements the LiveElementPrinter and SourcePrinter classes to // keep track of DWARF info as the current address is updated, and print out the -// source file line and variable liveness as needed. +// source file line and variable or inlined function liveness as needed. // //===----------------------------------------------------------------------===// @@ -17,6 +17,7 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" #include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/Support/FormatVariadic.h" #define DEBUG_TYPE "objdump" @@ -24,7 +25,70 @@ namespace llvm { namespace objdump { -bool LiveVariable::liveAtAddress(object::SectionedAddress Addr) { +bool InlinedFunction::liveAtAddress(object::SectionedAddress Addr) const { + if (!Range.valid()) + return false; + + return Range.LowPC <= Addr.Address && Range.HighPC > Addr.Address; +} + +void InlinedFunction::print(raw_ostream &OS, const MCRegisterInfo &MRI) const { + const char *MangledCallerName = FuncDie.getName(DINameKind::LinkageName); + if (!MangledCallerName) + return; + + if (Demangle) + OS << "inlined into " << demangle(MangledCallerName); + else + OS << "inlined into " << MangledCallerName; +} + +void InlinedFunction::dump(raw_ostream &OS) const { + OS << Name << " @ " << Range << ": "; +} + +void InlinedFunction::printElementLine(raw_ostream &OS, + object::SectionedAddress Addr, + bool IsEnd) const { + bool LiveIn = !IsEnd && Range.LowPC == Addr.Address; + bool LiveOut = IsEnd && Range.HighPC == Addr.Address; + if (!(LiveIn || LiveOut)) + return; + + uint32_t CallFile, CallLine, CallColumn, CallDiscriminator; + InlinedFuncDie.getCallerFrame(CallFile, CallLine, CallColumn, + CallDiscriminator); + const DWARFDebugLine::LineTable *LineTable = + Unit->getContext().getLineTableForUnit(Unit); + std::string FileName; + if (!LineTable->hasFileAtIndex(CallFile)) + return; + if (!LineTable->getFileNameByIndex( + CallFile, Unit->getCompilationDir(), + DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FileName)) + return; + + if (FileName.empty()) + return; + + const char *MangledCallerName = FuncDie.getName(DINameKind::LinkageName); + if (!MangledCallerName) + return; + + std::string CallerName = MangledCallerName; + std::string CalleeName = Name; + if (Demangle) { + CallerName = demangle(MangledCallerName); + CalleeName = demangle(Name); + } + + OS << "; " << FileName << ":" << CallLine << ":" << CallColumn << ": "; + if (IsEnd) + OS << "end of "; + OS << CalleeName << " inlined into " << CallerName << "\n"; +} + +bool LiveVariable::liveAtAddress(object::SectionedAddress Addr) const { if (LocExpr.Range == std::nullopt) return false; return LocExpr.Range->SectionIndex == Addr.SectionIndex && @@ -49,7 +113,24 @@ void LiveVariable::print(raw_ostream &OS, const MCRegisterInfo &MRI) const { printDwarfExpressionCompact(&Expression, OS, GetRegName); } -void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) { +void LiveVariable::dump(raw_ostream &OS) const { + OS << Name << " @ " << LocExpr.Range << ": "; +} + +void LiveElementPrinter::addInlinedFunction(DWARFDie FuncDie, + DWARFDie InlinedFuncDie) { + uint64_t FuncLowPC, FuncHighPC, SectionIndex; + if (!InlinedFuncDie.getLowAndHighPC(FuncLowPC, FuncHighPC, SectionIndex)) + return; + + DWARFUnit *U = InlinedFuncDie.getDwarfUnit(); + const char *InlinedFuncName = InlinedFuncDie.getName(DINameKind::LinkageName); + DWARFAddressRange Range{FuncLowPC, FuncHighPC, SectionIndex}; + LiveElements.emplace_back(std::make_unique<InlinedFunction>( + InlinedFuncName, U, FuncDie, InlinedFuncDie, Range)); +} + +void LiveElementPrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) { uint64_t FuncLowPC, FuncHighPC, SectionIndex; FuncDie.getLowAndHighPC(FuncLowPC, FuncHighPC, SectionIndex); const char *VarName = VarDie.getName(DINameKind::ShortName); @@ -67,7 +148,8 @@ void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) { for (const DWARFLocationExpression &LocExpr : *Locs) { if (LocExpr.Range) { - LiveVariables.emplace_back(LocExpr, VarName, U, FuncDie); + LiveElements.emplace_back( + std::make_unique<LiveVariable>(LocExpr, VarName, U, FuncDie)); } else { // If the LocExpr does not have an associated range, it is valid for // the whole of the function. @@ -75,24 +157,30 @@ void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) { // LocExpr, does that happen in reality? DWARFLocationExpression WholeFuncExpr{ DWARFAddressRange(FuncLowPC, FuncHighPC, SectionIndex), LocExpr.Expr}; - LiveVariables.emplace_back(WholeFuncExpr, VarName, U, FuncDie); + LiveElements.emplace_back( + std::make_unique<LiveVariable>(WholeFuncExpr, VarName, U, FuncDie)); } } } -void LiveVariablePrinter::addFunction(DWARFDie D) { +void LiveElementPrinter::addFunction(DWARFDie D) { for (const DWARFDie &Child : D.children()) { - if (Child.getTag() == dwarf::DW_TAG_variable || - Child.getTag() == dwarf::DW_TAG_formal_parameter) + if (DbgVariables != DFDisabled && + (Child.getTag() == dwarf::DW_TAG_variable || + Child.getTag() == dwarf::DW_TAG_formal_parameter)) { addVariable(D, Child); - else + } else if (DbgInlinedFunctions != DFDisabled && + Child.getTag() == dwarf::DW_TAG_inlined_subroutine) { + addInlinedFunction(D, Child); + addFunction(Child); + } else addFunction(Child); } } -// Get the column number (in characters) at which the first live variable +// Get the column number (in characters) at which the first live element // line should be printed. -unsigned LiveVariablePrinter::getIndentLevel() const { +unsigned LiveElementPrinter::getIndentLevel() const { return DbgIndent + getInstStartColumn(STI); } @@ -100,8 +188,8 @@ unsigned LiveVariablePrinter::getIndentLevel() const { // printed line, and return the index of that column. // TODO: formatted_raw_ostream uses "column" to mean a number of characters // since the last \n, and we use it to mean the number of slots in which we -// put live variable lines. Pick a less overloaded word. -unsigned LiveVariablePrinter::moveToFirstVarColumn(formatted_raw_ostream &OS) { +// put live element lines. Pick a less overloaded word. +unsigned LiveElementPrinter::moveToFirstVarColumn(formatted_raw_ostream &OS) { // Logical column number: column zero is the first column we print in, each // logical column is 2 physical columns wide. unsigned FirstUnprintedLogicalColumn = @@ -117,7 +205,7 @@ unsigned LiveVariablePrinter::moveToFirstVarColumn(formatted_raw_ostream &OS) { return FirstUnprintedLogicalColumn; } -unsigned LiveVariablePrinter::findFreeColumn() { +unsigned LiveElementPrinter::findFreeColumn() { for (unsigned ColIdx = 0; ColIdx < ActiveCols.size(); ++ColIdx) if (!ActiveCols[ColIdx].isActive()) return ColIdx; @@ -127,15 +215,15 @@ unsigned LiveVariablePrinter::findFreeColumn() { return OldSize; } -void LiveVariablePrinter::dump() const { - for (const LiveVariable &LV : LiveVariables) { - dbgs() << LV.VarName << " @ " << LV.LocExpr.Range << ": "; - LV.print(dbgs(), MRI); +void LiveElementPrinter::dump() const { + for (const std::unique_ptr<LiveElement> &LE : LiveElements) { + LE->dump(dbgs()); + LE->print(dbgs(), MRI); dbgs() << "\n"; } } -void LiveVariablePrinter::addCompileUnit(DWARFDie D) { +void LiveElementPrinter::addCompileUnit(DWARFDie D) { if (D.getTag() == dwarf::DW_TAG_subprogram) addFunction(D); else @@ -148,47 +236,57 @@ void LiveVariablePrinter::addCompileUnit(DWARFDie D) { /// live-in to the instruction, and any live range active at NextAddr is /// live-out of the instruction. If IncludeDefinedVars is false, then live /// ranges starting at NextAddr will be ignored. -void LiveVariablePrinter::update(object::SectionedAddress ThisAddr, - object::SectionedAddress NextAddr, - bool IncludeDefinedVars) { +void LiveElementPrinter::update(object::SectionedAddress ThisAddr, + object::SectionedAddress NextAddr, + bool IncludeDefinedVars) { + // Do not create live ranges when debug-inlined-funcs option is provided with + // line format option. + if (DbgInlinedFunctions == DFLimitsOnly) + return; + // First, check variables which have already been assigned a column, so // that we don't change their order. - SmallSet<unsigned, 8> CheckedVarIdxs; + SmallSet<unsigned, 8> CheckedElementIdxs; for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) { if (!ActiveCols[ColIdx].isActive()) continue; - CheckedVarIdxs.insert(ActiveCols[ColIdx].VarIdx); - LiveVariable &LV = LiveVariables[ActiveCols[ColIdx].VarIdx]; - ActiveCols[ColIdx].LiveIn = LV.liveAtAddress(ThisAddr); - ActiveCols[ColIdx].LiveOut = LV.liveAtAddress(NextAddr); + + CheckedElementIdxs.insert(ActiveCols[ColIdx].ElementIdx); + const std::unique_ptr<LiveElement> &LE = + LiveElements[ActiveCols[ColIdx].ElementIdx]; + ActiveCols[ColIdx].LiveIn = LE->liveAtAddress(ThisAddr); + ActiveCols[ColIdx].LiveOut = LE->liveAtAddress(NextAddr); + std::string Name = Demangle ? demangle(LE->getName()) : LE->getName(); LLVM_DEBUG(dbgs() << "pass 1, " << ThisAddr.Address << "-" - << NextAddr.Address << ", " << LV.VarName << ", Col " - << ColIdx << ": LiveIn=" << ActiveCols[ColIdx].LiveIn + << NextAddr.Address << ", " << Name << ", Col " << ColIdx + << ": LiveIn=" << ActiveCols[ColIdx].LiveIn << ", LiveOut=" << ActiveCols[ColIdx].LiveOut << "\n"); if (!ActiveCols[ColIdx].LiveIn && !ActiveCols[ColIdx].LiveOut) - ActiveCols[ColIdx].VarIdx = Column::NullVarIdx; + ActiveCols[ColIdx].ElementIdx = Column::NullElementIdx; } // Next, look for variables which don't already have a column, but which // are now live. if (IncludeDefinedVars) { - for (unsigned VarIdx = 0, End = LiveVariables.size(); VarIdx < End; - ++VarIdx) { - if (CheckedVarIdxs.count(VarIdx)) + for (unsigned ElementIdx = 0, End = LiveElements.size(); ElementIdx < End; + ++ElementIdx) { + if (CheckedElementIdxs.count(ElementIdx)) continue; - LiveVariable &LV = LiveVariables[VarIdx]; - bool LiveIn = LV.liveAtAddress(ThisAddr); - bool LiveOut = LV.liveAtAddress(NextAddr); + + const std::unique_ptr<LiveElement> &LE = LiveElements[ElementIdx]; + bool LiveIn = LE->liveAtAddress(ThisAddr); + bool LiveOut = LE->liveAtAddress(NextAddr); if (!LiveIn && !LiveOut) continue; unsigned ColIdx = findFreeColumn(); + std::string Name = Demangle ? demangle(LE->getName()) : LE->getName(); LLVM_DEBUG(dbgs() << "pass 2, " << ThisAddr.Address << "-" - << NextAddr.Address << ", " << LV.VarName << ", Col " + << NextAddr.Address << ", " << Name << ", Col " << ColIdx << ": LiveIn=" << LiveIn << ", LiveOut=" << LiveOut << "\n"); - ActiveCols[ColIdx].VarIdx = VarIdx; + ActiveCols[ColIdx].ElementIdx = ElementIdx; ActiveCols[ColIdx].LiveIn = LiveIn; ActiveCols[ColIdx].LiveOut = LiveOut; ActiveCols[ColIdx].MustDrawLabel = true; @@ -205,8 +303,8 @@ enum class LineChar { LabelCornerActive, LabelHoriz, }; -const char *LiveVariablePrinter::getLineChar(LineChar C) const { - bool IsASCII = DbgVariables == DVASCII; +const char *LiveElementPrinter::getLineChar(LineChar C) const { + bool IsASCII = DbgVariables == DFASCII || DbgInlinedFunctions == DFASCII; switch (C) { case LineChar::RangeStart: return IsASCII ? "^" : (const char *)u8"\u2548"; @@ -231,8 +329,8 @@ const char *LiveVariablePrinter::getLineChar(LineChar C) const { /// we only need to print active ranges or empty columns. If AfterInst is /// true, this is being printed after the last instruction fed to update(), /// otherwise this is being printed before it. -void LiveVariablePrinter::printAfterOtherLine(formatted_raw_ostream &OS, - bool AfterInst) { +void LiveElementPrinter::printAfterOtherLine(formatted_raw_ostream &OS, + bool AfterInst) { if (ActiveCols.size()) { unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS); for (size_t ColIdx = FirstUnprintedColumn, End = ActiveCols.size(); @@ -252,15 +350,15 @@ void LiveVariablePrinter::printAfterOtherLine(formatted_raw_ostream &OS, OS << "\n"; } -/// Print any live variable range info needed to the right of a -/// non-instruction line of disassembly. This is where we print the variable +/// Print any live element range info needed to the right of a +/// non-instruction line of disassembly. This is where we print the element /// names and expressions, with thin line-drawing characters connecting them /// to the live range which starts at the next instruction. If MustPrint is /// true, we have to print at least one line (with the continuation of any /// already-active live ranges) because something has already been printed /// earlier on this line. -void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream &OS, - bool MustPrint) { +void LiveElementPrinter::printBetweenInsts(formatted_raw_ostream &OS, + bool MustPrint) { bool PrintedSomething = false; for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) { if (ActiveCols[ColIdx].isActive() && ActiveCols[ColIdx].MustDrawLabel) { @@ -277,17 +375,20 @@ void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream &OS, OS << " "; } + const std::unique_ptr<LiveElement> &LE = + LiveElements[ActiveCols[ColIdx].ElementIdx]; // Then print the variable name and location of the new live range, // with box drawing characters joining it to the live range line. OS << getLineChar(ActiveCols[ColIdx].LiveIn ? LineChar::LabelCornerActive : LineChar::LabelCornerNew) << getLineChar(LineChar::LabelHoriz) << " "; - WithColor(OS, raw_ostream::GREEN) - << LiveVariables[ActiveCols[ColIdx].VarIdx].VarName; + + std::string Name = Demangle ? demangle(LE->getName()) : LE->getName(); + WithColor(OS, raw_ostream::GREEN) << Name; OS << " = "; { WithColor ExprColor(OS, raw_ostream::CYAN); - LiveVariables[ActiveCols[ColIdx].VarIdx].print(OS, MRI); + LE->print(OS, MRI); } // If there are any columns to the right of the expression we just @@ -317,8 +418,8 @@ void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream &OS, printAfterOtherLine(OS, false); } -/// Print the live variable ranges to the right of a disassembled instruction. -void LiveVariablePrinter::printAfterInst(formatted_raw_ostream &OS) { +/// Print the live element ranges to the right of a disassembled instruction. +void LiveElementPrinter::printAfterInst(formatted_raw_ostream &OS) { if (!ActiveCols.size()) return; unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS); @@ -337,6 +438,24 @@ void LiveVariablePrinter::printAfterInst(formatted_raw_ostream &OS) { } } +void LiveElementPrinter::printStartLine(formatted_raw_ostream &OS, + object::SectionedAddress Addr) { + // Print a line to idenfity the start of an inlined function if line format + // is specified. + if (DbgInlinedFunctions == DFLimitsOnly) + for (const std::unique_ptr<LiveElement> &LE : LiveElements) + LE->printElementLine(OS, Addr, false); +} + +void LiveElementPrinter::printEndLine(formatted_raw_ostream &OS, + object::SectionedAddress Addr) { + // Print a line to idenfity the end of an inlined function if line format is + // specified. + if (DbgInlinedFunctions == DFLimitsOnly) + for (const std::unique_ptr<LiveElement> &LE : LiveElements) + LE->printElementLine(OS, Addr, true); +} + bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) { std::unique_ptr<MemoryBuffer> Buffer; if (LineInfo.Source) { @@ -371,7 +490,7 @@ bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) { void SourcePrinter::printSourceLine(formatted_raw_ostream &OS, object::SectionedAddress Address, StringRef ObjectFilename, - LiveVariablePrinter &LVP, + LiveElementPrinter &LEP, StringRef Delimiter) { if (!Symbolizer) return; @@ -419,15 +538,16 @@ void SourcePrinter::printSourceLine(formatted_raw_ostream &OS, } if (PrintLines) - printLines(OS, LineInfo, Delimiter, LVP); + printLines(OS, Address, LineInfo, Delimiter, LEP); if (PrintSource) - printSources(OS, LineInfo, ObjectFilename, Delimiter, LVP); + printSources(OS, LineInfo, ObjectFilename, Delimiter, LEP); OldLineInfo = LineInfo; } void SourcePrinter::printLines(formatted_raw_ostream &OS, + object::SectionedAddress Address, const DILineInfo &LineInfo, StringRef Delimiter, - LiveVariablePrinter &LVP) { + LiveElementPrinter &LEP) { bool PrintFunctionName = LineInfo.FunctionName != DILineInfo::BadString && LineInfo.FunctionName != OldLineInfo.FunctionName; if (PrintFunctionName) { @@ -442,7 +562,7 @@ void SourcePrinter::printLines(formatted_raw_ostream &OS, (OldLineInfo.Line != LineInfo.Line || OldLineInfo.FileName != LineInfo.FileName || PrintFunctionName)) { OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line; - LVP.printBetweenInsts(OS, true); + LEP.printBetweenInsts(OS, true); } } @@ -477,7 +597,7 @@ StringRef SourcePrinter::getLine(const DILineInfo &LineInfo, void SourcePrinter::printSources(formatted_raw_ostream &OS, const DILineInfo &LineInfo, StringRef ObjectFilename, StringRef Delimiter, - LiveVariablePrinter &LVP) { + LiveElementPrinter &LEP) { if (LineInfo.FileName == DILineInfo::BadString || LineInfo.Line == 0 || (OldLineInfo.Line == LineInfo.Line && OldLineInfo.FileName == LineInfo.FileName)) @@ -486,7 +606,7 @@ void SourcePrinter::printSources(formatted_raw_ostream &OS, StringRef Line = getLine(LineInfo, ObjectFilename); if (!Line.empty()) { OS << Delimiter << Line; - LVP.printBetweenInsts(OS, true); + LEP.printBetweenInsts(OS, true); } } |