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