LLVM  11.0.0git
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 
117  return getAbsoluteRanges(BaseAddr, [&](uint32_t Index) {
118  return U.getAddrOffsetSectionItem(Index);
119  });
120 }
121 
125  LookupPooledAddress) const {
127  for (const RangeListEntry &RLE : Entries) {
128  if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
129  break;
130  if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
131  BaseAddr = LookupPooledAddress(RLE.Value0);
132  if (!BaseAddr)
133  BaseAddr = {RLE.Value0, -1ULL};
134  continue;
135  }
136  if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
137  BaseAddr = {RLE.Value0, RLE.SectionIndex};
138  continue;
139  }
140 
142  E.SectionIndex = RLE.SectionIndex;
143  if (BaseAddr && E.SectionIndex == -1ULL)
144  E.SectionIndex = BaseAddr->SectionIndex;
145 
146  switch (RLE.EntryKind) {
147  case dwarf::DW_RLE_offset_pair:
148  E.LowPC = RLE.Value0;
149  E.HighPC = RLE.Value1;
150  if (BaseAddr) {
151  E.LowPC += BaseAddr->Address;
152  E.HighPC += BaseAddr->Address;
153  }
154  break;
155  case dwarf::DW_RLE_start_end:
156  E.LowPC = RLE.Value0;
157  E.HighPC = RLE.Value1;
158  break;
159  case dwarf::DW_RLE_start_length:
160  E.LowPC = RLE.Value0;
161  E.HighPC = E.LowPC + RLE.Value1;
162  break;
163  case dwarf::DW_RLE_startx_length: {
164  auto Start = LookupPooledAddress(RLE.Value0);
165  if (!Start)
166  Start = {0, -1ULL};
167  E.SectionIndex = Start->SectionIndex;
168  E.LowPC = Start->Address;
169  E.HighPC = E.LowPC + RLE.Value1;
170  break;
171  }
172  default:
173  // Unsupported encodings should have been reported during extraction,
174  // so we should not run into any here.
175  llvm_unreachable("Unsupported range list encoding");
176  }
177  Res.push_back(E);
178  }
179  return Res;
180 }
181 
183  raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
184  uint64_t &CurrentBase, DIDumpOptions DumpOpts,
186  LookupPooledAddress) const {
187  auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
188  uint8_t AddrSize, DIDumpOptions DumpOpts) {
189  if (DumpOpts.Verbose) {
190  DumpOpts.DisplayRawContents = true;
191  DWARFAddressRange(Entry.Value0, Entry.Value1)
192  .dump(OS, AddrSize, DumpOpts);
193  OS << " => ";
194  }
195  };
196 
197  if (DumpOpts.Verbose) {
198  // Print the section offset in verbose mode.
199  OS << format("0x%8.8" PRIx64 ":", Offset);
200  auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
201  // Unsupported encodings should have been reported during parsing.
202  assert(!EncodingString.empty() && "Unknown range entry encoding");
203  OS << format(" [%s%*c", EncodingString.data(),
204  MaxEncodingStringLength - EncodingString.size() + 1, ']');
205  if (EntryKind != dwarf::DW_RLE_end_of_list)
206  OS << ": ";
207  }
208 
209  switch (EntryKind) {
210  case dwarf::DW_RLE_end_of_list:
211  OS << (DumpOpts.Verbose ? "" : "<End of list>");
212  break;
213  case dwarf::DW_RLE_base_addressx: {
214  if (auto SA = LookupPooledAddress(Value0))
215  CurrentBase = SA->Address;
216  else
217  CurrentBase = Value0;
218  if (!DumpOpts.Verbose)
219  return;
220  OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
221  break;
222  }
223  case dwarf::DW_RLE_base_address:
224  // In non-verbose mode we do not print anything for this entry.
225  CurrentBase = Value0;
226  if (!DumpOpts.Verbose)
227  return;
228  OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
229  break;
230  case dwarf::DW_RLE_start_length:
231  PrintRawEntry(OS, *this, AddrSize, DumpOpts);
232  DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
233  break;
234  case dwarf::DW_RLE_offset_pair:
235  PrintRawEntry(OS, *this, AddrSize, DumpOpts);
236  DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
237  .dump(OS, AddrSize, DumpOpts);
238  break;
239  case dwarf::DW_RLE_start_end:
240  DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
241  break;
242  case dwarf::DW_RLE_startx_length: {
243  PrintRawEntry(OS, *this, AddrSize, DumpOpts);
244  uint64_t Start = 0;
245  if (auto SA = LookupPooledAddress(Value0))
246  Start = SA->Address;
247  DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
248  break;
249  }
250  default:
251  llvm_unreachable("Unsupported range list encoding");
252  }
253  OS << "\n";
254 }
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:176
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_*).
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:181
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
uint8_t getAddressSize() const
Get the address size for this extractor.
Definition: DataExtractor.h:96
DWARFAddressRangesVector getAbsoluteRanges(Optional< object::SectionedAddress > BaseAddr, function_ref< Optional< object::SectionedAddress >(uint32_t)> LookupPooledAddress) const
Build a DWARFAddressRangesVector from a rangelist.
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:497
#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:332
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:46
Optional< object::SectionedAddress > getAddrOffsetSectionItem(uint32_t Index) const
Definition: DWARFUnit.cpp:219
A class representing a single range list entry.
void dump(raw_ostream &OS, uint32_t AddressSize, DIDumpOptions DumpOpts={}, const DWARFObject *Obj=nullptr) const
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1202