LLVM 20.0.0git
MarkupFilter.cpp
Go to the documentation of this file.
1//===-- lib/DebugInfo/Symbolize/MarkupFilter.cpp -------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines the implementation of a filter that replaces symbolizer
11/// markup with human-readable expressions.
12///
13/// See https://llvm.org/docs/SymbolizerMarkupFormat.html
14///
15//===----------------------------------------------------------------------===//
16
18
19#include "llvm/ADT/STLExtras.h"
28#include "llvm/Support/Error.h"
29#include "llvm/Support/Format.h"
33#include <optional>
34
35using namespace llvm;
36using namespace llvm::symbolize;
37
39 std::optional<bool> ColorsEnabled)
40 : OS(OS), Symbolizer(Symbolizer),
41 ColorsEnabled(
42 ColorsEnabled.value_or(WithColor::defaultAutoDetectFunction()(OS))) {}
43
44void MarkupFilter::filter(std::string &&InputLine) {
45 Line = std::move(InputLine);
46 resetColor();
47
48 Parser.parseLine(Line);
49 SmallVector<MarkupNode> DeferredNodes;
50 // See if the line is a contextual (i.e. contains a contextual element).
51 // In this case, anything after the contextual element is elided, or the whole
52 // line may be elided.
53 while (std::optional<MarkupNode> Node = Parser.nextNode()) {
54 // If this was a contextual line, then summarily stop processing.
55 if (tryContextualElement(*Node, DeferredNodes))
56 return;
57 // This node may yet be part of an elided contextual line.
58 DeferredNodes.push_back(*Node);
59 }
60
61 // This was not a contextual line, so nothing in it should be elided.
62 endAnyModuleInfoLine();
63 for (const MarkupNode &Node : DeferredNodes)
64 filterNode(Node);
65}
66
68 Parser.flush();
69 while (std::optional<MarkupNode> Node = Parser.nextNode())
70 filterNode(*Node);
71 endAnyModuleInfoLine();
72 resetColor();
73 Modules.clear();
74 MMaps.clear();
75}
76
77// See if the given node is a contextual element and handle it if so. This may
78// either output or defer the element; in the former case, it will first emit
79// any DeferredNodes.
80//
81// Returns true if the given element was a contextual element. In this case,
82// DeferredNodes should be considered handled and should not be emitted. The
83// rest of the containing line must also be ignored in case the element was
84// deferred to a following line.
85bool MarkupFilter::tryContextualElement(
86 const MarkupNode &Node, const SmallVector<MarkupNode> &DeferredNodes) {
87 if (tryMMap(Node, DeferredNodes))
88 return true;
89 if (tryReset(Node, DeferredNodes))
90 return true;
91 return tryModule(Node, DeferredNodes);
92}
93
94bool MarkupFilter::tryMMap(const MarkupNode &Node,
95 const SmallVector<MarkupNode> &DeferredNodes) {
96 if (Node.Tag != "mmap")
97 return false;
98 std::optional<MMap> ParsedMMap = parseMMap(Node);
99 if (!ParsedMMap)
100 return true;
101
102 if (const MMap *M = getOverlappingMMap(*ParsedMMap)) {
104 << formatv("overlapping mmap: #{0:x} [{1:x}-{2:x}]\n", M->Mod->ID,
105 M->Addr, M->Addr + M->Size - 1);
106 reportLocation(Node.Fields[0].begin());
107 return true;
108 }
109
110 auto Res = MMaps.emplace(ParsedMMap->Addr, std::move(*ParsedMMap));
111 assert(Res.second && "Overlap check should ensure emplace succeeds.");
112 MMap &MMap = Res.first->second;
113
114 if (!MIL || MIL->Mod != MMap.Mod) {
115 endAnyModuleInfoLine();
116 for (const MarkupNode &Node : DeferredNodes)
117 filterNode(Node);
118 beginModuleInfoLine(MMap.Mod);
119 OS << "; adds";
120 }
121 MIL->MMaps.push_back(&MMap);
122 return true;
123}
124
125bool MarkupFilter::tryReset(const MarkupNode &Node,
126 const SmallVector<MarkupNode> &DeferredNodes) {
127 if (Node.Tag != "reset")
128 return false;
129 if (!checkNumFields(Node, 0))
130 return true;
131
132 if (!Modules.empty() || !MMaps.empty()) {
133 endAnyModuleInfoLine();
134 for (const MarkupNode &Node : DeferredNodes)
135 filterNode(Node);
136 printRawElement(Node);
137 OS << lineEnding();
138
139 Modules.clear();
140 MMaps.clear();
141 }
142 return true;
143}
144
145bool MarkupFilter::tryModule(const MarkupNode &Node,
146 const SmallVector<MarkupNode> &DeferredNodes) {
147 if (Node.Tag != "module")
148 return false;
149 std::optional<Module> ParsedModule = parseModule(Node);
150 if (!ParsedModule)
151 return true;
152
153 auto Res = Modules.try_emplace(
154 ParsedModule->ID, std::make_unique<Module>(std::move(*ParsedModule)));
155 if (!Res.second) {
156 WithColor::error(errs()) << "duplicate module ID\n";
157 reportLocation(Node.Fields[0].begin());
158 return true;
159 }
160 Module &Module = *Res.first->second;
161
162 endAnyModuleInfoLine();
163 for (const MarkupNode &Node : DeferredNodes)
164 filterNode(Node);
165 beginModuleInfoLine(&Module);
166 OS << "; BuildID=";
167 printValue(toHex(Module.BuildID, /*LowerCase=*/true));
168 return true;
169}
170
171void MarkupFilter::beginModuleInfoLine(const Module *M) {
172 highlight();
173 OS << "[[[ELF module";
174 printValue(formatv(" #{0:x} ", M->ID));
175 OS << '"';
176 printValue(M->Name);
177 OS << '"';
178 MIL = ModuleInfoLine{M};
179}
180
181void MarkupFilter::endAnyModuleInfoLine() {
182 if (!MIL)
183 return;
184 llvm::stable_sort(MIL->MMaps, [](const MMap *A, const MMap *B) {
185 return A->Addr < B->Addr;
186 });
187 for (const MMap *M : MIL->MMaps) {
188 OS << (M == MIL->MMaps.front() ? ' ' : ',');
189 OS << '[';
190 printValue(formatv("{0:x}", M->Addr));
191 OS << '-';
192 printValue(formatv("{0:x}", M->Addr + M->Size - 1));
193 OS << "](";
194 printValue(M->Mode);
195 OS << ')';
196 }
197 OS << "]]]" << lineEnding();
198 restoreColor();
199 MIL.reset();
200}
201
202// Handle a node that is known not to be a contextual element.
203void MarkupFilter::filterNode(const MarkupNode &Node) {
204 if (!checkTag(Node))
205 return;
206 if (tryPresentation(Node))
207 return;
208 if (trySGR(Node))
209 return;
210
211 OS << Node.Text;
212}
213
214bool MarkupFilter::tryPresentation(const MarkupNode &Node) {
215 if (trySymbol(Node))
216 return true;
217 if (tryPC(Node))
218 return true;
219 if (tryBackTrace(Node))
220 return true;
221 return tryData(Node);
222}
223
224bool MarkupFilter::trySymbol(const MarkupNode &Node) {
225 if (Node.Tag != "symbol")
226 return false;
227 if (!checkNumFields(Node, 1))
228 return true;
229
230 highlight();
231 OS << llvm::demangle(Node.Fields.front().str());
232 restoreColor();
233 return true;
234}
235
236bool MarkupFilter::tryPC(const MarkupNode &Node) {
237 if (Node.Tag != "pc")
238 return false;
239 if (!checkNumFieldsAtLeast(Node, 1))
240 return true;
241 warnNumFieldsAtMost(Node, 2);
242
243 std::optional<uint64_t> Addr = parseAddr(Node.Fields[0]);
244 if (!Addr)
245 return true;
246
247 // PC addresses that aren't part of a backtrace are assumed to be precise code
248 // locations.
249 PCType Type = PCType::PreciseCode;
250 if (Node.Fields.size() == 2) {
251 std::optional<PCType> ParsedType = parsePCType(Node.Fields[1]);
252 if (!ParsedType)
253 return true;
254 Type = *ParsedType;
255 }
256 *Addr = adjustAddr(*Addr, Type);
257
258 const MMap *MMap = getContainingMMap(*Addr);
259 if (!MMap) {
260 WithColor::error() << "no mmap covers address\n";
261 reportLocation(Node.Fields[0].begin());
262 printRawElement(Node);
263 return true;
264 }
265
266 Expected<DILineInfo> LI = Symbolizer.symbolizeCode(
267 MMap->Mod->BuildID, {MMap->getModuleRelativeAddr(*Addr)});
268 if (!LI) {
270 printRawElement(Node);
271 return true;
272 }
273 if (!*LI) {
274 printRawElement(Node);
275 return true;
276 }
277
278 highlight();
279 printValue(LI->FunctionName);
280 OS << '[';
281 printValue(LI->FileName);
282 OS << ':';
283 printValue(Twine(LI->Line));
284 OS << ']';
285 restoreColor();
286 return true;
287}
288
289bool MarkupFilter::tryBackTrace(const MarkupNode &Node) {
290 if (Node.Tag != "bt")
291 return false;
292 if (!checkNumFieldsAtLeast(Node, 2))
293 return true;
294 warnNumFieldsAtMost(Node, 3);
295
296 std::optional<uint64_t> FrameNumber = parseFrameNumber(Node.Fields[0]);
297 if (!FrameNumber)
298 return true;
299
300 std::optional<uint64_t> Addr = parseAddr(Node.Fields[1]);
301 if (!Addr)
302 return true;
303
304 // Backtrace addresses are assumed to be return addresses by default.
305 PCType Type = PCType::ReturnAddress;
306 if (Node.Fields.size() == 3) {
307 std::optional<PCType> ParsedType = parsePCType(Node.Fields[2]);
308 if (!ParsedType)
309 return true;
310 Type = *ParsedType;
311 }
312 *Addr = adjustAddr(*Addr, Type);
313
314 const MMap *MMap = getContainingMMap(*Addr);
315 if (!MMap) {
316 WithColor::error() << "no mmap covers address\n";
317 reportLocation(Node.Fields[0].begin());
318 printRawElement(Node);
319 return true;
320 }
321 uint64_t MRA = MMap->getModuleRelativeAddr(*Addr);
322
324 Symbolizer.symbolizeInlinedCode(MMap->Mod->BuildID, {MRA});
325 if (!II) {
327 printRawElement(Node);
328 return true;
329 }
330
331 highlight();
332 for (unsigned I = 0, E = II->getNumberOfFrames(); I != E; ++I) {
333 auto Header = formatv("{0, +6}", formatv("#{0}", FrameNumber)).sstr<16>();
334 // Don't highlight the # sign as a value.
335 size_t NumberIdx = Header.find("#") + 1;
336 OS << Header.substr(0, NumberIdx);
337 printValue(Header.substr(NumberIdx));
338 if (I == E - 1) {
339 OS << " ";
340 } else {
341 OS << '.';
342 printValue(formatv("{0, -2}", I + 1));
343 }
344 printValue(formatv(" {0:x16} ", *Addr));
345
346 DILineInfo LI = II->getFrame(I);
347 if (LI) {
348 printValue(LI.FunctionName);
349 OS << ' ';
350 printValue(LI.FileName);
351 OS << ':';
352 printValue(Twine(LI.Line));
353 OS << ':';
354 printValue(Twine(LI.Column));
355 OS << ' ';
356 }
357 OS << '(';
358 printValue(MMap->Mod->Name);
359 OS << "+";
360 printValue(formatv("{0:x}", MRA));
361 OS << ')';
362 if (I != E - 1)
363 OS << lineEnding();
364 }
365 restoreColor();
366 return true;
367}
368
369bool MarkupFilter::tryData(const MarkupNode &Node) {
370 if (Node.Tag != "data")
371 return false;
372 if (!checkNumFields(Node, 1))
373 return true;
374 std::optional<uint64_t> Addr = parseAddr(Node.Fields[0]);
375 if (!Addr)
376 return true;
377
378 const MMap *MMap = getContainingMMap(*Addr);
379 if (!MMap) {
380 WithColor::error() << "no mmap covers address\n";
381 reportLocation(Node.Fields[0].begin());
382 printRawElement(Node);
383 return true;
384 }
385
387 MMap->Mod->BuildID, {MMap->getModuleRelativeAddr(*Addr)});
388 if (!Symbol) {
390 printRawElement(Node);
391 return true;
392 }
393
394 highlight();
395 OS << Symbol->Name;
396 restoreColor();
397 return true;
398}
399
400bool MarkupFilter::trySGR(const MarkupNode &Node) {
401 if (Node.Text == "\033[0m") {
402 resetColor();
403 return true;
404 }
405 if (Node.Text == "\033[1m") {
406 Bold = true;
407 if (ColorsEnabled)
409 return true;
410 }
412 .Case("\033[30m", raw_ostream::Colors::BLACK)
413 .Case("\033[31m", raw_ostream::Colors::RED)
414 .Case("\033[32m", raw_ostream::Colors::GREEN)
416 .Case("\033[34m", raw_ostream::Colors::BLUE)
418 .Case("\033[36m", raw_ostream::Colors::CYAN)
419 .Case("\033[37m", raw_ostream::Colors::WHITE)
420 .Default(std::nullopt);
421 if (SGRColor) {
422 Color = *SGRColor;
423 if (ColorsEnabled)
424 OS.changeColor(*Color);
425 return true;
426 }
427
428 return false;
429}
430
431// Begin highlighting text by picking a different color than the current color
432// state.
433void MarkupFilter::highlight() {
434 if (!ColorsEnabled)
435 return;
438 Bold);
439}
440
441// Begin highlighting a field within a highlighted markup string.
442void MarkupFilter::highlightValue() {
443 if (!ColorsEnabled)
444 return;
446}
447
448// Set the output stream's color to the current color and bold state of the SGR
449// abstract machine.
450void MarkupFilter::restoreColor() {
451 if (!ColorsEnabled)
452 return;
453 if (Color) {
454 OS.changeColor(*Color, Bold);
455 } else {
456 OS.resetColor();
457 if (Bold)
459 }
460}
461
462// Set the SGR and output stream's color and bold states back to the default.
463void MarkupFilter::resetColor() {
464 if (!Color && !Bold)
465 return;
466 Color.reset();
467 Bold = false;
468 if (ColorsEnabled)
469 OS.resetColor();
470}
471
472void MarkupFilter::printRawElement(const MarkupNode &Element) {
473 highlight();
474 OS << "[[[";
475 printValue(Element.Tag);
476 for (StringRef Field : Element.Fields) {
477 OS << ':';
478 printValue(Field);
479 }
480 OS << "]]]";
481 restoreColor();
482}
483
484void MarkupFilter::printValue(Twine Value) {
485 highlightValue();
486 OS << Value;
487 highlight();
488}
489
490// This macro helps reduce the amount of indirection done through Optional
491// below, since the usual case upon returning a std::nullopt Optional is to
492// return std::nullopt.
493#define ASSIGN_OR_RETURN_NONE(TYPE, NAME, EXPR) \
494 auto NAME##Opt = (EXPR); \
495 if (!NAME##Opt) \
496 return std::nullopt; \
497 TYPE NAME = std::move(*NAME##Opt)
498
499std::optional<MarkupFilter::Module>
500MarkupFilter::parseModule(const MarkupNode &Element) const {
501 if (!checkNumFieldsAtLeast(Element, 3))
502 return std::nullopt;
503 ASSIGN_OR_RETURN_NONE(uint64_t, ID, parseModuleID(Element.Fields[0]));
504 StringRef Name = Element.Fields[1];
505 StringRef Type = Element.Fields[2];
506 if (Type != "elf") {
507 WithColor::error() << "unknown module type\n";
508 reportLocation(Type.begin());
509 return std::nullopt;
510 }
511 if (!checkNumFields(Element, 4))
512 return std::nullopt;
513 SmallVector<uint8_t> BuildID = parseBuildID(Element.Fields[3]);
514 if (BuildID.empty())
515 return std::nullopt;
516 return Module{ID, Name.str(), std::move(BuildID)};
517}
518
519std::optional<MarkupFilter::MMap>
520MarkupFilter::parseMMap(const MarkupNode &Element) const {
521 if (!checkNumFieldsAtLeast(Element, 3))
522 return std::nullopt;
523 ASSIGN_OR_RETURN_NONE(uint64_t, Addr, parseAddr(Element.Fields[0]));
524 ASSIGN_OR_RETURN_NONE(uint64_t, Size, parseSize(Element.Fields[1]));
525 StringRef Type = Element.Fields[2];
526 if (Type != "load") {
527 WithColor::error() << "unknown mmap type\n";
528 reportLocation(Type.begin());
529 return std::nullopt;
530 }
531 if (!checkNumFields(Element, 6))
532 return std::nullopt;
533 ASSIGN_OR_RETURN_NONE(uint64_t, ID, parseModuleID(Element.Fields[3]));
534 ASSIGN_OR_RETURN_NONE(std::string, Mode, parseMode(Element.Fields[4]));
535 auto It = Modules.find(ID);
536 if (It == Modules.end()) {
537 WithColor::error() << "unknown module ID\n";
538 reportLocation(Element.Fields[3].begin());
539 return std::nullopt;
540 }
541 ASSIGN_OR_RETURN_NONE(uint64_t, ModuleRelativeAddr,
542 parseAddr(Element.Fields[5]));
543 return MMap{Addr, Size, It->second.get(), std::move(Mode),
544 ModuleRelativeAddr};
545}
546
547// Parse an address (%p in the spec).
548std::optional<uint64_t> MarkupFilter::parseAddr(StringRef Str) const {
549 if (Str.empty()) {
550 reportTypeError(Str, "address");
551 return std::nullopt;
552 }
553 if (all_of(Str, [](char C) { return C == '0'; }))
554 return 0;
555 if (!Str.starts_with("0x")) {
556 reportTypeError(Str, "address");
557 return std::nullopt;
558 }
560 if (Str.drop_front(2).getAsInteger(16, Addr)) {
561 reportTypeError(Str, "address");
562 return std::nullopt;
563 }
564 return Addr;
565}
566
567// Parse a module ID (%i in the spec).
568std::optional<uint64_t> MarkupFilter::parseModuleID(StringRef Str) const {
569 uint64_t ID;
570 if (Str.getAsInteger(0, ID)) {
571 reportTypeError(Str, "module ID");
572 return std::nullopt;
573 }
574 return ID;
575}
576
577// Parse a size (%i in the spec).
578std::optional<uint64_t> MarkupFilter::parseSize(StringRef Str) const {
579 uint64_t ID;
580 if (Str.getAsInteger(0, ID)) {
581 reportTypeError(Str, "size");
582 return std::nullopt;
583 }
584 return ID;
585}
586
587// Parse a frame number (%i in the spec).
588std::optional<uint64_t> MarkupFilter::parseFrameNumber(StringRef Str) const {
589 uint64_t ID;
590 if (Str.getAsInteger(10, ID)) {
591 reportTypeError(Str, "frame number");
592 return std::nullopt;
593 }
594 return ID;
595}
596
597// Parse a build ID (%x in the spec).
598object::BuildID MarkupFilter::parseBuildID(StringRef Str) const {
600 if (BID.empty())
601 reportTypeError(Str, "build ID");
602 return BID;
603}
604
605// Parses the mode string for an mmap element.
606std::optional<std::string> MarkupFilter::parseMode(StringRef Str) const {
607 if (Str.empty()) {
608 reportTypeError(Str, "mode");
609 return std::nullopt;
610 }
611
612 // Pop off each of r/R, w/W, and x/X from the front, in that order.
613 StringRef Remainder = Str;
614 Remainder.consume_front_insensitive("r");
615 Remainder.consume_front_insensitive("w");
616 Remainder.consume_front_insensitive("x");
617
618 // If anything remains, then the string wasn't a mode.
619 if (!Remainder.empty()) {
620 reportTypeError(Str, "mode");
621 return std::nullopt;
622 }
623
624 // Normalize the mode.
625 return Str.lower();
626}
627
628std::optional<MarkupFilter::PCType>
629MarkupFilter::parsePCType(StringRef Str) const {
630 std::optional<MarkupFilter::PCType> Type =
632 .Case("ra", MarkupFilter::PCType::ReturnAddress)
633 .Case("pc", MarkupFilter::PCType::PreciseCode)
634 .Default(std::nullopt);
635 if (!Type)
636 reportTypeError(Str, "PC type");
637 return Type;
638}
639
640bool MarkupFilter::checkTag(const MarkupNode &Node) const {
641 if (any_of(Node.Tag, [](char C) { return C < 'a' || C > 'z'; })) {
642 WithColor::error(errs()) << "tags must be all lowercase characters\n";
643 reportLocation(Node.Tag.begin());
644 return false;
645 }
646 return true;
647}
648
649bool MarkupFilter::checkNumFields(const MarkupNode &Element,
650 size_t Size) const {
651 if (Element.Fields.size() != Size) {
652 bool Warn = Element.Fields.size() > Size;
654 << (Warn ? "warning: " : "error: ") << "expected " << Size
655 << " field(s); found " << Element.Fields.size() << "\n";
656 reportLocation(Element.Tag.end());
657 return Warn;
658 }
659 return true;
660}
661
662bool MarkupFilter::checkNumFieldsAtLeast(const MarkupNode &Element,
663 size_t Size) const {
664 if (Element.Fields.size() < Size) {
666 << "expected at least " << Size << " field(s); found "
667 << Element.Fields.size() << "\n";
668 reportLocation(Element.Tag.end());
669 return false;
670 }
671 return true;
672}
673
674void MarkupFilter::warnNumFieldsAtMost(const MarkupNode &Element,
675 size_t Size) const {
676 if (Element.Fields.size() <= Size)
677 return;
679 << "expected at most " << Size << " field(s); found "
680 << Element.Fields.size() << "\n";
681 reportLocation(Element.Tag.end());
682}
683
684void MarkupFilter::reportTypeError(StringRef Str, StringRef TypeName) const {
685 WithColor::error(errs()) << "expected " << TypeName << "; found '" << Str
686 << "'\n";
687 reportLocation(Str.begin());
688}
689
690// Prints two lines that point out the given location in the current Line using
691// a caret. The iterator must be within the bounds of the most recent line
692// passed to beginLine().
693void MarkupFilter::reportLocation(StringRef::iterator Loc) const {
694 errs() << Line;
695 WithColor(errs().indent(Loc - StringRef(Line).begin()),
697 << '^';
698 errs() << '\n';
699}
700
701// Checks for an existing mmap that overlaps the given one and returns a
702// pointer to one of them.
703const MarkupFilter::MMap *
704MarkupFilter::getOverlappingMMap(const MMap &Map) const {
705 // If the given map contains the start of another mmap, they overlap.
706 auto I = MMaps.upper_bound(Map.Addr);
707 if (I != MMaps.end() && Map.contains(I->second.Addr))
708 return &I->second;
709
710 // If no element starts inside the given mmap, the only possible overlap would
711 // be if the preceding mmap contains the start point of the given mmap.
712 if (I != MMaps.begin()) {
713 --I;
714 if (I->second.contains(Map.Addr))
715 return &I->second;
716 }
717 return nullptr;
718}
719
720// Returns the MMap that contains the given address or nullptr if none.
721const MarkupFilter::MMap *MarkupFilter::getContainingMMap(uint64_t Addr) const {
722 // Find the first mmap starting >= Addr.
723 auto I = MMaps.lower_bound(Addr);
724 if (I != MMaps.end() && I->second.contains(Addr))
725 return &I->second;
726
727 // The previous mmap is the last one starting < Addr.
728 if (I == MMaps.begin())
729 return nullptr;
730 --I;
731 return I->second.contains(Addr) ? &I->second : nullptr;
732}
733
734uint64_t MarkupFilter::adjustAddr(uint64_t Addr, PCType Type) const {
735 // Decrementing return addresses by one moves them into the call instruction.
736 // The address doesn't have to be the start of the call instruction, just some
737 // byte on the inside. Subtracting one avoids needing detailed instruction
738 // length information here.
739 return Type == MarkupFilter::PCType::ReturnAddress ? Addr - 1 : Addr;
740}
741
742StringRef MarkupFilter::lineEnding() const {
743 return StringRef(Line).ends_with("\r\n") ? "\r\n" : "\n";
744}
745
746bool MarkupFilter::MMap::contains(uint64_t Addr) const {
747 return this->Addr <= Addr && Addr < this->Addr + Size;
748}
749
750// Returns the module-relative address for a given virtual address.
751uint64_t MarkupFilter::MMap::getModuleRelativeAddr(uint64_t Addr) const {
752 return Addr - this->Addr + ModuleRelativeAddr;
753}
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains several declarations for the debuginfod client and server.
uint64_t Addr
std::string Name
uint64_t Size
#define I(x, y, z)
Definition: MD5.cpp:58
#define ASSIGN_OR_RETURN_NONE(TYPE, NAME, EXPR)
This file declares a filter that replaces symbolizer markup with human-readable expressions.
This file declares the log symbolizer markup data model and parser.
uint64_t IntrinsicInst * II
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
This file contains some functions that are useful when dealing with strings.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&... Args)
Definition: DenseMap.h:226
bool empty() const
Definition: DenseMap.h:98
iterator end()
Definition: DenseMap.h:84
Tagged union holding either a T or a Error.
Definition: Error.h:481
Error takeError()
Take ownership of the stored error.
Definition: Error.h:608
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
bool empty() const
Definition: SmallVector.h:94
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
iterator end() const
Definition: StringRef.h:113
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition: StringRef.h:262
bool consume_front_insensitive(StringRef Prefix)
Returns true if this StringRef has the given prefix, ignoring case, and removes that prefix.
Definition: StringRef.h:630
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:69
R Default(T Value)
Definition: StringSwitch.h:182
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:74
An RAII object that temporarily switches an output stream to a specific color.
Definition: WithColor.h:54
static raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
Definition: WithColor.cpp:85
static raw_ostream & error()
Convenience method for printing "error: " to stderr.
Definition: WithColor.cpp:83
static void defaultErrorHandler(Error Err)
Implement default handling for Error.
Definition: WithColor.cpp:158
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
virtual raw_ostream & changeColor(enum Colors Color, bool Bold=false, bool BG=false)
Changes the foreground color of text that will be output from this point forward.
virtual raw_ostream & resetColor()
Resets the colors to terminal defaults.
Expected< DIInliningInfo > symbolizeInlinedCode(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
Definition: Symbolize.cpp:135
Expected< DILineInfo > symbolizeCode(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
Definition: Symbolize.cpp:84
Expected< DIGlobal > symbolizeData(const ObjectFile &Obj, object::SectionedAddress ModuleOffset)
Definition: Symbolize.cpp:180
MarkupFilter(raw_ostream &OS, LLVMSymbolizer &Symbolizer, std::optional< bool > ColorsEnabled=std::nullopt)
void filter(std::string &&InputLine)
Filters a line containing symbolizer markup and writes the human-readable results to the output strea...
void finish()
Records that the input stream has ended and writes any deferred output.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
BuildID parseBuildID(StringRef Str)
Parses a build ID from a hex string.
Definition: BuildID.cpp:47
static std::string toHex(uint64_t V)
Definition: DIPrinter.cpp:288
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:227
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void stable_sort(R &&Range)
Definition: STLExtras.h:2020
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1722
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1729
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
std::string demangle(std::string_view MangledName)
Attempt to demangle a string using different demangling schemes.
Definition: Demangle.cpp:20
A format-neutral container for source line information.
Definition: DIContext.h:32
uint32_t Line
Definition: DIContext.h:46
std::string FileName
Definition: DIContext.h:38
std::string FunctionName
Definition: DIContext.h:39
uint32_t Column
Definition: DIContext.h:47
A node of symbolizer markup.
Definition: Markup.h:33
SmallVector< StringRef > Fields
If this represents an element with fields, a list of the field contents.
Definition: Markup.h:42
StringRef Tag
If this represents an element, the tag. Otherwise, empty.
Definition: Markup.h:38