Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

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