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
18using namespace llvm;
19using namespace llvm::logicalview;
20
21#define DEBUG_TYPE "Location"
22
23void 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.
27std::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(Fmt: "lit%d", Vals: 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(Opcode: Code, Operands));
45 Stream << format(Fmt: "breg%d+%d%s", Vals: Code - dwarf::DW_OP_breg0, Vals: Operands[0],
46 Vals: 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(Opcode: Code, Operands));
55 Stream << format(Fmt: "reg%d%s", Vals: Code - dwarf::DW_OP_reg0,
56 Vals: RegisterName.c_str());
57 return;
58 }
59
60 Stream << format(Fmt: "#0x%02x ", Vals: Code) << hexString(Value: Operands[0]) << " "
61 << hexString(Value: 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(Value: 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(Fmt: "bregx %d%s+%d", Vals: Operands[0], Vals: RegisterName.c_str(),
104 Vals: unsigned(Operands[1]));
105 break;
106 }
107 case dwarf::DW_OP_regval_type: {
108 std::string RegisterName(getReader().getRegisterName(Opcode, Operands));
109 Stream << format(Fmt: "regval_type %d%s+%d", Vals: Operands[0], Vals: RegisterName.c_str(),
110 Vals: 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(Value: 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(Value: 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(Value: 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(Value: Operands[0]);
243 break;
244 case dwarf::DW_OP_call4:
245 Stream << "call4 DIE offset " << hexString(Value: Operands[0]);
246 break;
247 case dwarf::DW_OP_call_ref:
248 Stream << "call_ref DIE offset " << hexString(Value: 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(Value: Operands[0]);
256 break;
257 case dwarf::DW_OP_reinterpret:
258 Stream << "reinterpret DIE offset " << hexString(Value: 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(Value: 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(Value: 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.
347std::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(Code: 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(Fmt: "#0x%02x: ", Vals: Opcode) << hexString(Value: Operands[0]) << " "
388 << hexString(Value: Operands[1]) << "#";
389 break;
390 }
391
392 return String;
393}
394
395namespace {
396const char *const KindBaseClassOffset = "BaseClassOffset";
397const char *const KindBaseClassStep = "BaseClassStep";
398const char *const KindClassOffset = "ClassOffset";
399const char *const KindFixedAddress = "FixedAddress";
400const char *const KindMissingInfo = "Missing";
401const char *const KindOperation = "Operation";
402const char *const KindOperationList = "OperationList";
403const char *const KindRegister = "Register";
404const char *const KindUndefined = "Undefined";
405} // end anonymous namespace
406
407//===----------------------------------------------------------------------===//
408// DWARF location information.
409//===----------------------------------------------------------------------===//
410const 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
431std::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(Value: getLowerAddress()) << ":"
456 << hexString(Value: getUpperAddress()) << "]";
457
458 return String;
459}
460
461// Validate the ranges associated with the location.
462bool 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(Location: 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
496bool 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
532void LVLocation::printRaw(raw_ostream &OS, bool Full) const {
533 // Print the active range (low pc and high pc).
534 OS << " [" << hexString(Value: getLowerAddress()) << ":"
535 << hexString(Value: getUpperAddress()) << "]\n";
536 // Print any DWARF operations.
537 printRawExtra(OS, Full);
538}
539
540void LVLocation::printInterval(raw_ostream &OS, bool Full) const {
541 if (hasAssociatedRange())
542 OS << getIntervalInfo();
543}
544
545void LVLocation::print(raw_ostream &OS, bool Full) const {
546 if (getReader().doPrintLocation(Location: this)) {
547 LVObject::print(OS, Full);
548 printExtra(OS, Full);
549 }
550}
551
552void 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.
561void 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.
579void LVLocationSymbol::addObject(LVSmall Opcode,
580 ArrayRef<LVUnsigned> Operands) {
581 if (!Entries)
582 Entries = std::make_unique<LVOperations>();
583 Entries->push_back(Elt: getReader().createOperation(OpCode: Opcode, Operands));
584}
585
586// Based on the DWARF attribute, define the location kind.
587void 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
606void 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
614void 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).
621void 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(Fmt: "%.2f%%", Vals: Percentage);
637 if (!Location->getIsLocationSimple())
638 Stream << format(Fmt: " (%d/%d)", Vals: Symbol->getCoverageFactor(),
639 Vals: Symbol->getParentScope()->getCoverageFactor());
640 Symbol->printAttributes(OS, Full, Name: "{Coverage} ", Parent: Symbol, Value: 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
651void 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, Name: "{Entry} ", Parent: const_cast<LVLocationSymbol *>(this),
670 Value: StringRef(Stream.str()),
671 /*UseQuotes=*/false,
672 /*PrintRef=*/false);
673 }
674}
675