[AMDGPU] Check for immediate SrcC in mfma in AsmParser
[llvm-core.git] / lib / DebugInfo / DWARF / DWARFDebugLoc.cpp
blob1469a210785bef69736e265a488b8cf513b8ed89
1 //===- DWARFDebugLoc.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 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
10 #include "llvm/ADT/StringRef.h"
11 #include "llvm/BinaryFormat/Dwarf.h"
12 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
13 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
14 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
15 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
16 #include "llvm/Support/Compiler.h"
17 #include "llvm/Support/Format.h"
18 #include "llvm/Support/WithColor.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include <algorithm>
21 #include <cinttypes>
22 #include <cstdint>
24 using namespace llvm;
26 // When directly dumping the .debug_loc without a compile unit, we have to guess
27 // at the DWARF version. This only affects DW_OP_call_ref, which is a rare
28 // expression that LLVM doesn't produce. Guessing the wrong version means we
29 // won't be able to pretty print expressions in DWARF2 binaries produced by
30 // non-LLVM tools.
31 static void dumpExpression(raw_ostream &OS, ArrayRef<char> Data,
32 bool IsLittleEndian, unsigned AddressSize,
33 const MCRegisterInfo *MRI, DWARFUnit *U) {
34 DWARFDataExtractor Extractor(StringRef(Data.data(), Data.size()),
35 IsLittleEndian, AddressSize);
36 DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI, U);
39 void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
40 unsigned AddressSize,
41 const MCRegisterInfo *MRI,
42 DWARFUnit *U,
43 uint64_t BaseAddress,
44 unsigned Indent) const {
45 for (const Entry &E : Entries) {
46 OS << '\n';
47 OS.indent(Indent);
48 OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2,
49 BaseAddress + E.Begin);
50 OS << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2,
51 BaseAddress + E.End);
52 OS << ": ";
54 dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, U);
58 DWARFDebugLoc::LocationList const *
59 DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const {
60 auto It = partition_point(
61 Locations, [=](const LocationList &L) { return L.Offset < Offset; });
62 if (It != Locations.end() && It->Offset == Offset)
63 return &(*It);
64 return nullptr;
67 void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
68 Optional<uint64_t> Offset) const {
69 auto DumpLocationList = [&](const LocationList &L) {
70 OS << format("0x%8.8" PRIx64 ": ", L.Offset);
71 L.dump(OS, IsLittleEndian, AddressSize, MRI, nullptr, 0, 12);
72 OS << "\n\n";
75 if (Offset) {
76 if (auto *L = getLocationListAtOffset(*Offset))
77 DumpLocationList(*L);
78 return;
81 for (const LocationList &L : Locations) {
82 DumpLocationList(L);
86 Optional<DWARFDebugLoc::LocationList>
87 DWARFDebugLoc::parseOneLocationList(DWARFDataExtractor Data, uint64_t *Offset) {
88 LocationList LL;
89 LL.Offset = *Offset;
91 // 2.6.2 Location Lists
92 // A location list entry consists of:
93 while (true) {
94 Entry E;
95 if (!Data.isValidOffsetForDataOfSize(*Offset, 2 * Data.getAddressSize())) {
96 WithColor::error() << "location list overflows the debug_loc section.\n";
97 return None;
100 // 1. A beginning address offset. ...
101 E.Begin = Data.getRelocatedAddress(Offset);
103 // 2. An ending address offset. ...
104 E.End = Data.getRelocatedAddress(Offset);
106 // The end of any given location list is marked by an end of list entry,
107 // which consists of a 0 for the beginning address offset and a 0 for the
108 // ending address offset.
109 if (E.Begin == 0 && E.End == 0)
110 return LL;
112 if (!Data.isValidOffsetForDataOfSize(*Offset, 2)) {
113 WithColor::error() << "location list overflows the debug_loc section.\n";
114 return None;
117 unsigned Bytes = Data.getU16(Offset);
118 if (!Data.isValidOffsetForDataOfSize(*Offset, Bytes)) {
119 WithColor::error() << "location list overflows the debug_loc section.\n";
120 return None;
122 // A single location description describing the location of the object...
123 StringRef str = Data.getData().substr(*Offset, Bytes);
124 *Offset += Bytes;
125 E.Loc.reserve(str.size());
126 llvm::copy(str, std::back_inserter(E.Loc));
127 LL.Entries.push_back(std::move(E));
131 void DWARFDebugLoc::parse(const DWARFDataExtractor &data) {
132 IsLittleEndian = data.isLittleEndian();
133 AddressSize = data.getAddressSize();
135 uint64_t Offset = 0;
136 while (data.isValidOffset(Offset + data.getAddressSize() - 1)) {
137 if (auto LL = parseOneLocationList(data, &Offset))
138 Locations.push_back(std::move(*LL));
139 else
140 break;
142 if (data.isValidOffset(Offset))
143 WithColor::error() << "failed to consume entire .debug_loc section\n";
146 Optional<DWARFDebugLoclists::LocationList>
147 DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, uint64_t *Offset,
148 unsigned Version) {
149 LocationList LL;
150 LL.Offset = *Offset;
152 // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list.
153 while (auto Kind =
154 static_cast<dwarf::LocationListEntry>(Data.getU8(Offset))) {
156 Entry E;
157 E.Kind = Kind;
158 switch (Kind) {
159 case dwarf::DW_LLE_startx_length:
160 E.Value0 = Data.getULEB128(Offset);
161 // Pre-DWARF 5 has different interpretation of the length field. We have
162 // to support both pre- and standartized styles for the compatibility.
163 if (Version < 5)
164 E.Value1 = Data.getU32(Offset);
165 else
166 E.Value1 = Data.getULEB128(Offset);
167 break;
168 case dwarf::DW_LLE_start_length:
169 E.Value0 = Data.getAddress(Offset);
170 E.Value1 = Data.getULEB128(Offset);
171 break;
172 case dwarf::DW_LLE_offset_pair:
173 E.Value0 = Data.getULEB128(Offset);
174 E.Value1 = Data.getULEB128(Offset);
175 break;
176 case dwarf::DW_LLE_base_address:
177 E.Value0 = Data.getAddress(Offset);
178 break;
179 default:
180 WithColor::error() << "dumping support for LLE of kind " << (int)Kind
181 << " not implemented\n";
182 return None;
185 if (Kind != dwarf::DW_LLE_base_address) {
186 unsigned Bytes =
187 Version >= 5 ? Data.getULEB128(Offset) : Data.getU16(Offset);
188 // A single location description describing the location of the object...
189 StringRef str = Data.getData().substr(*Offset, Bytes);
190 *Offset += Bytes;
191 E.Loc.resize(str.size());
192 llvm::copy(str, E.Loc.begin());
195 LL.Entries.push_back(std::move(E));
197 return LL;
200 void DWARFDebugLoclists::parse(DataExtractor data, unsigned Version) {
201 IsLittleEndian = data.isLittleEndian();
202 AddressSize = data.getAddressSize();
204 uint64_t Offset = 0;
205 while (data.isValidOffset(Offset)) {
206 if (auto LL = parseOneLocationList(data, &Offset, Version))
207 Locations.push_back(std::move(*LL));
208 else
209 return;
213 DWARFDebugLoclists::LocationList const *
214 DWARFDebugLoclists::getLocationListAtOffset(uint64_t Offset) const {
215 auto It = partition_point(
216 Locations, [=](const LocationList &L) { return L.Offset < Offset; });
217 if (It != Locations.end() && It->Offset == Offset)
218 return &(*It);
219 return nullptr;
222 void DWARFDebugLoclists::LocationList::dump(raw_ostream &OS, uint64_t BaseAddr,
223 bool IsLittleEndian,
224 unsigned AddressSize,
225 const MCRegisterInfo *MRI,
226 DWARFUnit *U,
227 unsigned Indent) const {
228 for (const Entry &E : Entries) {
229 switch (E.Kind) {
230 case dwarf::DW_LLE_startx_length:
231 OS << '\n';
232 OS.indent(Indent);
233 OS << "Addr idx " << E.Value0 << " (w/ length " << E.Value1 << "): ";
234 break;
235 case dwarf::DW_LLE_start_length:
236 OS << '\n';
237 OS.indent(Indent);
238 OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2,
239 AddressSize * 2, E.Value0, AddressSize * 2, AddressSize * 2,
240 E.Value0 + E.Value1);
241 break;
242 case dwarf::DW_LLE_offset_pair:
243 OS << '\n';
244 OS.indent(Indent);
245 OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2,
246 AddressSize * 2, BaseAddr + E.Value0, AddressSize * 2,
247 AddressSize * 2, BaseAddr + E.Value1);
248 break;
249 case dwarf::DW_LLE_base_address:
250 BaseAddr = E.Value0;
251 break;
252 default:
253 llvm_unreachable("unreachable locations list kind");
256 dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, U);
260 void DWARFDebugLoclists::dump(raw_ostream &OS, uint64_t BaseAddr,
261 const MCRegisterInfo *MRI,
262 Optional<uint64_t> Offset) const {
263 auto DumpLocationList = [&](const LocationList &L) {
264 OS << format("0x%8.8" PRIx64 ": ", L.Offset);
265 L.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, nullptr, /*Indent=*/12);
266 OS << "\n\n";
269 if (Offset) {
270 if (auto *L = getLocationListAtOffset(*Offset))
271 DumpLocationList(*L);
272 return;
275 for (const LocationList &L : Locations) {
276 DumpLocationList(L);