Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnwindTablePrinter.cpp
213799 views
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
9
#include "llvm/DebugInfo/DWARF/DWARFUnwindTablePrinter.h"
10
#include "llvm/DebugInfo/DIContext.h"
11
#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
12
#include "llvm/Support/ErrorHandling.h"
13
#include "llvm/Support/Format.h"
14
#include "llvm/Support/raw_ostream.h"
15
#include <cassert>
16
#include <cinttypes>
17
#include <cstdint>
18
#include <optional>
19
20
using namespace llvm;
21
using namespace dwarf;
22
23
static void printRegister(raw_ostream &OS, DIDumpOptions DumpOpts,
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.
49
static void printUnwindLocation(const UnwindLocation &UL, raw_ostream &OS,
50
DIDumpOptions DumpOpts) {
51
if (UL.getDereference())
52
OS << '[';
53
switch (UL.getLocation()) {
54
case UnwindLocation::Unspecified:
55
OS << "unspecified";
56
break;
57
case UnwindLocation::Undefined:
58
OS << "undefined";
59
break;
60
case UnwindLocation::Same:
61
OS << "same";
62
break;
63
case UnwindLocation::CFAPlusOffset:
64
OS << "CFA";
65
if (UL.getOffset() == 0)
66
break;
67
if (UL.getOffset() > 0)
68
OS << "+";
69
OS << UL.getOffset();
70
break;
71
case UnwindLocation::RegPlusOffset:
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;
81
case UnwindLocation::DWARFExpr: {
82
if (UL.getDWARFExpressionBytes()) {
83
auto Expr = *UL.getDWARFExpressionBytes();
84
printDwarfExpression(&Expr, OS, DumpOpts, nullptr);
85
}
86
break;
87
}
88
case UnwindLocation::Constant:
89
OS << UL.getOffset();
90
break;
91
}
92
if (UL.getDereference())
93
OS << ']';
94
}
95
96
raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,
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.
117
static void printRegisterLocations(const RegisterLocations &RL, raw_ostream &OS,
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
132
raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,
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.
155
static 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
169
raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindRow &Row) {
170
auto DumpOpts = DIDumpOptions();
171
printUnwindRow(Row, OS, DumpOpts, 0);
172
return OS;
173
}
174
175
void llvm::dwarf::printUnwindTable(const UnwindTable &Rows, raw_ostream &OS,
176
DIDumpOptions DumpOpts,
177
unsigned IndentLevel) {
178
for (const UnwindRow &Row : Rows)
179
printUnwindRow(Row, OS, DumpOpts, IndentLevel);
180
}
181
182
raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) {
183
auto DumpOpts = DIDumpOptions();
184
printUnwindTable(Rows, OS, DumpOpts, 0);
185
return OS;
186
}
187
188