LLVM  10.0.0svn
DWARFDebugLoc.cpp
Go to the documentation of this file.
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 
10 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Support/Compiler.h"
17 #include "llvm/Support/Format.h"
18 #include "llvm/Support/WithColor.h"
20 #include <algorithm>
21 #include <cinttypes>
22 #include <cstdint>
23 
24 using namespace llvm;
25 
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.
32  bool IsLittleEndian, unsigned AddressSize,
33  const MCRegisterInfo *MRI, DWARFUnit *U) {
34  DWARFDataExtractor Extractor(toStringRef(Data), IsLittleEndian, AddressSize);
35  DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI, U);
36 }
37 
38 void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, uint64_t BaseAddress,
39  bool IsLittleEndian,
40  unsigned AddressSize,
41  const MCRegisterInfo *MRI, DWARFUnit *U,
42  DIDumpOptions DumpOpts,
43  unsigned Indent) const {
44  for (const Entry &E : Entries) {
45  OS << '\n';
46  OS.indent(Indent);
47  OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2,
48  BaseAddress + E.Begin);
49  OS << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2,
50  BaseAddress + E.End);
51  OS << ": ";
52 
53  dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, U);
54  }
55 }
56 
59  auto It = partition_point(
60  Locations, [=](const LocationList &L) { return L.Offset < Offset; });
61  if (It != Locations.end() && It->Offset == Offset)
62  return &(*It);
63  return nullptr;
64 }
65 
67  Optional<uint64_t> Offset) const {
68  auto DumpLocationList = [&](const LocationList &L) {
69  OS << format("0x%8.8" PRIx64 ": ", L.Offset);
70  L.dump(OS, 0, IsLittleEndian, AddressSize, MRI, nullptr, DumpOpts, 12);
71  OS << "\n";
72  };
73 
74  if (Offset) {
75  if (auto *L = getLocationListAtOffset(*Offset))
76  DumpLocationList(*L);
77  return;
78  }
79 
80  for (const LocationList &L : Locations) {
81  DumpLocationList(L);
82  if (&L != &Locations.back())
83  OS << '\n';
84  }
85 }
86 
89  uint64_t *Offset) {
90  LocationList LL;
91  LL.Offset = *Offset;
92  AddressSize = Data.getAddressSize();
93  DataExtractor::Cursor C(*Offset);
94 
95  // 2.6.2 Location Lists
96  // A location list entry consists of:
97  while (true) {
98  Entry E;
99 
100  // 1. A beginning address offset. ...
101  E.Begin = Data.getRelocatedAddress(C);
102 
103  // 2. An ending address offset. ...
104  E.End = Data.getRelocatedAddress(C);
105 
106  if (Error Err = C.takeError())
107  return std::move(Err);
108 
109  // The end of any given location list is marked by an end of list entry,
110  // which consists of a 0 for the beginning address offset and a 0 for the
111  // ending address offset.
112  if (E.Begin == 0 && E.End == 0) {
113  *Offset = C.tell();
114  return LL;
115  }
116 
117  if (E.Begin != (AddressSize == 4 ? -1U : -1ULL)) {
118  unsigned Bytes = Data.getU16(C);
119  // A single location description describing the location of the object...
120  Data.getU8(C, E.Loc, Bytes);
121  }
122 
123  LL.Entries.push_back(std::move(E));
124  }
125 }
126 
128  IsLittleEndian = data.isLittleEndian();
129  AddressSize = data.getAddressSize();
130 
131  uint64_t Offset = 0;
132  while (Offset < data.getData().size()) {
133  if (auto LL = parseOneLocationList(data, &Offset))
134  Locations.push_back(std::move(*LL));
135  else {
136  logAllUnhandledErrors(LL.takeError(), WithColor::error());
137  break;
138  }
139  }
140 }
141 
144  uint64_t *Offset, unsigned Version) {
145  LocationList LL;
146  LL.Offset = *Offset;
147  DataExtractor::Cursor C(*Offset);
148 
149  // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list.
150  while (auto Kind = Data.getU8(C)) {
151  Entry E;
152  E.Kind = Kind;
153  E.Offset = C.tell() - 1;
154  switch (Kind) {
155  case dwarf::DW_LLE_base_addressx:
156  E.Value0 = Data.getULEB128(C);
157  break;
158  case dwarf::DW_LLE_startx_length:
159  E.Value0 = Data.getULEB128(C);
160  // Pre-DWARF 5 has different interpretation of the length field. We have
161  // to support both pre- and standartized styles for the compatibility.
162  if (Version < 5)
163  E.Value1 = Data.getU32(C);
164  else
165  E.Value1 = Data.getULEB128(C);
166  break;
167  case dwarf::DW_LLE_start_length:
168  E.Value0 = Data.getAddress(C);
169  E.Value1 = Data.getULEB128(C);
170  break;
171  case dwarf::DW_LLE_offset_pair:
172  E.Value0 = Data.getULEB128(C);
173  E.Value1 = Data.getULEB128(C);
174  break;
175  case dwarf::DW_LLE_base_address:
176  E.Value0 = Data.getAddress(C);
177  break;
178  default:
179  cantFail(C.takeError());
181  "LLE of kind %x not supported", (int)Kind);
182  }
183 
184  if (Kind != dwarf::DW_LLE_base_address &&
185  Kind != dwarf::DW_LLE_base_addressx) {
186  unsigned Bytes = Version >= 5 ? Data.getULEB128(C) : Data.getU16(C);
187  // A single location description describing the location of the object...
188  Data.getU8(C, E.Loc, Bytes);
189  }
190 
191  LL.Entries.push_back(std::move(E));
192  }
193  if (Error Err = C.takeError())
194  return std::move(Err);
195  Entry E;
196  E.Kind = dwarf::DW_LLE_end_of_list;
197  E.Offset = C.tell() - 1;
198  LL.Entries.push_back(E);
199  *Offset = C.tell();
200  return LL;
201 }
202 
203 void DWARFDebugLoclists::parse(DataExtractor data, uint64_t Offset, uint64_t EndOffset, uint16_t Version) {
204  IsLittleEndian = data.isLittleEndian();
205  AddressSize = data.getAddressSize();
206 
207  while (Offset < EndOffset) {
208  if (auto LL = parseOneLocationList(data, &Offset, Version))
209  Locations.push_back(std::move(*LL));
210  else {
211  logAllUnhandledErrors(LL.takeError(), WithColor::error());
212  return;
213  }
214  }
215 }
216 
219  auto It = partition_point(
220  Locations, [=](const LocationList &L) { return L.Offset < Offset; });
221  if (It != Locations.end() && It->Offset == Offset)
222  return &(*It);
223  return nullptr;
224 }
225 
226 void DWARFDebugLoclists::Entry::dump(raw_ostream &OS, uint64_t &BaseAddr,
227  bool IsLittleEndian, unsigned AddressSize,
228  const MCRegisterInfo *MRI, DWARFUnit *U,
229  DIDumpOptions DumpOpts, unsigned Indent,
230  size_t MaxEncodingStringLength) const {
231  if (DumpOpts.Verbose) {
232  OS << "\n";
233  OS.indent(Indent);
234  auto EncodingString = dwarf::LocListEncodingString(Kind);
235  // Unsupported encodings should have been reported during parsing.
236  assert(!EncodingString.empty() && "Unknown loclist entry encoding");
237  OS << format("%s%*c", EncodingString.data(),
238  MaxEncodingStringLength - EncodingString.size() + 1, '(');
239  switch (Kind) {
240  case dwarf::DW_LLE_startx_length:
241  case dwarf::DW_LLE_start_length:
242  case dwarf::DW_LLE_offset_pair:
243  OS << format("0x%*.*" PRIx64 ", 0x%*.*" PRIx64, AddressSize * 2,
244  AddressSize * 2, Value0, AddressSize * 2, AddressSize * 2,
245  Value1);
246  break;
247  case dwarf::DW_LLE_base_addressx:
248  case dwarf::DW_LLE_base_address:
249  OS << format("0x%*.*" PRIx64, AddressSize * 2, AddressSize * 2,
250  Value0);
251  break;
252  case dwarf::DW_LLE_end_of_list:
253  break;
254  }
255  OS << ')';
256  }
257  auto PrintPrefix = [&] {
258  OS << "\n";
259  OS.indent(Indent);
260  if (DumpOpts.Verbose)
261  OS << format("%*s", MaxEncodingStringLength, (const char *)"=> ");
262  };
263  switch (Kind) {
264  case dwarf::DW_LLE_startx_length:
265  PrintPrefix();
266  OS << "Addr idx " << Value0 << " (w/ length " << Value1 << "): ";
267  break;
268  case dwarf::DW_LLE_start_length:
269  PrintPrefix();
270  DWARFAddressRange(Value0, Value0 + Value1)
271  .dump(OS, AddressSize, DumpOpts);
272  OS << ": ";
273  break;
274  case dwarf::DW_LLE_offset_pair:
275  PrintPrefix();
276  DWARFAddressRange(BaseAddr + Value0, BaseAddr + Value1)
277  .dump(OS, AddressSize, DumpOpts);
278  OS << ": ";
279  break;
280  case dwarf::DW_LLE_base_addressx:
281  if (!DumpOpts.Verbose)
282  return;
283  break;
284  case dwarf::DW_LLE_end_of_list:
285  if (!DumpOpts.Verbose)
286  return;
287  break;
288  case dwarf::DW_LLE_base_address:
289  BaseAddr = Value0;
290  if (!DumpOpts.Verbose)
291  return;
292  break;
293  default:
294  llvm_unreachable("unreachable locations list kind");
295  }
296 
297  dumpExpression(OS, Loc, IsLittleEndian, AddressSize, MRI, U);
298 }
300  bool IsLittleEndian,
301  unsigned AddressSize,
302  const MCRegisterInfo *MRI,
303  DWARFUnit *U,
304  DIDumpOptions DumpOpts,
305  unsigned Indent) const {
306  size_t MaxEncodingStringLength = 0;
307  if (DumpOpts.Verbose)
308  for (const auto &Entry : Entries)
309  MaxEncodingStringLength =
310  std::max(MaxEncodingStringLength,
312 
313  for (const Entry &E : Entries)
314  E.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, U, DumpOpts, Indent,
315  MaxEncodingStringLength);
316 }
317 
318 void DWARFDebugLoclists::dump(raw_ostream &OS, uint64_t BaseAddr,
319  const MCRegisterInfo *MRI, DIDumpOptions DumpOpts,
320  Optional<uint64_t> Offset) const {
321  auto DumpLocationList = [&](const LocationList &L) {
322  OS << format("0x%8.8" PRIx64 ": ", L.Offset);
323  L.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, nullptr, DumpOpts,
324  /*Indent=*/12);
325  OS << "\n";
326  };
327 
328  if (Offset) {
329  if (auto *L = getLocationListAtOffset(*Offset))
330  DumpLocationList(*L);
331  return;
332  }
333 
334  for (const LocationList &L : Locations) {
335  DumpLocationList(L);
336  if (&L != &Locations.back())
337  OS << '\n';
338  }
339 }
A list of locations that contain one variable.
Definition: DWARFDebugLoc.h:37
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:703
uint64_t CallInst * C
uint8_t getU8(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint8_t value from *offset_ptr.
uint64_t getRelocatedAddress(uint64_t *Off, uint64_t *SecIx=nullptr) const
Extracts an address-sized value and applies a relocation to the result if one exists for the given of...
uint16_t getU16(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint16_t value from *offset_ptr.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
uint64_t tell() const
Return the current position of this Cursor.
Definition: DataExtractor.h:71
void dump(raw_ostream &OS, uint64_t BaseAddress, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U, DIDumpOptions DumpOpts, unsigned Indent) const
Dump this list on OS.
static raw_ostream & error()
Convenience method for printing "error: " to stderr.
Definition: WithColor.cpp:60
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
raw_ostream & indent(unsigned NumSpaces)
indent - Insert &#39;NumSpaces&#39; spaces.
uint32_t getU32(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint32_t value from *offset_ptr.
StringRef getData() const
Get the data pointed to by this extractor.
Definition: DataExtractor.h:92
Error takeError()
Return error contained inside this Cursor, if any.
Definition: DataExtractor.h:75
A single location within a location list.
Definition: DWARFDebugLoc.h:27
Tagged union holding either a T or a Error.
Definition: yaml2obj.h:21
auto partition_point(R &&Range, Predicate P) -> decltype(adl_begin(Range))
Binary search for the first iterator in a range where a predicate is false.
Definition: STLExtras.h:1302
void dump(raw_ostream &OS, uint64_t &BaseAddr, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U, DIDumpOptions DumpOpts, unsigned Indent, size_t MaxEncodingStringLength) const
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:144
bool isLittleEndian() const
Get the endianness for this extractor.
Definition: DataExtractor.h:94
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:171
unsigned const MachineRegisterInfo * MRI
void dump(raw_ostream &OS, uint32_t AddressSize, DIDumpOptions DumpOpts={}) const
LocationList const * getLocationListAtOffset(uint64_t Offset) const
Return the location list at the given offset or nullptr.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
uint8_t getAddressSize() const
Get the address size for this extractor.
Definition: DataExtractor.h:96
Expected< LocationList > parseOneLocationList(const DWARFDataExtractor &Data, uint64_t *Offset)
A class representing a position in a DataExtractor, as well as any error encountered during extractio...
Definition: DataExtractor.h:54
uint64_t getULEB128(uint64_t *offset_ptr, llvm::Error *Err=nullptr) const
Extract a unsigned LEB128 value from *offset_ptr.
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
Definition: StringExtras.h:52
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Definition: Error.cpp:61
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
SmallVector< uint8_t, 4 > Loc
Definition: DWARFDebugLoc.h:84
void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, DIDumpOptions DumpOpts, Optional< uint64_t > Offset) const
Print the location lists found within the debug_loc section.
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
void dump(raw_ostream &OS, uint64_t BaseAddr, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *RegInfo, DWARFUnit *U, DIDumpOptions DumpOpts, unsigned Indent) const
static Expected< LocationList > parseOneLocationList(const DataExtractor &Data, uint64_t *Offset, unsigned Version)
uint64_t Begin
The beginning address of the instruction range.
Definition: DWARFDebugLoc.h:29
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:389
LocationList const * getLocationListAtOffset(uint64_t Offset) const
Return the location list at the given offset or nullptr.
static void dumpExpression(raw_ostream &OS, ArrayRef< uint8_t > Data, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U)
void dump(raw_ostream &OS, uint64_t BaseAddr, const MCRegisterInfo *RegInfo, DIDumpOptions DumpOpts, Optional< uint64_t > Offset) const
void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, DWARFUnit *U, bool IsEH=false) const
This file contains constants used for implementing Dwarf debug support.
SmallVector< uint8_t, 4 > Loc
The location of the variable within the specified range.
Definition: DWARFDebugLoc.h:33
uint64_t Offset
The beginning offset where this location list is stored in the debug_loc section. ...
Definition: DWARFDebugLoc.h:40
uint64_t End
The ending address of the instruction range.
Definition: DWARFDebugLoc.h:31
void parse(DataExtractor data, uint64_t Offset, uint64_t EndOffset, uint16_t Version)
uint64_t getAddress(uint64_t *offset_ptr) const
Extract an pointer from *offset_ptr.
StringRef LocListEncodingString(unsigned Encoding)
Definition: Dwarf.cpp:478
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
SmallVector< Entry, 2 > Entries
All the locations in which the variable is stored.
Definition: DWARFDebugLoc.h:42
const uint64_t Version
Definition: InstrProf.h:980
void parse(const DWARFDataExtractor &data)
Parse the debug_loc section accessible via the &#39;data&#39; parameter using the address size also given in ...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1177