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