LLVM  7.0.0svn
DWARFDebugLoc.cpp
Go to the documentation of this file.
1 //===- DWARFDebugLoc.cpp --------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
11 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/Compiler.h"
18 #include "llvm/Support/Format.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) {
34  DWARFDataExtractor Extractor(StringRef(Data.data(), Data.size()),
35  IsLittleEndian, AddressSize);
36  DWARFExpression(Extractor, AddressSize, dwarf::DWARF_VERSION).print(OS, MRI);
37 }
38 
39 void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
40  unsigned AddressSize,
41  const MCRegisterInfo *MRI,
42  unsigned Indent) const {
43  for (const Entry &E : Entries) {
44  OS << '\n';
45  OS.indent(Indent);
46  OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2,
47  E.Begin)
48  << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2, E.End);
49  OS << ": ";
50 
51  dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
52  }
53 }
54 
57  auto It = std::lower_bound(
58  Locations.begin(), Locations.end(), Offset,
59  [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; });
60  if (It != Locations.end() && It->Offset == Offset)
61  return &(*It);
62  return nullptr;
63 }
64 
66  Optional<uint64_t> Offset) const {
67  auto DumpLocationList = [&](const LocationList &L) {
68  OS << format("0x%8.8x: ", L.Offset);
69  L.dump(OS, IsLittleEndian, AddressSize, MRI, 12);
70  OS << "\n\n";
71  };
72 
73  if (Offset) {
74  if (auto *L = getLocationListAtOffset(*Offset))
75  DumpLocationList(*L);
76  return;
77  }
78 
79  for (const LocationList &L : Locations) {
80  DumpLocationList(L);
81  }
82 }
83 
86  LocationList LL;
87  LL.Offset = *Offset;
88 
89  // 2.6.2 Location Lists
90  // A location list entry consists of:
91  while (true) {
92  Entry E;
93  if (!Data.isValidOffsetForDataOfSize(*Offset, 2 * Data.getAddressSize())) {
94  llvm::errs() << "Location list overflows the debug_loc section.\n";
95  return None;
96  }
97 
98  // 1. A beginning address offset. ...
99  E.Begin = Data.getRelocatedAddress(Offset);
100 
101  // 2. An ending address offset. ...
102  E.End = Data.getRelocatedAddress(Offset);
103 
104  // The end of any given location list is marked by an end of list entry,
105  // which consists of a 0 for the beginning address offset and a 0 for the
106  // ending address offset.
107  if (E.Begin == 0 && E.End == 0)
108  return LL;
109 
110  if (!Data.isValidOffsetForDataOfSize(*Offset, 2)) {
111  llvm::errs() << "Location list overflows the debug_loc section.\n";
112  return None;
113  }
114 
115  unsigned Bytes = Data.getU16(Offset);
116  if (!Data.isValidOffsetForDataOfSize(*Offset, Bytes)) {
117  llvm::errs() << "Location list overflows the debug_loc section.\n";
118  return None;
119  }
120  // A single location description describing the location of the object...
121  StringRef str = Data.getData().substr(*Offset, Bytes);
122  *Offset += Bytes;
123  E.Loc.reserve(str.size());
124  std::copy(str.begin(), str.end(), std::back_inserter(E.Loc));
125  LL.Entries.push_back(std::move(E));
126  }
127 }
128 
130  IsLittleEndian = data.isLittleEndian();
131  AddressSize = data.getAddressSize();
132 
133  uint32_t Offset = 0;
134  while (data.isValidOffset(Offset + data.getAddressSize() - 1)) {
135  if (auto LL = parseOneLocationList(data, &Offset))
136  Locations.push_back(std::move(*LL));
137  else
138  break;
139  }
140  if (data.isValidOffset(Offset))
141  errs() << "error: failed to consume entire .debug_loc section\n";
142 }
143 
146  LocationList LL;
147  LL.Offset = *Offset;
148 
149  // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list.
150  while (auto Kind =
151  static_cast<dwarf::LocationListEntry>(Data.getU8(Offset))) {
153  llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind
154  << " not implemented\n";
155  return None;
156  }
157 
158  Entry E;
159  E.Start = Data.getULEB128(Offset);
160  E.Length = Data.getU32(Offset);
161 
162  unsigned Bytes = Data.getU16(Offset);
163  // A single location description describing the location of the object...
164  StringRef str = Data.getData().substr(*Offset, Bytes);
165  *Offset += Bytes;
166  E.Loc.resize(str.size());
167  std::copy(str.begin(), str.end(), E.Loc.begin());
168 
169  LL.Entries.push_back(std::move(E));
170  }
171  return LL;
172 }
173 
175  IsLittleEndian = data.isLittleEndian();
176  AddressSize = data.getAddressSize();
177 
178  uint32_t Offset = 0;
179  while (data.isValidOffset(Offset)) {
180  if (auto LL = parseOneLocationList(data, &Offset))
181  Locations.push_back(std::move(*LL));
182  else
183  return;
184  }
185 }
186 
189  auto It = std::lower_bound(
190  Locations.begin(), Locations.end(), Offset,
191  [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; });
192  if (It != Locations.end() && It->Offset == Offset)
193  return &(*It);
194  return nullptr;
195 }
196 
197 void DWARFDebugLocDWO::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
198  unsigned AddressSize,
199  const MCRegisterInfo *MRI,
200  unsigned Indent) const {
201  for (const Entry &E : Entries) {
202  OS << '\n';
203  OS.indent(Indent);
204  OS << "Addr idx " << E.Start << " (w/ length " << E.Length << "): ";
205  dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
206  }
207 }
208 
210  Optional<uint64_t> Offset) const {
211  auto DumpLocationList = [&](const LocationList &L) {
212  OS << format("0x%8.8x: ", L.Offset);
213  L.dump(OS, IsLittleEndian, AddressSize, MRI, /*Indent=*/12);
214  OS << "\n\n";
215  };
216 
217  if (Offset) {
218  if (auto *L = getLocationListAtOffset(*Offset))
219  DumpLocationList(*L);
220  return;
221  }
222 
223  for (const LocationList &L : Locations) {
224  DumpLocationList(L);
225  }
226 }
A list of locations that contain one variable.
Definition: DWARFDebugLoc.h:37
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
uint64_t getULEB128(uint32_t *offset_ptr) const
Extract a unsigned LEB128 value from *offset_ptr.
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
void print(raw_ostream &OS, const MCRegisterInfo *RegInfo)
void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, Optional< uint64_t > Offset) const
Print the location lists found within the debug_loc section.
unsigned Offset
The beginning offset where this location list is stored in the debug_loc section. ...
Definition: DWARFDebugLoc.h:40
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
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.
uint64_t getRelocatedAddress(uint32_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...
StringRef getData() const
Get the data pointed to by this extractor.
Definition: DataExtractor.h:55
void reserve(size_type N)
Definition: SmallVector.h:378
uint16_t getU16(uint32_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
uint32_t getU32(uint32_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
A single location within a location list.
Definition: DWARFDebugLoc.h:27
LocationList const * getLocationListAtOffset(uint64_t Offset) const
Return the location list at the given offset or nullptr.
void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI, unsigned Indent) const
Dump this list on OS.
SmallVector< char, 4 > Loc
The location of the variable within the specified range.
Definition: DWARFDebugLoc.h:33
void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *RegInfo, unsigned Indent) const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range))
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:910
bool isLittleEndian() const
Get the endianness for this extractor.
Definition: DataExtractor.h:57
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:598
void parse(DataExtractor data)
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
bool isValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const
Test the availability of length bytes of data from offset.
unsigned const MachineRegisterInfo * MRI
LocationList const * getLocationListAtOffset(uint64_t Offset) const
Return the location list at the given offset or nullptr.
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:149
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:116
uint8_t getAddressSize() const
Get the address size for this extractor.
Definition: DataExtractor.h:59
uint8_t getU8(uint32_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
static void dumpExpression(raw_ostream &OS, ArrayRef< char > Data, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI)
void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, Optional< uint64_t > Offset) const
Optional< LocationList > parseOneLocationList(DWARFDataExtractor Data, uint32_t *Offset)
static Optional< LocationList > parseOneLocationList(DataExtractor Data, uint32_t *Offset)
const T * data() const
Definition: ArrayRef.h:146
SmallVector< Entry, 2 > Entries
Definition: DWARFDebugLoc.h:85
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
uint64_t Begin
The beginning address of the instruction range.
Definition: DWARFDebugLoc.h:29
SmallVector< char, 4 > Loc
Definition: DWARFDebugLoc.h:80
This file contains constants used for implementing Dwarf debug support.
iterator begin() const
Definition: StringRef.h:106
uint64_t End
The ending address of the instruction range.
Definition: DWARFDebugLoc.h:31
bool isValidOffset(uint32_t offset) const
Test the validity of offset.
const unsigned Kind
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:44
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
OutputIt copy(R &&Range, OutputIt Out)
Definition: STLExtras.h:866
iterator end() const
Definition: StringRef.h:108
SmallVector< Entry, 2 > Entries
All the locations in which the variable is stored.
Definition: DWARFDebugLoc.h:42
void parse(const DWARFDataExtractor &data)
Parse the debug_loc section accessible via the &#39;data&#39; parameter using the address size also given in ...
void resize(size_type N)
Definition: SmallVector.h:353