1 //===- DWARFGdbIndex.cpp --------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
10 #include "llvm/ADT/SmallVector.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/Support/Format.h"
13 #include "llvm/Support/FormatVariadic.h"
14 #include "llvm/Support/raw_ostream.h"
23 // .gdb_index section format reference:
24 // https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html
26 void DWARFGdbIndex::dumpCUList(raw_ostream
&OS
) const {
27 OS
<< format("\n CU list offset = 0x%x, has %" PRId64
" entries:",
28 CuListOffset
, (uint64_t)CuList
.size())
31 for (const CompUnitEntry
&CU
: CuList
)
32 OS
<< format(" %d: Offset = 0x%llx, Length = 0x%llx\n", I
++, CU
.Offset
,
36 void DWARFGdbIndex::dumpTUList(raw_ostream
&OS
) const {
37 OS
<< formatv("\n Types CU list offset = {0:x}, has {1} entries:\n",
38 TuListOffset
, TuList
.size());
40 for (const TypeUnitEntry
&TU
: TuList
)
41 OS
<< formatv(" {0}: offset = {1:x8}, type_offset = {2:x8}, "
42 "type_signature = {3:x16}\n",
43 I
++, TU
.Offset
, TU
.TypeOffset
, TU
.TypeSignature
);
46 void DWARFGdbIndex::dumpAddressArea(raw_ostream
&OS
) const {
47 OS
<< format("\n Address area offset = 0x%x, has %" PRId64
" entries:",
48 AddressAreaOffset
, (uint64_t)AddressArea
.size())
50 for (const AddressEntry
&Addr
: AddressArea
)
52 " Low/High address = [0x%llx, 0x%llx) (Size: 0x%llx), CU id = %d\n",
53 Addr
.LowAddress
, Addr
.HighAddress
, Addr
.HighAddress
- Addr
.LowAddress
,
57 void DWARFGdbIndex::dumpSymbolTable(raw_ostream
&OS
) const {
58 OS
<< format("\n Symbol table offset = 0x%x, size = %" PRId64
60 SymbolTableOffset
, (uint64_t)SymbolTable
.size())
63 for (const SymTableEntry
&E
: SymbolTable
) {
65 if (!E
.NameOffset
&& !E
.VecOffset
)
68 OS
<< format(" %d: Name offset = 0x%x, CU vector offset = 0x%x\n", I
,
69 E
.NameOffset
, E
.VecOffset
);
71 StringRef Name
= ConstantPoolStrings
.substr(
72 ConstantPoolOffset
- StringPoolOffset
+ E
.NameOffset
);
74 auto CuVector
= std::find_if(
75 ConstantPoolVectors
.begin(), ConstantPoolVectors
.end(),
76 [&](const std::pair
<uint32_t, SmallVector
<uint32_t, 0>> &V
) {
77 return V
.first
== E
.VecOffset
;
79 assert(CuVector
!= ConstantPoolVectors
.end() && "Invalid symbol table");
80 uint32_t CuVectorId
= CuVector
- ConstantPoolVectors
.begin();
81 OS
<< format(" String name: %s, CU vector index: %d\n", Name
.data(),
86 void DWARFGdbIndex::dumpConstantPool(raw_ostream
&OS
) const {
87 OS
<< format("\n Constant pool offset = 0x%x, has %" PRId64
" CU vectors:",
88 ConstantPoolOffset
, (uint64_t)ConstantPoolVectors
.size());
90 for (const auto &V
: ConstantPoolVectors
) {
91 OS
<< format("\n %d(0x%x): ", I
++, V
.first
);
92 for (uint32_t Val
: V
.second
)
93 OS
<< format("0x%x ", Val
);
98 void DWARFGdbIndex::dump(raw_ostream
&OS
) {
100 OS
<< "\n<error parsing>\n";
105 OS
<< " Version = " << Version
<< '\n';
110 dumpConstantPool(OS
);
114 bool DWARFGdbIndex::parseImpl(DataExtractor Data
) {
117 // Only version 7 is supported at this moment.
118 Version
= Data
.getU32(&Offset
);
122 CuListOffset
= Data
.getU32(&Offset
);
123 TuListOffset
= Data
.getU32(&Offset
);
124 AddressAreaOffset
= Data
.getU32(&Offset
);
125 SymbolTableOffset
= Data
.getU32(&Offset
);
126 ConstantPoolOffset
= Data
.getU32(&Offset
);
128 if (Offset
!= CuListOffset
)
131 uint32_t CuListSize
= (TuListOffset
- CuListOffset
) / 16;
132 CuList
.reserve(CuListSize
);
133 for (uint32_t i
= 0; i
< CuListSize
; ++i
) {
134 uint64_t CuOffset
= Data
.getU64(&Offset
);
135 uint64_t CuLength
= Data
.getU64(&Offset
);
136 CuList
.push_back({CuOffset
, CuLength
});
139 // CU Types are no longer needed as DWARF skeleton type units never made it
140 // into the standard.
141 uint32_t TuListSize
= (AddressAreaOffset
- TuListOffset
) / 24;
142 TuList
.resize(TuListSize
);
143 for (uint32_t I
= 0; I
< TuListSize
; ++I
) {
144 uint64_t CuOffset
= Data
.getU64(&Offset
);
145 uint64_t TypeOffset
= Data
.getU64(&Offset
);
146 uint64_t Signature
= Data
.getU64(&Offset
);
147 TuList
[I
] = {CuOffset
, TypeOffset
, Signature
};
150 uint32_t AddressAreaSize
= (SymbolTableOffset
- AddressAreaOffset
) / 20;
151 AddressArea
.reserve(AddressAreaSize
);
152 for (uint32_t i
= 0; i
< AddressAreaSize
; ++i
) {
153 uint64_t LowAddress
= Data
.getU64(&Offset
);
154 uint64_t HighAddress
= Data
.getU64(&Offset
);
155 uint32_t CuIndex
= Data
.getU32(&Offset
);
156 AddressArea
.push_back({LowAddress
, HighAddress
, CuIndex
});
159 // The symbol table. This is an open addressed hash table. The size of the
160 // hash table is always a power of 2.
161 // Each slot in the hash table consists of a pair of offset_type values. The
162 // first value is the offset of the symbol's name in the constant pool. The
163 // second value is the offset of the CU vector in the constant pool.
164 // If both values are 0, then this slot in the hash table is empty. This is ok
165 // because while 0 is a valid constant pool index, it cannot be a valid index
166 // for both a string and a CU vector.
167 uint32_t SymTableSize
= (ConstantPoolOffset
- SymbolTableOffset
) / 8;
168 SymbolTable
.reserve(SymTableSize
);
169 uint32_t CuVectorsTotal
= 0;
170 for (uint32_t i
= 0; i
< SymTableSize
; ++i
) {
171 uint32_t NameOffset
= Data
.getU32(&Offset
);
172 uint32_t CuVecOffset
= Data
.getU32(&Offset
);
173 SymbolTable
.push_back({NameOffset
, CuVecOffset
});
174 if (NameOffset
|| CuVecOffset
)
178 // The constant pool. CU vectors are stored first, followed by strings.
179 // The first value is the number of CU indices in the vector. Each subsequent
180 // value is the index and symbol attributes of a CU in the CU list.
181 for (uint32_t i
= 0; i
< CuVectorsTotal
; ++i
) {
182 ConstantPoolVectors
.emplace_back(0, SmallVector
<uint32_t, 0>());
183 auto &Vec
= ConstantPoolVectors
.back();
184 Vec
.first
= Offset
- ConstantPoolOffset
;
186 uint32_t Num
= Data
.getU32(&Offset
);
187 for (uint32_t j
= 0; j
< Num
; ++j
)
188 Vec
.second
.push_back(Data
.getU32(&Offset
));
191 ConstantPoolStrings
= Data
.getData().drop_front(Offset
);
192 StringPoolOffset
= Offset
;
196 void DWARFGdbIndex::parse(DataExtractor Data
) {
197 HasContent
= !Data
.getData().empty();
198 HasError
= HasContent
&& !parseImpl(Data
);