1//===- DWARFUnitIndex.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_DWARFUNITINDEX_H
10#define LLVM_DEBUGINFO_DWARF_DWARFUNITINDEX_H
11
12#include "llvm/ADT/ArrayRef.h"
13#include "llvm/ADT/StringRef.h"
14#include <cstdint>
15#include <memory>
16
17namespace llvm {
18
19class raw_ostream;
20class DataExtractor;
21
22/// The enum of section identifiers to be used in internal interfaces.
23///
24/// Pre-standard implementation of package files defined a number of section
25/// identifiers with values that clash definitions in the DWARFv5 standard.
26/// See https://gcc.gnu.org/wiki/DebugFissionDWP and Section 7.3.5.3 in DWARFv5.
27///
28/// The following identifiers are the same in the proposal and in DWARFv5:
29/// - DW_SECT_INFO         = 1 (.debug_info.dwo)
30/// - DW_SECT_ABBREV       = 3 (.debug_abbrev.dwo)
31/// - DW_SECT_LINE         = 4 (.debug_line.dwo)
32/// - DW_SECT_STR_OFFSETS  = 6 (.debug_str_offsets.dwo)
33///
34/// The following identifiers are defined only in DWARFv5:
35/// - DW_SECT_LOCLISTS     = 5 (.debug_loclists.dwo)
36/// - DW_SECT_RNGLISTS     = 8 (.debug_rnglists.dwo)
37///
38/// The following identifiers are defined only in the GNU proposal:
39/// - DW_SECT_TYPES        = 2 (.debug_types.dwo)
40/// - DW_SECT_LOC          = 5 (.debug_loc.dwo)
41/// - DW_SECT_MACINFO      = 7 (.debug_macinfo.dwo)
42///
43/// DW_SECT_MACRO for the .debug_macro.dwo section is defined in both standards,
44/// but with different values, 8 in GNU and 7 in DWARFv5.
45///
46/// This enum defines constants to represent the identifiers of both sets.
47/// For DWARFv5 ones, the values are the same as defined in the standard.
48/// For pre-standard ones that correspond to sections being deprecated in
49/// DWARFv5, the values are chosen arbitrary and a tag "_EXT_" is added to
50/// the names.
51///
52/// The enum is for internal use only. The user should not expect the values
53/// to correspond to any input/output constants. Special conversion functions,
54/// serializeSectionKind() and deserializeSectionKind(), should be used for
55/// the translation.
56enum DWARFSectionKind {
57  /// Denotes a value read from an index section that does not correspond
58  /// to any of the supported standards.
59  DW_SECT_EXT_unknown = 0,
60#define HANDLE_DW_SECT(ID, NAME) DW_SECT_##NAME = ID,
61#include "llvm/BinaryFormat/Dwarf.def"
62  DW_SECT_EXT_TYPES = 2,
63  DW_SECT_EXT_LOC = 9,
64  DW_SECT_EXT_MACINFO = 10,
65};
66
67inline const char *toString(DWARFSectionKind Kind) {
68  switch (Kind) {
69  case DW_SECT_EXT_unknown:
70    return "Unknown DW_SECT value 0";
71#define STRINGIZE(X) #X
72#define HANDLE_DW_SECT(ID, NAME)                                               \
73  case DW_SECT_##NAME:                                                         \
74    return "DW_SECT_" STRINGIZE(NAME);
75#include "llvm/BinaryFormat/Dwarf.def"
76  case DW_SECT_EXT_TYPES:
77    return "DW_SECT_TYPES";
78  case DW_SECT_EXT_LOC:
79    return "DW_SECT_LOC";
80  case DW_SECT_EXT_MACINFO:
81    return "DW_SECT_MACINFO";
82  }
83  llvm_unreachable("unknown DWARFSectionKind");
84}
85
86/// Convert the internal value for a section kind to an on-disk value.
87///
88/// The conversion depends on the version of the index section.
89/// IndexVersion is expected to be either 2 for pre-standard GNU proposal
90/// or 5 for DWARFv5 package file.
91uint32_t serializeSectionKind(DWARFSectionKind Kind, unsigned IndexVersion);
92
93/// Convert a value read from an index section to the internal representation.
94///
95/// The conversion depends on the index section version, which is expected
96/// to be either 2 for pre-standard GNU proposal or 5 for DWARFv5 package file.
97DWARFSectionKind deserializeSectionKind(uint32_t Value, unsigned IndexVersion);
98
99class DWARFUnitIndex {
100  struct Header {
101    uint32_t Version;
102    uint32_t NumColumns;
103    uint32_t NumUnits;
104    uint32_t NumBuckets = 0;
105
106    bool parse(DataExtractor IndexData, uint64_t *OffsetPtr);
107    void dump(raw_ostream &OS) const;
108  };
109
110public:
111  class Entry {
112  public:
113    class SectionContribution {
114    private:
115      uint64_t Offset;
116      uint64_t Length;
117
118    public:
119      SectionContribution() : Offset(0), Length(0) {}
120      SectionContribution(uint64_t Offset, uint64_t Length)
121          : Offset(Offset), Length(Length) {}
122
123      void setOffset(uint64_t Value) { Offset = Value; }
124      void setLength(uint64_t Value) { Length = Value; }
125      uint64_t getOffset() const { return Offset; }
126      uint64_t getLength() const { return Length; }
127      uint32_t getOffset32() const { return (uint32_t)Offset; }
128      uint32_t getLength32() const { return (uint32_t)Length; }
129    };
130
131  private:
132    const DWARFUnitIndex *Index;
133    uint64_t Signature;
134    std::unique_ptr<SectionContribution[]> Contributions;
135    friend class DWARFUnitIndex;
136
137  public:
138    const SectionContribution *getContribution(DWARFSectionKind Sec) const;
139    const SectionContribution *getContribution() const;
140    SectionContribution &getContribution();
141
142    const SectionContribution *getContributions() const {
143      return Contributions.get();
144    }
145
146    uint64_t getSignature() const { return Signature; }
147    bool isValid() { return Index; }
148  };
149
150private:
151  struct Header Header;
152
153  DWARFSectionKind InfoColumnKind;
154  int InfoColumn = -1;
155  std::unique_ptr<DWARFSectionKind[]> ColumnKinds;
156  // This is a parallel array of section identifiers as they read from the input
157  // file. The mapping from raw values to DWARFSectionKind is not revertable in
158  // case of unknown identifiers, so we keep them here.
159  std::unique_ptr<uint32_t[]> RawSectionIds;
160  std::unique_ptr<Entry[]> Rows;
161  mutable std::vector<Entry *> OffsetLookup;
162
163  static StringRef getColumnHeader(DWARFSectionKind DS);
164
165  bool parseImpl(DataExtractor IndexData);
166
167public:
168  DWARFUnitIndex(DWARFSectionKind InfoColumnKind)
169      : InfoColumnKind(InfoColumnKind) {}
170
171  explicit operator bool() const { return Header.NumBuckets; }
172
173  bool parse(DataExtractor IndexData);
174  void dump(raw_ostream &OS) const;
175
176  uint32_t getVersion() const { return Header.Version; }
177
178  const Entry *getFromOffset(uint64_t Offset) const;
179  const Entry *getFromHash(uint64_t Offset) const;
180
181  ArrayRef<DWARFSectionKind> getColumnKinds() const {
182    return ArrayRef(ColumnKinds.get(), Header.NumColumns);
183  }
184
185  ArrayRef<Entry> getRows() const {
186    return ArrayRef(Rows.get(), Header.NumBuckets);
187  }
188
189  MutableArrayRef<Entry> getMutableRows() {
190    return MutableArrayRef(Rows.get(), Header.NumBuckets);
191  }
192};
193
194} // end namespace llvm
195
196#endif // LLVM_DEBUGINFO_DWARF_DWARFUNITINDEX_H
197