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/MemoryBuffer.h" 200b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 210b57cec5SDimitry Andric #include <algorithm> 220b57cec5SDimitry Andric #include <cmath> 230b57cec5SDimitry Andric #include <cstddef> 240b57cec5SDimitry Andric #include <cstdint> 250b57cec5SDimitry Andric #include <memory> 260b57cec5SDimitry Andric #include <string> 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric namespace llvm { 290b57cec5SDimitry Andric namespace symbolize { 300b57cec5SDimitry Andric 31fe6060f1SDimitry Andric class SourceCode { 32fe6060f1SDimitry Andric std::unique_ptr<MemoryBuffer> MemBuf; 330b57cec5SDimitry Andric 3404eeddc0SDimitry Andric Optional<StringRef> load(StringRef FileName, 35fe6060f1SDimitry Andric const Optional<StringRef> &EmbeddedSource) { 36fe6060f1SDimitry Andric if (Lines <= 0) 37fe6060f1SDimitry Andric return None; 38fe6060f1SDimitry Andric 39fe6060f1SDimitry Andric if (EmbeddedSource) 40fe6060f1SDimitry Andric return EmbeddedSource; 41fe6060f1SDimitry Andric else { 420b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 430b57cec5SDimitry Andric MemoryBuffer::getFile(FileName); 440b57cec5SDimitry Andric if (!BufOrErr) 45fe6060f1SDimitry Andric return None; 46fe6060f1SDimitry Andric MemBuf = std::move(*BufOrErr); 47fe6060f1SDimitry Andric return MemBuf->getBuffer(); 48fe6060f1SDimitry Andric } 49fe6060f1SDimitry Andric } 50fe6060f1SDimitry Andric 5104eeddc0SDimitry Andric Optional<StringRef> pruneSource(const Optional<StringRef> &Source) { 52fe6060f1SDimitry Andric if (!Source) 53fe6060f1SDimitry Andric return None; 54fe6060f1SDimitry Andric size_t FirstLinePos = StringRef::npos, Pos = 0; 55fe6060f1SDimitry Andric for (int64_t L = 1; L <= LastLine; ++L, ++Pos) { 56fe6060f1SDimitry Andric if (L == FirstLine) 57fe6060f1SDimitry Andric FirstLinePos = Pos; 58fe6060f1SDimitry Andric Pos = Source->find('\n', Pos); 59fe6060f1SDimitry Andric if (Pos == StringRef::npos) 60fe6060f1SDimitry Andric break; 61fe6060f1SDimitry Andric } 62fe6060f1SDimitry Andric if (FirstLinePos == StringRef::npos) 63fe6060f1SDimitry Andric return None; 64fe6060f1SDimitry Andric return Source->substr(FirstLinePos, (Pos == StringRef::npos) 65fe6060f1SDimitry Andric ? StringRef::npos 66fe6060f1SDimitry Andric : Pos - FirstLinePos); 67fe6060f1SDimitry Andric } 68fe6060f1SDimitry Andric 69fe6060f1SDimitry Andric public: 70fe6060f1SDimitry Andric const int64_t Line; 71fe6060f1SDimitry Andric const int Lines; 72fe6060f1SDimitry Andric const int64_t FirstLine; 73fe6060f1SDimitry Andric const int64_t LastLine; 74fe6060f1SDimitry Andric const Optional<StringRef> PrunedSource; 75fe6060f1SDimitry Andric 76fe6060f1SDimitry Andric SourceCode( 77fe6060f1SDimitry Andric StringRef FileName, int64_t Line, int Lines, 78fe6060f1SDimitry Andric const Optional<StringRef> &EmbeddedSource = Optional<StringRef>(None)) 79fe6060f1SDimitry Andric : Line(Line), Lines(Lines), 80fe6060f1SDimitry Andric FirstLine(std::max(static_cast<int64_t>(1), Line - Lines / 2)), 81fe6060f1SDimitry Andric LastLine(FirstLine + Lines - 1), 82fe6060f1SDimitry Andric PrunedSource(pruneSource(load(FileName, EmbeddedSource))) {} 83fe6060f1SDimitry Andric 84fe6060f1SDimitry Andric void format(raw_ostream &OS) { 85fe6060f1SDimitry Andric if (!PrunedSource) 860b57cec5SDimitry Andric return; 870b57cec5SDimitry Andric size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine)); 88fe6060f1SDimitry Andric int64_t L = FirstLine; 89fe6060f1SDimitry Andric for (size_t Pos = 0; Pos < PrunedSource->size(); ++L) { 90fe6060f1SDimitry Andric size_t PosEnd = PrunedSource->find('\n', Pos); 91fe6060f1SDimitry Andric StringRef String = PrunedSource->substr( 92fe6060f1SDimitry Andric Pos, (PosEnd == StringRef::npos) ? StringRef::npos : (PosEnd - Pos)); 93fe6060f1SDimitry Andric if (String.endswith("\r")) 94fe6060f1SDimitry Andric String = String.drop_back(1); 950b57cec5SDimitry Andric OS << format_decimal(L, MaxLineNumberWidth); 960b57cec5SDimitry Andric if (L == Line) 970b57cec5SDimitry Andric OS << " >: "; 980b57cec5SDimitry Andric else 990b57cec5SDimitry Andric OS << " : "; 100fe6060f1SDimitry Andric OS << String << '\n'; 101fe6060f1SDimitry Andric if (PosEnd == StringRef::npos) 102fe6060f1SDimitry Andric break; 103fe6060f1SDimitry Andric Pos = PosEnd + 1; 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric } 106fe6060f1SDimitry Andric }; 107fe6060f1SDimitry Andric 108fe6060f1SDimitry Andric void PlainPrinterBase::printHeader(uint64_t Address) { 109fe6060f1SDimitry Andric if (Config.PrintAddress) { 110fe6060f1SDimitry Andric OS << "0x"; 111fe6060f1SDimitry Andric OS.write_hex(Address); 112fe6060f1SDimitry Andric StringRef Delimiter = Config.Pretty ? ": " : "\n"; 113fe6060f1SDimitry Andric OS << Delimiter; 114fe6060f1SDimitry Andric } 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 117fe6060f1SDimitry Andric // Prints source code around in the FileName the Line. 118fe6060f1SDimitry Andric void PlainPrinterBase::printContext(SourceCode SourceCode) { 119fe6060f1SDimitry Andric SourceCode.format(OS); 120fe6060f1SDimitry Andric } 121fe6060f1SDimitry Andric 122fe6060f1SDimitry Andric void PlainPrinterBase::printFunctionName(StringRef FunctionName, bool Inlined) { 123fe6060f1SDimitry Andric if (Config.PrintFunctions) { 1248bcb0991SDimitry Andric if (FunctionName == DILineInfo::BadString) 1258bcb0991SDimitry Andric FunctionName = DILineInfo::Addr2LineBadString; 126fe6060f1SDimitry Andric StringRef Delimiter = Config.Pretty ? " at " : "\n"; 127fe6060f1SDimitry Andric StringRef Prefix = (Config.Pretty && Inlined) ? " (inlined by) " : ""; 1280b57cec5SDimitry Andric OS << Prefix << FunctionName << Delimiter; 1290b57cec5SDimitry Andric } 130fe6060f1SDimitry Andric } 131fe6060f1SDimitry Andric 132fe6060f1SDimitry Andric void LLVMPrinter::printSimpleLocation(StringRef Filename, 133fe6060f1SDimitry Andric const DILineInfo &Info) { 134fe6060f1SDimitry Andric OS << Filename << ':' << Info.Line << ':' << Info.Column << '\n'; 135fe6060f1SDimitry Andric printContext( 136fe6060f1SDimitry Andric SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source)); 137fe6060f1SDimitry Andric } 138fe6060f1SDimitry Andric 139fe6060f1SDimitry Andric void GNUPrinter::printSimpleLocation(StringRef Filename, 140fe6060f1SDimitry Andric const DILineInfo &Info) { 141fe6060f1SDimitry Andric OS << Filename << ':' << Info.Line; 142fe6060f1SDimitry Andric if (Info.Discriminator) 143fe6060f1SDimitry Andric OS << " (discriminator " << Info.Discriminator << ')'; 144fe6060f1SDimitry Andric OS << '\n'; 145fe6060f1SDimitry Andric printContext( 146fe6060f1SDimitry Andric SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source)); 147fe6060f1SDimitry Andric } 148fe6060f1SDimitry Andric 149fe6060f1SDimitry Andric void PlainPrinterBase::printVerbose(StringRef Filename, 150fe6060f1SDimitry Andric const DILineInfo &Info) { 151fe6060f1SDimitry Andric OS << " Filename: " << Filename << '\n'; 152fe6060f1SDimitry Andric if (Info.StartLine) { 153fe6060f1SDimitry Andric OS << " Function start filename: " << Info.StartFileName << '\n'; 154fe6060f1SDimitry Andric OS << " Function start line: " << Info.StartLine << '\n'; 155fe6060f1SDimitry Andric } 156fe6060f1SDimitry Andric printStartAddress(Info); 157fe6060f1SDimitry Andric OS << " Line: " << Info.Line << '\n'; 158fe6060f1SDimitry Andric OS << " Column: " << Info.Column << '\n'; 159fe6060f1SDimitry Andric if (Info.Discriminator) 160fe6060f1SDimitry Andric OS << " Discriminator: " << Info.Discriminator << '\n'; 161fe6060f1SDimitry Andric } 162fe6060f1SDimitry Andric 163fe6060f1SDimitry Andric void LLVMPrinter::printStartAddress(const DILineInfo &Info) { 164fe6060f1SDimitry Andric if (Info.StartAddress) { 165fe6060f1SDimitry Andric OS << " Function start address: 0x"; 166fe6060f1SDimitry Andric OS.write_hex(*Info.StartAddress); 167fe6060f1SDimitry Andric OS << '\n'; 168fe6060f1SDimitry Andric } 169fe6060f1SDimitry Andric } 170fe6060f1SDimitry Andric 171fe6060f1SDimitry Andric void LLVMPrinter::printFooter() { OS << '\n'; } 172fe6060f1SDimitry Andric 173fe6060f1SDimitry Andric void PlainPrinterBase::print(const DILineInfo &Info, bool Inlined) { 174fe6060f1SDimitry Andric printFunctionName(Info.FunctionName, Inlined); 175fe6060f1SDimitry Andric StringRef Filename = Info.FileName; 1768bcb0991SDimitry Andric if (Filename == DILineInfo::BadString) 1778bcb0991SDimitry Andric Filename = DILineInfo::Addr2LineBadString; 178fe6060f1SDimitry Andric if (Config.Verbose) 179fe6060f1SDimitry Andric printVerbose(Filename, Info); 180fe6060f1SDimitry Andric else 181fe6060f1SDimitry Andric printSimpleLocation(Filename, Info); 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 184fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, const DILineInfo &Info) { 185fe6060f1SDimitry Andric printHeader(*Request.Address); 1860b57cec5SDimitry Andric print(Info, false); 187fe6060f1SDimitry Andric printFooter(); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 190fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, 191fe6060f1SDimitry Andric const DIInliningInfo &Info) { 192fe6060f1SDimitry Andric printHeader(*Request.Address); 1930b57cec5SDimitry Andric uint32_t FramesNum = Info.getNumberOfFrames(); 194fe6060f1SDimitry Andric if (FramesNum == 0) 1950b57cec5SDimitry Andric print(DILineInfo(), false); 196fe6060f1SDimitry Andric else 197fe6060f1SDimitry Andric for (uint32_t I = 0; I < FramesNum; ++I) 198fe6060f1SDimitry Andric print(Info.getFrame(I), I > 0); 199fe6060f1SDimitry Andric printFooter(); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 202fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, const DIGlobal &Global) { 203fe6060f1SDimitry Andric printHeader(*Request.Address); 204fe6060f1SDimitry Andric StringRef Name = Global.Name; 2058bcb0991SDimitry Andric if (Name == DILineInfo::BadString) 2068bcb0991SDimitry Andric Name = DILineInfo::Addr2LineBadString; 2070b57cec5SDimitry Andric OS << Name << "\n"; 2080b57cec5SDimitry Andric OS << Global.Start << " " << Global.Size << "\n"; 209*81ad6265SDimitry Andric if (Global.DeclFile.empty()) 210*81ad6265SDimitry Andric OS << "??:?\n"; 211*81ad6265SDimitry Andric else 212*81ad6265SDimitry Andric OS << Global.DeclFile << ":" << Global.DeclLine << "\n"; 213fe6060f1SDimitry Andric printFooter(); 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 216fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, 217fe6060f1SDimitry Andric const std::vector<DILocal> &Locals) { 218fe6060f1SDimitry Andric printHeader(*Request.Address); 219fe6060f1SDimitry Andric if (Locals.empty()) 220fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString << '\n'; 221480093f4SDimitry Andric else 222fe6060f1SDimitry Andric for (const DILocal &L : Locals) { 223fe6060f1SDimitry Andric if (L.FunctionName.empty()) 224fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 225480093f4SDimitry Andric else 226fe6060f1SDimitry Andric OS << L.FunctionName; 227fe6060f1SDimitry Andric OS << '\n'; 228480093f4SDimitry Andric 229fe6060f1SDimitry Andric if (L.Name.empty()) 230fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 2310b57cec5SDimitry Andric else 232fe6060f1SDimitry Andric OS << L.Name; 233fe6060f1SDimitry Andric OS << '\n'; 234480093f4SDimitry Andric 235fe6060f1SDimitry Andric if (L.DeclFile.empty()) 236fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 237fe6060f1SDimitry Andric else 238fe6060f1SDimitry Andric OS << L.DeclFile; 239fe6060f1SDimitry Andric 240fe6060f1SDimitry Andric OS << ':' << L.DeclLine << '\n'; 241fe6060f1SDimitry Andric 242fe6060f1SDimitry Andric if (L.FrameOffset) 243fe6060f1SDimitry Andric OS << *L.FrameOffset; 244fe6060f1SDimitry Andric else 245fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 246fe6060f1SDimitry Andric OS << ' '; 247fe6060f1SDimitry Andric 248fe6060f1SDimitry Andric if (L.Size) 249fe6060f1SDimitry Andric OS << *L.Size; 250fe6060f1SDimitry Andric else 251fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 252fe6060f1SDimitry Andric OS << ' '; 253fe6060f1SDimitry Andric 254fe6060f1SDimitry Andric if (L.TagOffset) 255fe6060f1SDimitry Andric OS << *L.TagOffset; 256fe6060f1SDimitry Andric else 257fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 258fe6060f1SDimitry Andric OS << '\n'; 259fe6060f1SDimitry Andric } 260fe6060f1SDimitry Andric printFooter(); 261fe6060f1SDimitry Andric } 262fe6060f1SDimitry Andric 263fe6060f1SDimitry Andric void PlainPrinterBase::printInvalidCommand(const Request &Request, 264fe6060f1SDimitry Andric StringRef Command) { 265fe6060f1SDimitry Andric OS << Command << '\n'; 266fe6060f1SDimitry Andric } 267fe6060f1SDimitry Andric 268fe6060f1SDimitry Andric bool PlainPrinterBase::printError(const Request &Request, 269fe6060f1SDimitry Andric const ErrorInfoBase &ErrorInfo, 270fe6060f1SDimitry Andric StringRef ErrorBanner) { 271fe6060f1SDimitry Andric ES << ErrorBanner; 272fe6060f1SDimitry Andric ErrorInfo.log(ES); 273fe6060f1SDimitry Andric ES << '\n'; 274fe6060f1SDimitry Andric // Print an empty struct too. 275fe6060f1SDimitry Andric return true; 276fe6060f1SDimitry Andric } 277fe6060f1SDimitry Andric 278fe6060f1SDimitry Andric static std::string toHex(uint64_t V) { 279fe6060f1SDimitry Andric return ("0x" + Twine::utohexstr(V)).str(); 280fe6060f1SDimitry Andric } 281fe6060f1SDimitry Andric 282fe6060f1SDimitry Andric static json::Object toJSON(const Request &Request, StringRef ErrorMsg = "") { 283fe6060f1SDimitry Andric json::Object Json({{"ModuleName", Request.ModuleName.str()}}); 284fe6060f1SDimitry Andric if (Request.Address) 285fe6060f1SDimitry Andric Json["Address"] = toHex(*Request.Address); 286fe6060f1SDimitry Andric if (!ErrorMsg.empty()) 287fe6060f1SDimitry Andric Json["Error"] = json::Object({{"Message", ErrorMsg.str()}}); 288fe6060f1SDimitry Andric return Json; 289fe6060f1SDimitry Andric } 290fe6060f1SDimitry Andric 291fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request, const DILineInfo &Info) { 292fe6060f1SDimitry Andric DIInliningInfo InliningInfo; 293fe6060f1SDimitry Andric InliningInfo.addFrame(Info); 294fe6060f1SDimitry Andric print(Request, InliningInfo); 295fe6060f1SDimitry Andric } 296fe6060f1SDimitry Andric 297fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request, const DIInliningInfo &Info) { 298fe6060f1SDimitry Andric json::Array Array; 299fe6060f1SDimitry Andric for (uint32_t I = 0, N = Info.getNumberOfFrames(); I < N; ++I) { 300fe6060f1SDimitry Andric const DILineInfo &LineInfo = Info.getFrame(I); 301fe6060f1SDimitry Andric json::Object Object( 302fe6060f1SDimitry Andric {{"FunctionName", LineInfo.FunctionName != DILineInfo::BadString 303fe6060f1SDimitry Andric ? LineInfo.FunctionName 304fe6060f1SDimitry Andric : ""}, 305fe6060f1SDimitry Andric {"StartFileName", LineInfo.StartFileName != DILineInfo::BadString 306fe6060f1SDimitry Andric ? LineInfo.StartFileName 307fe6060f1SDimitry Andric : ""}, 308fe6060f1SDimitry Andric {"StartLine", LineInfo.StartLine}, 309fe6060f1SDimitry Andric {"StartAddress", 310fe6060f1SDimitry Andric LineInfo.StartAddress ? toHex(*LineInfo.StartAddress) : ""}, 311fe6060f1SDimitry Andric {"FileName", 312fe6060f1SDimitry Andric LineInfo.FileName != DILineInfo::BadString ? LineInfo.FileName : ""}, 313fe6060f1SDimitry Andric {"Line", LineInfo.Line}, 314fe6060f1SDimitry Andric {"Column", LineInfo.Column}, 315fe6060f1SDimitry Andric {"Discriminator", LineInfo.Discriminator}}); 316fe6060f1SDimitry Andric SourceCode SourceCode(LineInfo.FileName, LineInfo.Line, 317fe6060f1SDimitry Andric Config.SourceContextLines, LineInfo.Source); 318fe6060f1SDimitry Andric std::string FormattedSource; 319fe6060f1SDimitry Andric raw_string_ostream Stream(FormattedSource); 320fe6060f1SDimitry Andric SourceCode.format(Stream); 321fe6060f1SDimitry Andric if (!FormattedSource.empty()) 322fe6060f1SDimitry Andric Object["Source"] = std::move(FormattedSource); 323fe6060f1SDimitry Andric Array.push_back(std::move(Object)); 324fe6060f1SDimitry Andric } 325fe6060f1SDimitry Andric json::Object Json = toJSON(Request); 326fe6060f1SDimitry Andric Json["Symbol"] = std::move(Array); 327fe6060f1SDimitry Andric if (ObjectList) 328fe6060f1SDimitry Andric ObjectList->push_back(std::move(Json)); 329fe6060f1SDimitry Andric else 330fe6060f1SDimitry Andric printJSON(std::move(Json)); 331fe6060f1SDimitry Andric } 332fe6060f1SDimitry Andric 333fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request, const DIGlobal &Global) { 334fe6060f1SDimitry Andric json::Object Data( 335fe6060f1SDimitry Andric {{"Name", Global.Name != DILineInfo::BadString ? Global.Name : ""}, 336fe6060f1SDimitry Andric {"Start", toHex(Global.Start)}, 337fe6060f1SDimitry Andric {"Size", toHex(Global.Size)}}); 338fe6060f1SDimitry Andric json::Object Json = toJSON(Request); 339fe6060f1SDimitry Andric Json["Data"] = std::move(Data); 340fe6060f1SDimitry Andric if (ObjectList) 341fe6060f1SDimitry Andric ObjectList->push_back(std::move(Json)); 342fe6060f1SDimitry Andric else 343fe6060f1SDimitry Andric printJSON(std::move(Json)); 344fe6060f1SDimitry Andric } 345fe6060f1SDimitry Andric 346fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request, 347fe6060f1SDimitry Andric const std::vector<DILocal> &Locals) { 348fe6060f1SDimitry Andric json::Array Frame; 349fe6060f1SDimitry Andric for (const DILocal &Local : Locals) { 350fe6060f1SDimitry Andric json::Object FrameObject( 351fe6060f1SDimitry Andric {{"FunctionName", Local.FunctionName}, 352fe6060f1SDimitry Andric {"Name", Local.Name}, 353fe6060f1SDimitry Andric {"DeclFile", Local.DeclFile}, 354fe6060f1SDimitry Andric {"DeclLine", int64_t(Local.DeclLine)}, 355fe6060f1SDimitry Andric {"Size", Local.Size ? toHex(*Local.Size) : ""}, 356fe6060f1SDimitry Andric {"TagOffset", Local.TagOffset ? toHex(*Local.TagOffset) : ""}}); 3570b57cec5SDimitry Andric if (Local.FrameOffset) 358fe6060f1SDimitry Andric FrameObject["FrameOffset"] = *Local.FrameOffset; 359fe6060f1SDimitry Andric Frame.push_back(std::move(FrameObject)); 360fe6060f1SDimitry Andric } 361fe6060f1SDimitry Andric json::Object Json = toJSON(Request); 362fe6060f1SDimitry Andric Json["Frame"] = std::move(Frame); 363fe6060f1SDimitry Andric if (ObjectList) 364fe6060f1SDimitry Andric ObjectList->push_back(std::move(Json)); 3650b57cec5SDimitry Andric else 366fe6060f1SDimitry Andric printJSON(std::move(Json)); 367fe6060f1SDimitry Andric } 368480093f4SDimitry Andric 369fe6060f1SDimitry Andric void JSONPrinter::printInvalidCommand(const Request &Request, 370fe6060f1SDimitry Andric StringRef Command) { 371fe6060f1SDimitry Andric printError(Request, 372fe6060f1SDimitry Andric StringError("unable to parse arguments: " + Command, 373fe6060f1SDimitry Andric std::make_error_code(std::errc::invalid_argument)), 374fe6060f1SDimitry Andric ""); 375fe6060f1SDimitry Andric } 376480093f4SDimitry Andric 377fe6060f1SDimitry Andric bool JSONPrinter::printError(const Request &Request, 378fe6060f1SDimitry Andric const ErrorInfoBase &ErrorInfo, 379fe6060f1SDimitry Andric StringRef ErrorBanner) { 380fe6060f1SDimitry Andric json::Object Json = toJSON(Request, ErrorInfo.message()); 381fe6060f1SDimitry Andric if (ObjectList) 382fe6060f1SDimitry Andric ObjectList->push_back(std::move(Json)); 3830b57cec5SDimitry Andric else 384fe6060f1SDimitry Andric printJSON(std::move(Json)); 385fe6060f1SDimitry Andric return false; 386fe6060f1SDimitry Andric } 387fe6060f1SDimitry Andric 388fe6060f1SDimitry Andric void JSONPrinter::listBegin() { 389fe6060f1SDimitry Andric assert(!ObjectList); 390fe6060f1SDimitry Andric ObjectList = std::make_unique<json::Array>(); 391fe6060f1SDimitry Andric } 392fe6060f1SDimitry Andric 393fe6060f1SDimitry Andric void JSONPrinter::listEnd() { 394fe6060f1SDimitry Andric assert(ObjectList); 395fe6060f1SDimitry Andric printJSON(std::move(*ObjectList)); 396fe6060f1SDimitry Andric ObjectList.reset(); 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric } // end namespace symbolize 4000b57cec5SDimitry Andric } // end namespace llvm 401