1//===- lib/DebugInfo/Symbolize/DIPrinter.cpp ------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines the DIPrinter class, which is responsible for printing 11// structures defined in DebugInfo/DIContext.h 12// 13//===----------------------------------------------------------------------===// 14 15#include "llvm/DebugInfo/Symbolize/DIPrinter.h" 16 17#include "llvm/DebugInfo/DIContext.h" 18#include "llvm/Support/LineIterator.h" 19 20namespace llvm { 21namespace symbolize { 22 23// By default, DILineInfo contains "<invalid>" for function/filename it 24// cannot fetch. We replace it to "??" to make our output closer to addr2line. 25static const char kDILineInfoBadString[] = "<invalid>"; 26static const char kBadString[] = "??"; 27 28// Prints source code around in the FileName the Line. 29void DIPrinter::printContext(std::string FileName, int64_t Line) { 30 if (PrintSourceContext <= 0) 31 return; 32 33 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 34 MemoryBuffer::getFile(FileName); 35 if (!BufOrErr) 36 return; 37 38 std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get()); 39 int64_t FirstLine = 40 std::max(static_cast<int64_t>(1), Line - PrintSourceContext / 2); 41 int64_t LastLine = FirstLine + PrintSourceContext; 42 size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine)); 43 44 for (line_iterator I = line_iterator(*Buf, false); 45 !I.is_at_eof() && I.line_number() <= LastLine; ++I) { 46 int64_t L = I.line_number(); 47 if (L >= FirstLine && L <= LastLine) { 48 OS << format_decimal(L, MaxLineNumberWidth); 49 if (L == Line) 50 OS << " >: "; 51 else 52 OS << " : "; 53 OS << *I << "\n"; 54 } 55 } 56} 57 58void DIPrinter::print(const DILineInfo &Info, bool Inlined) { 59 if (PrintFunctionNames) { 60 std::string FunctionName = Info.FunctionName; 61 if (FunctionName == kDILineInfoBadString) 62 FunctionName = kBadString; 63 64 StringRef Delimiter = (PrintPretty == true) ? " at " : "\n"; 65 StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : ""; 66 OS << Prefix << FunctionName << Delimiter; 67 } 68 std::string Filename = Info.FileName; 69 if (Filename == kDILineInfoBadString) 70 Filename = kBadString; 71 OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n"; 72 printContext(Filename, Info.Line); 73} 74 75DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) { 76 print(Info, false); 77 return *this; 78} 79 80DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) { 81 uint32_t FramesNum = Info.getNumberOfFrames(); 82 if (FramesNum == 0) { 83 print(DILineInfo(), false); 84 return *this; 85 } 86 for (uint32_t i = 0; i < FramesNum; i++) 87 print(Info.getFrame(i), i > 0); 88 return *this; 89} 90 91DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) { 92 std::string Name = Global.Name; 93 if (Name == kDILineInfoBadString) 94 Name = kBadString; 95 OS << Name << "\n"; 96 OS << Global.Start << " " << Global.Size << "\n"; 97 return *this; 98} 99 100} 101} 102