LLVM  10.0.0svn
DWARFDebugRnglists.cpp
Go to the documentation of this file.
1 //===- DWARFDebugRnglists.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 
12 #include "llvm/Support/Errc.h"
13 #include "llvm/Support/Error.h"
14 #include "llvm/Support/Format.h"
16 
17 using namespace llvm;
18 
20  uint64_t *OffsetPtr) {
21  Offset = *OffsetPtr;
22  SectionIndex = -1ULL;
23  // The caller should guarantee that we have at least 1 byte available, so
24  // we just assert instead of revalidate.
25  assert(*OffsetPtr < End &&
26  "not enough space to extract a rangelist encoding");
27  uint8_t Encoding = Data.getU8(OffsetPtr);
28 
29  switch (Encoding) {
30  case dwarf::DW_RLE_end_of_list:
31  Value0 = Value1 = 0;
32  break;
33  // TODO: Support other encodings.
34  case dwarf::DW_RLE_base_addressx: {
35  uint64_t PreviousOffset = *OffsetPtr - 1;
36  Value0 = Data.getULEB128(OffsetPtr);
37  if (End < *OffsetPtr)
38  return createStringError(
40  "read past end of table when reading "
41  "DW_RLE_base_addressx encoding at offset 0x%" PRIx64,
42  PreviousOffset);
43  break;
44  }
45  case dwarf::DW_RLE_startx_endx:
47  "unsupported rnglists encoding DW_RLE_startx_endx at "
48  "offset 0x%" PRIx64,
49  *OffsetPtr - 1);
50  case dwarf::DW_RLE_startx_length: {
51  uint64_t PreviousOffset = *OffsetPtr - 1;
52  Value0 = Data.getULEB128(OffsetPtr);
53  Value1 = Data.getULEB128(OffsetPtr);
54  if (End < *OffsetPtr)
55  return createStringError(
57  "read past end of table when reading "
58  "DW_RLE_startx_length encoding at offset 0x%" PRIx64,
59  PreviousOffset);
60  break;
61  }
62  case dwarf::DW_RLE_offset_pair: {
63  uint64_t PreviousOffset = *OffsetPtr - 1;
64  Value0 = Data.getULEB128(OffsetPtr);
65  Value1 = Data.getULEB128(OffsetPtr);
66  if (End < *OffsetPtr)
68  "read past end of table when reading "
69  "DW_RLE_offset_pair encoding at offset 0x%" PRIx64,
70  PreviousOffset);
71  break;
72  }
73  case dwarf::DW_RLE_base_address: {
74  if ((End - *OffsetPtr) < Data.getAddressSize())
76  "insufficient space remaining in table for "
77  "DW_RLE_base_address encoding at offset 0x%" PRIx64,
78  *OffsetPtr - 1);
79  Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
80  break;
81  }
82  case dwarf::DW_RLE_start_end: {
83  if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
85  "insufficient space remaining in table for "
86  "DW_RLE_start_end encoding "
87  "at offset 0x%" PRIx64,
88  *OffsetPtr - 1);
89  Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
90  Value1 = Data.getRelocatedAddress(OffsetPtr);
91  break;
92  }
93  case dwarf::DW_RLE_start_length: {
94  uint64_t PreviousOffset = *OffsetPtr - 1;
95  Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
96  Value1 = Data.getULEB128(OffsetPtr);
97  if (End < *OffsetPtr)
99  "read past end of table when reading "
100  "DW_RLE_start_length encoding at offset 0x%" PRIx64,
101  PreviousOffset);
102  break;
103  }
104  default:
106  "unknown rnglists encoding 0x%" PRIx32
107  " at offset 0x%" PRIx64,
108  uint32_t(Encoding), *OffsetPtr - 1);
109  }
110 
111  EntryKind = Encoding;
112  return Error::success();
113 }
114 
118  for (const RangeListEntry &RLE : Entries) {
119  if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
120  break;
121  if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
122  BaseAddr = U.getAddrOffsetSectionItem(RLE.Value0);
123  if (!BaseAddr)
124  BaseAddr = {RLE.Value0, -1ULL};
125  continue;
126  }
127  if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
128  BaseAddr = {RLE.Value0, RLE.SectionIndex};
129  continue;
130  }
131 
133  E.SectionIndex = RLE.SectionIndex;
134  if (BaseAddr && E.SectionIndex == -1ULL)
135  E.SectionIndex = BaseAddr->SectionIndex;
136 
137  switch (RLE.EntryKind) {
138  case dwarf::DW_RLE_offset_pair:
139  E.LowPC = RLE.Value0;
140  E.HighPC = RLE.Value1;
141  if (BaseAddr) {
142  E.LowPC += BaseAddr->Address;
143  E.HighPC += BaseAddr->Address;
144  }
145  break;
146  case dwarf::DW_RLE_start_end:
147  E.LowPC = RLE.Value0;
148  E.HighPC = RLE.Value1;
149  break;
150  case dwarf::DW_RLE_start_length:
151  E.LowPC = RLE.Value0;
152  E.HighPC = E.LowPC + RLE.Value1;
153  break;
154  case dwarf::DW_RLE_startx_length: {
155  auto Start = U.getAddrOffsetSectionItem(RLE.Value0);
156  if (!Start)
157  Start = {0, -1ULL};
158  E.SectionIndex = Start->SectionIndex;
159  E.LowPC = Start->Address;
160  E.HighPC = E.LowPC + RLE.Value1;
161  break;
162  }
163  default:
164  // Unsupported encodings should have been reported during extraction,
165  // so we should not run into any here.
166  llvm_unreachable("Unsupported range list encoding");
167  }
168  Res.push_back(E);
169  }
170  return Res;
171 }
172 
174  raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
175  uint64_t &CurrentBase, DIDumpOptions DumpOpts,
177  LookupPooledAddress) const {
178  auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
179  uint8_t AddrSize, DIDumpOptions DumpOpts) {
180  if (DumpOpts.Verbose) {
181  DumpOpts.DisplayRawContents = true;
182  DWARFAddressRange(Entry.Value0, Entry.Value1)
183  .dump(OS, AddrSize, DumpOpts);
184  OS << " => ";
185  }
186  };
187 
188  if (DumpOpts.Verbose) {
189  // Print the section offset in verbose mode.
190  OS << format("0x%8.8" PRIx64 ":", Offset);
191  auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
192  // Unsupported encodings should have been reported during parsing.
193  assert(!EncodingString.empty() && "Unknown range entry encoding");
194  OS << format(" [%s%*c", EncodingString.data(),
195  MaxEncodingStringLength - EncodingString.size() + 1, ']');
196  if (EntryKind != dwarf::DW_RLE_end_of_list)
197  OS << ": ";
198  }
199 
200  switch (EntryKind) {
201  case dwarf::DW_RLE_end_of_list:
202  OS << (DumpOpts.Verbose ? "" : "<End of list>");
203  break;
204  case dwarf::DW_RLE_base_addressx: {
205  if (auto SA = LookupPooledAddress(Value0))
206  CurrentBase = SA->Address;
207  else
208  CurrentBase = Value0;
209  if (!DumpOpts.Verbose)
210  return;
211  OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
212  break;
213  }
214  case dwarf::DW_RLE_base_address:
215  // In non-verbose mode we do not print anything for this entry.
216  CurrentBase = Value0;
217  if (!DumpOpts.Verbose)
218  return;
219  OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
220  break;
221  case dwarf::DW_RLE_start_length:
222  PrintRawEntry(OS, *this, AddrSize, DumpOpts);
223  DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
224  break;
225  case dwarf::DW_RLE_offset_pair:
226  PrintRawEntry(OS, *this, AddrSize, DumpOpts);
227  DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
228  .dump(OS, AddrSize, DumpOpts);
229  break;
230  case dwarf::DW_RLE_start_end:
231  DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
232  break;
233  case dwarf::DW_RLE_startx_length: {
234  PrintRawEntry(OS, *this, AddrSize, DumpOpts);
235  uint64_t Start = 0;
236  if (auto SA = LookupPooledAddress(Value0))
237  Start = SA->Address;
238  DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
239  break;
240  }
241  default:
242  llvm_unreachable("Unsupported range list encoding");
243  }
244  OS << "\n";
245 }
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...
uint64_t Value0
The values making up the range list entry.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
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:104
uint64_t Offset
The offset at which the entry is located in the section.
uint8_t EntryKind
The DWARF encoding (DW_RLE_* or DW_LLE_*).
DWARFAddressRangesVector getAbsoluteRanges(llvm::Optional< object::SectionedAddress > BaseAddr, DWARFUnit &U) const
Build a DWARFAddressRangesVector from a rangelist.
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:171
* 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:91
uint64_t getULEB128(uint64_t *offset_ptr, llvm::Error *Err=nullptr) const
Extract a unsigned LEB128 value from *offset_ptr.
StringRef RangeListEncodingString(unsigned Encoding)
Definition: Dwarf.cpp:464
#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...
Error extract(DWARFDataExtractor Data, uint64_t End, uint64_t *OffsetPtr)
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, uint64_t &CurrentBase, DIDumpOptions DumpOpts, llvm::function_ref< Optional< object::SectionedAddress >(uint32_t)> LookupPooledAddress) const
This file contains constants used for implementing Dwarf debug support.
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:157
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
Optional< object::SectionedAddress > getAddrOffsetSectionItem(uint32_t Index) const
Definition: DWARFUnit.cpp:201
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:1177