xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp (revision 8bcb0991864975618c09697b1aca10683346d9f0)
10b57cec5SDimitry Andric //===- lib/DebugInfo/Symbolize/DIPrinter.cpp ------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the DIPrinter class, which is responsible for printing
100b57cec5SDimitry Andric // structures defined in DebugInfo/DIContext.h
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/DebugInfo/Symbolize/DIPrinter.h"
150b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
160b57cec5SDimitry Andric #include "llvm/DebugInfo/DIContext.h"
170b57cec5SDimitry Andric #include "llvm/Support/ErrorOr.h"
180b57cec5SDimitry Andric #include "llvm/Support/Format.h"
190b57cec5SDimitry Andric #include "llvm/Support/LineIterator.h"
200b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
210b57cec5SDimitry Andric #include "llvm/Support/Path.h"
220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
230b57cec5SDimitry Andric #include <algorithm>
240b57cec5SDimitry Andric #include <cmath>
250b57cec5SDimitry Andric #include <cstddef>
260b57cec5SDimitry Andric #include <cstdint>
270b57cec5SDimitry Andric #include <memory>
280b57cec5SDimitry Andric #include <string>
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric namespace llvm {
310b57cec5SDimitry Andric namespace symbolize {
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric // Prints source code around in the FileName the Line.
340b57cec5SDimitry Andric void DIPrinter::printContext(const std::string &FileName, int64_t Line) {
350b57cec5SDimitry Andric   if (PrintSourceContext <= 0)
360b57cec5SDimitry Andric     return;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
390b57cec5SDimitry Andric       MemoryBuffer::getFile(FileName);
400b57cec5SDimitry Andric   if (!BufOrErr)
410b57cec5SDimitry Andric     return;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
440b57cec5SDimitry Andric   int64_t FirstLine =
450b57cec5SDimitry Andric       std::max(static_cast<int64_t>(1), Line - PrintSourceContext / 2);
460b57cec5SDimitry Andric   int64_t LastLine = FirstLine + PrintSourceContext;
470b57cec5SDimitry Andric   size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   for (line_iterator I = line_iterator(*Buf, false);
500b57cec5SDimitry Andric        !I.is_at_eof() && I.line_number() <= LastLine; ++I) {
510b57cec5SDimitry Andric     int64_t L = I.line_number();
520b57cec5SDimitry Andric     if (L >= FirstLine && L <= LastLine) {
530b57cec5SDimitry Andric       OS << format_decimal(L, MaxLineNumberWidth);
540b57cec5SDimitry Andric       if (L == Line)
550b57cec5SDimitry Andric         OS << " >: ";
560b57cec5SDimitry Andric       else
570b57cec5SDimitry Andric         OS << "  : ";
580b57cec5SDimitry Andric       OS << *I << "\n";
590b57cec5SDimitry Andric     }
600b57cec5SDimitry Andric   }
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
640b57cec5SDimitry Andric   if (PrintFunctionNames) {
650b57cec5SDimitry Andric     std::string FunctionName = Info.FunctionName;
66*8bcb0991SDimitry Andric     if (FunctionName == DILineInfo::BadString)
67*8bcb0991SDimitry Andric       FunctionName = DILineInfo::Addr2LineBadString;
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric     StringRef Delimiter = PrintPretty ? " at " : "\n";
700b57cec5SDimitry Andric     StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : "";
710b57cec5SDimitry Andric     OS << Prefix << FunctionName << Delimiter;
720b57cec5SDimitry Andric   }
730b57cec5SDimitry Andric   std::string Filename = Info.FileName;
74*8bcb0991SDimitry Andric   if (Filename == DILineInfo::BadString)
75*8bcb0991SDimitry Andric     Filename = DILineInfo::Addr2LineBadString;
760b57cec5SDimitry Andric   else if (Basenames)
770b57cec5SDimitry Andric     Filename = llvm::sys::path::filename(Filename);
780b57cec5SDimitry Andric   if (!Verbose) {
790b57cec5SDimitry Andric     OS << Filename << ":" << Info.Line;
800b57cec5SDimitry Andric     if (Style == OutputStyle::LLVM)
810b57cec5SDimitry Andric       OS << ":" << Info.Column;
820b57cec5SDimitry Andric     OS << "\n";
830b57cec5SDimitry Andric     printContext(Filename, Info.Line);
840b57cec5SDimitry Andric     return;
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric   OS << "  Filename: " << Filename << "\n";
870b57cec5SDimitry Andric   if (Info.StartLine)
880b57cec5SDimitry Andric     OS << "Function start line: " << Info.StartLine << "\n";
890b57cec5SDimitry Andric   OS << "  Line: " << Info.Line << "\n";
900b57cec5SDimitry Andric   OS << "  Column: " << Info.Column << "\n";
910b57cec5SDimitry Andric   if (Info.Discriminator)
920b57cec5SDimitry Andric     OS << "  Discriminator: " << Info.Discriminator << "\n";
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
960b57cec5SDimitry Andric   print(Info, false);
970b57cec5SDimitry Andric   return *this;
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
1010b57cec5SDimitry Andric   uint32_t FramesNum = Info.getNumberOfFrames();
1020b57cec5SDimitry Andric   if (FramesNum == 0) {
1030b57cec5SDimitry Andric     print(DILineInfo(), false);
1040b57cec5SDimitry Andric     return *this;
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric   for (uint32_t i = 0; i < FramesNum; i++)
1070b57cec5SDimitry Andric     print(Info.getFrame(i), i > 0);
1080b57cec5SDimitry Andric   return *this;
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
1120b57cec5SDimitry Andric   std::string Name = Global.Name;
113*8bcb0991SDimitry Andric   if (Name == DILineInfo::BadString)
114*8bcb0991SDimitry Andric     Name = DILineInfo::Addr2LineBadString;
1150b57cec5SDimitry Andric   OS << Name << "\n";
1160b57cec5SDimitry Andric   OS << Global.Start << " " << Global.Size << "\n";
1170b57cec5SDimitry Andric   return *this;
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric DIPrinter &DIPrinter::operator<<(const DILocal &Local) {
1210b57cec5SDimitry Andric   OS << Local.FunctionName << '\n';
1220b57cec5SDimitry Andric   OS << Local.Name << '\n';
1230b57cec5SDimitry Andric   if (Local.DeclFile.empty())
1240b57cec5SDimitry Andric     OS << "??";
1250b57cec5SDimitry Andric   else
1260b57cec5SDimitry Andric     OS << Local.DeclFile;
1270b57cec5SDimitry Andric   OS << ':' << Local.DeclLine << '\n';
1280b57cec5SDimitry Andric   if (Local.FrameOffset)
1290b57cec5SDimitry Andric     OS << *Local.FrameOffset << ' ';
1300b57cec5SDimitry Andric   else
1310b57cec5SDimitry Andric     OS << "?? ";
1320b57cec5SDimitry Andric   if (Local.Size)
1330b57cec5SDimitry Andric     OS << *Local.Size << ' ';
1340b57cec5SDimitry Andric   else
1350b57cec5SDimitry Andric     OS << "?? ";
1360b57cec5SDimitry Andric   if (Local.TagOffset)
1370b57cec5SDimitry Andric     OS << *Local.TagOffset << '\n';
1380b57cec5SDimitry Andric   else
1390b57cec5SDimitry Andric     OS << "??\n";
1400b57cec5SDimitry Andric   return *this;
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric } // end namespace symbolize
1440b57cec5SDimitry Andric } // end namespace llvm
145