xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1 //===-- LVLocation.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 // This implements the LVOperation and LVLocation classes.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/DebugInfo/LogicalView/Core/LVLocation.h"
14 #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
15 #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
16 #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
17 
18 using namespace llvm;
19 using namespace llvm::logicalview;
20 
21 #define DEBUG_TYPE "Location"
22 
print(raw_ostream & OS,bool Full) const23 void LVOperation::print(raw_ostream &OS, bool Full) const {}
24 
25 // Identify the most common type of operations and print them using a high
26 // level format, trying to isolate the DWARF complexity.
getOperandsDWARFInfo()27 std::string LVOperation::getOperandsDWARFInfo() {
28   std::string String;
29   raw_string_ostream Stream(String);
30 
31   auto PrintRegisterInfo = [&](LVSmall Code) {
32     //-----------------------------------------------------------------------
33     // 2.5.1.1 Literal encodings.
34     //-----------------------------------------------------------------------
35     if (dwarf::DW_OP_lit0 <= Code && Code <= dwarf::DW_OP_lit31) {
36       Stream << format("lit%d", Code - dwarf::DW_OP_lit0);
37       return;
38     }
39 
40     //-----------------------------------------------------------------------
41     // 2.5.1.2 Register values.
42     //-----------------------------------------------------------------------
43     if (dwarf::DW_OP_breg0 <= Code && Code <= dwarf::DW_OP_breg31) {
44       std::string RegisterName(getReader().getRegisterName(Code, Operands));
45       Stream << format("breg%d+%d%s", Code - dwarf::DW_OP_breg0, Operands[0],
46                        RegisterName.c_str());
47       return;
48     }
49 
50     //-----------------------------------------------------------------------
51     // 2.6.1.1.3 Register location descriptions.
52     //-----------------------------------------------------------------------
53     if (dwarf::DW_OP_reg0 <= Code && Code <= dwarf::DW_OP_reg31) {
54       std::string RegisterName(getReader().getRegisterName(Code, Operands));
55       Stream << format("reg%d%s", Code - dwarf::DW_OP_reg0,
56                        RegisterName.c_str());
57       return;
58     }
59 
60     Stream << format("#0x%02x ", Code) << hexString(Operands[0]) << " "
61            << hexString(Operands[1]) << "#";
62   };
63 
64   switch (Opcode) {
65   //-------------------------------------------------------------------------
66   // 2.5.1.1 Literal encodings.
67   //-------------------------------------------------------------------------
68   case dwarf::DW_OP_addr:
69     Stream << "addr " << hexString(Operands[0]);
70     break;
71   case dwarf::DW_OP_constu:
72   case dwarf::DW_OP_const1u:
73   case dwarf::DW_OP_const2u:
74   case dwarf::DW_OP_const4u:
75   case dwarf::DW_OP_const8u:
76     Stream << "const_u " << unsigned(Operands[0]);
77     break;
78   case dwarf::DW_OP_consts:
79   case dwarf::DW_OP_const1s:
80   case dwarf::DW_OP_const2s:
81   case dwarf::DW_OP_const4s:
82   case dwarf::DW_OP_const8s:
83     Stream << "const_s " << int(Operands[0]);
84     break;
85   case dwarf::DW_OP_addrx:
86     Stream << "addrx " << unsigned(Operands[0]);
87     break;
88   case dwarf::DW_OP_constx:
89     Stream << "constx " << unsigned(Operands[0]);
90     break;
91   case dwarf::DW_OP_const_type:
92     Stream << "TODO: DW_OP_const_type";
93     break;
94 
95   //-------------------------------------------------------------------------
96   // 2.5.1.2 Register values.
97   //-------------------------------------------------------------------------
98   case dwarf::DW_OP_fbreg:
99     Stream << "fbreg " << int(Operands[0]);
100     break;
101   case dwarf::DW_OP_bregx: {
102     std::string RegisterName(getReader().getRegisterName(Opcode, Operands));
103     Stream << format("bregx %d%s+%d", Operands[0], RegisterName.c_str(),
104                      unsigned(Operands[1]));
105     break;
106   }
107   case dwarf::DW_OP_regval_type: {
108     std::string RegisterName(getReader().getRegisterName(Opcode, Operands));
109     Stream << format("regval_type %d%s+%d", Operands[0], RegisterName.c_str(),
110                      unsigned(Operands[1]));
111     break;
112   }
113 
114   //-------------------------------------------------------------------------
115   // 2.5.1.3 Stack operations.
116   //-------------------------------------------------------------------------
117   case dwarf::DW_OP_dup:
118     Stream << "dup";
119     break;
120   case dwarf::DW_OP_drop:
121     Stream << "drop";
122     break;
123   case dwarf::DW_OP_pick:
124     Stream << "pick " << unsigned(Operands[0]);
125     break;
126   case dwarf::DW_OP_over:
127     Stream << "over";
128     break;
129   case dwarf::DW_OP_swap:
130     Stream << "swap";
131     break;
132   case dwarf::DW_OP_rot:
133     Stream << "rot";
134     break;
135   case dwarf::DW_OP_deref:
136     Stream << "deref";
137     break;
138   case dwarf::DW_OP_deref_size:
139     Stream << "deref_size " << unsigned(Operands[0]);
140     break;
141   case dwarf::DW_OP_deref_type:
142     Stream << "deref_type " << unsigned(Operands[0]) << " DIE offset "
143            << hexString(Operands[1]);
144     break;
145   case dwarf::DW_OP_xderef:
146     Stream << "xderef";
147     break;
148   case dwarf::DW_OP_xderef_size:
149     Stream << "xderef_size " << unsigned(Operands[0]);
150     break;
151   case dwarf::DW_OP_xderef_type:
152     Stream << "xderef_type " << unsigned(Operands[0]) << " DIE offset "
153            << hexString(Operands[1]);
154     break;
155   case dwarf::DW_OP_push_object_address:
156     Stream << "push_object_address";
157     break;
158   case dwarf::DW_OP_form_tls_address:
159     Stream << "form_tls_address " << hexString(Operands[0]);
160     break;
161   case dwarf::DW_OP_call_frame_cfa:
162     Stream << "call_frame_cfa";
163     break;
164 
165   //-------------------------------------------------------------------------
166   // 2.5.1.4 Arithmetic and Logical Operations.
167   //-------------------------------------------------------------------------
168   case dwarf::DW_OP_abs:
169     Stream << "abs";
170     break;
171   case dwarf::DW_OP_and:
172     Stream << "and";
173     break;
174   case dwarf::DW_OP_div:
175     Stream << "div";
176     break;
177   case dwarf::DW_OP_minus:
178     Stream << "minus";
179     break;
180   case dwarf::DW_OP_mod:
181     Stream << "mod";
182     break;
183   case dwarf::DW_OP_mul:
184     Stream << "mul";
185     break;
186   case dwarf::DW_OP_neg:
187     Stream << "neg";
188     break;
189   case dwarf::DW_OP_not:
190     Stream << "not";
191     break;
192   case dwarf::DW_OP_or:
193     Stream << "or";
194     break;
195   case dwarf::DW_OP_plus:
196     Stream << "plus";
197     break;
198   case dwarf::DW_OP_plus_uconst:
199     Stream << "plus_uconst " << unsigned(Operands[0]);
200     break;
201   case dwarf::DW_OP_shl:
202     Stream << "shl";
203     break;
204   case dwarf::DW_OP_shr:
205     Stream << "shr";
206     break;
207   case dwarf::DW_OP_shra:
208     Stream << "shra";
209     break;
210   case dwarf::DW_OP_xor:
211     Stream << "xor";
212     break;
213 
214   //-------------------------------------------------------------------------
215   // 2.5.1.5 Control Flow Operations.
216   //-------------------------------------------------------------------------
217   case dwarf::DW_OP_le:
218     Stream << "le";
219     break;
220   case dwarf::DW_OP_ge:
221     Stream << "ge";
222     break;
223   case dwarf::DW_OP_eq:
224     Stream << "eq";
225     break;
226   case dwarf::DW_OP_lt:
227     Stream << "lt";
228     break;
229   case dwarf::DW_OP_gt:
230     Stream << "gt";
231     break;
232   case dwarf::DW_OP_ne:
233     Stream << "ne";
234     break;
235   case dwarf::DW_OP_skip:
236     Stream << "skip " << signed(Operands[0]);
237     break;
238   case dwarf::DW_OP_bra:
239     Stream << "bra " << signed(Operands[0]);
240     break;
241   case dwarf::DW_OP_call2:
242     Stream << "call2 DIE offset " << hexString(Operands[0]);
243     break;
244   case dwarf::DW_OP_call4:
245     Stream << "call4 DIE offset " << hexString(Operands[0]);
246     break;
247   case dwarf::DW_OP_call_ref:
248     Stream << "call_ref DIE offset " << hexString(Operands[0]);
249     break;
250 
251   //-------------------------------------------------------------------------
252   // 2.5.1.6 Type Conversions.
253   //-------------------------------------------------------------------------
254   case dwarf::DW_OP_convert:
255     Stream << "convert DIE offset " << hexString(Operands[0]);
256     break;
257   case dwarf::DW_OP_reinterpret:
258     Stream << "reinterpret DIE offset " << hexString(Operands[0]);
259     break;
260 
261   //-------------------------------------------------------------------------
262   // 2.5.1.7 Special Operations.
263   //-------------------------------------------------------------------------
264   case dwarf::DW_OP_nop:
265     Stream << "nop";
266     break;
267   case dwarf::DW_OP_entry_value:
268     Stream << "TODO: DW_OP_entry_value";
269     break;
270 
271   //-------------------------------------------------------------------------
272   // 2.6.1.1.3 Register location descriptions.
273   //-------------------------------------------------------------------------
274   case dwarf::DW_OP_regx:
275     Stream << "regx" << getReader().getRegisterName(Opcode, Operands);
276     break;
277 
278   //-------------------------------------------------------------------------
279   // 2.6.1.1.4 Implicit location descriptions.
280   //-------------------------------------------------------------------------
281   case dwarf::DW_OP_stack_value:
282     Stream << "stack_value";
283     break;
284   case dwarf::DW_OP_implicit_value:
285     Stream << "TODO: DW_OP_implicit_value";
286     break;
287   case dwarf::DW_OP_implicit_pointer:
288     Stream << "implicit_pointer DIE offset " << hexString(Operands[0]) << " "
289            << int(Operands[1]);
290     break;
291 
292   //-------------------------------------------------------------------------
293   // 2.6.1.2 Composite location descriptions.
294   //-------------------------------------------------------------------------
295   case dwarf::DW_OP_piece:
296     Stream << "piece " << int(Operands[0]);
297     break;
298   case dwarf::DW_OP_bit_piece:
299     Stream << "bit_piece " << int(Operands[0]) << " offset "
300            << int(Operands[1]);
301     break;
302 
303   //-------------------------------------------------------------------------
304   // GNU extensions.
305   //-------------------------------------------------------------------------
306   case dwarf::DW_OP_GNU_entry_value:
307     Stream << "gnu_entry_value ";
308     PrintRegisterInfo(dwarf::DW_OP_reg0);
309     break;
310   case dwarf::DW_OP_GNU_push_tls_address:
311     Stream << "gnu_push_tls_address " << hexString(Operands[0]);
312     break;
313   case dwarf::DW_OP_GNU_addr_index:
314     Stream << "gnu_addr_index " << unsigned(Operands[0]);
315     break;
316   case dwarf::DW_OP_GNU_const_index:
317     Stream << "gnu_const_index " << unsigned(Operands[0]);
318     break;
319 
320   //-------------------------------------------------------------------------
321   // Member location.
322   //-------------------------------------------------------------------------
323   case LVLocationMemberOffset:
324     Stream << "offset " << int(Operands[0]);
325     break;
326 
327   //-------------------------------------------------------------------------
328   // Missing location.
329   //-------------------------------------------------------------------------
330   case dwarf::DW_OP_hi_user:
331     Stream << "missing";
332     break;
333 
334   //-------------------------------------------------------------------------
335   // Register values.
336   //-------------------------------------------------------------------------
337   default:
338     PrintRegisterInfo(Opcode);
339     break;
340   }
341 
342   return String;
343 }
344 
345 // Identify the most common type of operations and print them using a high
346 // level format, trying to isolate the CodeView complexity.
getOperandsCodeViewInfo()347 std::string LVOperation::getOperandsCodeViewInfo() {
348   std::string String;
349   raw_string_ostream Stream(String);
350 
351   // Get original CodeView operation code.
352   uint16_t OperationCode = getCodeViewOperationCode(Opcode);
353 
354   switch (OperationCode) {
355   // Operands: [Offset].
356   case codeview::SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL:
357     Stream << "frame_pointer_rel " << int(Operands[0]);
358     break;
359   case codeview::SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
360     Stream << "frame_pointer_rel_full_scope " << int(Operands[0]);
361     break;
362 
363   // Operands: [Register].
364   case codeview::SymbolKind::S_DEFRANGE_REGISTER:
365     Stream << "register " << getReader().getRegisterName(Opcode, Operands);
366     break;
367   case codeview::SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER:
368     Stream << "subfield_register "
369            << getReader().getRegisterName(Opcode, Operands);
370     break;
371 
372   // Operands: [Register, Offset].
373   case codeview::SymbolKind::S_DEFRANGE_REGISTER_REL:
374     Stream << "register_rel " << getReader().getRegisterName(Opcode, Operands)
375            << " offset " << int(Operands[1]);
376     break;
377 
378   // Operands: [Program].
379   case codeview::SymbolKind::S_DEFRANGE:
380     Stream << "frame " << int(Operands[0]);
381     break;
382   case codeview::SymbolKind::S_DEFRANGE_SUBFIELD:
383     Stream << "subfield " << int(Operands[0]);
384     break;
385 
386   default:
387     Stream << format("#0x%02x: ", Opcode) << hexString(Operands[0]) << " "
388            << hexString(Operands[1]) << "#";
389     break;
390   }
391 
392   return String;
393 }
394 
395 namespace {
396 const char *const KindBaseClassOffset = "BaseClassOffset";
397 const char *const KindBaseClassStep = "BaseClassStep";
398 const char *const KindClassOffset = "ClassOffset";
399 const char *const KindFixedAddress = "FixedAddress";
400 const char *const KindMissingInfo = "Missing";
401 const char *const KindOperation = "Operation";
402 const char *const KindOperationList = "OperationList";
403 const char *const KindRegister = "Register";
404 const char *const KindUndefined = "Undefined";
405 } // end anonymous namespace
406 
407 //===----------------------------------------------------------------------===//
408 // DWARF location information.
409 //===----------------------------------------------------------------------===//
kind() const410 const char *LVLocation::kind() const {
411   const char *Kind = KindUndefined;
412   if (getIsBaseClassOffset())
413     Kind = KindBaseClassOffset;
414   else if (getIsBaseClassStep())
415     Kind = KindBaseClassStep;
416   else if (getIsClassOffset())
417     Kind = KindClassOffset;
418   else if (getIsFixedAddress())
419     Kind = KindFixedAddress;
420   else if (getIsGapEntry())
421     Kind = KindMissingInfo;
422   else if (getIsOperation())
423     Kind = KindOperation;
424   else if (getIsOperationList())
425     Kind = KindOperationList;
426   else if (getIsRegister())
427     Kind = KindRegister;
428   return Kind;
429 }
430 
getIntervalInfo() const431 std::string LVLocation::getIntervalInfo() const {
432   static const char *const Question = "?";
433   std::string String;
434   raw_string_ostream Stream(String);
435   if (getIsAddressRange())
436     Stream << "{Range}";
437 
438   auto PrintLine = [&](const LVLine *Line) {
439     if (Line) {
440       std::string TheLine;
441       TheLine = Line->lineNumberAsStringStripped();
442       Stream << TheLine.c_str();
443     } else {
444       Stream << Question;
445     }
446   };
447 
448   Stream << " Lines ";
449   PrintLine(getLowerLine());
450   Stream << ":";
451   PrintLine(getUpperLine());
452 
453   if (options().getAttributeOffset())
454     // Print the active range (low pc and high pc).
455     Stream << " [" << hexString(getLowerAddress()) << ":"
456            << hexString(getUpperAddress()) << "]";
457 
458   return String;
459 }
460 
461 // Validate the ranges associated with the location.
validateRanges()462 bool LVLocation::validateRanges() {
463   // Traverse the locations and validate them against the address to line
464   // mapping in the current compile unit. Record those invalid ranges.
465   // A valid range must meet the following conditions:
466   // a) line(lopc) <= line(hipc)
467   // b) line(lopc) and line(hipc) are valid.
468 
469   if (!hasAssociatedRange())
470     return true;
471 
472   LVLineRange Range = getReaderCompileUnit()->lineRange(this);
473   LVLine *LowLine = Range.first;
474   LVLine *HighLine = Range.second;
475   if (LowLine)
476     setLowerLine(LowLine);
477   else {
478     setIsInvalidLower();
479     return false;
480   }
481   if (HighLine)
482     setUpperLine(HighLine);
483   else {
484     setIsInvalidUpper();
485     return false;
486   }
487   // Check for a valid interval.
488   if (LowLine->getLineNumber() > HighLine->getLineNumber()) {
489     setIsInvalidRange();
490     return false;
491   }
492 
493   return true;
494 }
495 
calculateCoverage(LVLocations * Locations,unsigned & Factor,float & Percentage)496 bool LVLocation::calculateCoverage(LVLocations *Locations, unsigned &Factor,
497                                    float &Percentage) {
498   if (!options().getAttributeCoverage() && !Locations)
499     return false;
500 
501   // Calculate the coverage depending on the kind of location. We have
502   // the simple and composed locations.
503   if (Locations->size() == 1) {
504     // Simple: fixed address, class offset, stack offset.
505     LVLocation *Location = Locations->front();
506     // Some types of locations do not have specific kind. Now is the time
507     // to set those types, depending on the operation type.
508     Location->updateKind();
509     if (Location->getIsLocationSimple()) {
510       Factor = 100;
511       Percentage = 100;
512       return true;
513     }
514   }
515 
516   // Composed locations.
517   LVAddress LowerAddress = 0;
518   LVAddress UpperAddress = 0;
519   for (const LVLocation *Location : *Locations)
520     // Do not include locations representing a gap.
521     if (!Location->getIsGapEntry()) {
522       LowerAddress = Location->getLowerAddress();
523       UpperAddress = Location->getUpperAddress();
524       Factor += (UpperAddress > LowerAddress) ? UpperAddress - LowerAddress
525                                               : LowerAddress - UpperAddress;
526     }
527 
528   Percentage = 0;
529   return false;
530 }
531 
printRaw(raw_ostream & OS,bool Full) const532 void LVLocation::printRaw(raw_ostream &OS, bool Full) const {
533   // Print the active range (low pc and high pc).
534   OS << " [" << hexString(getLowerAddress()) << ":"
535      << hexString(getUpperAddress()) << "]\n";
536   // Print any DWARF operations.
537   printRawExtra(OS, Full);
538 }
539 
printInterval(raw_ostream & OS,bool Full) const540 void LVLocation::printInterval(raw_ostream &OS, bool Full) const {
541   if (hasAssociatedRange())
542     OS << getIntervalInfo();
543 }
544 
print(raw_ostream & OS,bool Full) const545 void LVLocation::print(raw_ostream &OS, bool Full) const {
546   if (getReader().doPrintLocation(this)) {
547     LVObject::print(OS, Full);
548     printExtra(OS, Full);
549   }
550 }
551 
printExtra(raw_ostream & OS,bool Full) const552 void LVLocation::printExtra(raw_ostream &OS, bool Full) const {
553   printInterval(OS, Full);
554   OS << "\n";
555 }
556 
557 //===----------------------------------------------------------------------===//
558 // DWARF location for a symbol.
559 //===----------------------------------------------------------------------===//
560 // Add a Location Entry.
addObject(LVAddress LowPC,LVAddress HighPC,LVUnsigned SectionOffset,uint64_t LocDescOffset)561 void LVLocationSymbol::addObject(LVAddress LowPC, LVAddress HighPC,
562                                  LVUnsigned SectionOffset,
563                                  uint64_t LocDescOffset) {
564   setLowerAddress(LowPC);
565   setUpperAddress(HighPC);
566 
567   // Record the offset where the location information begins.
568   setOffset(LocDescOffset ? LocDescOffset : SectionOffset);
569 
570   // A -1 HighPC value, indicates no range.
571   if (HighPC == LVAddress(UINT64_MAX))
572     setIsDiscardedRange();
573 
574   // Update the location kind, using the DWARF attribute.
575   setKind();
576 }
577 
578 // Add a Location Record.
addObject(LVSmall Opcode,ArrayRef<LVUnsigned> Operands)579 void LVLocationSymbol::addObject(LVSmall Opcode,
580                                  ArrayRef<LVUnsigned> Operands) {
581   if (!Entries)
582     Entries = std::make_unique<LVOperations>();
583   Entries->push_back(getReader().createOperation(Opcode, Operands));
584 }
585 
586 // Based on the DWARF attribute, define the location kind.
setKind()587 void LVLocation::setKind() {
588   switch (getAttr()) {
589   case dwarf::DW_AT_data_member_location:
590     setIsClassOffset();
591     break;
592   case dwarf::DW_AT_location:
593     // Depending on the operand, we have a fixed address.
594     setIsFixedAddress();
595     break;
596   default:
597     break;
598   }
599   // For those symbols with absolute location information, ignore any
600   // gaps in their location description; that is the case with absolute
601   // memory addresses and members located at specific offsets.
602   if (hasAssociatedRange())
603     getParentSymbol()->setFillGaps();
604 }
605 
updateKind()606 void LVLocationSymbol::updateKind() {
607   // Update the location type for simple ones.
608   if (Entries && Entries->size() == 1) {
609     if (dwarf::DW_OP_fbreg == Entries->front()->getOpcode())
610       setIsStackOffset();
611   }
612 }
613 
printRawExtra(raw_ostream & OS,bool Full) const614 void LVLocationSymbol::printRawExtra(raw_ostream &OS, bool Full) const {
615   if (Entries)
616     for (const LVOperation *Operation : *Entries)
617       Operation->print(OS, Full);
618 }
619 
620 // Print location (formatted version).
print(LVLocations * Locations,raw_ostream & OS,bool Full)621 void LVLocation::print(LVLocations *Locations, raw_ostream &OS, bool Full) {
622   if (!Locations || Locations->empty())
623     return;
624 
625   // Print the symbol coverage.
626   if (options().getAttributeCoverage()) {
627     // The location entries are contained within a symbol. Get a location,
628     // to access basic information about indentation, parent, etc.
629     LVLocation *Location = Locations->front();
630     LVSymbol *Symbol = Location->getParentSymbol();
631     float Percentage = Symbol->getCoveragePercentage();
632 
633     // The coverage is dependent on the kind of location.
634     std::string String;
635     raw_string_ostream Stream(String);
636     Stream << format("%.2f%%", Percentage);
637     if (!Location->getIsLocationSimple())
638       Stream << format(" (%d/%d)", Symbol->getCoverageFactor(),
639                        Symbol->getParentScope()->getCoverageFactor());
640     Symbol->printAttributes(OS, Full, "{Coverage} ", Symbol, StringRef(String),
641                             /*UseQuotes=*/false,
642                             /*PrintRef=*/false);
643   }
644 
645   // Print the symbol location, including the missing entries.
646   if (getReader().doPrintLocation(/*Location=*/nullptr))
647     for (const LVLocation *Location : *Locations)
648       Location->print(OS, Full);
649 }
650 
printExtra(raw_ostream & OS,bool Full) const651 void LVLocationSymbol::printExtra(raw_ostream &OS, bool Full) const {
652   OS << "{Location}";
653   if (getIsCallSite())
654     OS << " -> CallSite";
655   printInterval(OS, Full);
656   OS << "\n";
657 
658   // Print location entries.
659   if (Full && Entries) {
660     bool CodeViewLocation = getParentSymbol()->getHasCodeViewLocation();
661     std::stringstream Stream;
662     std::string Leading;
663     for (LVOperation *Operation : *Entries) {
664       Stream << Leading
665              << (CodeViewLocation ? Operation->getOperandsCodeViewInfo()
666                                   : Operation->getOperandsDWARFInfo());
667       Leading = ", ";
668     }
669     printAttributes(OS, Full, "{Entry} ", const_cast<LVLocationSymbol *>(this),
670                     StringRef(Stream.str()),
671                     /*UseQuotes=*/false,
672                     /*PrintRef=*/false);
673   }
674 }
675