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 33fe6060f1SDimitry Andric class SourceCode { 34fe6060f1SDimitry Andric std::unique_ptr<MemoryBuffer> MemBuf; 350b57cec5SDimitry Andric 36*04eeddc0SDimitry Andric Optional<StringRef> load(StringRef FileName, 37fe6060f1SDimitry Andric const Optional<StringRef> &EmbeddedSource) { 38fe6060f1SDimitry Andric if (Lines <= 0) 39fe6060f1SDimitry Andric return None; 40fe6060f1SDimitry Andric 41fe6060f1SDimitry Andric if (EmbeddedSource) 42fe6060f1SDimitry Andric return EmbeddedSource; 43fe6060f1SDimitry Andric else { 440b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 450b57cec5SDimitry Andric MemoryBuffer::getFile(FileName); 460b57cec5SDimitry Andric if (!BufOrErr) 47fe6060f1SDimitry Andric return None; 48fe6060f1SDimitry Andric MemBuf = std::move(*BufOrErr); 49fe6060f1SDimitry Andric return MemBuf->getBuffer(); 50fe6060f1SDimitry Andric } 51fe6060f1SDimitry Andric } 52fe6060f1SDimitry Andric 53*04eeddc0SDimitry Andric Optional<StringRef> pruneSource(const Optional<StringRef> &Source) { 54fe6060f1SDimitry Andric if (!Source) 55fe6060f1SDimitry Andric return None; 56fe6060f1SDimitry Andric size_t FirstLinePos = StringRef::npos, Pos = 0; 57fe6060f1SDimitry Andric for (int64_t L = 1; L <= LastLine; ++L, ++Pos) { 58fe6060f1SDimitry Andric if (L == FirstLine) 59fe6060f1SDimitry Andric FirstLinePos = Pos; 60fe6060f1SDimitry Andric Pos = Source->find('\n', Pos); 61fe6060f1SDimitry Andric if (Pos == StringRef::npos) 62fe6060f1SDimitry Andric break; 63fe6060f1SDimitry Andric } 64fe6060f1SDimitry Andric if (FirstLinePos == StringRef::npos) 65fe6060f1SDimitry Andric return None; 66fe6060f1SDimitry Andric return Source->substr(FirstLinePos, (Pos == StringRef::npos) 67fe6060f1SDimitry Andric ? StringRef::npos 68fe6060f1SDimitry Andric : Pos - FirstLinePos); 69fe6060f1SDimitry Andric } 70fe6060f1SDimitry Andric 71fe6060f1SDimitry Andric public: 72fe6060f1SDimitry Andric const int64_t Line; 73fe6060f1SDimitry Andric const int Lines; 74fe6060f1SDimitry Andric const int64_t FirstLine; 75fe6060f1SDimitry Andric const int64_t LastLine; 76fe6060f1SDimitry Andric const Optional<StringRef> PrunedSource; 77fe6060f1SDimitry Andric 78fe6060f1SDimitry Andric SourceCode( 79fe6060f1SDimitry Andric StringRef FileName, int64_t Line, int Lines, 80fe6060f1SDimitry Andric const Optional<StringRef> &EmbeddedSource = Optional<StringRef>(None)) 81fe6060f1SDimitry Andric : Line(Line), Lines(Lines), 82fe6060f1SDimitry Andric FirstLine(std::max(static_cast<int64_t>(1), Line - Lines / 2)), 83fe6060f1SDimitry Andric LastLine(FirstLine + Lines - 1), 84fe6060f1SDimitry Andric PrunedSource(pruneSource(load(FileName, EmbeddedSource))) {} 85fe6060f1SDimitry Andric 86fe6060f1SDimitry Andric void format(raw_ostream &OS) { 87fe6060f1SDimitry Andric if (!PrunedSource) 880b57cec5SDimitry Andric return; 890b57cec5SDimitry Andric size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine)); 90fe6060f1SDimitry Andric int64_t L = FirstLine; 91fe6060f1SDimitry Andric for (size_t Pos = 0; Pos < PrunedSource->size(); ++L) { 92fe6060f1SDimitry Andric size_t PosEnd = PrunedSource->find('\n', Pos); 93fe6060f1SDimitry Andric StringRef String = PrunedSource->substr( 94fe6060f1SDimitry Andric Pos, (PosEnd == StringRef::npos) ? StringRef::npos : (PosEnd - Pos)); 95fe6060f1SDimitry Andric if (String.endswith("\r")) 96fe6060f1SDimitry Andric String = String.drop_back(1); 970b57cec5SDimitry Andric OS << format_decimal(L, MaxLineNumberWidth); 980b57cec5SDimitry Andric if (L == Line) 990b57cec5SDimitry Andric OS << " >: "; 1000b57cec5SDimitry Andric else 1010b57cec5SDimitry Andric OS << " : "; 102fe6060f1SDimitry Andric OS << String << '\n'; 103fe6060f1SDimitry Andric if (PosEnd == StringRef::npos) 104fe6060f1SDimitry Andric break; 105fe6060f1SDimitry Andric Pos = PosEnd + 1; 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric } 108fe6060f1SDimitry Andric }; 109fe6060f1SDimitry Andric 110fe6060f1SDimitry Andric void PlainPrinterBase::printHeader(uint64_t Address) { 111fe6060f1SDimitry Andric if (Config.PrintAddress) { 112fe6060f1SDimitry Andric OS << "0x"; 113fe6060f1SDimitry Andric OS.write_hex(Address); 114fe6060f1SDimitry Andric StringRef Delimiter = Config.Pretty ? ": " : "\n"; 115fe6060f1SDimitry Andric OS << Delimiter; 116fe6060f1SDimitry Andric } 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 119fe6060f1SDimitry Andric // Prints source code around in the FileName the Line. 120fe6060f1SDimitry Andric void PlainPrinterBase::printContext(SourceCode SourceCode) { 121fe6060f1SDimitry Andric SourceCode.format(OS); 122fe6060f1SDimitry Andric } 123fe6060f1SDimitry Andric 124fe6060f1SDimitry Andric void PlainPrinterBase::printFunctionName(StringRef FunctionName, bool Inlined) { 125fe6060f1SDimitry Andric if (Config.PrintFunctions) { 1268bcb0991SDimitry Andric if (FunctionName == DILineInfo::BadString) 1278bcb0991SDimitry Andric FunctionName = DILineInfo::Addr2LineBadString; 128fe6060f1SDimitry Andric StringRef Delimiter = Config.Pretty ? " at " : "\n"; 129fe6060f1SDimitry Andric StringRef Prefix = (Config.Pretty && Inlined) ? " (inlined by) " : ""; 1300b57cec5SDimitry Andric OS << Prefix << FunctionName << Delimiter; 1310b57cec5SDimitry Andric } 132fe6060f1SDimitry Andric } 133fe6060f1SDimitry Andric 134fe6060f1SDimitry Andric void LLVMPrinter::printSimpleLocation(StringRef Filename, 135fe6060f1SDimitry Andric const DILineInfo &Info) { 136fe6060f1SDimitry Andric OS << Filename << ':' << Info.Line << ':' << Info.Column << '\n'; 137fe6060f1SDimitry Andric printContext( 138fe6060f1SDimitry Andric SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source)); 139fe6060f1SDimitry Andric } 140fe6060f1SDimitry Andric 141fe6060f1SDimitry Andric void GNUPrinter::printSimpleLocation(StringRef Filename, 142fe6060f1SDimitry Andric const DILineInfo &Info) { 143fe6060f1SDimitry Andric OS << Filename << ':' << Info.Line; 144fe6060f1SDimitry Andric if (Info.Discriminator) 145fe6060f1SDimitry Andric OS << " (discriminator " << Info.Discriminator << ')'; 146fe6060f1SDimitry Andric OS << '\n'; 147fe6060f1SDimitry Andric printContext( 148fe6060f1SDimitry Andric SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source)); 149fe6060f1SDimitry Andric } 150fe6060f1SDimitry Andric 151fe6060f1SDimitry Andric void PlainPrinterBase::printVerbose(StringRef Filename, 152fe6060f1SDimitry Andric const DILineInfo &Info) { 153fe6060f1SDimitry Andric OS << " Filename: " << Filename << '\n'; 154fe6060f1SDimitry Andric if (Info.StartLine) { 155fe6060f1SDimitry Andric OS << " Function start filename: " << Info.StartFileName << '\n'; 156fe6060f1SDimitry Andric OS << " Function start line: " << Info.StartLine << '\n'; 157fe6060f1SDimitry Andric } 158fe6060f1SDimitry Andric printStartAddress(Info); 159fe6060f1SDimitry Andric OS << " Line: " << Info.Line << '\n'; 160fe6060f1SDimitry Andric OS << " Column: " << Info.Column << '\n'; 161fe6060f1SDimitry Andric if (Info.Discriminator) 162fe6060f1SDimitry Andric OS << " Discriminator: " << Info.Discriminator << '\n'; 163fe6060f1SDimitry Andric } 164fe6060f1SDimitry Andric 165fe6060f1SDimitry Andric void LLVMPrinter::printStartAddress(const DILineInfo &Info) { 166fe6060f1SDimitry Andric if (Info.StartAddress) { 167fe6060f1SDimitry Andric OS << " Function start address: 0x"; 168fe6060f1SDimitry Andric OS.write_hex(*Info.StartAddress); 169fe6060f1SDimitry Andric OS << '\n'; 170fe6060f1SDimitry Andric } 171fe6060f1SDimitry Andric } 172fe6060f1SDimitry Andric 173fe6060f1SDimitry Andric void LLVMPrinter::printFooter() { OS << '\n'; } 174fe6060f1SDimitry Andric 175fe6060f1SDimitry Andric void PlainPrinterBase::print(const DILineInfo &Info, bool Inlined) { 176fe6060f1SDimitry Andric printFunctionName(Info.FunctionName, Inlined); 177fe6060f1SDimitry Andric StringRef Filename = Info.FileName; 1788bcb0991SDimitry Andric if (Filename == DILineInfo::BadString) 1798bcb0991SDimitry Andric Filename = DILineInfo::Addr2LineBadString; 180fe6060f1SDimitry Andric if (Config.Verbose) 181fe6060f1SDimitry Andric printVerbose(Filename, Info); 182fe6060f1SDimitry Andric else 183fe6060f1SDimitry Andric printSimpleLocation(Filename, Info); 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 186fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, const DILineInfo &Info) { 187fe6060f1SDimitry Andric printHeader(*Request.Address); 1880b57cec5SDimitry Andric print(Info, false); 189fe6060f1SDimitry Andric printFooter(); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric 192fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, 193fe6060f1SDimitry Andric const DIInliningInfo &Info) { 194fe6060f1SDimitry Andric printHeader(*Request.Address); 1950b57cec5SDimitry Andric uint32_t FramesNum = Info.getNumberOfFrames(); 196fe6060f1SDimitry Andric if (FramesNum == 0) 1970b57cec5SDimitry Andric print(DILineInfo(), false); 198fe6060f1SDimitry Andric else 199fe6060f1SDimitry Andric for (uint32_t I = 0; I < FramesNum; ++I) 200fe6060f1SDimitry Andric print(Info.getFrame(I), I > 0); 201fe6060f1SDimitry Andric printFooter(); 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 204fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, const DIGlobal &Global) { 205fe6060f1SDimitry Andric printHeader(*Request.Address); 206fe6060f1SDimitry Andric StringRef Name = Global.Name; 2078bcb0991SDimitry Andric if (Name == DILineInfo::BadString) 2088bcb0991SDimitry Andric Name = DILineInfo::Addr2LineBadString; 2090b57cec5SDimitry Andric OS << Name << "\n"; 2100b57cec5SDimitry Andric OS << Global.Start << " " << Global.Size << "\n"; 211fe6060f1SDimitry Andric printFooter(); 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 214fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, 215fe6060f1SDimitry Andric const std::vector<DILocal> &Locals) { 216fe6060f1SDimitry Andric printHeader(*Request.Address); 217fe6060f1SDimitry Andric if (Locals.empty()) 218fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString << '\n'; 219480093f4SDimitry Andric else 220fe6060f1SDimitry Andric for (const DILocal &L : Locals) { 221fe6060f1SDimitry Andric if (L.FunctionName.empty()) 222fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 223480093f4SDimitry Andric else 224fe6060f1SDimitry Andric OS << L.FunctionName; 225fe6060f1SDimitry Andric OS << '\n'; 226480093f4SDimitry Andric 227fe6060f1SDimitry Andric if (L.Name.empty()) 228fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 2290b57cec5SDimitry Andric else 230fe6060f1SDimitry Andric OS << L.Name; 231fe6060f1SDimitry Andric OS << '\n'; 232480093f4SDimitry Andric 233fe6060f1SDimitry Andric if (L.DeclFile.empty()) 234fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 235fe6060f1SDimitry Andric else 236fe6060f1SDimitry Andric OS << L.DeclFile; 237fe6060f1SDimitry Andric 238fe6060f1SDimitry Andric OS << ':' << L.DeclLine << '\n'; 239fe6060f1SDimitry Andric 240fe6060f1SDimitry Andric if (L.FrameOffset) 241fe6060f1SDimitry Andric OS << *L.FrameOffset; 242fe6060f1SDimitry Andric else 243fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 244fe6060f1SDimitry Andric OS << ' '; 245fe6060f1SDimitry Andric 246fe6060f1SDimitry Andric if (L.Size) 247fe6060f1SDimitry Andric OS << *L.Size; 248fe6060f1SDimitry Andric else 249fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 250fe6060f1SDimitry Andric OS << ' '; 251fe6060f1SDimitry Andric 252fe6060f1SDimitry Andric if (L.TagOffset) 253fe6060f1SDimitry Andric OS << *L.TagOffset; 254fe6060f1SDimitry Andric else 255fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 256fe6060f1SDimitry Andric OS << '\n'; 257fe6060f1SDimitry Andric } 258fe6060f1SDimitry Andric printFooter(); 259fe6060f1SDimitry Andric } 260fe6060f1SDimitry Andric 261fe6060f1SDimitry Andric void PlainPrinterBase::printInvalidCommand(const Request &Request, 262fe6060f1SDimitry Andric StringRef Command) { 263fe6060f1SDimitry Andric OS << Command << '\n'; 264fe6060f1SDimitry Andric } 265fe6060f1SDimitry Andric 266fe6060f1SDimitry Andric bool PlainPrinterBase::printError(const Request &Request, 267fe6060f1SDimitry Andric const ErrorInfoBase &ErrorInfo, 268fe6060f1SDimitry Andric StringRef ErrorBanner) { 269fe6060f1SDimitry Andric ES << ErrorBanner; 270fe6060f1SDimitry Andric ErrorInfo.log(ES); 271fe6060f1SDimitry Andric ES << '\n'; 272fe6060f1SDimitry Andric // Print an empty struct too. 273fe6060f1SDimitry Andric return true; 274fe6060f1SDimitry Andric } 275fe6060f1SDimitry Andric 276fe6060f1SDimitry Andric static std::string toHex(uint64_t V) { 277fe6060f1SDimitry Andric return ("0x" + Twine::utohexstr(V)).str(); 278fe6060f1SDimitry Andric } 279fe6060f1SDimitry Andric 280fe6060f1SDimitry Andric static json::Object toJSON(const Request &Request, StringRef ErrorMsg = "") { 281fe6060f1SDimitry Andric json::Object Json({{"ModuleName", Request.ModuleName.str()}}); 282fe6060f1SDimitry Andric if (Request.Address) 283fe6060f1SDimitry Andric Json["Address"] = toHex(*Request.Address); 284fe6060f1SDimitry Andric if (!ErrorMsg.empty()) 285fe6060f1SDimitry Andric Json["Error"] = json::Object({{"Message", ErrorMsg.str()}}); 286fe6060f1SDimitry Andric return Json; 287fe6060f1SDimitry Andric } 288fe6060f1SDimitry Andric 289fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request, const DILineInfo &Info) { 290fe6060f1SDimitry Andric DIInliningInfo InliningInfo; 291fe6060f1SDimitry Andric InliningInfo.addFrame(Info); 292fe6060f1SDimitry Andric print(Request, InliningInfo); 293fe6060f1SDimitry Andric } 294fe6060f1SDimitry Andric 295fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request, const DIInliningInfo &Info) { 296fe6060f1SDimitry Andric json::Array Array; 297fe6060f1SDimitry Andric for (uint32_t I = 0, N = Info.getNumberOfFrames(); I < N; ++I) { 298fe6060f1SDimitry Andric const DILineInfo &LineInfo = Info.getFrame(I); 299fe6060f1SDimitry Andric json::Object Object( 300fe6060f1SDimitry Andric {{"FunctionName", LineInfo.FunctionName != DILineInfo::BadString 301fe6060f1SDimitry Andric ? LineInfo.FunctionName 302fe6060f1SDimitry Andric : ""}, 303fe6060f1SDimitry Andric {"StartFileName", LineInfo.StartFileName != DILineInfo::BadString 304fe6060f1SDimitry Andric ? LineInfo.StartFileName 305fe6060f1SDimitry Andric : ""}, 306fe6060f1SDimitry Andric {"StartLine", LineInfo.StartLine}, 307fe6060f1SDimitry Andric {"StartAddress", 308fe6060f1SDimitry Andric LineInfo.StartAddress ? toHex(*LineInfo.StartAddress) : ""}, 309fe6060f1SDimitry Andric {"FileName", 310fe6060f1SDimitry Andric LineInfo.FileName != DILineInfo::BadString ? LineInfo.FileName : ""}, 311fe6060f1SDimitry Andric {"Line", LineInfo.Line}, 312fe6060f1SDimitry Andric {"Column", LineInfo.Column}, 313fe6060f1SDimitry Andric {"Discriminator", LineInfo.Discriminator}}); 314fe6060f1SDimitry Andric SourceCode SourceCode(LineInfo.FileName, LineInfo.Line, 315fe6060f1SDimitry Andric Config.SourceContextLines, LineInfo.Source); 316fe6060f1SDimitry Andric std::string FormattedSource; 317fe6060f1SDimitry Andric raw_string_ostream Stream(FormattedSource); 318fe6060f1SDimitry Andric SourceCode.format(Stream); 319fe6060f1SDimitry Andric if (!FormattedSource.empty()) 320fe6060f1SDimitry Andric Object["Source"] = std::move(FormattedSource); 321fe6060f1SDimitry Andric Array.push_back(std::move(Object)); 322fe6060f1SDimitry Andric } 323fe6060f1SDimitry Andric json::Object Json = toJSON(Request); 324fe6060f1SDimitry Andric Json["Symbol"] = std::move(Array); 325fe6060f1SDimitry Andric if (ObjectList) 326fe6060f1SDimitry Andric ObjectList->push_back(std::move(Json)); 327fe6060f1SDimitry Andric else 328fe6060f1SDimitry Andric printJSON(std::move(Json)); 329fe6060f1SDimitry Andric } 330fe6060f1SDimitry Andric 331fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request, const DIGlobal &Global) { 332fe6060f1SDimitry Andric json::Object Data( 333fe6060f1SDimitry Andric {{"Name", Global.Name != DILineInfo::BadString ? Global.Name : ""}, 334fe6060f1SDimitry Andric {"Start", toHex(Global.Start)}, 335fe6060f1SDimitry Andric {"Size", toHex(Global.Size)}}); 336fe6060f1SDimitry Andric json::Object Json = toJSON(Request); 337fe6060f1SDimitry Andric Json["Data"] = std::move(Data); 338fe6060f1SDimitry Andric if (ObjectList) 339fe6060f1SDimitry Andric ObjectList->push_back(std::move(Json)); 340fe6060f1SDimitry Andric else 341fe6060f1SDimitry Andric printJSON(std::move(Json)); 342fe6060f1SDimitry Andric } 343fe6060f1SDimitry Andric 344fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request, 345fe6060f1SDimitry Andric const std::vector<DILocal> &Locals) { 346fe6060f1SDimitry Andric json::Array Frame; 347fe6060f1SDimitry Andric for (const DILocal &Local : Locals) { 348fe6060f1SDimitry Andric json::Object FrameObject( 349fe6060f1SDimitry Andric {{"FunctionName", Local.FunctionName}, 350fe6060f1SDimitry Andric {"Name", Local.Name}, 351fe6060f1SDimitry Andric {"DeclFile", Local.DeclFile}, 352fe6060f1SDimitry Andric {"DeclLine", int64_t(Local.DeclLine)}, 353fe6060f1SDimitry Andric {"Size", Local.Size ? toHex(*Local.Size) : ""}, 354fe6060f1SDimitry Andric {"TagOffset", Local.TagOffset ? toHex(*Local.TagOffset) : ""}}); 3550b57cec5SDimitry Andric if (Local.FrameOffset) 356fe6060f1SDimitry Andric FrameObject["FrameOffset"] = *Local.FrameOffset; 357fe6060f1SDimitry Andric Frame.push_back(std::move(FrameObject)); 358fe6060f1SDimitry Andric } 359fe6060f1SDimitry Andric json::Object Json = toJSON(Request); 360fe6060f1SDimitry Andric Json["Frame"] = std::move(Frame); 361fe6060f1SDimitry Andric if (ObjectList) 362fe6060f1SDimitry Andric ObjectList->push_back(std::move(Json)); 3630b57cec5SDimitry Andric else 364fe6060f1SDimitry Andric printJSON(std::move(Json)); 365fe6060f1SDimitry Andric } 366480093f4SDimitry Andric 367fe6060f1SDimitry Andric void JSONPrinter::printInvalidCommand(const Request &Request, 368fe6060f1SDimitry Andric StringRef Command) { 369fe6060f1SDimitry Andric printError(Request, 370fe6060f1SDimitry Andric StringError("unable to parse arguments: " + Command, 371fe6060f1SDimitry Andric std::make_error_code(std::errc::invalid_argument)), 372fe6060f1SDimitry Andric ""); 373fe6060f1SDimitry Andric } 374480093f4SDimitry Andric 375fe6060f1SDimitry Andric bool JSONPrinter::printError(const Request &Request, 376fe6060f1SDimitry Andric const ErrorInfoBase &ErrorInfo, 377fe6060f1SDimitry Andric StringRef ErrorBanner) { 378fe6060f1SDimitry Andric json::Object Json = toJSON(Request, ErrorInfo.message()); 379fe6060f1SDimitry Andric if (ObjectList) 380fe6060f1SDimitry Andric ObjectList->push_back(std::move(Json)); 3810b57cec5SDimitry Andric else 382fe6060f1SDimitry Andric printJSON(std::move(Json)); 383fe6060f1SDimitry Andric return false; 384fe6060f1SDimitry Andric } 385fe6060f1SDimitry Andric 386fe6060f1SDimitry Andric void JSONPrinter::listBegin() { 387fe6060f1SDimitry Andric assert(!ObjectList); 388fe6060f1SDimitry Andric ObjectList = std::make_unique<json::Array>(); 389fe6060f1SDimitry Andric } 390fe6060f1SDimitry Andric 391fe6060f1SDimitry Andric void JSONPrinter::listEnd() { 392fe6060f1SDimitry Andric assert(ObjectList); 393fe6060f1SDimitry Andric printJSON(std::move(*ObjectList)); 394fe6060f1SDimitry Andric ObjectList.reset(); 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric } // end namespace symbolize 3980b57cec5SDimitry Andric } // end namespace llvm 399