1c623945dSTim Northover //===-- SourcePrinter.cpp - source interleaving utilities ----------------===// 2c623945dSTim Northover // 3c623945dSTim Northover // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4c623945dSTim Northover // See https://llvm.org/LICENSE.txt for license information. 5c623945dSTim Northover // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c623945dSTim Northover // 7c623945dSTim Northover //===----------------------------------------------------------------------===// 8c623945dSTim Northover // 9c623945dSTim Northover // This file implements the LiveVariablePrinter and SourcePrinter classes to 10c623945dSTim Northover // keep track of DWARF info as the current address is updated, and print out the 11c623945dSTim Northover // source file line and variable liveness as needed. 12c623945dSTim Northover // 13c623945dSTim Northover //===----------------------------------------------------------------------===// 14c623945dSTim Northover 15c623945dSTim Northover #include "SourcePrinter.h" 16c623945dSTim Northover #include "llvm-objdump.h" 17c623945dSTim Northover #include "llvm/ADT/SmallSet.h" 18290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFExpression.h" 19c623945dSTim Northover #include "llvm/Support/FormatVariadic.h" 20c623945dSTim Northover 21c623945dSTim Northover #define DEBUG_TYPE "objdump" 22c623945dSTim Northover 23c623945dSTim Northover namespace llvm { 24c623945dSTim Northover namespace objdump { 25c623945dSTim Northover 26c623945dSTim Northover bool LiveVariable::liveAtAddress(object::SectionedAddress Addr) { 27b4482f7cSKazu Hirata if (LocExpr.Range == std::nullopt) 28c623945dSTim Northover return false; 29c623945dSTim Northover return LocExpr.Range->SectionIndex == Addr.SectionIndex && 30c623945dSTim Northover LocExpr.Range->LowPC <= Addr.Address && 31c623945dSTim Northover LocExpr.Range->HighPC > Addr.Address; 32c623945dSTim Northover } 33c623945dSTim Northover 34c623945dSTim Northover void LiveVariable::print(raw_ostream &OS, const MCRegisterInfo &MRI) const { 35c623945dSTim Northover DataExtractor Data({LocExpr.Expr.data(), LocExpr.Expr.size()}, 36c623945dSTim Northover Unit->getContext().isLittleEndian(), 0); 37c623945dSTim Northover DWARFExpression Expression(Data, Unit->getAddressByteSize()); 38617ed4f0SShubham Sandeep Rastogi 39617ed4f0SShubham Sandeep Rastogi auto GetRegName = [&MRI, &OS](uint64_t DwarfRegNum, bool IsEH) -> StringRef { 40f78a48cfSCraig Topper if (std::optional<MCRegister> LLVMRegNum = 41617ed4f0SShubham Sandeep Rastogi MRI.getLLVMRegNum(DwarfRegNum, IsEH)) 42617ed4f0SShubham Sandeep Rastogi if (const char *RegName = MRI.getName(*LLVMRegNum)) 43617ed4f0SShubham Sandeep Rastogi return StringRef(RegName); 44617ed4f0SShubham Sandeep Rastogi OS << "<unknown register " << DwarfRegNum << ">"; 45617ed4f0SShubham Sandeep Rastogi return {}; 46617ed4f0SShubham Sandeep Rastogi }; 47617ed4f0SShubham Sandeep Rastogi 48617ed4f0SShubham Sandeep Rastogi Expression.printCompact(OS, GetRegName); 49c623945dSTim Northover } 50c623945dSTim Northover 51c623945dSTim Northover void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) { 52c623945dSTim Northover uint64_t FuncLowPC, FuncHighPC, SectionIndex; 53c623945dSTim Northover FuncDie.getLowAndHighPC(FuncLowPC, FuncHighPC, SectionIndex); 54c623945dSTim Northover const char *VarName = VarDie.getName(DINameKind::ShortName); 55c623945dSTim Northover DWARFUnit *U = VarDie.getDwarfUnit(); 56c623945dSTim Northover 57c623945dSTim Northover Expected<DWARFLocationExpressionsVector> Locs = 58c623945dSTim Northover VarDie.getLocations(dwarf::DW_AT_location); 59c623945dSTim Northover if (!Locs) { 60c623945dSTim Northover // If the variable doesn't have any locations, just ignore it. We don't 61c623945dSTim Northover // report an error or warning here as that could be noisy on optimised 62c623945dSTim Northover // code. 63c623945dSTim Northover consumeError(Locs.takeError()); 64c623945dSTim Northover return; 65c623945dSTim Northover } 66c623945dSTim Northover 67c623945dSTim Northover for (const DWARFLocationExpression &LocExpr : *Locs) { 68c623945dSTim Northover if (LocExpr.Range) { 69c623945dSTim Northover LiveVariables.emplace_back(LocExpr, VarName, U, FuncDie); 70c623945dSTim Northover } else { 71c623945dSTim Northover // If the LocExpr does not have an associated range, it is valid for 72c623945dSTim Northover // the whole of the function. 73c623945dSTim Northover // TODO: technically it is not valid for any range covered by another 74c623945dSTim Northover // LocExpr, does that happen in reality? 75c623945dSTim Northover DWARFLocationExpression WholeFuncExpr{ 76c623945dSTim Northover DWARFAddressRange(FuncLowPC, FuncHighPC, SectionIndex), LocExpr.Expr}; 77c623945dSTim Northover LiveVariables.emplace_back(WholeFuncExpr, VarName, U, FuncDie); 78c623945dSTim Northover } 79c623945dSTim Northover } 80c623945dSTim Northover } 81c623945dSTim Northover 82c623945dSTim Northover void LiveVariablePrinter::addFunction(DWARFDie D) { 83c623945dSTim Northover for (const DWARFDie &Child : D.children()) { 84c623945dSTim Northover if (Child.getTag() == dwarf::DW_TAG_variable || 85c623945dSTim Northover Child.getTag() == dwarf::DW_TAG_formal_parameter) 86c623945dSTim Northover addVariable(D, Child); 87c623945dSTim Northover else 88c623945dSTim Northover addFunction(Child); 89c623945dSTim Northover } 90c623945dSTim Northover } 91c623945dSTim Northover 92c623945dSTim Northover // Get the column number (in characters) at which the first live variable 93c623945dSTim Northover // line should be printed. 94c623945dSTim Northover unsigned LiveVariablePrinter::getIndentLevel() const { 95c623945dSTim Northover return DbgIndent + getInstStartColumn(STI); 96c623945dSTim Northover } 97c623945dSTim Northover 98c623945dSTim Northover // Indent to the first live-range column to the right of the currently 99c623945dSTim Northover // printed line, and return the index of that column. 100c623945dSTim Northover // TODO: formatted_raw_ostream uses "column" to mean a number of characters 101c623945dSTim Northover // since the last \n, and we use it to mean the number of slots in which we 102c623945dSTim Northover // put live variable lines. Pick a less overloaded word. 103c623945dSTim Northover unsigned LiveVariablePrinter::moveToFirstVarColumn(formatted_raw_ostream &OS) { 104c623945dSTim Northover // Logical column number: column zero is the first column we print in, each 105c623945dSTim Northover // logical column is 2 physical columns wide. 106c623945dSTim Northover unsigned FirstUnprintedLogicalColumn = 107c623945dSTim Northover std::max((int)(OS.getColumn() - getIndentLevel() + 1) / 2, 0); 108c623945dSTim Northover // Physical column number: the actual column number in characters, with 109c623945dSTim Northover // zero being the left-most side of the screen. 110c623945dSTim Northover unsigned FirstUnprintedPhysicalColumn = 111c623945dSTim Northover getIndentLevel() + FirstUnprintedLogicalColumn * 2; 112c623945dSTim Northover 113c623945dSTim Northover if (FirstUnprintedPhysicalColumn > OS.getColumn()) 114c623945dSTim Northover OS.PadToColumn(FirstUnprintedPhysicalColumn); 115c623945dSTim Northover 116c623945dSTim Northover return FirstUnprintedLogicalColumn; 117c623945dSTim Northover } 118c623945dSTim Northover 119c623945dSTim Northover unsigned LiveVariablePrinter::findFreeColumn() { 120c623945dSTim Northover for (unsigned ColIdx = 0; ColIdx < ActiveCols.size(); ++ColIdx) 121c623945dSTim Northover if (!ActiveCols[ColIdx].isActive()) 122c623945dSTim Northover return ColIdx; 123c623945dSTim Northover 124c623945dSTim Northover size_t OldSize = ActiveCols.size(); 125c623945dSTim Northover ActiveCols.grow(std::max<size_t>(OldSize * 2, 1)); 126c623945dSTim Northover return OldSize; 127c623945dSTim Northover } 128c623945dSTim Northover 129c623945dSTim Northover void LiveVariablePrinter::dump() const { 130c623945dSTim Northover for (const LiveVariable &LV : LiveVariables) { 131c623945dSTim Northover dbgs() << LV.VarName << " @ " << LV.LocExpr.Range << ": "; 132c623945dSTim Northover LV.print(dbgs(), MRI); 133c623945dSTim Northover dbgs() << "\n"; 134c623945dSTim Northover } 135c623945dSTim Northover } 136c623945dSTim Northover 137c623945dSTim Northover void LiveVariablePrinter::addCompileUnit(DWARFDie D) { 138c623945dSTim Northover if (D.getTag() == dwarf::DW_TAG_subprogram) 139c623945dSTim Northover addFunction(D); 140c623945dSTim Northover else 141c623945dSTim Northover for (const DWARFDie &Child : D.children()) 142c623945dSTim Northover addFunction(Child); 143c623945dSTim Northover } 144c623945dSTim Northover 145c623945dSTim Northover /// Update to match the state of the instruction between ThisAddr and 146c623945dSTim Northover /// NextAddr. In the common case, any live range active at ThisAddr is 147c623945dSTim Northover /// live-in to the instruction, and any live range active at NextAddr is 148c623945dSTim Northover /// live-out of the instruction. If IncludeDefinedVars is false, then live 149c623945dSTim Northover /// ranges starting at NextAddr will be ignored. 150c623945dSTim Northover void LiveVariablePrinter::update(object::SectionedAddress ThisAddr, 151c623945dSTim Northover object::SectionedAddress NextAddr, 152c623945dSTim Northover bool IncludeDefinedVars) { 153c623945dSTim Northover // First, check variables which have already been assigned a column, so 154c623945dSTim Northover // that we don't change their order. 155c623945dSTim Northover SmallSet<unsigned, 8> CheckedVarIdxs; 156c623945dSTim Northover for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) { 157c623945dSTim Northover if (!ActiveCols[ColIdx].isActive()) 158c623945dSTim Northover continue; 159c623945dSTim Northover CheckedVarIdxs.insert(ActiveCols[ColIdx].VarIdx); 160c623945dSTim Northover LiveVariable &LV = LiveVariables[ActiveCols[ColIdx].VarIdx]; 161c623945dSTim Northover ActiveCols[ColIdx].LiveIn = LV.liveAtAddress(ThisAddr); 162c623945dSTim Northover ActiveCols[ColIdx].LiveOut = LV.liveAtAddress(NextAddr); 163c623945dSTim Northover LLVM_DEBUG(dbgs() << "pass 1, " << ThisAddr.Address << "-" 164c623945dSTim Northover << NextAddr.Address << ", " << LV.VarName << ", Col " 165c623945dSTim Northover << ColIdx << ": LiveIn=" << ActiveCols[ColIdx].LiveIn 166c623945dSTim Northover << ", LiveOut=" << ActiveCols[ColIdx].LiveOut << "\n"); 167c623945dSTim Northover 168c623945dSTim Northover if (!ActiveCols[ColIdx].LiveIn && !ActiveCols[ColIdx].LiveOut) 169c623945dSTim Northover ActiveCols[ColIdx].VarIdx = Column::NullVarIdx; 170c623945dSTim Northover } 171c623945dSTim Northover 172c623945dSTim Northover // Next, look for variables which don't already have a column, but which 173c623945dSTim Northover // are now live. 174c623945dSTim Northover if (IncludeDefinedVars) { 175c623945dSTim Northover for (unsigned VarIdx = 0, End = LiveVariables.size(); VarIdx < End; 176c623945dSTim Northover ++VarIdx) { 177c623945dSTim Northover if (CheckedVarIdxs.count(VarIdx)) 178c623945dSTim Northover continue; 179c623945dSTim Northover LiveVariable &LV = LiveVariables[VarIdx]; 180c623945dSTim Northover bool LiveIn = LV.liveAtAddress(ThisAddr); 181c623945dSTim Northover bool LiveOut = LV.liveAtAddress(NextAddr); 182c623945dSTim Northover if (!LiveIn && !LiveOut) 183c623945dSTim Northover continue; 184c623945dSTim Northover 185c623945dSTim Northover unsigned ColIdx = findFreeColumn(); 186c623945dSTim Northover LLVM_DEBUG(dbgs() << "pass 2, " << ThisAddr.Address << "-" 187c623945dSTim Northover << NextAddr.Address << ", " << LV.VarName << ", Col " 188c623945dSTim Northover << ColIdx << ": LiveIn=" << LiveIn 189c623945dSTim Northover << ", LiveOut=" << LiveOut << "\n"); 190c623945dSTim Northover ActiveCols[ColIdx].VarIdx = VarIdx; 191c623945dSTim Northover ActiveCols[ColIdx].LiveIn = LiveIn; 192c623945dSTim Northover ActiveCols[ColIdx].LiveOut = LiveOut; 193c623945dSTim Northover ActiveCols[ColIdx].MustDrawLabel = true; 194c623945dSTim Northover } 195c623945dSTim Northover } 196c623945dSTim Northover } 197c623945dSTim Northover 198c623945dSTim Northover enum class LineChar { 199c623945dSTim Northover RangeStart, 200c623945dSTim Northover RangeMid, 201c623945dSTim Northover RangeEnd, 202c623945dSTim Northover LabelVert, 203c623945dSTim Northover LabelCornerNew, 204c623945dSTim Northover LabelCornerActive, 205c623945dSTim Northover LabelHoriz, 206c623945dSTim Northover }; 207c623945dSTim Northover const char *LiveVariablePrinter::getLineChar(LineChar C) const { 208c623945dSTim Northover bool IsASCII = DbgVariables == DVASCII; 209c623945dSTim Northover switch (C) { 210c623945dSTim Northover case LineChar::RangeStart: 211c623945dSTim Northover return IsASCII ? "^" : (const char *)u8"\u2548"; 212c623945dSTim Northover case LineChar::RangeMid: 213c623945dSTim Northover return IsASCII ? "|" : (const char *)u8"\u2503"; 214c623945dSTim Northover case LineChar::RangeEnd: 215c623945dSTim Northover return IsASCII ? "v" : (const char *)u8"\u253b"; 216c623945dSTim Northover case LineChar::LabelVert: 217c623945dSTim Northover return IsASCII ? "|" : (const char *)u8"\u2502"; 218c623945dSTim Northover case LineChar::LabelCornerNew: 219c623945dSTim Northover return IsASCII ? "/" : (const char *)u8"\u250c"; 220c623945dSTim Northover case LineChar::LabelCornerActive: 221c623945dSTim Northover return IsASCII ? "|" : (const char *)u8"\u2520"; 222c623945dSTim Northover case LineChar::LabelHoriz: 223c623945dSTim Northover return IsASCII ? "-" : (const char *)u8"\u2500"; 224c623945dSTim Northover } 225c623945dSTim Northover llvm_unreachable("Unhandled LineChar enum"); 226c623945dSTim Northover } 227c623945dSTim Northover 228c623945dSTim Northover /// Print live ranges to the right of an existing line. This assumes the 229c623945dSTim Northover /// line is not an instruction, so doesn't start or end any live ranges, so 230c623945dSTim Northover /// we only need to print active ranges or empty columns. If AfterInst is 231c623945dSTim Northover /// true, this is being printed after the last instruction fed to update(), 232c623945dSTim Northover /// otherwise this is being printed before it. 233c623945dSTim Northover void LiveVariablePrinter::printAfterOtherLine(formatted_raw_ostream &OS, 234c623945dSTim Northover bool AfterInst) { 235c623945dSTim Northover if (ActiveCols.size()) { 236c623945dSTim Northover unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS); 237c623945dSTim Northover for (size_t ColIdx = FirstUnprintedColumn, End = ActiveCols.size(); 238c623945dSTim Northover ColIdx < End; ++ColIdx) { 239c623945dSTim Northover if (ActiveCols[ColIdx].isActive()) { 240c623945dSTim Northover if ((AfterInst && ActiveCols[ColIdx].LiveOut) || 241c623945dSTim Northover (!AfterInst && ActiveCols[ColIdx].LiveIn)) 242c623945dSTim Northover OS << getLineChar(LineChar::RangeMid); 243c623945dSTim Northover else if (!AfterInst && ActiveCols[ColIdx].LiveOut) 244c623945dSTim Northover OS << getLineChar(LineChar::LabelVert); 245c623945dSTim Northover else 246c623945dSTim Northover OS << " "; 247c623945dSTim Northover } 248c623945dSTim Northover OS << " "; 249c623945dSTim Northover } 250c623945dSTim Northover } 251c623945dSTim Northover OS << "\n"; 252c623945dSTim Northover } 253c623945dSTim Northover 254c623945dSTim Northover /// Print any live variable range info needed to the right of a 255c623945dSTim Northover /// non-instruction line of disassembly. This is where we print the variable 256c623945dSTim Northover /// names and expressions, with thin line-drawing characters connecting them 257c623945dSTim Northover /// to the live range which starts at the next instruction. If MustPrint is 258c623945dSTim Northover /// true, we have to print at least one line (with the continuation of any 259c623945dSTim Northover /// already-active live ranges) because something has already been printed 260c623945dSTim Northover /// earlier on this line. 261c623945dSTim Northover void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream &OS, 262c623945dSTim Northover bool MustPrint) { 263c623945dSTim Northover bool PrintedSomething = false; 264c623945dSTim Northover for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) { 265c623945dSTim Northover if (ActiveCols[ColIdx].isActive() && ActiveCols[ColIdx].MustDrawLabel) { 266c623945dSTim Northover // First we need to print the live range markers for any active 267c623945dSTim Northover // columns to the left of this one. 268c623945dSTim Northover OS.PadToColumn(getIndentLevel()); 269c623945dSTim Northover for (unsigned ColIdx2 = 0; ColIdx2 < ColIdx; ++ColIdx2) { 270c623945dSTim Northover if (ActiveCols[ColIdx2].isActive()) { 271c623945dSTim Northover if (ActiveCols[ColIdx2].MustDrawLabel && !ActiveCols[ColIdx2].LiveIn) 272c623945dSTim Northover OS << getLineChar(LineChar::LabelVert) << " "; 273c623945dSTim Northover else 274c623945dSTim Northover OS << getLineChar(LineChar::RangeMid) << " "; 275c623945dSTim Northover } else 276c623945dSTim Northover OS << " "; 277c623945dSTim Northover } 278c623945dSTim Northover 279c623945dSTim Northover // Then print the variable name and location of the new live range, 280c623945dSTim Northover // with box drawing characters joining it to the live range line. 281c623945dSTim Northover OS << getLineChar(ActiveCols[ColIdx].LiveIn ? LineChar::LabelCornerActive 282c623945dSTim Northover : LineChar::LabelCornerNew) 283c623945dSTim Northover << getLineChar(LineChar::LabelHoriz) << " "; 284c623945dSTim Northover WithColor(OS, raw_ostream::GREEN) 285c623945dSTim Northover << LiveVariables[ActiveCols[ColIdx].VarIdx].VarName; 286c623945dSTim Northover OS << " = "; 287c623945dSTim Northover { 288c623945dSTim Northover WithColor ExprColor(OS, raw_ostream::CYAN); 289c623945dSTim Northover LiveVariables[ActiveCols[ColIdx].VarIdx].print(OS, MRI); 290c623945dSTim Northover } 291c623945dSTim Northover 292c623945dSTim Northover // If there are any columns to the right of the expression we just 293c623945dSTim Northover // printed, then continue their live range lines. 294c623945dSTim Northover unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS); 295c623945dSTim Northover for (unsigned ColIdx2 = FirstUnprintedColumn, End = ActiveCols.size(); 296c623945dSTim Northover ColIdx2 < End; ++ColIdx2) { 297c623945dSTim Northover if (ActiveCols[ColIdx2].isActive() && ActiveCols[ColIdx2].LiveIn) 298c623945dSTim Northover OS << getLineChar(LineChar::RangeMid) << " "; 299c623945dSTim Northover else 300c623945dSTim Northover OS << " "; 301c623945dSTim Northover } 302c623945dSTim Northover 303c623945dSTim Northover OS << "\n"; 304c623945dSTim Northover PrintedSomething = true; 305c623945dSTim Northover } 306c623945dSTim Northover } 307c623945dSTim Northover 308c623945dSTim Northover for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) 309c623945dSTim Northover if (ActiveCols[ColIdx].isActive()) 310c623945dSTim Northover ActiveCols[ColIdx].MustDrawLabel = false; 311c623945dSTim Northover 312c623945dSTim Northover // If we must print something (because we printed a line/column number), 313c623945dSTim Northover // but don't have any new variables to print, then print a line which 314c623945dSTim Northover // just continues any existing live ranges. 315c623945dSTim Northover if (MustPrint && !PrintedSomething) 316c623945dSTim Northover printAfterOtherLine(OS, false); 317c623945dSTim Northover } 318c623945dSTim Northover 319c623945dSTim Northover /// Print the live variable ranges to the right of a disassembled instruction. 320c623945dSTim Northover void LiveVariablePrinter::printAfterInst(formatted_raw_ostream &OS) { 321c623945dSTim Northover if (!ActiveCols.size()) 322c623945dSTim Northover return; 323c623945dSTim Northover unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS); 324c623945dSTim Northover for (unsigned ColIdx = FirstUnprintedColumn, End = ActiveCols.size(); 325c623945dSTim Northover ColIdx < End; ++ColIdx) { 326c623945dSTim Northover if (!ActiveCols[ColIdx].isActive()) 327c623945dSTim Northover OS << " "; 328c623945dSTim Northover else if (ActiveCols[ColIdx].LiveIn && ActiveCols[ColIdx].LiveOut) 329c623945dSTim Northover OS << getLineChar(LineChar::RangeMid) << " "; 330c623945dSTim Northover else if (ActiveCols[ColIdx].LiveOut) 331c623945dSTim Northover OS << getLineChar(LineChar::RangeStart) << " "; 332c623945dSTim Northover else if (ActiveCols[ColIdx].LiveIn) 333c623945dSTim Northover OS << getLineChar(LineChar::RangeEnd) << " "; 334c623945dSTim Northover else 335c623945dSTim Northover llvm_unreachable("var must be live in or out!"); 336c623945dSTim Northover } 337c623945dSTim Northover } 338c623945dSTim Northover 339c623945dSTim Northover bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) { 340c623945dSTim Northover std::unique_ptr<MemoryBuffer> Buffer; 341c623945dSTim Northover if (LineInfo.Source) { 342c623945dSTim Northover Buffer = MemoryBuffer::getMemBuffer(*LineInfo.Source); 343c623945dSTim Northover } else { 344*74dcf0b5SAbhina Sree auto BufferOrError = 345*74dcf0b5SAbhina Sree MemoryBuffer::getFile(LineInfo.FileName, /*IsText=*/true); 346c623945dSTim Northover if (!BufferOrError) { 347c623945dSTim Northover if (MissingSources.insert(LineInfo.FileName).second) 348c623945dSTim Northover reportWarning("failed to find source " + LineInfo.FileName, 349c623945dSTim Northover Obj->getFileName()); 350c623945dSTim Northover return false; 351c623945dSTim Northover } 352c623945dSTim Northover Buffer = std::move(*BufferOrError); 353c623945dSTim Northover } 354c623945dSTim Northover // Chomp the file to get lines 355c623945dSTim Northover const char *BufferStart = Buffer->getBufferStart(), 356c623945dSTim Northover *BufferEnd = Buffer->getBufferEnd(); 357c623945dSTim Northover std::vector<StringRef> &Lines = LineCache[LineInfo.FileName]; 358c623945dSTim Northover const char *Start = BufferStart; 359c623945dSTim Northover for (const char *I = BufferStart; I != BufferEnd; ++I) 360c623945dSTim Northover if (*I == '\n') { 361c623945dSTim Northover Lines.emplace_back(Start, I - Start - (BufferStart < I && I[-1] == '\r')); 362c623945dSTim Northover Start = I + 1; 363c623945dSTim Northover } 364c623945dSTim Northover if (Start < BufferEnd) 365c623945dSTim Northover Lines.emplace_back(Start, BufferEnd - Start); 366c623945dSTim Northover SourceCache[LineInfo.FileName] = std::move(Buffer); 367c623945dSTim Northover return true; 368c623945dSTim Northover } 369c623945dSTim Northover 370c623945dSTim Northover void SourcePrinter::printSourceLine(formatted_raw_ostream &OS, 371c623945dSTim Northover object::SectionedAddress Address, 372c623945dSTim Northover StringRef ObjectFilename, 373c623945dSTim Northover LiveVariablePrinter &LVP, 374c623945dSTim Northover StringRef Delimiter) { 375c623945dSTim Northover if (!Symbolizer) 376c623945dSTim Northover return; 377c623945dSTim Northover 378c623945dSTim Northover DILineInfo LineInfo = DILineInfo(); 379c623945dSTim Northover Expected<DILineInfo> ExpectedLineInfo = 380c623945dSTim Northover Symbolizer->symbolizeCode(*Obj, Address); 381c623945dSTim Northover std::string ErrorMessage; 382c623945dSTim Northover if (ExpectedLineInfo) { 383c623945dSTim Northover LineInfo = *ExpectedLineInfo; 384c623945dSTim Northover } else if (!WarnedInvalidDebugInfo) { 385c623945dSTim Northover WarnedInvalidDebugInfo = true; 386c623945dSTim Northover // TODO Untested. 387c623945dSTim Northover reportWarning("failed to parse debug information: " + 388c623945dSTim Northover toString(ExpectedLineInfo.takeError()), 389c623945dSTim Northover ObjectFilename); 390c623945dSTim Northover } 391c623945dSTim Northover 392c623945dSTim Northover if (!objdump::Prefix.empty() && 393c623945dSTim Northover sys::path::is_absolute_gnu(LineInfo.FileName)) { 394c623945dSTim Northover // FileName has at least one character since is_absolute_gnu is false for 395c623945dSTim Northover // an empty string. 396c623945dSTim Northover assert(!LineInfo.FileName.empty()); 397c623945dSTim Northover if (PrefixStrip > 0) { 398c623945dSTim Northover uint32_t Level = 0; 399c623945dSTim Northover auto StrippedNameStart = LineInfo.FileName.begin(); 400c623945dSTim Northover 401c623945dSTim Northover // Path.h iterator skips extra separators. Therefore it cannot be used 402c623945dSTim Northover // here to keep compatibility with GNU Objdump. 403c623945dSTim Northover for (auto Pos = StrippedNameStart + 1, End = LineInfo.FileName.end(); 404c623945dSTim Northover Pos != End && Level < PrefixStrip; ++Pos) { 405c623945dSTim Northover if (sys::path::is_separator(*Pos)) { 406c623945dSTim Northover StrippedNameStart = Pos; 407c623945dSTim Northover ++Level; 408c623945dSTim Northover } 409c623945dSTim Northover } 410c623945dSTim Northover 411c623945dSTim Northover LineInfo.FileName = 412c623945dSTim Northover std::string(StrippedNameStart, LineInfo.FileName.end()); 413c623945dSTim Northover } 414c623945dSTim Northover 415c623945dSTim Northover SmallString<128> FilePath; 416c623945dSTim Northover sys::path::append(FilePath, Prefix, LineInfo.FileName); 417c623945dSTim Northover 418c623945dSTim Northover LineInfo.FileName = std::string(FilePath); 419c623945dSTim Northover } 420c623945dSTim Northover 421c623945dSTim Northover if (PrintLines) 422c623945dSTim Northover printLines(OS, LineInfo, Delimiter, LVP); 423c623945dSTim Northover if (PrintSource) 424c623945dSTim Northover printSources(OS, LineInfo, ObjectFilename, Delimiter, LVP); 425c623945dSTim Northover OldLineInfo = LineInfo; 426c623945dSTim Northover } 427c623945dSTim Northover 428c623945dSTim Northover void SourcePrinter::printLines(formatted_raw_ostream &OS, 429c623945dSTim Northover const DILineInfo &LineInfo, StringRef Delimiter, 430c623945dSTim Northover LiveVariablePrinter &LVP) { 431c623945dSTim Northover bool PrintFunctionName = LineInfo.FunctionName != DILineInfo::BadString && 432c623945dSTim Northover LineInfo.FunctionName != OldLineInfo.FunctionName; 433c623945dSTim Northover if (PrintFunctionName) { 434c623945dSTim Northover OS << Delimiter << LineInfo.FunctionName; 435c623945dSTim Northover // If demangling is successful, FunctionName will end with "()". Print it 436c623945dSTim Northover // only if demangling did not run or was unsuccessful. 437586ecdf2SKazu Hirata if (!StringRef(LineInfo.FunctionName).ends_with("()")) 438c623945dSTim Northover OS << "()"; 439c623945dSTim Northover OS << ":\n"; 440c623945dSTim Northover } 441c623945dSTim Northover if (LineInfo.FileName != DILineInfo::BadString && LineInfo.Line != 0 && 442c623945dSTim Northover (OldLineInfo.Line != LineInfo.Line || 443c623945dSTim Northover OldLineInfo.FileName != LineInfo.FileName || PrintFunctionName)) { 444c623945dSTim Northover OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line; 445c623945dSTim Northover LVP.printBetweenInsts(OS, true); 446c623945dSTim Northover } 447c623945dSTim Northover } 448c623945dSTim Northover 449c8e055d4SEduard Zingerman // Get the source line text for LineInfo: 450c8e055d4SEduard Zingerman // - use LineInfo::LineSource if available; 451c8e055d4SEduard Zingerman // - use LineCache if LineInfo::Source otherwise. 452c8e055d4SEduard Zingerman StringRef SourcePrinter::getLine(const DILineInfo &LineInfo, 453c8e055d4SEduard Zingerman StringRef ObjectFilename) { 454c8e055d4SEduard Zingerman if (LineInfo.LineSource) 455c8e055d4SEduard Zingerman return LineInfo.LineSource.value(); 456c8e055d4SEduard Zingerman 457c8e055d4SEduard Zingerman if (SourceCache.find(LineInfo.FileName) == SourceCache.end()) 458c8e055d4SEduard Zingerman if (!cacheSource(LineInfo)) 459c8e055d4SEduard Zingerman return {}; 460c8e055d4SEduard Zingerman 461c8e055d4SEduard Zingerman auto LineBuffer = LineCache.find(LineInfo.FileName); 462c8e055d4SEduard Zingerman if (LineBuffer == LineCache.end()) 463c8e055d4SEduard Zingerman return {}; 464c8e055d4SEduard Zingerman 465c8e055d4SEduard Zingerman if (LineInfo.Line > LineBuffer->second.size()) { 466c8e055d4SEduard Zingerman reportWarning( 467c8e055d4SEduard Zingerman formatv("debug info line number {0} exceeds the number of lines in {1}", 468c8e055d4SEduard Zingerman LineInfo.Line, LineInfo.FileName), 469c8e055d4SEduard Zingerman ObjectFilename); 470c8e055d4SEduard Zingerman return {}; 471c8e055d4SEduard Zingerman } 472c8e055d4SEduard Zingerman 473c8e055d4SEduard Zingerman // Vector begins at 0, line numbers are non-zero 474c8e055d4SEduard Zingerman return LineBuffer->second[LineInfo.Line - 1]; 475c8e055d4SEduard Zingerman } 476c8e055d4SEduard Zingerman 477c623945dSTim Northover void SourcePrinter::printSources(formatted_raw_ostream &OS, 478c623945dSTim Northover const DILineInfo &LineInfo, 479c623945dSTim Northover StringRef ObjectFilename, StringRef Delimiter, 480c623945dSTim Northover LiveVariablePrinter &LVP) { 481c623945dSTim Northover if (LineInfo.FileName == DILineInfo::BadString || LineInfo.Line == 0 || 482c623945dSTim Northover (OldLineInfo.Line == LineInfo.Line && 483c623945dSTim Northover OldLineInfo.FileName == LineInfo.FileName)) 484c623945dSTim Northover return; 485c623945dSTim Northover 486c8e055d4SEduard Zingerman StringRef Line = getLine(LineInfo, ObjectFilename); 487c8e055d4SEduard Zingerman if (!Line.empty()) { 488c8e055d4SEduard Zingerman OS << Delimiter << Line; 489c623945dSTim Northover LVP.printBetweenInsts(OS, true); 490c623945dSTim Northover } 491c623945dSTim Northover } 492c623945dSTim Northover 493c623945dSTim Northover SourcePrinter::SourcePrinter(const object::ObjectFile *Obj, 494c623945dSTim Northover StringRef DefaultArch) 495c623945dSTim Northover : Obj(Obj) { 496c623945dSTim Northover symbolize::LLVMSymbolizer::Options SymbolizerOpts; 497c623945dSTim Northover SymbolizerOpts.PrintFunctions = 498c623945dSTim Northover DILineInfoSpecifier::FunctionNameKind::LinkageName; 499c623945dSTim Northover SymbolizerOpts.Demangle = Demangle; 500c623945dSTim Northover SymbolizerOpts.DefaultArch = std::string(DefaultArch); 501c623945dSTim Northover Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts)); 502c623945dSTim Northover } 503c623945dSTim Northover 504c623945dSTim Northover } // namespace objdump 505c623945dSTim Northover } // namespace llvm 506