xref: /freebsd/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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