1292915Sdim//===- lib/DebugInfo/Symbolize/DIPrinter.cpp ------------------------------===// 2292915Sdim// 3292915Sdim// The LLVM Compiler Infrastructure 4292915Sdim// 5292915Sdim// This file is distributed under the University of Illinois Open Source 6292915Sdim// License. See LICENSE.TXT for details. 7292915Sdim// 8292915Sdim//===----------------------------------------------------------------------===// 9292915Sdim// 10292915Sdim// This file defines the DIPrinter class, which is responsible for printing 11292915Sdim// structures defined in DebugInfo/DIContext.h 12292915Sdim// 13292915Sdim//===----------------------------------------------------------------------===// 14292915Sdim 15292915Sdim#include "llvm/DebugInfo/Symbolize/DIPrinter.h" 16292915Sdim 17292915Sdim#include "llvm/DebugInfo/DIContext.h" 18294024Sdim#include "llvm/Support/LineIterator.h" 19292915Sdim 20292915Sdimnamespace llvm { 21292915Sdimnamespace symbolize { 22292915Sdim 23292915Sdim// By default, DILineInfo contains "<invalid>" for function/filename it 24292915Sdim// cannot fetch. We replace it to "??" to make our output closer to addr2line. 25292915Sdimstatic const char kDILineInfoBadString[] = "<invalid>"; 26292915Sdimstatic const char kBadString[] = "??"; 27292915Sdim 28294024Sdim// Prints source code around in the FileName the Line. 29294024Sdimvoid DIPrinter::printContext(std::string FileName, int64_t Line) { 30294024Sdim if (PrintSourceContext <= 0) 31294024Sdim return; 32294024Sdim 33294024Sdim ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 34294024Sdim MemoryBuffer::getFile(FileName); 35294024Sdim if (!BufOrErr) 36294024Sdim return; 37294024Sdim 38294024Sdim std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get()); 39294024Sdim int64_t FirstLine = 40294024Sdim std::max(static_cast<int64_t>(1), Line - PrintSourceContext / 2); 41294024Sdim int64_t LastLine = FirstLine + PrintSourceContext; 42294024Sdim size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine)); 43294024Sdim 44294024Sdim for (line_iterator I = line_iterator(*Buf, false); 45294024Sdim !I.is_at_eof() && I.line_number() <= LastLine; ++I) { 46294024Sdim int64_t L = I.line_number(); 47294024Sdim if (L >= FirstLine && L <= LastLine) { 48294024Sdim OS << format_decimal(L, MaxLineNumberWidth); 49294024Sdim if (L == Line) 50294024Sdim OS << " >: "; 51294024Sdim else 52294024Sdim OS << " : "; 53294024Sdim OS << *I << "\n"; 54294024Sdim } 55294024Sdim } 56294024Sdim} 57294024Sdim 58294024Sdimvoid DIPrinter::print(const DILineInfo &Info, bool Inlined) { 59292915Sdim if (PrintFunctionNames) { 60292915Sdim std::string FunctionName = Info.FunctionName; 61292915Sdim if (FunctionName == kDILineInfoBadString) 62292915Sdim FunctionName = kBadString; 63292915Sdim 64292915Sdim StringRef Delimiter = (PrintPretty == true) ? " at " : "\n"; 65292915Sdim StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : ""; 66292915Sdim OS << Prefix << FunctionName << Delimiter; 67292915Sdim } 68292915Sdim std::string Filename = Info.FileName; 69292915Sdim if (Filename == kDILineInfoBadString) 70292915Sdim Filename = kBadString; 71292915Sdim OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n"; 72294024Sdim printContext(Filename, Info.Line); 73292915Sdim} 74292915Sdim 75292915SdimDIPrinter &DIPrinter::operator<<(const DILineInfo &Info) { 76294024Sdim print(Info, false); 77292915Sdim return *this; 78292915Sdim} 79292915Sdim 80292915SdimDIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) { 81292915Sdim uint32_t FramesNum = Info.getNumberOfFrames(); 82292915Sdim if (FramesNum == 0) { 83294024Sdim print(DILineInfo(), false); 84292915Sdim return *this; 85292915Sdim } 86292915Sdim for (uint32_t i = 0; i < FramesNum; i++) 87294024Sdim print(Info.getFrame(i), i > 0); 88292915Sdim return *this; 89292915Sdim} 90292915Sdim 91292915SdimDIPrinter &DIPrinter::operator<<(const DIGlobal &Global) { 92292915Sdim std::string Name = Global.Name; 93292915Sdim if (Name == kDILineInfoBadString) 94292915Sdim Name = kBadString; 95292915Sdim OS << Name << "\n"; 96292915Sdim OS << Global.Start << " " << Global.Size << "\n"; 97292915Sdim return *this; 98292915Sdim} 99292915Sdim 100292915Sdim} 101292915Sdim} 102