File: | llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp |
Warning: | line 263, column 14 Although the value stored to 'Value1' is used in the enclosing expression, the value is never actually read from 'Value1' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | //===----------------------------------------------------------------------===// |
8 | |
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> |
23 | |
24 | using namespace llvm; |
25 | using object::SectionedAddress; |
26 | |
27 | namespace { |
28 | class DWARFLocationInterpreter { |
29 | Optional<object::SectionedAddress> Base; |
30 | std::function<Optional<object::SectionedAddress>(uint32_t)> LookupAddr; |
31 | |
32 | public: |
33 | DWARFLocationInterpreter( |
34 | Optional<object::SectionedAddress> Base, |
35 | std::function<Optional<object::SectionedAddress>(uint32_t)> LookupAddr) |
36 | : Base(Base), LookupAddr(std::move(LookupAddr)) {} |
37 | |
38 | Expected<Optional<DWARFLocationExpression>> |
39 | Interpret(const DWARFLocationEntry &E); |
40 | }; |
41 | } // namespace |
42 | |
43 | static Error createResolverError(uint32_t Index, unsigned Kind) { |
44 | return createStringError(errc::invalid_argument, |
45 | "Unable to resolve indirect address %u for: %s", |
46 | Index, dwarf::LocListEncodingString(Kind).data()); |
47 | } |
48 | |
49 | Expected<Optional<DWARFLocationExpression>> |
50 | DWARFLocationInterpreter::Interpret(const DWARFLocationEntry &E) { |
51 | switch (E.Kind) { |
52 | case dwarf::DW_LLE_end_of_list: |
53 | return None; |
54 | case dwarf::DW_LLE_base_addressx: { |
55 | Base = LookupAddr(E.Value0); |
56 | if (!Base) |
57 | return createResolverError(E.Value0, E.Kind); |
58 | return None; |
59 | } |
60 | case dwarf::DW_LLE_startx_endx: { |
61 | Optional<SectionedAddress> LowPC = LookupAddr(E.Value0); |
62 | if (!LowPC) |
63 | return createResolverError(E.Value0, E.Kind); |
64 | Optional<SectionedAddress> HighPC = LookupAddr(E.Value1); |
65 | if (!HighPC) |
66 | return createResolverError(E.Value1, E.Kind); |
67 | return DWARFLocationExpression{ |
68 | DWARFAddressRange{LowPC->Address, HighPC->Address, LowPC->SectionIndex}, |
69 | E.Loc}; |
70 | } |
71 | case dwarf::DW_LLE_startx_length: { |
72 | Optional<SectionedAddress> LowPC = LookupAddr(E.Value0); |
73 | if (!LowPC) |
74 | return createResolverError(E.Value0, E.Kind); |
75 | return DWARFLocationExpression{DWARFAddressRange{LowPC->Address, |
76 | LowPC->Address + E.Value1, |
77 | LowPC->SectionIndex}, |
78 | E.Loc}; |
79 | } |
80 | case dwarf::DW_LLE_offset_pair: { |
81 | if (!Base) { |
82 | return createStringError(inconvertibleErrorCode(), |
83 | "Unable to resolve location list offset pair: " |
84 | "Base address not defined"); |
85 | } |
86 | DWARFAddressRange Range{Base->Address + E.Value0, Base->Address + E.Value1, |
87 | Base->SectionIndex}; |
88 | if (Range.SectionIndex == SectionedAddress::UndefSection) |
89 | Range.SectionIndex = E.SectionIndex; |
90 | return DWARFLocationExpression{Range, E.Loc}; |
91 | } |
92 | case dwarf::DW_LLE_default_location: |
93 | return DWARFLocationExpression{None, E.Loc}; |
94 | case dwarf::DW_LLE_base_address: |
95 | Base = SectionedAddress{E.Value0, E.SectionIndex}; |
96 | return None; |
97 | case dwarf::DW_LLE_start_end: |
98 | return DWARFLocationExpression{ |
99 | DWARFAddressRange{E.Value0, E.Value1, E.SectionIndex}, E.Loc}; |
100 | case dwarf::DW_LLE_start_length: |
101 | return DWARFLocationExpression{ |
102 | DWARFAddressRange{E.Value0, E.Value0 + E.Value1, E.SectionIndex}, |
103 | E.Loc}; |
104 | default: |
105 | llvm_unreachable("unreachable locations list kind")::llvm::llvm_unreachable_internal("unreachable locations list kind" , "/build/llvm-toolchain-snapshot-12~++20210107111113+c9154e8fa377/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp" , 105); |
106 | } |
107 | } |
108 | |
109 | static void dumpExpression(raw_ostream &OS, DIDumpOptions DumpOpts, |
110 | ArrayRef<uint8_t> Data, bool IsLittleEndian, |
111 | unsigned AddressSize, const MCRegisterInfo *MRI, |
112 | DWARFUnit *U) { |
113 | DWARFDataExtractor Extractor(Data, IsLittleEndian, AddressSize); |
114 | // Note. We do not pass any format to DWARFExpression, even if the |
115 | // corresponding unit is known. For now, there is only one operation, |
116 | // DW_OP_call_ref, which depends on the format; it is rarely used, and |
117 | // is unexpected in location tables. |
118 | DWARFExpression(Extractor, AddressSize).print(OS, DumpOpts, MRI, U); |
119 | } |
120 | |
121 | bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS, |
122 | Optional<SectionedAddress> BaseAddr, |
123 | const MCRegisterInfo *MRI, |
124 | const DWARFObject &Obj, DWARFUnit *U, |
125 | DIDumpOptions DumpOpts, |
126 | unsigned Indent) const { |
127 | DWARFLocationInterpreter Interp( |
128 | BaseAddr, [U](uint32_t Index) -> Optional<SectionedAddress> { |
129 | if (U) |
130 | return U->getAddrOffsetSectionItem(Index); |
131 | return None; |
132 | }); |
133 | OS << format("0x%8.8" PRIx64"l" "x" ": ", *Offset); |
134 | Error E = visitLocationList(Offset, [&](const DWARFLocationEntry &E) { |
135 | Expected<Optional<DWARFLocationExpression>> Loc = Interp.Interpret(E); |
136 | if (!Loc || DumpOpts.DisplayRawContents) |
137 | dumpRawEntry(E, OS, Indent, DumpOpts, Obj); |
138 | if (Loc && *Loc) { |
139 | OS << "\n"; |
140 | OS.indent(Indent); |
141 | if (DumpOpts.DisplayRawContents) |
142 | OS << " => "; |
143 | |
144 | DIDumpOptions RangeDumpOpts(DumpOpts); |
145 | RangeDumpOpts.DisplayRawContents = false; |
146 | if (Loc.get()->Range) |
147 | Loc.get()->Range->dump(OS, Data.getAddressSize(), RangeDumpOpts, &Obj); |
148 | else |
149 | OS << "<default>"; |
150 | } |
151 | if (!Loc) |
152 | consumeError(Loc.takeError()); |
153 | |
154 | if (E.Kind != dwarf::DW_LLE_base_address && |
155 | E.Kind != dwarf::DW_LLE_base_addressx && |
156 | E.Kind != dwarf::DW_LLE_end_of_list) { |
157 | OS << ": "; |
158 | dumpExpression(OS, DumpOpts, E.Loc, Data.isLittleEndian(), |
159 | Data.getAddressSize(), MRI, U); |
160 | } |
161 | return true; |
162 | }); |
163 | if (E) { |
164 | DumpOpts.RecoverableErrorHandler(std::move(E)); |
165 | return false; |
166 | } |
167 | return true; |
168 | } |
169 | |
170 | Error DWARFLocationTable::visitAbsoluteLocationList( |
171 | uint64_t Offset, Optional<SectionedAddress> BaseAddr, |
172 | std::function<Optional<SectionedAddress>(uint32_t)> LookupAddr, |
173 | function_ref<bool(Expected<DWARFLocationExpression>)> Callback) const { |
174 | DWARFLocationInterpreter Interp(BaseAddr, std::move(LookupAddr)); |
175 | return visitLocationList(&Offset, [&](const DWARFLocationEntry &E) { |
176 | Expected<Optional<DWARFLocationExpression>> Loc = Interp.Interpret(E); |
177 | if (!Loc) |
178 | return Callback(Loc.takeError()); |
179 | if (*Loc) |
180 | return Callback(**Loc); |
181 | return true; |
182 | }); |
183 | } |
184 | |
185 | void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, |
186 | const DWARFObject &Obj, DIDumpOptions DumpOpts, |
187 | Optional<uint64_t> DumpOffset) const { |
188 | auto BaseAddr = None; |
189 | unsigned Indent = 12; |
190 | if (DumpOffset) { |
191 | dumpLocationList(&*DumpOffset, OS, BaseAddr, MRI, Obj, nullptr, DumpOpts, |
192 | Indent); |
193 | } else { |
194 | uint64_t Offset = 0; |
195 | StringRef Separator; |
196 | bool CanContinue = true; |
197 | while (CanContinue && Data.isValidOffset(Offset)) { |
198 | OS << Separator; |
199 | Separator = "\n"; |
200 | |
201 | CanContinue = dumpLocationList(&Offset, OS, BaseAddr, MRI, Obj, nullptr, |
202 | DumpOpts, Indent); |
203 | OS << '\n'; |
204 | } |
205 | } |
206 | } |
207 | |
208 | Error DWARFDebugLoc::visitLocationList( |
209 | uint64_t *Offset, |
210 | function_ref<bool(const DWARFLocationEntry &)> Callback) const { |
211 | DataExtractor::Cursor C(*Offset); |
212 | while (true) { |
213 | uint64_t SectionIndex; |
214 | uint64_t Value0 = Data.getRelocatedAddress(C); |
215 | uint64_t Value1 = Data.getRelocatedAddress(C, &SectionIndex); |
216 | |
217 | DWARFLocationEntry E; |
218 | |
219 | // The end of any given location list is marked by an end of list entry, |
220 | // which consists of a 0 for the beginning address offset and a 0 for the |
221 | // ending address offset. A beginning offset of 0xff...f marks the base |
222 | // address selection entry. |
223 | if (Value0 == 0 && Value1 == 0) { |
224 | E.Kind = dwarf::DW_LLE_end_of_list; |
225 | } else if (Value0 == (Data.getAddressSize() == 4 ? -1U : -1ULL)) { |
226 | E.Kind = dwarf::DW_LLE_base_address; |
227 | E.Value0 = Value1; |
228 | E.SectionIndex = SectionIndex; |
229 | } else { |
230 | E.Kind = dwarf::DW_LLE_offset_pair; |
231 | E.Value0 = Value0; |
232 | E.Value1 = Value1; |
233 | E.SectionIndex = SectionIndex; |
234 | unsigned Bytes = Data.getU16(C); |
235 | // A single location description describing the location of the object... |
236 | Data.getU8(C, E.Loc, Bytes); |
237 | } |
238 | |
239 | if (!C) |
240 | return C.takeError(); |
241 | if (!Callback(E) || E.Kind == dwarf::DW_LLE_end_of_list) |
242 | break; |
243 | } |
244 | *Offset = C.tell(); |
245 | return Error::success(); |
246 | } |
247 | |
248 | void DWARFDebugLoc::dumpRawEntry(const DWARFLocationEntry &Entry, |
249 | raw_ostream &OS, unsigned Indent, |
250 | DIDumpOptions DumpOpts, |
251 | const DWARFObject &Obj) const { |
252 | uint64_t Value0, Value1; |
253 | switch (Entry.Kind) { |
254 | case dwarf::DW_LLE_base_address: |
255 | Value0 = Data.getAddressSize() == 4 ? -1U : -1ULL; |
256 | Value1 = Entry.Value0; |
257 | break; |
258 | case dwarf::DW_LLE_offset_pair: |
259 | Value0 = Entry.Value0; |
260 | Value1 = Entry.Value1; |
261 | break; |
262 | case dwarf::DW_LLE_end_of_list: |
263 | Value0 = Value1 = 0; |
Although the value stored to 'Value1' is used in the enclosing expression, the value is never actually read from 'Value1' | |
264 | return; |
265 | default: |
266 | llvm_unreachable("Not possible in DWARF4!")::llvm::llvm_unreachable_internal("Not possible in DWARF4!", "/build/llvm-toolchain-snapshot-12~++20210107111113+c9154e8fa377/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp" , 266); |
267 | } |
268 | OS << '\n'; |
269 | OS.indent(Indent); |
270 | OS << '(' << format_hex(Value0, 2 + Data.getAddressSize() * 2) << ", " |
271 | << format_hex(Value1, 2 + Data.getAddressSize() * 2) << ')'; |
272 | DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, Entry.SectionIndex); |
273 | } |
274 | |
275 | Error DWARFDebugLoclists::visitLocationList( |
276 | uint64_t *Offset, function_ref<bool(const DWARFLocationEntry &)> F) const { |
277 | |
278 | DataExtractor::Cursor C(*Offset); |
279 | bool Continue = true; |
280 | while (Continue) { |
281 | DWARFLocationEntry E; |
282 | E.Kind = Data.getU8(C); |
283 | switch (E.Kind) { |
284 | case dwarf::DW_LLE_end_of_list: |
285 | break; |
286 | case dwarf::DW_LLE_base_addressx: |
287 | E.Value0 = Data.getULEB128(C); |
288 | break; |
289 | case dwarf::DW_LLE_startx_endx: |
290 | E.Value0 = Data.getULEB128(C); |
291 | E.Value1 = Data.getULEB128(C); |
292 | break; |
293 | case dwarf::DW_LLE_startx_length: |
294 | E.Value0 = Data.getULEB128(C); |
295 | // Pre-DWARF 5 has different interpretation of the length field. We have |
296 | // to support both pre- and standartized styles for the compatibility. |
297 | if (Version < 5) |
298 | E.Value1 = Data.getU32(C); |
299 | else |
300 | E.Value1 = Data.getULEB128(C); |
301 | break; |
302 | case dwarf::DW_LLE_offset_pair: |
303 | E.Value0 = Data.getULEB128(C); |
304 | E.Value1 = Data.getULEB128(C); |
305 | E.SectionIndex = SectionedAddress::UndefSection; |
306 | break; |
307 | case dwarf::DW_LLE_default_location: |
308 | break; |
309 | case dwarf::DW_LLE_base_address: |
310 | E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex); |
311 | break; |
312 | case dwarf::DW_LLE_start_end: |
313 | E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex); |
314 | E.Value1 = Data.getRelocatedAddress(C); |
315 | break; |
316 | case dwarf::DW_LLE_start_length: |
317 | E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex); |
318 | E.Value1 = Data.getULEB128(C); |
319 | break; |
320 | default: |
321 | cantFail(C.takeError()); |
322 | return createStringError(errc::illegal_byte_sequence, |
323 | "LLE of kind %x not supported", (int)E.Kind); |
324 | } |
325 | |
326 | if (E.Kind != dwarf::DW_LLE_base_address && |
327 | E.Kind != dwarf::DW_LLE_base_addressx && |
328 | E.Kind != dwarf::DW_LLE_end_of_list) { |
329 | unsigned Bytes = Version >= 5 ? Data.getULEB128(C) : Data.getU16(C); |
330 | // A single location description describing the location of the object... |
331 | Data.getU8(C, E.Loc, Bytes); |
332 | } |
333 | |
334 | if (!C) |
335 | return C.takeError(); |
336 | Continue = F(E) && E.Kind != dwarf::DW_LLE_end_of_list; |
337 | } |
338 | *Offset = C.tell(); |
339 | return Error::success(); |
340 | } |
341 | |
342 | void DWARFDebugLoclists::dumpRawEntry(const DWARFLocationEntry &Entry, |
343 | raw_ostream &OS, unsigned Indent, |
344 | DIDumpOptions DumpOpts, |
345 | const DWARFObject &Obj) const { |
346 | size_t MaxEncodingStringLength = 0; |
347 | #define HANDLE_DW_LLE(ID, NAME) \ |
348 | MaxEncodingStringLength = std::max(MaxEncodingStringLength, \ |
349 | dwarf::LocListEncodingString(ID).size()); |
350 | #include "llvm/BinaryFormat/Dwarf.def" |
351 | |
352 | OS << "\n"; |
353 | OS.indent(Indent); |
354 | StringRef EncodingString = dwarf::LocListEncodingString(Entry.Kind); |
355 | // Unsupported encodings should have been reported during parsing. |
356 | assert(!EncodingString.empty() && "Unknown loclist entry encoding")((!EncodingString.empty() && "Unknown loclist entry encoding" ) ? static_cast<void> (0) : __assert_fail ("!EncodingString.empty() && \"Unknown loclist entry encoding\"" , "/build/llvm-toolchain-snapshot-12~++20210107111113+c9154e8fa377/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp" , 356, __PRETTY_FUNCTION__)); |
357 | OS << format("%-*s(", MaxEncodingStringLength, EncodingString.data()); |
358 | unsigned FieldSize = 2 + 2 * Data.getAddressSize(); |
359 | switch (Entry.Kind) { |
360 | case dwarf::DW_LLE_end_of_list: |
361 | case dwarf::DW_LLE_default_location: |
362 | break; |
363 | case dwarf::DW_LLE_startx_endx: |
364 | case dwarf::DW_LLE_startx_length: |
365 | case dwarf::DW_LLE_offset_pair: |
366 | case dwarf::DW_LLE_start_end: |
367 | case dwarf::DW_LLE_start_length: |
368 | OS << format_hex(Entry.Value0, FieldSize) << ", " |
369 | << format_hex(Entry.Value1, FieldSize); |
370 | break; |
371 | case dwarf::DW_LLE_base_addressx: |
372 | case dwarf::DW_LLE_base_address: |
373 | OS << format_hex(Entry.Value0, FieldSize); |
374 | break; |
375 | } |
376 | OS << ')'; |
377 | switch (Entry.Kind) { |
378 | case dwarf::DW_LLE_base_address: |
379 | case dwarf::DW_LLE_start_end: |
380 | case dwarf::DW_LLE_start_length: |
381 | DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, Entry.SectionIndex); |
382 | break; |
383 | default: |
384 | break; |
385 | } |
386 | } |
387 | |
388 | void DWARFDebugLoclists::dumpRange(uint64_t StartOffset, uint64_t Size, |
389 | raw_ostream &OS, const MCRegisterInfo *MRI, |
390 | const DWARFObject &Obj, |
391 | DIDumpOptions DumpOpts) { |
392 | if (!Data.isValidOffsetForDataOfSize(StartOffset, Size)) { |
393 | OS << "Invalid dump range\n"; |
394 | return; |
395 | } |
396 | uint64_t Offset = StartOffset; |
397 | StringRef Separator; |
398 | bool CanContinue = true; |
399 | while (CanContinue && Offset < StartOffset + Size) { |
400 | OS << Separator; |
401 | Separator = "\n"; |
402 | |
403 | CanContinue = dumpLocationList(&Offset, OS, /*BaseAddr=*/None, MRI, Obj, |
404 | nullptr, DumpOpts, /*Indent=*/12); |
405 | OS << '\n'; |
406 | } |
407 | } |