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 #include "llvm/ADT/StringRef.h" 17 #include "llvm/DebugInfo/DIContext.h" 18 #include "llvm/Support/ErrorOr.h" 19 #include "llvm/Support/Format.h" 20 #include "llvm/Support/LineIterator.h" 21 #include "llvm/Support/MemoryBuffer.h" 22 #include "llvm/Support/raw_ostream.h" 23 #include <algorithm> 24 #include <cmath> 25 #include <cstddef> 26 #include <cstdint> 27 #include <memory> 28 #include <string> 29 30 namespace llvm { 31 namespace symbolize { 32 33 // By default, DILineInfo contains "<invalid>" for function/filename it 34 // cannot fetch. We replace it to "??" to make our output closer to addr2line. 35 static const char kDILineInfoBadString[] = "<invalid>"; 36 static const char kBadString[] = "??"; 37 38 // Prints source code around in the FileName the Line. 39 void DIPrinter::printContext(const std::string &FileName, int64_t Line) { 40 if (PrintSourceContext <= 0) 41 return; 42 43 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 44 MemoryBuffer::getFile(FileName); 45 if (!BufOrErr) 46 return; 47 48 std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get()); 49 int64_t FirstLine = 50 std::max(static_cast<int64_t>(1), Line - PrintSourceContext / 2); 51 int64_t LastLine = FirstLine + PrintSourceContext; 52 size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine)); 53 54 for (line_iterator I = line_iterator(*Buf, false); 55 !I.is_at_eof() && I.line_number() <= LastLine; ++I) { 56 int64_t L = I.line_number(); 57 if (L >= FirstLine && L <= LastLine) { 58 OS << format_decimal(L, MaxLineNumberWidth); 59 if (L == Line) 60 OS << " >: "; 61 else 62 OS << " : "; 63 OS << *I << "\n"; 64 } 65 } 66 } 67 68 void DIPrinter::print(const DILineInfo &Info, bool Inlined) { 69 if (PrintFunctionNames) { 70 std::string FunctionName = Info.FunctionName; 71 if (FunctionName == kDILineInfoBadString) 72 FunctionName = kBadString; 73 74 StringRef Delimiter = PrintPretty ? " at " : "\n"; 75 StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : ""; 76 OS << Prefix << FunctionName << Delimiter; 77 } 78 std::string Filename = Info.FileName; 79 if (Filename == kDILineInfoBadString) 80 Filename = kBadString; 81 if (!Verbose) { 82 OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n"; 83 printContext(Filename, Info.Line); 84 return; 85 } 86 OS << " Filename: " << Filename << "\n"; 87 if (Info.StartLine) 88 OS << "Function start line: " << Info.StartLine << "\n"; 89 OS << " Line: " << Info.Line << "\n"; 90 OS << " Column: " << Info.Column << "\n"; 91 if (Info.Discriminator) 92 OS << " Discriminator: " << Info.Discriminator << "\n"; 93 } 94 95 DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) { 96 print(Info, false); 97 return *this; 98 } 99 100 DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) { 101 uint32_t FramesNum = Info.getNumberOfFrames(); 102 if (FramesNum == 0) { 103 print(DILineInfo(), false); 104 return *this; 105 } 106 for (uint32_t i = 0; i < FramesNum; i++) 107 print(Info.getFrame(i), i > 0); 108 return *this; 109 } 110 111 DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) { 112 std::string Name = Global.Name; 113 if (Name == kDILineInfoBadString) 114 Name = kBadString; 115 OS << Name << "\n"; 116 OS << Global.Start << " " << Global.Size << "\n"; 117 return *this; 118 } 119 120 } // end namespace symbolize 121 } // end namespace llvm 122