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