]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / DebugInfo / DWARF / DWARFListTable.h
1 //===- DWARFListTable.h -----------------------------------------*- C++ -*-===//
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
10 #ifndef LLVM_DEBUGINFO_DWARFLISTTABLE_H
11 #define LLVM_DEBUGINFO_DWARFLISTTABLE_H
12
13 #include "llvm/BinaryFormat/Dwarf.h"
14 #include "llvm/DebugInfo/DIContext.h"
15 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
16 #include "llvm/Support/Errc.h"
17 #include "llvm/Support/Error.h"
18 #include "llvm/Support/Format.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include <cstdint>
21 #include <map>
22 #include <vector>
23
24 namespace llvm {
25
26 /// A base class for DWARF list entries, such as range or location list
27 /// entries.
28 struct DWARFListEntryBase {
29   /// The offset at which the entry is located in the section.
30   uint32_t Offset;
31   /// The DWARF encoding (DW_RLE_* or DW_LLE_*).
32   uint8_t EntryKind;
33   /// The index of the section this entry belongs to.
34   uint64_t SectionIndex;
35 };
36
37 /// A base class for lists of entries that are extracted from a particular
38 /// section, such as range lists or location lists.
39 template <typename ListEntryType> class DWARFListType {
40   using EntryType = ListEntryType;
41   using ListEntries = std::vector<EntryType>;
42
43 protected:
44   ListEntries Entries;
45
46 public:
47   const ListEntries &getEntries() const { return Entries; }
48   bool empty() const { return Entries.empty(); }
49   void clear() { Entries.clear(); }
50   Error extract(DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End,
51                 uint32_t *OffsetPtr, StringRef SectionName,
52                 StringRef ListStringName);
53 };
54
55 /// A class representing the header of a list table such as the range list
56 /// table in the .debug_rnglists section.
57 class DWARFListTableHeader {
58   struct Header {
59     /// The total length of the entries for this table, not including the length
60     /// field itself.
61     uint32_t Length = 0;
62     /// The DWARF version number.
63     uint16_t Version;
64     /// The size in bytes of an address on the target architecture. For
65     /// segmented addressing, this is the size of the offset portion of the
66     /// address.
67     uint8_t AddrSize;
68     /// The size in bytes of a segment selector on the target architecture.
69     /// If the target system uses a flat address space, this value is 0.
70     uint8_t SegSize;
71     /// The number of offsets that follow the header before the range lists.
72     uint32_t OffsetEntryCount;
73   };
74
75   Header HeaderData;
76   /// The offset table, which contains offsets to the individual list entries.
77   /// It is used by forms such as DW_FORM_rnglistx.
78   /// FIXME: Generate the table and use the appropriate forms.
79   std::vector<uint32_t> Offsets;
80   /// The table's format, either DWARF32 or DWARF64.
81   dwarf::DwarfFormat Format;
82   /// The offset at which the header (and hence the table) is located within
83   /// its section.
84   uint32_t HeaderOffset;
85   /// The name of the section the list is located in.
86   StringRef SectionName;
87   /// A characterization of the list for dumping purposes, e.g. "range" or
88   /// "location".
89   StringRef ListTypeString;
90
91 public:
92   DWARFListTableHeader(StringRef SectionName, StringRef ListTypeString)
93       : SectionName(SectionName), ListTypeString(ListTypeString) {}
94
95   void clear() {
96     HeaderData = {};
97     Offsets.clear();
98   }
99   uint32_t getHeaderOffset() const { return HeaderOffset; }
100   uint8_t getAddrSize() const { return HeaderData.AddrSize; }
101   uint32_t getLength() const { return HeaderData.Length; }
102   uint16_t getVersion() const { return HeaderData.Version; }
103   StringRef getSectionName() const { return SectionName; }
104   StringRef getListTypeString() const { return ListTypeString; }
105   dwarf::DwarfFormat getFormat() const { return Format; }
106
107   void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
108   Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
109     if (Index < Offsets.size())
110       return Offsets[Index];
111     return None;
112   }
113
114   /// Extract the table header and the array of offsets.
115   Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
116
117   /// Returns the length of the table, including the length field, or 0 if the
118   /// length has not been determined (e.g. because the table has not yet been
119   /// parsed, or there was a problem in parsing).
120   uint32_t length() const;
121 };
122
123 /// A class representing a table of lists as specified in the DWARF v5
124 /// standard for location lists and range lists. The table consists of a header
125 /// followed by an array of offsets into a DWARF section, followed by zero or
126 /// more list entries. The list entries are kept in a map where the keys are
127 /// the lists' section offsets.
128 template <typename DWARFListType> class DWARFListTableBase {
129   DWARFListTableHeader Header;
130   /// A mapping between file offsets and lists. It is used to find a particular
131   /// list based on an offset (obtained from DW_AT_ranges, for example).
132   std::map<uint32_t, DWARFListType> ListMap;
133   /// This string is displayed as a heading before the list is dumped
134   /// (e.g. "ranges:").
135   StringRef HeaderString;
136
137 protected:
138   DWARFListTableBase(StringRef SectionName, StringRef HeaderString,
139                      StringRef ListTypeString)
140       : Header(SectionName, ListTypeString), HeaderString(HeaderString) {}
141
142 public:
143   void clear() {
144     Header.clear();
145     ListMap.clear();
146   }
147   /// Extract the table header and the array of offsets.
148   Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint32_t *OffsetPtr) {
149     return Header.extract(Data, OffsetPtr);
150   }
151   /// Extract an entire table, including all list entries.
152   Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
153   /// Look up a list based on a given offset. Extract it and enter it into the
154   /// list map if necessary.
155   Expected<DWARFListType> findList(DWARFDataExtractor Data, uint32_t Offset);
156
157   uint32_t getHeaderOffset() const { return Header.getHeaderOffset(); }
158   uint8_t getAddrSize() const { return Header.getAddrSize(); }
159
160   void dump(raw_ostream &OS,
161             llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
162                 LookupPooledAddress,
163             DIDumpOptions DumpOpts = {}) const;
164
165   /// Return the contents of the offset entry designated by a given index.
166   Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
167     return Header.getOffsetEntry(Index);
168   }
169   /// Return the size of the table header including the length but not including
170   /// the offsets. This is dependent on the table format, which is unambiguously
171   /// derived from parsing the table.
172   uint8_t getHeaderSize() const {
173     switch (Header.getFormat()) {
174     case dwarf::DwarfFormat::DWARF32:
175       return 12;
176     case dwarf::DwarfFormat::DWARF64:
177       return 20;
178     }
179     llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64");
180   }
181
182   uint32_t length() { return Header.length(); }
183 };
184
185 template <typename DWARFListType>
186 Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data,
187                                                  uint32_t *OffsetPtr) {
188   clear();
189   if (Error E = extractHeaderAndOffsets(Data, OffsetPtr))
190     return E;
191
192   Data.setAddressSize(Header.getAddrSize());
193   uint32_t End = getHeaderOffset() + Header.length();
194   while (*OffsetPtr < End) {
195     DWARFListType CurrentList;
196     uint32_t Off = *OffsetPtr;
197     if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr,
198                                       Header.getSectionName(),
199                                       Header.getListTypeString()))
200       return E;
201     ListMap[Off] = CurrentList;
202   }
203
204   assert(*OffsetPtr == End &&
205          "mismatch between expected length of table and length "
206          "of extracted data");
207   return Error::success();
208 }
209
210 template <typename ListEntryType>
211 Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data,
212                                             uint32_t HeaderOffset, uint32_t End,
213                                             uint32_t *OffsetPtr,
214                                             StringRef SectionName,
215                                             StringRef ListTypeString) {
216   if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End)
217     return createStringError(errc::invalid_argument,
218                        "invalid %s list offset 0x%" PRIx32,
219                        ListTypeString.data(), *OffsetPtr);
220   Entries.clear();
221   while (*OffsetPtr < End) {
222     ListEntryType Entry;
223     if (Error E = Entry.extract(Data, End, OffsetPtr))
224       return E;
225     Entries.push_back(Entry);
226     if (Entry.isSentinel())
227       return Error::success();
228   }
229   return createStringError(errc::illegal_byte_sequence,
230                      "no end of list marker detected at end of %s table "
231                      "starting at offset 0x%" PRIx32,
232                      SectionName.data(), HeaderOffset);
233 }
234
235 template <typename DWARFListType>
236 void DWARFListTableBase<DWARFListType>::dump(
237     raw_ostream &OS,
238     llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
239         LookupPooledAddress,
240     DIDumpOptions DumpOpts) const {
241   Header.dump(OS, DumpOpts);
242   OS << HeaderString << "\n";
243
244   // Determine the length of the longest encoding string we have in the table,
245   // so we can align the output properly. We only need this in verbose mode.
246   size_t MaxEncodingStringLength = 0;
247   if (DumpOpts.Verbose) {
248     for (const auto &List : ListMap)
249       for (const auto &Entry : List.second.getEntries())
250         MaxEncodingStringLength =
251             std::max(MaxEncodingStringLength,
252                      dwarf::RangeListEncodingString(Entry.EntryKind).size());
253   }
254
255   uint64_t CurrentBase = 0;
256   for (const auto &List : ListMap)
257     for (const auto &Entry : List.second.getEntries())
258       Entry.dump(OS, getAddrSize(), MaxEncodingStringLength, CurrentBase,
259                  DumpOpts, LookupPooledAddress);
260 }
261
262 template <typename DWARFListType>
263 Expected<DWARFListType>
264 DWARFListTableBase<DWARFListType>::findList(DWARFDataExtractor Data,
265                                             uint32_t Offset) {
266   auto Entry = ListMap.find(Offset);
267   if (Entry != ListMap.end())
268     return Entry->second;
269
270   // Extract the list from the section and enter it into the list map.
271   DWARFListType List;
272   uint32_t End = getHeaderOffset() + Header.length();
273   uint32_t StartingOffset = Offset;
274   if (Error E =
275           List.extract(Data, getHeaderOffset(), End, &Offset,
276                        Header.getSectionName(), Header.getListTypeString()))
277     return std::move(E);
278   ListMap[StartingOffset] = List;
279   return List;
280 }
281
282 } // end namespace llvm
283
284 #endif // LLVM_DEBUGINFO_DWARFLISTTABLE_H