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/ADT/StringExtras.h"
11#include "llvm/DebugInfo/DIContext.h"
12#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
13#include "llvm/Support/ErrorHandling.h"
14#include "llvm/Support/Format.h"
15#include "llvm/Support/FormatVariadic.h"
16#include "llvm/Support/raw_ostream.h"
17#include <cassert>
18#include <cinttypes>
19#include <cstdint>
20
21using namespace llvm;
22using namespace dwarf;
23
24static void printRegister(raw_ostream &OS, DIDumpOptions DumpOpts,
25 unsigned RegNum) {
26 if (DumpOpts.GetNameForDWARFReg) {
27 auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH);
28 if (!RegName.empty()) {
29 OS << RegName;
30 return;
31 }
32 }
33 OS << "reg" << RegNum;
34}
35
36/// Print an unwind location expression as text and use the register information
37/// if some is provided.
38///
39/// \param R the unwind location to print.
40///
41/// \param OS the stream to use for output.
42///
43/// \param MRI register information that helps emit register names insteead
44/// of raw register numbers.
45///
46/// \param IsEH true if the DWARF Call Frame Information is from .eh_frame
47/// instead of from .debug_frame. This is needed for register number
48/// conversion because some register numbers differ between the two sections
49/// for certain architectures like x86.
50static void printUnwindLocation(const UnwindLocation &UL, raw_ostream &OS,
51 DIDumpOptions DumpOpts) {
52 if (UL.getDereference())
53 OS << '[';
54 switch (UL.getLocation()) {
55 case UnwindLocation::Unspecified:
56 OS << "unspecified";
57 break;
58 case UnwindLocation::Undefined:
59 OS << "undefined";
60 break;
61 case UnwindLocation::Same:
62 OS << "same";
63 break;
64 case UnwindLocation::CFAPlusOffset:
65 OS << "CFA";
66 if (UL.getOffset() == 0)
67 break;
68 if (UL.getOffset() > 0)
69 OS << "+";
70 OS << UL.getOffset();
71 break;
72 case UnwindLocation::RegPlusOffset:
73 printRegister(OS, DumpOpts, RegNum: UL.getRegister());
74 if (UL.getOffset() == 0 && !UL.hasAddressSpace())
75 break;
76 if (UL.getOffset() >= 0)
77 OS << "+";
78 OS << UL.getOffset();
79 if (UL.hasAddressSpace())
80 OS << " in addrspace" << UL.getAddressSpace();
81 break;
82 case UnwindLocation::DWARFExpr: {
83 if (UL.getDWARFExpressionBytes()) {
84 auto Expr = *UL.getDWARFExpressionBytes();
85 printDwarfExpression(E: &Expr, OS, DumpOpts, U: nullptr);
86 }
87 break;
88 }
89 case UnwindLocation::Constant:
90 OS << UL.getOffset();
91 break;
92 }
93 if (UL.getDereference())
94 OS << ']';
95}
96
97raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,
98 const UnwindLocation &UL) {
99 auto DumpOpts = DIDumpOptions();
100 printUnwindLocation(UL, OS, DumpOpts);
101 return OS;
102}
103
104/// Print all registers + locations that are currently defined in a register
105/// locations.
106///
107/// \param RL the register locations to print.
108///
109/// \param OS the stream to use for output.
110///
111/// \param MRI register information that helps emit register names insteead
112/// of raw register numbers.
113///
114/// \param IsEH true if the DWARF Call Frame Information is from .eh_frame
115/// instead of from .debug_frame. This is needed for register number
116/// conversion because some register numbers differ between the two sections
117/// for certain architectures like x86.
118static void printRegisterLocations(const RegisterLocations &RL, raw_ostream &OS,
119 DIDumpOptions DumpOpts) {
120 ListSeparator LS;
121 for (uint32_t Reg : RL.getRegisters()) {
122 auto Loc = *RL.getRegisterLocation(RegNum: Reg);
123 OS << LS;
124 printRegister(OS, DumpOpts, RegNum: Reg);
125 OS << '=';
126 printUnwindLocation(UL: Loc, OS, DumpOpts);
127 }
128}
129
130raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,
131 const RegisterLocations &RL) {
132 auto DumpOpts = DIDumpOptions();
133 printRegisterLocations(RL, OS, DumpOpts);
134 return OS;
135}
136
137/// Print an UnwindRow to the stream.
138///
139/// \param Row the UnwindRow to print.
140///
141/// \param OS the stream to use for output.
142///
143/// \param MRI register information that helps emit register names insteead
144/// of raw register numbers.
145///
146/// \param IsEH true if the DWARF Call Frame Information is from .eh_frame
147/// instead of from .debug_frame. This is needed for register number
148/// conversion because some register numbers differ between the two sections
149/// for certain architectures like x86.
150///
151/// \param IndentLevel specify the indent level as an integer. The UnwindRow
152/// will be output to the stream preceded by 2 * IndentLevel number of spaces.
153static void printUnwindRow(const UnwindRow &Row, raw_ostream &OS,
154 DIDumpOptions DumpOpts, unsigned IndentLevel) {
155 OS.indent(NumSpaces: 2 * IndentLevel);
156 if (Row.hasAddress())
157 OS << formatv(Fmt: "{0:x}: ", Vals: Row.getAddress());
158 OS << "CFA=";
159 printUnwindLocation(UL: Row.getCFAValue(), OS, DumpOpts);
160 if (Row.getRegisterLocations().hasLocations()) {
161 OS << ": ";
162 printRegisterLocations(RL: Row.getRegisterLocations(), OS, DumpOpts);
163 }
164 OS << "\n";
165}
166
167raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindRow &Row) {
168 auto DumpOpts = DIDumpOptions();
169 printUnwindRow(Row, OS, DumpOpts, IndentLevel: 0);
170 return OS;
171}
172
173void llvm::dwarf::printUnwindTable(const UnwindTable &Rows, raw_ostream &OS,
174 DIDumpOptions DumpOpts,
175 unsigned IndentLevel) {
176 for (const UnwindRow &Row : Rows)
177 printUnwindRow(Row, OS, DumpOpts, IndentLevel);
178}
179
180raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) {
181 auto DumpOpts = DIDumpOptions();
182 printUnwindTable(Rows, OS, DumpOpts, IndentLevel: 0);
183 return OS;
184}
185