xref: /llvm-project/bolt/lib/Core/GDBIndex.cpp (revision 33960ce5a8e26baf05521fd7f8be5c5abb6bb0ff)
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 //===----------------------------------------------------------------------===//
8 
9 #include "bolt/Core/GDBIndex.h"
10 
11 using namespace llvm::bolt;
12 using namespace llvm::support::endian;
13 
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);
19 }
20 
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.
28 
29   StringRef GdbIndexContents = BC.getGdbIndexSection()->getContents();
30 
31   const char *Data = GdbIndexContents.data();
32 
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);
38   }
39 
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;
49 
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());
73 
74   if (!((CUListSize == NumCUs * 16) ||
75         (CUListSize == (NumCUs + NumDWARF5TUs) * 16))) {
76     errs() << "BOLT-ERROR: .gdb_index: CU count mismatch\n";
77     exit(1);
78   }
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);
90     }
91 
92     OriginalOffsets.insert(Offset);
93     OffsetToIndexMap[Offset] = Index;
94   }
95 
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;
100 
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;
106   }
107 
108   // Difference between old and new table (and section) sizes.
109   // Could be negative.
110   int32_t Delta = NewAddressTableSize - OldAddressTableSize;
111 
112   size_t NewGdbIndexSize = GdbIndexContents.size() + Delta;
113 
114   // Free'd by ExecutableFileMemoryManager.
115   auto *NewGdbIndexContents = new uint8_t[NewGdbIndexSize];
116   uint8_t *Buffer = NewGdbIndexContents;
117 
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;
125 
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;
132             });
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;
142   }
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);
158     }
159 
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;
170     }
171   }
172 
173   const size_t TrailingSize =
174       GdbIndexContents.data() + GdbIndexContents.size() - Data;
175   assert(Buffer + TrailingSize == NewGdbIndexContents + NewGdbIndexSize &&
176          "size calculation error");
177 
178   // Copy over the rest of the original data.
179   memcpy(Buffer, Data, TrailingSize);
180 
181   // Register the new section.
182   BC.registerOrUpdateNoteSection(".gdb_index", NewGdbIndexContents,
183                                  NewGdbIndexSize);
184 }
185