LLVM 22.0.0git
DWARFUnwindTablePrinter.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
13#include "llvm/Support/Format.h"
15#include <cassert>
16#include <cinttypes>
17#include <cstdint>
18#include <optional>
19
20using namespace llvm;
21using namespace dwarf;
22
24 unsigned RegNum) {
25 if (DumpOpts.GetNameForDWARFReg) {
26 auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH);
27 if (!RegName.empty()) {
28 OS << RegName;
29 return;
30 }
31 }
32 OS << "reg" << RegNum;
33}
34
35/// Print an unwind location expression as text and use the register information
36/// if some is provided.
37///
38/// \param R the unwind location to print.
39///
40/// \param OS the stream to use for output.
41///
42/// \param MRI register information that helps emit register names insteead
43/// of raw register numbers.
44///
45/// \param IsEH true if the DWARF Call Frame Information is from .eh_frame
46/// instead of from .debug_frame. This is needed for register number
47/// conversion because some register numbers differ between the two sections
48/// for certain architectures like x86.
50 DIDumpOptions DumpOpts) {
51 if (UL.getDereference())
52 OS << '[';
53 switch (UL.getLocation()) {
55 OS << "unspecified";
56 break;
58 OS << "undefined";
59 break;
61 OS << "same";
62 break;
64 OS << "CFA";
65 if (UL.getOffset() == 0)
66 break;
67 if (UL.getOffset() > 0)
68 OS << "+";
69 OS << UL.getOffset();
70 break;
72 printRegister(OS, DumpOpts, UL.getRegister());
73 if (UL.getOffset() == 0 && !UL.hasAddressSpace())
74 break;
75 if (UL.getOffset() >= 0)
76 OS << "+";
77 OS << UL.getOffset();
78 if (UL.hasAddressSpace())
79 OS << " in addrspace" << UL.getAddressSpace();
80 break;
82 if (UL.getDWARFExpressionBytes()) {
83 auto Expr = *UL.getDWARFExpressionBytes();
84 printDwarfExpression(&Expr, OS, DumpOpts, nullptr);
85 }
86 break;
87 }
89 OS << UL.getOffset();
90 break;
91 }
92 if (UL.getDereference())
93 OS << ']';
94}
95
97 const UnwindLocation &UL) {
98 auto DumpOpts = DIDumpOptions();
99 printUnwindLocation(UL, OS, DumpOpts);
100 return OS;
101}
102
103/// Print all registers + locations that are currently defined in a register
104/// locations.
105///
106/// \param RL the register locations to print.
107///
108/// \param OS the stream to use for output.
109///
110/// \param MRI register information that helps emit register names insteead
111/// of raw register numbers.
112///
113/// \param IsEH true if the DWARF Call Frame Information is from .eh_frame
114/// instead of from .debug_frame. This is needed for register number
115/// conversion because some register numbers differ between the two sections
116/// for certain architectures like x86.
118 DIDumpOptions DumpOpts) {
119 bool First = true;
120 for (uint32_t Reg : RL.getRegisters()) {
121 auto Loc = *RL.getRegisterLocation(Reg);
122 if (First)
123 First = false;
124 else
125 OS << ", ";
126 printRegister(OS, DumpOpts, Reg);
127 OS << '=';
128 printUnwindLocation(Loc, OS, DumpOpts);
129 }
130}
131
133 const RegisterLocations &RL) {
134 auto DumpOpts = DIDumpOptions();
135 printRegisterLocations(RL, OS, DumpOpts);
136 return OS;
137}
138
139/// Print an UnwindRow to the stream.
140///
141/// \param Row the UnwindRow to print.
142///
143/// \param OS the stream to use for output.
144///
145/// \param MRI register information that helps emit register names insteead
146/// of raw register numbers.
147///
148/// \param IsEH true if the DWARF Call Frame Information is from .eh_frame
149/// instead of from .debug_frame. This is needed for register number
150/// conversion because some register numbers differ between the two sections
151/// for certain architectures like x86.
152///
153/// \param IndentLevel specify the indent level as an integer. The UnwindRow
154/// will be output to the stream preceded by 2 * IndentLevel number of spaces.
155static void printUnwindRow(const UnwindRow &Row, raw_ostream &OS,
156 DIDumpOptions DumpOpts, unsigned IndentLevel) {
157 OS.indent(2 * IndentLevel);
158 if (Row.hasAddress())
159 OS << format("0x%" PRIx64 ": ", Row.getAddress());
160 OS << "CFA=";
161 printUnwindLocation(Row.getCFAValue(), OS, DumpOpts);
162 if (Row.getRegisterLocations().hasLocations()) {
163 OS << ": ";
164 printRegisterLocations(Row.getRegisterLocations(), OS, DumpOpts);
165 }
166 OS << "\n";
167}
168
170 auto DumpOpts = DIDumpOptions();
171 printUnwindRow(Row, OS, DumpOpts, 0);
172 return OS;
173}
174
176 DIDumpOptions DumpOpts,
177 unsigned IndentLevel) {
178 for (const UnwindRow &Row : Rows)
179 printUnwindRow(Row, OS, DumpOpts, IndentLevel);
180}
181
183 auto DumpOpts = DIDumpOptions();
184 printUnwindTable(Rows, OS, DumpOpts, 0);
185 return OS;
186}
static void printRegisterLocations(const RegisterLocations &RL, raw_ostream &OS, DIDumpOptions DumpOpts)
Print all registers + locations that are currently defined in a register locations.
static void printRegister(raw_ostream &OS, DIDumpOptions DumpOpts, unsigned RegNum)
static void printUnwindRow(const UnwindRow &Row, raw_ostream &OS, DIDumpOptions DumpOpts, unsigned IndentLevel)
Print an UnwindRow to the stream.
static void printUnwindLocation(const UnwindLocation &UL, raw_ostream &OS, DIDumpOptions DumpOpts)
Print an unwind location expression as text and use the register information if some is provided.
#define RegName(no)
raw_pwrite_stream & OS
A class that can track all registers with locations in a UnwindRow object.
std::optional< UnwindLocation > getRegisterLocation(uint32_t RegNum) const
Return the location for the register in RegNum if there is a location.
SmallVector< uint32_t, 4 > getRegisters() const
A class that represents a location for the Call Frame Address (CFA) or a register.
@ Undefined
Register is not available and can't be recovered.
@ Constant
Value is a constant value contained in "Offset": reg = Offset.
@ DWARFExpr
Register or CFA value is in or at a value found by evaluating a DWARF expression: reg = eval(dwarf_ex...
@ Same
Register value is in the register, nothing needs to be done to unwind it: reg = reg.
@ CFAPlusOffset
Register is in or at the CFA plus an offset: reg = CFA + offset reg = defef(CFA + offset)
@ RegPlusOffset
Register or CFA is in or at a register plus offset, optionally in an address space: reg = reg + offse...
uint32_t getAddressSpace() const
std::optional< DWARFExpression > getDWARFExpressionBytes() const
A class that represents a single row in the unwind table that is decoded by parsing the DWARF Call Fr...
A class that contains all UnwindRow objects for an FDE or a single unwind row for a CIE.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
LLVM_ABI void printUnwindTable(const UnwindTable &Rows, raw_ostream &OS, DIDumpOptions DumpOpts, unsigned IndentLevel=0)
Print a UnwindTable to the stream.
LLVM_ABI raw_ostream & operator<<(raw_ostream &OS, const UnwindLocation &R)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
LLVM_ABI void printDwarfExpression(const DWARFExpression *E, raw_ostream &OS, DIDumpOptions DumpOpts, DWARFUnit *U, bool IsEH=false)
Print a Dwarf expression/.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:126
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:196
std::function< llvm::StringRef(uint64_t DwarfRegNum, bool IsEH)> GetNameForDWARFReg
Definition: DIContext.h:215