LLVM  14.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 
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  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 < Data.size() &&
26  "not enough space to extract a rangelist encoding");
27  uint8_t Encoding = Data.getU8(OffsetPtr);
28 
29  DataExtractor::Cursor C(*OffsetPtr);
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  Value0 = Data.getULEB128(C);
37  break;
38  }
39  case dwarf::DW_RLE_startx_endx:
40  Value0 = Data.getULEB128(C);
41  Value1 = Data.getULEB128(C);
42  break;
43  case dwarf::DW_RLE_startx_length: {
44  Value0 = Data.getULEB128(C);
45  Value1 = Data.getULEB128(C);
46  break;
47  }
48  case dwarf::DW_RLE_offset_pair: {
49  Value0 = Data.getULEB128(C);
50  Value1 = Data.getULEB128(C);
51  break;
52  }
53  case dwarf::DW_RLE_base_address: {
54  Value0 = Data.getRelocatedAddress(C, &SectionIndex);
55  break;
56  }
57  case dwarf::DW_RLE_start_end: {
58  Value0 = Data.getRelocatedAddress(C, &SectionIndex);
59  Value1 = Data.getRelocatedAddress(C);
60  break;
61  }
62  case dwarf::DW_RLE_start_length: {
63  Value0 = Data.getRelocatedAddress(C, &SectionIndex);
64  Value1 = Data.getULEB128(C);
65  break;
66  }
67  default:
68  consumeError(C.takeError());
70  "unknown rnglists encoding 0x%" PRIx32
71  " at offset 0x%" PRIx64,
72  uint32_t(Encoding), Offset);
73  }
74 
75  if (!C) {
76  consumeError(C.takeError());
77  return createStringError(
79  "read past end of table when reading %s encoding at offset 0x%" PRIx64,
80  dwarf::RLEString(Encoding).data(), Offset);
81  }
82 
83  *OffsetPtr = C.tell();
84  EntryKind = Encoding;
85  return Error::success();
86 }
87 
90  return getAbsoluteRanges(
91  BaseAddr, U.getAddressByteSize(),
92  [&](uint32_t Index) { return U.getAddrOffsetSectionItem(Index); });
93 }
94 
96  Optional<object::SectionedAddress> BaseAddr, uint8_t AddressByteSize,
98  LookupPooledAddress) const {
100  uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressByteSize);
101  for (const RangeListEntry &RLE : Entries) {
102  if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
103  break;
104  if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
105  BaseAddr = LookupPooledAddress(RLE.Value0);
106  if (!BaseAddr)
107  BaseAddr = {RLE.Value0, -1ULL};
108  continue;
109  }
110  if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
111  BaseAddr = {RLE.Value0, RLE.SectionIndex};
112  continue;
113  }
114 
116  E.SectionIndex = RLE.SectionIndex;
117  if (BaseAddr && E.SectionIndex == -1ULL)
118  E.SectionIndex = BaseAddr->SectionIndex;
119 
120  switch (RLE.EntryKind) {
121  case dwarf::DW_RLE_offset_pair:
122  E.LowPC = RLE.Value0;
123  if (E.LowPC == Tombstone)
124  continue;
125  E.HighPC = RLE.Value1;
126  if (BaseAddr) {
127  if (BaseAddr->Address == Tombstone)
128  continue;
129  E.LowPC += BaseAddr->Address;
130  E.HighPC += BaseAddr->Address;
131  }
132  break;
133  case dwarf::DW_RLE_start_end:
134  E.LowPC = RLE.Value0;
135  E.HighPC = RLE.Value1;
136  break;
137  case dwarf::DW_RLE_start_length:
138  E.LowPC = RLE.Value0;
139  E.HighPC = E.LowPC + RLE.Value1;
140  break;
141  case dwarf::DW_RLE_startx_length: {
142  auto Start = LookupPooledAddress(RLE.Value0);
143  if (!Start)
144  Start = {0, -1ULL};
145  E.SectionIndex = Start->SectionIndex;
146  E.LowPC = Start->Address;
147  E.HighPC = E.LowPC + RLE.Value1;
148  break;
149  }
150  case dwarf::DW_RLE_startx_endx: {
151  auto Start = LookupPooledAddress(RLE.Value0);
152  if (!Start)
153  Start = {0, -1ULL};
154  auto End = LookupPooledAddress(RLE.Value1);
155  if (!End)
156  End = {0, -1ULL};
157  // FIXME: Some error handling if Start.SectionIndex != End.SectionIndex
158  E.SectionIndex = Start->SectionIndex;
159  E.LowPC = Start->Address;
160  E.HighPC = End->Address;
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  if (E.LowPC == Tombstone)
169  continue;
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" PRIx64 ":", 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  uint64_t Tombstone = dwarf::computeTombstoneAddress(AddrSize);
203 
204  switch (EntryKind) {
205  case dwarf::DW_RLE_end_of_list:
206  OS << (DumpOpts.Verbose ? "" : "<End of list>");
207  break;
208  case dwarf::DW_RLE_base_addressx: {
209  if (auto SA = LookupPooledAddress(Value0))
210  CurrentBase = SA->Address;
211  else
212  CurrentBase = Value0;
213  if (!DumpOpts.Verbose)
214  return;
215  DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);
216  break;
217  }
218  case dwarf::DW_RLE_base_address:
219  // In non-verbose mode we do not print anything for this entry.
220  CurrentBase = Value0;
221  if (!DumpOpts.Verbose)
222  return;
223  DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);
224  break;
225  case dwarf::DW_RLE_start_length:
226  PrintRawEntry(OS, *this, AddrSize, DumpOpts);
227  DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
228  break;
229  case dwarf::DW_RLE_offset_pair:
230  PrintRawEntry(OS, *this, AddrSize, DumpOpts);
231  if (CurrentBase != Tombstone)
232  DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
233  .dump(OS, AddrSize, DumpOpts);
234  else
235  OS << "dead code";
236  break;
237  case dwarf::DW_RLE_start_end:
238  DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
239  break;
240  case dwarf::DW_RLE_startx_length: {
241  PrintRawEntry(OS, *this, AddrSize, DumpOpts);
242  uint64_t Start = 0;
243  if (auto SA = LookupPooledAddress(Value0))
244  Start = SA->Address;
245  DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
246  break;
247  }
248  case dwarf::DW_RLE_startx_endx: {
249  PrintRawEntry(OS, *this, AddrSize, DumpOpts);
250  uint64_t Start = 0;
251  if (auto SA = LookupPooledAddress(Value0))
252  Start = SA->Address;
253  uint64_t End = 0;
254  if (auto SA = LookupPooledAddress(Value1))
255  End = SA->Address;
256  DWARFAddressRange(Start, End).dump(OS, AddrSize, DumpOpts);
257  break;
258  }
259  default:
260  llvm_unreachable("Unsupported range list encoding");
261  }
262  OS << "\n";
263 }
DWARFFormValue.h
llvm::errc::invalid_argument
@ invalid_argument
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::DWARFListEntryBase::Offset
uint64_t Offset
The offset at which the entry is located in the section.
Definition: DWARFListTable.h:29
llvm::DWARFListEntryBase::EntryKind
uint8_t EntryKind
The DWARF encoding (DW_RLE_* or DW_LLE_*).
Definition: DWARFListTable.h:31
llvm::object::SectionedAddress::Address
uint64_t Address
Definition: ObjectFile.h:147
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
Error.h
Errc.h
llvm::dwarf::RangeListEncodingString
StringRef RangeListEncodingString(unsigned Encoding)
Definition: Dwarf.cpp:514
llvm::Optional
Definition: APInt.h:33
llvm::DWARFDataExtractor
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
Definition: DWARFDataExtractor.h:21
llvm::DWARFListType< RangeListEntry >::Entries
ListEntries Entries
Definition: DWARFListTable.h:43
Format.h
llvm::consumeError
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1045
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::object::SectionedAddress::SectionIndex
uint64_t SectionIndex
Definition: ObjectFile.h:148
llvm::RangeListEntry::extract
Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr)
Definition: DWARFDebugRnglists.cpp:20
llvm::DIDumpOptions::Verbose
bool Verbose
Definition: DIContext.h:191
llvm::dwarf::computeTombstoneAddress
uint64_t computeTombstoneAddress(uint8_t AddressByteSize)
Definition: Dwarf.h:772
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::RangeListEntry
A class representing a single range list entry.
Definition: DWARFDebugRnglists.h:28
llvm::DWARFDebugRnglist::getAbsoluteRanges
DWARFAddressRangesVector getAbsoluteRanges(Optional< object::SectionedAddress > BaseAddr, uint8_t AddressByteSize, function_ref< Optional< object::SectionedAddress >(uint32_t)> LookupPooledAddress) const
Build a DWARFAddressRangesVector from a rangelist.
Definition: DWARFDebugRnglists.cpp:95
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:168
Index
uint32_t Index
Definition: ELFObjHandler.cpp:84
uint64_t
DWARFUnit.h
DWARFDebugRnglists.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::DWARFAddressRange::dump
void dump(raw_ostream &OS, uint32_t AddressSize, DIDumpOptions DumpOpts={}, const DWARFObject *Obj=nullptr) const
Definition: DWARFAddressRange.cpp:16
llvm::DataExtractor::Cursor
A class representing a position in a DataExtractor, as well as any error encountered during extractio...
Definition: DataExtractor.h:54
llvm::DWARFFormValue::dumpAddress
void dumpAddress(raw_ostream &OS, uint64_t Address) const
Dwarf.h
llvm::errc::not_supported
@ not_supported
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
if
if(llvm_vc STREQUAL "") set(fake_version_inc "$
Definition: CMakeLists.txt:14
uint32_t
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::RangeListEntry::dump
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
Definition: DWARFDebugRnglists.cpp:175
llvm::DWARFUnit::getAddressByteSize
uint8_t getAddressByteSize() const
Definition: DWARFUnit.h:286
llvm::DWARFAddressRangesVector
std::vector< DWARFAddressRange > DWARFAddressRangesVector
DWARFAddressRangesVector - represents a set of absolute address ranges.
Definition: DWARFAddressRange.h:85
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1241
llvm::DWARFListEntryBase::SectionIndex
uint64_t SectionIndex
The index of the section this entry belongs to.
Definition: DWARFListTable.h:33
llvm::DWARFUnit
Definition: DWARFUnit.h:203
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::DIDumpOptions::DisplayRawContents
bool DisplayRawContents
Definition: DIContext.h:192
llvm::RangeListEntry::Value1
uint64_t Value1
Definition: DWARFDebugRnglists.h:34
llvm::dwarf::RLEString
StringRef RLEString(unsigned RLE)
Definition: Dwarf.cpp:804
llvm::DWARFAddressRange
Definition: DWARFAddressRange.h:22
llvm::RangeListEntry::Value0
uint64_t Value0
The values making up the range list entry.
Definition: DWARFDebugRnglists.h:33
raw_ostream.h
llvm::DIDumpOptions
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:180