reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
//===- lib/DebugInfo/Symbolize/DIPrinter.cpp ------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the DIPrinter class, which is responsible for printing
// structures defined in DebugInfo/DIContext.h
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/Symbolize/DIPrinter.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>

namespace llvm {
namespace symbolize {

// Prints source code around in the FileName the Line.
void DIPrinter::printContext(const std::string &FileName, int64_t Line) {
  if (PrintSourceContext <= 0)
    return;

  ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
      MemoryBuffer::getFile(FileName);
  if (!BufOrErr)
    return;

  std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
  int64_t FirstLine =
      std::max(static_cast<int64_t>(1), Line - PrintSourceContext / 2);
  int64_t LastLine = FirstLine + PrintSourceContext;
  size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));

  for (line_iterator I = line_iterator(*Buf, false);
       !I.is_at_eof() && I.line_number() <= LastLine; ++I) {
    int64_t L = I.line_number();
    if (L >= FirstLine && L <= LastLine) {
      OS << format_decimal(L, MaxLineNumberWidth);
      if (L == Line)
        OS << " >: ";
      else
        OS << "  : ";
      OS << *I << "\n";
    }
  }
}

void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
  if (PrintFunctionNames) {
    std::string FunctionName = Info.FunctionName;
    if (FunctionName == DILineInfo::BadString)
      FunctionName = DILineInfo::Addr2LineBadString;

    StringRef Delimiter = PrintPretty ? " at " : "\n";
    StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : "";
    OS << Prefix << FunctionName << Delimiter;
  }
  std::string Filename = Info.FileName;
  if (Filename == DILineInfo::BadString)
    Filename = DILineInfo::Addr2LineBadString;
  else if (Basenames)
    Filename = llvm::sys::path::filename(Filename);
  if (!Verbose) {
    OS << Filename << ":" << Info.Line;
    if (Style == OutputStyle::LLVM)
      OS << ":" << Info.Column;
    OS << "\n";
    printContext(Filename, Info.Line);
    return;
  }
  OS << "  Filename: " << Filename << "\n";
  if (Info.StartLine)
    OS << "Function start line: " << Info.StartLine << "\n";
  OS << "  Line: " << Info.Line << "\n";
  OS << "  Column: " << Info.Column << "\n";
  if (Info.Discriminator)
    OS << "  Discriminator: " << Info.Discriminator << "\n";
}

DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
  print(Info, false);
  return *this;
}

DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
  uint32_t FramesNum = Info.getNumberOfFrames();
  if (FramesNum == 0) {
    print(DILineInfo(), false);
    return *this;
  }
  for (uint32_t i = 0; i < FramesNum; i++)
    print(Info.getFrame(i), i > 0);
  return *this;
}

DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
  std::string Name = Global.Name;
  if (Name == DILineInfo::BadString)
    Name = DILineInfo::Addr2LineBadString;
  OS << Name << "\n";
  OS << Global.Start << " " << Global.Size << "\n";
  return *this;
}

DIPrinter &DIPrinter::operator<<(const DILocal &Local) {
  OS << Local.FunctionName << '\n';
  OS << Local.Name << '\n';
  if (Local.DeclFile.empty())
    OS << "??";
  else
    OS << Local.DeclFile;
  OS << ':' << Local.DeclLine << '\n';
  if (Local.FrameOffset)
    OS << *Local.FrameOffset << ' ';
  else
    OS << "?? ";
  if (Local.Size)
    OS << *Local.Size << ' ';
  else
    OS << "?? ";
  if (Local.TagOffset)
    OS << *Local.TagOffset << '\n';
  else
    OS << "??\n";
  return *this;
}

} // end namespace symbolize
} // end namespace llvm