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