1 //===-- DWARFGdbIndex.cpp -------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h" 11 #include "llvm/ADT/Twine.h" 12 #include "llvm/Support/ErrorHandling.h" 13 #include "llvm/Support/Format.h" 14 15 using namespace llvm; 16 17 // .gdb_index section format reference: 18 // https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html 19 20 void DWARFGdbIndex::dumpCUList(raw_ostream &OS) const { 21 OS << format("\n CU list offset = 0x%x, has %" PRId64 " entries:", 22 CuListOffset, (uint64_t)CuList.size()) 23 << '\n'; 24 uint32_t I = 0; 25 for (const CompUnitEntry &CU : CuList) 26 OS << format(" %d: Offset = 0x%llx, Length = 0x%llx\n", I++, CU.Offset, 27 CU.Length); 28 } 29 30 void DWARFGdbIndex::dumpAddressArea(raw_ostream &OS) const { 31 OS << format("\n Address area offset = 0x%x, has %" PRId64 " entries:", 32 AddressAreaOffset, (uint64_t)AddressArea.size()) 33 << '\n'; 34 for (const AddressEntry &Addr : AddressArea) 35 OS << format( 36 " Low address = 0x%llx, High address = 0x%llx, CU index = %d\n", 37 Addr.LowAddress, Addr.HighAddress, Addr.CuIndex); 38 } 39 40 void DWARFGdbIndex::dumpSymbolTable(raw_ostream &OS) const { 41 OS << format("\n Symbol table offset = 0x%x, size = %" PRId64 42 ", filled slots:", 43 SymbolTableOffset, (uint64_t)SymbolTable.size()) 44 << '\n'; 45 uint32_t I = -1; 46 for (const SymTableEntry &E : SymbolTable) { 47 ++I; 48 if (!E.NameOffset && !E.VecOffset) 49 continue; 50 51 OS << format(" %d: Name offset = 0x%x, CU vector offset = 0x%x\n", I, 52 E.NameOffset, E.VecOffset); 53 54 StringRef Name = ConstantPoolStrings.substr( 55 ConstantPoolOffset - StringPoolOffset + E.NameOffset); 56 57 auto CuVector = std::find_if( 58 ConstantPoolVectors.begin(), ConstantPoolVectors.end(), 59 [&](const std::pair<uint32_t, SmallVector<uint32_t, 0>> &V) { 60 return V.first == E.VecOffset; 61 }); 62 assert(CuVector != ConstantPoolVectors.end() && "Invalid symbol table"); 63 uint32_t CuVectorId = CuVector - ConstantPoolVectors.begin(); 64 OS << format(" String name: %s, CU vector index: %d\n", Name.data(), 65 CuVectorId); 66 } 67 } 68 69 void DWARFGdbIndex::dumpConstantPool(raw_ostream &OS) const { 70 OS << format("\n Constant pool offset = 0x%x, has %" PRId64 " CU vectors:", 71 ConstantPoolOffset, (uint64_t)ConstantPoolVectors.size()); 72 uint32_t I = 0; 73 for (const auto &V : ConstantPoolVectors) { 74 OS << format("\n %d(0x%x): ", I++, V.first); 75 for (uint32_t Val : V.second) 76 OS << format("0x%x ", Val); 77 } 78 OS << '\n'; 79 } 80 81 void DWARFGdbIndex::dump(raw_ostream &OS) { 82 if (HasError) { 83 OS << "\n<error parsing>\n"; 84 return; 85 } 86 87 if (HasContent) { 88 OS << " Version = " << Version << '\n'; 89 dumpCUList(OS); 90 dumpAddressArea(OS); 91 dumpSymbolTable(OS); 92 dumpConstantPool(OS); 93 } 94 } 95 96 bool DWARFGdbIndex::parseImpl(DataExtractor Data) { 97 uint32_t Offset = 0; 98 99 // Only version 7 is supported at this moment. 100 Version = Data.getU32(&Offset); 101 if (Version != 7) 102 return false; 103 104 CuListOffset = Data.getU32(&Offset); 105 uint32_t CuTypesOffset = Data.getU32(&Offset); 106 AddressAreaOffset = Data.getU32(&Offset); 107 SymbolTableOffset = Data.getU32(&Offset); 108 ConstantPoolOffset = Data.getU32(&Offset); 109 110 if (Offset != CuListOffset) 111 return false; 112 113 uint32_t CuListSize = (CuTypesOffset - CuListOffset) / 16; 114 CuList.reserve(CuListSize); 115 for (uint32_t i = 0; i < CuListSize; ++i) { 116 uint64_t CuOffset = Data.getU64(&Offset); 117 uint64_t CuLength = Data.getU64(&Offset); 118 CuList.push_back({CuOffset, CuLength}); 119 } 120 121 // CU Types are no longer needed as DWARF skeleton type units never made it 122 // into the standard. 123 uint32_t CuTypesListSize = (AddressAreaOffset - CuTypesOffset) / 24; 124 if (CuTypesListSize != 0) 125 return false; 126 127 uint32_t AddressAreaSize = (SymbolTableOffset - AddressAreaOffset) / 20; 128 AddressArea.reserve(AddressAreaSize); 129 for (uint32_t i = 0; i < AddressAreaSize; ++i) { 130 uint64_t LowAddress = Data.getU64(&Offset); 131 uint64_t HighAddress = Data.getU64(&Offset); 132 uint32_t CuIndex = Data.getU32(&Offset); 133 AddressArea.push_back({LowAddress, HighAddress, CuIndex}); 134 } 135 136 // The symbol table. This is an open addressed hash table. The size of the 137 // hash table is always a power of 2. 138 // Each slot in the hash table consists of a pair of offset_type values. The 139 // first value is the offset of the symbol's name in the constant pool. The 140 // second value is the offset of the CU vector in the constant pool. 141 // If both values are 0, then this slot in the hash table is empty. This is ok 142 // because while 0 is a valid constant pool index, it cannot be a valid index 143 // for both a string and a CU vector. 144 uint32_t SymTableSize = (ConstantPoolOffset - SymbolTableOffset) / 8; 145 SymbolTable.reserve(SymTableSize); 146 uint32_t CuVectorsTotal = 0; 147 for (uint32_t i = 0; i < SymTableSize; ++i) { 148 uint32_t NameOffset = Data.getU32(&Offset); 149 uint32_t CuVecOffset = Data.getU32(&Offset); 150 SymbolTable.push_back({NameOffset, CuVecOffset}); 151 if (NameOffset || CuVecOffset) 152 ++CuVectorsTotal; 153 } 154 155 // The constant pool. CU vectors are stored first, followed by strings. 156 // The first value is the number of CU indices in the vector. Each subsequent 157 // value is the index and symbol attributes of a CU in the CU list. 158 for (uint32_t i = 0; i < CuVectorsTotal; ++i) { 159 ConstantPoolVectors.emplace_back(0, SmallVector<uint32_t, 0>()); 160 auto &Vec = ConstantPoolVectors.back(); 161 Vec.first = Offset - ConstantPoolOffset; 162 163 uint32_t Num = Data.getU32(&Offset); 164 for (uint32_t j = 0; j < Num; ++j) 165 Vec.second.push_back(Data.getU32(&Offset)); 166 } 167 168 ConstantPoolStrings = Data.getData().drop_front(Offset); 169 StringPoolOffset = Offset; 170 return true; 171 } 172 173 void DWARFGdbIndex::parse(DataExtractor Data) { 174 HasContent = !Data.getData().empty(); 175 HasError = HasContent && !parseImpl(Data); 176 } 177