[TargetVersion] Only enable on RISC-V and AArch64 (#115991)
[llvm-project.git] / bolt / lib / Core / GDBIndex.cpp
blobc7fb4889646b4ae12ef04eda36a5d86497d69129
1 //===- bolt/Core/GDBIndex.cpp - GDB Index support ------------------------===//
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 //===----------------------------------------------------------------------===//
9 #include "bolt/Core/GDBIndex.h"
11 using namespace llvm::bolt;
12 using namespace llvm::support::endian;
14 void GDBIndex::addGDBTypeUnitEntry(const GDBIndexTUEntry &&Entry) {
15 std::lock_guard<std::mutex> Lock(GDBIndexMutex);
16 if (!BC.getGdbIndexSection())
17 return;
18 GDBIndexTUEntryVector.emplace_back(Entry);
21 void GDBIndex::updateGdbIndexSection(
22 const CUOffsetMap &CUMap, const uint32_t NumCUs,
23 DebugARangesSectionWriter &ARangesSectionWriter) {
24 if (!BC.getGdbIndexSection())
25 return;
26 // See https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html
27 // for .gdb_index section format.
29 StringRef GdbIndexContents = BC.getGdbIndexSection()->getContents();
31 const char *Data = GdbIndexContents.data();
33 // Parse the header.
34 const uint32_t Version = read32le(Data);
35 if (Version != 7 && Version != 8) {
36 errs() << "BOLT-ERROR: can only process .gdb_index versions 7 and 8\n";
37 exit(1);
40 // Some .gdb_index generators use file offsets while others use section
41 // offsets. Hence we can only rely on offsets relative to each other,
42 // and ignore their absolute values.
43 const uint32_t CUListOffset = read32le(Data + 4);
44 const uint32_t CUTypesOffset = read32le(Data + 8);
45 const uint32_t AddressTableOffset = read32le(Data + 12);
46 const uint32_t SymbolTableOffset = read32le(Data + 16);
47 const uint32_t ConstantPoolOffset = read32le(Data + 20);
48 Data += 24;
50 // Map CUs offsets to indices and verify existing index table.
51 std::map<uint32_t, uint32_t> OffsetToIndexMap;
52 const uint32_t CUListSize = CUTypesOffset - CUListOffset;
53 const uint32_t TUListSize = AddressTableOffset - CUTypesOffset;
54 const unsigned NUmCUsEncoded = CUListSize / 16;
55 unsigned MaxDWARFVersion = BC.DwCtx->getMaxVersion();
56 unsigned NumDWARF5TUs =
57 getGDBIndexTUEntryVector().size() - BC.DwCtx->getNumTypeUnits();
58 bool SkipTypeUnits = false;
59 // For DWARF5 Types are in .debug_info.
60 // LLD doesn't generate Types CU List, and in CU list offset
61 // only includes CUs.
62 // GDB 11+ includes only CUs in CU list and generates Types
63 // list.
64 // GDB 9 includes CUs and TUs in CU list and generates TYpes
65 // list. The NumCUs is CUs + TUs, so need to modify the check.
66 // For split-dwarf
67 // GDB-11, DWARF5: TU units from dwo are not included.
68 // GDB-11, DWARF4: TU units from dwo are included.
69 if (MaxDWARFVersion >= 5)
70 SkipTypeUnits = !TUListSize ? true
71 : ((NUmCUsEncoded + NumDWARF5TUs) ==
72 BC.DwCtx->getNumCompileUnits());
74 if (!((CUListSize == NumCUs * 16) ||
75 (CUListSize == (NumCUs + NumDWARF5TUs) * 16))) {
76 errs() << "BOLT-ERROR: .gdb_index: CU count mismatch\n";
77 exit(1);
79 DenseSet<uint64_t> OriginalOffsets;
80 for (unsigned Index = 0, Units = BC.DwCtx->getNumCompileUnits();
81 Index < Units; ++Index) {
82 const DWARFUnit *CU = BC.DwCtx->getUnitAtIndex(Index);
83 if (SkipTypeUnits && CU->isTypeUnit())
84 continue;
85 const uint64_t Offset = read64le(Data);
86 Data += 16;
87 if (CU->getOffset() != Offset) {
88 errs() << "BOLT-ERROR: .gdb_index CU offset mismatch\n";
89 exit(1);
92 OriginalOffsets.insert(Offset);
93 OffsetToIndexMap[Offset] = Index;
96 // Ignore old address table.
97 const uint32_t OldAddressTableSize = SymbolTableOffset - AddressTableOffset;
98 // Move Data to the beginning of symbol table.
99 Data += SymbolTableOffset - CUTypesOffset;
101 // Calculate the size of the new address table.
102 uint32_t NewAddressTableSize = 0;
103 for (const auto &CURangesPair : ARangesSectionWriter.getCUAddressRanges()) {
104 const SmallVector<DebugAddressRange, 2> &Ranges = CURangesPair.second;
105 NewAddressTableSize += Ranges.size() * 20;
108 // Difference between old and new table (and section) sizes.
109 // Could be negative.
110 int32_t Delta = NewAddressTableSize - OldAddressTableSize;
112 size_t NewGdbIndexSize = GdbIndexContents.size() + Delta;
114 // Free'd by ExecutableFileMemoryManager.
115 auto *NewGdbIndexContents = new uint8_t[NewGdbIndexSize];
116 uint8_t *Buffer = NewGdbIndexContents;
118 write32le(Buffer, Version);
119 write32le(Buffer + 4, CUListOffset);
120 write32le(Buffer + 8, CUTypesOffset);
121 write32le(Buffer + 12, AddressTableOffset);
122 write32le(Buffer + 16, SymbolTableOffset + Delta);
123 write32le(Buffer + 20, ConstantPoolOffset + Delta);
124 Buffer += 24;
126 using MapEntry = std::pair<uint32_t, CUInfo>;
127 std::vector<MapEntry> CUVector(CUMap.begin(), CUMap.end());
128 // Need to sort since we write out all of TUs in .debug_info before CUs.
129 std::sort(CUVector.begin(), CUVector.end(),
130 [](const MapEntry &E1, const MapEntry &E2) -> bool {
131 return E1.second.Offset < E2.second.Offset;
133 // Writing out CU List <Offset, Size>
134 for (auto &CUInfo : CUVector) {
135 // Skipping TU for DWARF5 when they are not included in CU list.
136 if (!OriginalOffsets.count(CUInfo.first))
137 continue;
138 write64le(Buffer, CUInfo.second.Offset);
139 // Length encoded in CU doesn't contain first 4 bytes that encode length.
140 write64le(Buffer + 8, CUInfo.second.Length + 4);
141 Buffer += 16;
143 sortGDBIndexTUEntryVector();
144 // Rewrite TU CU List, since abbrevs can be different.
145 // Entry example:
146 // 0: offset = 0x00000000, type_offset = 0x0000001e, type_signature =
147 // 0x418503b8111e9a7b Spec says " triplet, the first value is the CU offset,
148 // the second value is the type offset in the CU, and the third value is the
149 // type signature" Looking at what is being generated by gdb-add-index. The
150 // first entry is TU offset, second entry is offset from it, and third entry
151 // is the type signature.
152 if (TUListSize)
153 for (const GDBIndexTUEntry &Entry : getGDBIndexTUEntryVector()) {
154 write64le(Buffer, Entry.UnitOffset);
155 write64le(Buffer + 8, Entry.TypeDIERelativeOffset);
156 write64le(Buffer + 16, Entry.TypeHash);
157 Buffer += sizeof(GDBIndexTUEntry);
160 // Generate new address table.
161 for (const std::pair<const uint64_t, DebugAddressRangesVector> &CURangesPair :
162 ARangesSectionWriter.getCUAddressRanges()) {
163 const uint32_t CUIndex = OffsetToIndexMap[CURangesPair.first];
164 const DebugAddressRangesVector &Ranges = CURangesPair.second;
165 for (const DebugAddressRange &Range : Ranges) {
166 write64le(Buffer, Range.LowPC);
167 write64le(Buffer + 8, Range.HighPC);
168 write32le(Buffer + 16, CUIndex);
169 Buffer += 20;
173 const size_t TrailingSize =
174 GdbIndexContents.data() + GdbIndexContents.size() - Data;
175 assert(Buffer + TrailingSize == NewGdbIndexContents + NewGdbIndexSize &&
176 "size calculation error");
178 // Copy over the rest of the original data.
179 memcpy(Buffer, Data, TrailingSize);
181 // Register the new section.
182 BC.registerOrUpdateNoteSection(".gdb_index", NewGdbIndexContents,
183 NewGdbIndexSize);