LLVM  8.0.1
DWARFDebugRnglists.cpp
Go to the documentation of this file.
1 //===- DWARFDebugRnglists.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 
13 #include "llvm/Support/Errc.h"
14 #include "llvm/Support/Error.h"
15 #include "llvm/Support/Format.h"
17 
18 using namespace llvm;
19 
21  uint32_t *OffsetPtr) {
22  Offset = *OffsetPtr;
23  SectionIndex = -1ULL;
24  // The caller should guarantee that we have at least 1 byte available, so
25  // we just assert instead of revalidate.
26  assert(*OffsetPtr < End &&
27  "not enough space to extract a rangelist encoding");
28  uint8_t Encoding = Data.getU8(OffsetPtr);
29 
30  switch (Encoding) {
31  case dwarf::DW_RLE_end_of_list:
32  Value0 = Value1 = 0;
33  break;
34  // TODO: Support other encodings.
35  case dwarf::DW_RLE_base_addressx: {
36  uint32_t PreviousOffset = *OffsetPtr - 1;
37  Value0 = Data.getULEB128(OffsetPtr);
38  if (End < *OffsetPtr)
39  return createStringError(
41  "read past end of table when reading "
42  "DW_RLE_base_addressx encoding at offset 0x%" PRIx32,
43  PreviousOffset);
44  break;
45  }
46  case dwarf::DW_RLE_startx_endx:
48  "unsupported rnglists encoding DW_RLE_startx_endx at "
49  "offset 0x%" PRIx32,
50  *OffsetPtr - 1);
51  case dwarf::DW_RLE_startx_length: {
52  uint32_t PreviousOffset = *OffsetPtr - 1;
53  Value0 = Data.getULEB128(OffsetPtr);
54  Value1 = Data.getULEB128(OffsetPtr);
55  if (End < *OffsetPtr)
56  return createStringError(
58  "read past end of table when reading "
59  "DW_RLE_startx_length encoding at offset 0x%" PRIx32,
60  PreviousOffset);
61  break;
62  }
63  case dwarf::DW_RLE_offset_pair: {
64  uint32_t PreviousOffset = *OffsetPtr - 1;
65  Value0 = Data.getULEB128(OffsetPtr);
66  Value1 = Data.getULEB128(OffsetPtr);
67  if (End < *OffsetPtr)
69  "read past end of table when reading "
70  "DW_RLE_offset_pair encoding at offset 0x%" PRIx32,
71  PreviousOffset);
72  break;
73  }
74  case dwarf::DW_RLE_base_address: {
75  if ((End - *OffsetPtr) < Data.getAddressSize())
77  "insufficient space remaining in table for "
78  "DW_RLE_base_address encoding at offset 0x%" PRIx32,
79  *OffsetPtr - 1);
80  Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
81  break;
82  }
83  case dwarf::DW_RLE_start_end: {
84  if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
86  "insufficient space remaining in table for "
87  "DW_RLE_start_end encoding "
88  "at offset 0x%" PRIx32,
89  *OffsetPtr - 1);
90  Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
91  Value1 = Data.getRelocatedAddress(OffsetPtr);
92  break;
93  }
94  case dwarf::DW_RLE_start_length: {
95  uint32_t PreviousOffset = *OffsetPtr - 1;
96  Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
97  Value1 = Data.getULEB128(OffsetPtr);
98  if (End < *OffsetPtr)
100  "read past end of table when reading "
101  "DW_RLE_start_length encoding at offset 0x%" PRIx32,
102  PreviousOffset);
103  break;
104  }
105  default:
107  "unknown rnglists encoding 0x%" PRIx32
108  " at offset 0x%" PRIx32,
109  uint32_t(Encoding), *OffsetPtr - 1);
110  }
111 
112  EntryKind = Encoding;
113  return Error::success();
114 }
115 
118  DWARFUnit &U) const {
120  for (const RangeListEntry &RLE : Entries) {
121  if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
122  break;
123  if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
124  BaseAddr = U.getAddrOffsetSectionItem(RLE.Value0);
125  if (!BaseAddr)
126  BaseAddr = {RLE.Value0, -1ULL};
127  continue;
128  }
129  if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
130  BaseAddr = {RLE.Value0, RLE.SectionIndex};
131  continue;
132  }
133 
135  E.SectionIndex = RLE.SectionIndex;
136  if (BaseAddr && E.SectionIndex == -1ULL)
137  E.SectionIndex = BaseAddr->SectionIndex;
138 
139  switch (RLE.EntryKind) {
140  case dwarf::DW_RLE_offset_pair:
141  E.LowPC = RLE.Value0;
142  E.HighPC = RLE.Value1;
143  if (BaseAddr) {
144  E.LowPC += BaseAddr->Address;
145  E.HighPC += BaseAddr->Address;
146  }
147  break;
148  case dwarf::DW_RLE_start_end:
149  E.LowPC = RLE.Value0;
150  E.HighPC = RLE.Value1;
151  break;
152  case dwarf::DW_RLE_start_length:
153  E.LowPC = RLE.Value0;
154  E.HighPC = E.LowPC + RLE.Value1;
155  break;
156  case dwarf::DW_RLE_startx_length: {
157  auto Start = U.getAddrOffsetSectionItem(RLE.Value0);
158  if (!Start)
159  Start = {0, -1ULL};
160  E.SectionIndex = Start->SectionIndex;
161  E.LowPC = Start->Address;
162  E.HighPC = E.LowPC + RLE.Value1;
163  break;
164  }
165  default:
166  // Unsupported encodings should have been reported during extraction,
167  // so we should not run into any here.
168  llvm_unreachable("Unsupported range list encoding");
169  }
170  Res.push_back(E);
171  }
172  return Res;
173 }
174 
176  raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
177  uint64_t &CurrentBase, DIDumpOptions DumpOpts,
179  LookupPooledAddress) const {
180  auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
181  uint8_t AddrSize, DIDumpOptions DumpOpts) {
182  if (DumpOpts.Verbose) {
183  DumpOpts.DisplayRawContents = true;
184  DWARFAddressRange(Entry.Value0, Entry.Value1)
185  .dump(OS, AddrSize, DumpOpts);
186  OS << " => ";
187  }
188  };
189 
190  if (DumpOpts.Verbose) {
191  // Print the section offset in verbose mode.
192  OS << format("0x%8.8" PRIx32 ":", Offset);
193  auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
194  // Unsupported encodings should have been reported during parsing.
195  assert(!EncodingString.empty() && "Unknown range entry encoding");
196  OS << format(" [%s%*c", EncodingString.data(),
197  MaxEncodingStringLength - EncodingString.size() + 1, ']');
198  if (EntryKind != dwarf::DW_RLE_end_of_list)
199  OS << ": ";
200  }
201 
202  switch (EntryKind) {
203  case dwarf::DW_RLE_end_of_list:
204  OS << (DumpOpts.Verbose ? "" : "<End of list>");
205  break;
206  // case dwarf::DW_RLE_base_addressx:
207  case dwarf::DW_RLE_base_addressx: {
208  if (auto SA = LookupPooledAddress(Value0))
209  CurrentBase = SA->Address;
210  else
211  CurrentBase = Value0;
212  if (!DumpOpts.Verbose)
213  return;
214  OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
215  break;
216  }
217  case dwarf::DW_RLE_base_address:
218  // In non-verbose mode we do not print anything for this entry.
219  CurrentBase = Value0;
220  if (!DumpOpts.Verbose)
221  return;
222  OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
223  break;
224  case dwarf::DW_RLE_start_length:
225  PrintRawEntry(OS, *this, AddrSize, DumpOpts);
226  DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
227  break;
228  case dwarf::DW_RLE_offset_pair:
229  PrintRawEntry(OS, *this, AddrSize, DumpOpts);
230  DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
231  .dump(OS, AddrSize, DumpOpts);
232  break;
233  case dwarf::DW_RLE_start_end:
234  DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
235  break;
236  case dwarf::DW_RLE_startx_length: {
237  PrintRawEntry(OS, *this, AddrSize, DumpOpts);
238  uint64_t Start = 0;
239  if (auto SA = LookupPooledAddress(Value0))
240  Start = SA->Address;
241  DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
242  break;
243  } break;
244  default:
245  llvm_unreachable("Unsupported range list encoding");
246  }
247  OS << "\n";
248 }
uint64_t getULEB128(uint32_t *offset_ptr) const
Extract a unsigned LEB128 value from *offset_ptr.
uint64_t Value0
The values making up the range list entry.
This class represents lattice values for constants.
Definition: AllocatorList.h:24
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:117
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...
uint8_t EntryKind
The DWARF encoding (DW_RLE_* or DW_LLE_*).
uint64_t SectionIndex
The index of the section this entry belongs to.
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:159
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
void dump(raw_ostream &OS, uint32_t AddressSize, DIDumpOptions DumpOpts={}) const
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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.
StringRef RangeListEncodingString(unsigned Encoding)
Definition: Dwarf.cpp:459
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
static ErrorSuccess success()
Create a success value.
Definition: Error.h:327
uint32_t Offset
The offset at which the entry is located in the section.
This file contains constants used for implementing Dwarf debug support.
Optional< SectionedAddress > getAddrOffsetSectionItem(uint32_t Index) const
Definition: DWARFUnit.cpp:202
void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, uint64_t &CurrentBase, DIDumpOptions DumpOpts, llvm::function_ref< Optional< SectionedAddress >(uint32_t)> LookupPooledAddress) const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::vector< DWARFAddressRange > DWARFAddressRangesVector
DWARFAddressRangesVector - represents a set of absolute address ranges.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
DWARFAddressRangesVector getAbsoluteRanges(llvm::Optional< SectionedAddress > BaseAddr, DWARFUnit &U) const
Build a DWARFAddressRangesVector from a rangelist.
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
A class representing a single range list entry.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1164
Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr)